1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 13:37:45 +00:00

LibCpp: Parse Namespace declaration

Also, remove unused State::Context
This commit is contained in:
Itamar 2021-03-19 21:47:43 +02:00 committed by Andreas Kling
parent 505c84fdf0
commit b5cab861e3
4 changed files with 111 additions and 57 deletions

View file

@ -43,7 +43,7 @@ void ASTNode::dump(size_t indent) const
void TranslationUnit::dump(size_t indent) const void TranslationUnit::dump(size_t indent) const
{ {
ASTNode::dump(indent); ASTNode::dump(indent);
for (const auto& child : m_children) { for (const auto& child : m_declarations) {
child.dump(indent + 1); child.dump(indent + 1);
} }
} }
@ -413,4 +413,14 @@ NonnullRefPtrVector<Declaration> IfStatement::declarations() const
declarations.append(m_else->declarations()); declarations.append(m_else->declarations());
return declarations; return declarations;
} }
void NamespaceDeclaration::dump(size_t indent) const
{
ASTNode::dump(indent);
print_indent(indent + 1);
outln("{}", m_name);
for (auto& decl : m_declarations)
decl.dump(indent + 1);
}
} }

View file

@ -96,23 +96,16 @@ class TranslationUnit : public ASTNode {
public: public:
virtual ~TranslationUnit() override = default; virtual ~TranslationUnit() override = default;
const NonnullRefPtrVector<Declaration>& children() const { return m_children; }
virtual const char* class_name() const override { return "TranslationUnit"; } virtual const char* class_name() const override { return "TranslationUnit"; }
virtual void dump(size_t indent) const override; virtual void dump(size_t indent) const override;
void append(NonnullRefPtr<Declaration> child) virtual NonnullRefPtrVector<Declaration> declarations() const override { return m_declarations; }
{
m_children.append(move(child));
}
virtual NonnullRefPtrVector<Declaration> declarations() const override { return m_children; }
public:
TranslationUnit(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename) TranslationUnit(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename)
: ASTNode(parent, start, end, filename) : ASTNode(parent, start, end, filename)
{ {
} }
private: NonnullRefPtrVector<Declaration> m_declarations;
NonnullRefPtrVector<Declaration> m_children;
}; };
class Statement : public ASTNode { class Statement : public ASTNode {
@ -140,6 +133,7 @@ public:
virtual bool is_struct() const { return false; } virtual bool is_struct() const { return false; }
virtual bool is_class() const { return false; } virtual bool is_class() const { return false; }
virtual bool is_function() const { return false; } virtual bool is_function() const { return false; }
virtual bool is_namespace() const { return false; }
const StringView& name() const { return m_name; } const StringView& name() const { return m_name; }
StringView m_name; StringView m_name;
@ -618,4 +612,22 @@ public:
RefPtr<Statement> m_else; RefPtr<Statement> m_else;
}; };
class NamespaceDeclaration : public Declaration {
public:
virtual ~NamespaceDeclaration() override = default;
virtual const char* class_name() const override { return "NamespaceDeclaration"; }
virtual void dump(size_t indent) const override;
virtual bool is_namespace() const override { return true; }
NamespaceDeclaration(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename)
: Declaration(parent, start, end, filename)
{
}
virtual NonnullRefPtrVector<Declaration> declarations() const override { return m_declarations; }
StringView m_name;
NonnullRefPtrVector<Declaration> m_declarations;
};
} }

View file

@ -78,7 +78,28 @@ NonnullRefPtr<TranslationUnit> Parser::parse()
if (m_tokens.is_empty()) if (m_tokens.is_empty())
return create_root_ast_node({}, {}); return create_root_ast_node({}, {});
auto unit = create_root_ast_node(m_tokens.first().start(), m_tokens.last().end()); auto unit = create_root_ast_node(m_tokens.first().start(), m_tokens.last().end());
while (!done()) { unit->m_declarations = parse_declarations_in_translation_unit(*unit);
return unit;
}
NonnullRefPtrVector<Declaration> Parser::parse_declarations_in_translation_unit(ASTNode& parent)
{
NonnullRefPtrVector<Declaration> declarations;
while (!eof()) {
auto declaration = parse_single_declaration_in_translation_unit(parent);
if (declaration) {
declarations.append(declaration.release_nonnull());
} else {
error("unexpected token");
consume();
}
}
return declarations;
}
RefPtr<Declaration> Parser::parse_single_declaration_in_translation_unit(ASTNode& parent)
{
while (!eof()) {
if (match_comment()) { if (match_comment()) {
consume(Token::Type::Comment); consume(Token::Type::Comment);
continue; continue;
@ -89,29 +110,13 @@ NonnullRefPtr<TranslationUnit> Parser::parse()
continue; continue;
} }
auto declaration = match_declaration(); auto declaration = match_declaration_in_translation_unit();
if (declaration.has_value()) { if (declaration.has_value()) {
unit->append(parse_declaration(*unit, declaration.value())); return parse_declaration(parent, declaration.value());
continue;
} }
error("unexpected token");
consume();
}
return unit;
}
Optional<Parser::DeclarationType> Parser::match_declaration()
{
switch (m_state.context) {
case Context::InTranslationUnit:
return match_declaration_in_translation_unit();
case Context::InFunctionDefinition:
return match_declaration_in_function_definition();
default:
error("unexpected context");
return {}; return {};
} }
return {};
} }
NonnullRefPtr<Declaration> Parser::parse_declaration(ASTNode& parent, DeclarationType declaration_type) NonnullRefPtr<Declaration> Parser::parse_declaration(ASTNode& parent, DeclarationType declaration_type)
@ -125,6 +130,8 @@ NonnullRefPtr<Declaration> Parser::parse_declaration(ASTNode& parent, Declaratio
return parse_enum_declaration(parent); return parse_enum_declaration(parent);
case DeclarationType::Struct: case DeclarationType::Struct:
return parse_struct_or_class_declaration(parent, StructOrClassDeclaration::Type::Struct); return parse_struct_or_class_declaration(parent, StructOrClassDeclaration::Type::Struct);
case DeclarationType::Namespace:
return parse_namespace_declaration(parent);
default: default:
error("unexpected declaration type"); error("unexpected declaration type");
return create_ast_node<InvalidDeclaration>(parent, position(), position()); return create_ast_node<InvalidDeclaration>(parent, position(), position());
@ -233,7 +240,7 @@ NonnullRefPtr<BlockStatement> Parser::parse_block_statement(ASTNode& parent)
SCOPE_LOGGER(); SCOPE_LOGGER();
auto block_statement = create_ast_node<BlockStatement>(parent, position(), {}); auto block_statement = create_ast_node<BlockStatement>(parent, position(), {});
consume(Token::Type::LeftCurly); consume(Token::Type::LeftCurly);
while (peek().type() != Token::Type::RightCurly) { while (!eof() && peek().type() != Token::Type::RightCurly) {
block_statement->m_statements.append(parse_statement(*block_statement)); block_statement->m_statements.append(parse_statement(*block_statement));
} }
consume(Token::Type::RightCurly); consume(Token::Type::RightCurly);
@ -524,17 +531,24 @@ Optional<Parser::DeclarationType> Parser::match_declaration_in_translation_unit(
return DeclarationType::Enum; return DeclarationType::Enum;
if (match_struct_declaration()) if (match_struct_declaration())
return DeclarationType::Struct; return DeclarationType::Struct;
if (match_namespace_declaration())
return DeclarationType::Namespace;
return {}; return {};
} }
bool Parser::match_enum_declaration() bool Parser::match_enum_declaration()
{ {
return peek().type() == Token::Type::Keyword && text_of_token(peek()) == "enum"; return match_keyword("enum");
} }
bool Parser::match_struct_declaration() bool Parser::match_struct_declaration()
{ {
return peek().type() == Token::Type::Keyword && text_of_token(peek()) == "struct"; return match_keyword("struct");
}
bool Parser::match_namespace_declaration()
{
return match_keyword("namespace");
} }
bool Parser::match_function_declaration() bool Parser::match_function_declaration()
@ -687,16 +701,6 @@ void Parser::load_state()
m_state = m_saved_states.take_last(); m_state = m_saved_states.take_last();
} }
Optional<Parser::DeclarationType> Parser::match_declaration_in_function_definition()
{
VERIFY_NOT_REACHED();
}
bool Parser::done()
{
return m_state.token_index == m_tokens.size();
}
StringView Parser::text_of_token(const Cpp::Token& token) const StringView Parser::text_of_token(const Cpp::Token& token) const
{ {
return token.text(); return token.text();
@ -906,7 +910,7 @@ NonnullRefPtr<EnumDeclaration> Parser::parse_enum_declaration(ASTNode& parent)
auto name_token = consume(Token::Type::Identifier); auto name_token = consume(Token::Type::Identifier);
enum_decl->m_name = text_of_token(name_token); enum_decl->m_name = text_of_token(name_token);
consume(Token::Type::LeftCurly); consume(Token::Type::LeftCurly);
while (peek().type() != Token::Type::RightCurly && !eof()) { while (!eof() && peek().type() != Token::Type::RightCurly) {
enum_decl->m_entries.append(text_of_token(consume(Token::Type::Identifier))); enum_decl->m_entries.append(text_of_token(consume(Token::Type::Identifier)));
if (peek().type() != Token::Type::Comma) { if (peek().type() != Token::Type::Comma) {
break; break;
@ -962,7 +966,7 @@ NonnullRefPtr<StructOrClassDeclaration> Parser::parse_struct_or_class_declaratio
consume(Token::Type::LeftCurly); consume(Token::Type::LeftCurly);
while (peek().type() != Token::Type::RightCurly && !eof()) { while (!eof() && peek().type() != Token::Type::RightCurly) {
decl->m_members.append(parse_member_declaration(*decl)); decl->m_members.append(parse_member_declaration(*decl));
} }
@ -1073,7 +1077,7 @@ Vector<StringView> Parser::parse_type_qualifiers()
{ {
SCOPE_LOGGER(); SCOPE_LOGGER();
Vector<StringView> qualifiers; Vector<StringView> qualifiers;
while (!done()) { while (!eof()) {
auto token = peek(); auto token = peek();
if (token.type() != Token::Type::Keyword) if (token.type() != Token::Type::Keyword)
break; break;
@ -1096,7 +1100,7 @@ void Parser::consume_attribute_specification()
consume(); // __attribute__ consume(); // __attribute__
consume(Token::Type::LeftParen); consume(Token::Type::LeftParen);
size_t left_count = 1; size_t left_count = 1;
while (!done()) { while (!eof()) {
auto token = consume(); auto token = consume();
if (token.type() == Token::Type::LeftParen) { if (token.type() == Token::Type::LeftParen) {
++left_count; ++left_count;
@ -1129,4 +1133,36 @@ void Parser::add_tokens_for_preprocessor(Token& replaced_token, Preprocessor::De
} }
} }
NonnullRefPtr<NamespaceDeclaration> Parser::parse_namespace_declaration(ASTNode& parent, bool is_nested_namespace)
{
auto namespace_decl = create_ast_node<NamespaceDeclaration>(parent, position(), {});
if (!is_nested_namespace)
consume(Token::Type::Keyword);
auto name_token = consume(Token::Type::Identifier);
namespace_decl->m_name = name_token.text();
if (peek().type() == Token::Type::ColonColon) {
consume(Token::Type::ColonColon);
namespace_decl->m_declarations.append(parse_namespace_declaration(*namespace_decl, true));
namespace_decl->set_end(position());
return namespace_decl;
}
consume(Token::Type::LeftCurly);
while (!eof() && peek().type() != Token::Type::RightCurly) {
auto declaration = parse_single_declaration_in_translation_unit(*namespace_decl);
if (declaration) {
namespace_decl->m_declarations.append(declaration.release_nonnull());
} else {
error("unexpected token");
consume();
}
}
consume(Token::Type::RightCurly);
namespace_decl->set_end(position());
return namespace_decl;
}
} }

View file

@ -68,13 +68,10 @@ private:
Variable, Variable,
Enum, Enum,
Struct, Struct,
Namespace,
}; };
bool done();
Optional<DeclarationType> match_declaration();
Optional<DeclarationType> match_declaration_in_translation_unit(); Optional<DeclarationType> match_declaration_in_translation_unit();
Optional<DeclarationType> match_declaration_in_function_definition();
bool match_function_declaration(); bool match_function_declaration();
bool match_comment(); bool match_comment();
bool match_preprocessor(); bool match_preprocessor();
@ -90,6 +87,7 @@ private:
bool match_boolean_literal(); bool match_boolean_literal();
bool match_keyword(const String&); bool match_keyword(const String&);
bool match_block_statement(); bool match_block_statement();
bool match_namespace_declaration();
Optional<NonnullRefPtrVector<Parameter>> parse_parameter_list(ASTNode& parent); Optional<NonnullRefPtrVector<Parameter>> parse_parameter_list(ASTNode& parent);
Optional<Token> consume_whitespace(); Optional<Token> consume_whitespace();
@ -119,6 +117,10 @@ private:
NonnullRefPtr<BlockStatement> parse_block_statement(ASTNode& parent); NonnullRefPtr<BlockStatement> parse_block_statement(ASTNode& parent);
NonnullRefPtr<Comment> parse_comment(ASTNode& parent); NonnullRefPtr<Comment> parse_comment(ASTNode& parent);
NonnullRefPtr<IfStatement> parse_if_statement(ASTNode& parent); NonnullRefPtr<IfStatement> parse_if_statement(ASTNode& parent);
NonnullRefPtr<NamespaceDeclaration> parse_namespace_declaration(ASTNode& parent, bool is_nested_namespace = false);
NonnullRefPtrVector<Declaration> parse_declarations_in_translation_unit(ASTNode& parent);
RefPtr<Declaration> parse_single_declaration_in_translation_unit(ASTNode& parent);
bool match(Token::Type); bool match(Token::Type);
Token consume(Token::Type); Token consume(Token::Type);
@ -132,13 +134,7 @@ private:
void save_state(); void save_state();
void load_state(); void load_state();
enum class Context {
InTranslationUnit,
InFunctionDefinition,
};
struct State { struct State {
Context context { Context::InTranslationUnit };
size_t token_index { 0 }; size_t token_index { 0 };
}; };