瀏覽代碼

LibCpp: Parse Namespace declaration

Also, remove unused State::Context
Itamar 4 年之前
父節點
當前提交
b5cab861e3

+ 11 - 1
Userland/Libraries/LibCpp/AST.cpp

@@ -43,7 +43,7 @@ void ASTNode::dump(size_t indent) const
 void TranslationUnit::dump(size_t indent) const
 {
     ASTNode::dump(indent);
-    for (const auto& child : m_children) {
+    for (const auto& child : m_declarations) {
         child.dump(indent + 1);
     }
 }
@@ -413,4 +413,14 @@ NonnullRefPtrVector<Declaration> IfStatement::declarations() const
     declarations.append(m_else->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);
+}
+
 }

+ 21 - 9
Userland/Libraries/LibCpp/AST.h

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

+ 73 - 37
Userland/Libraries/LibCpp/Parser.cpp

@@ -78,7 +78,28 @@ NonnullRefPtr<TranslationUnit> Parser::parse()
     if (m_tokens.is_empty())
         return create_root_ast_node({}, {});
     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()) {
             consume(Token::Type::Comment);
             continue;
@@ -89,29 +110,13 @@ NonnullRefPtr<TranslationUnit> Parser::parse()
             continue;
         }
 
-        auto declaration = match_declaration();
+        auto declaration = match_declaration_in_translation_unit();
         if (declaration.has_value()) {
-            unit->append(parse_declaration(*unit, declaration.value()));
-            continue;
+            return parse_declaration(parent, declaration.value());
         }
-
-        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 {};
 }
 
 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);
     case DeclarationType::Struct:
         return parse_struct_or_class_declaration(parent, StructOrClassDeclaration::Type::Struct);
+    case DeclarationType::Namespace:
+        return parse_namespace_declaration(parent);
     default:
         error("unexpected declaration type");
         return create_ast_node<InvalidDeclaration>(parent, position(), position());
@@ -233,7 +240,7 @@ NonnullRefPtr<BlockStatement> Parser::parse_block_statement(ASTNode& parent)
     SCOPE_LOGGER();
     auto block_statement = create_ast_node<BlockStatement>(parent, position(), {});
     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));
     }
     consume(Token::Type::RightCurly);
@@ -524,17 +531,24 @@ Optional<Parser::DeclarationType> Parser::match_declaration_in_translation_unit(
         return DeclarationType::Enum;
     if (match_struct_declaration())
         return DeclarationType::Struct;
+    if (match_namespace_declaration())
+        return DeclarationType::Namespace;
     return {};
 }
 
 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()
 {
-    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()
@@ -687,16 +701,6 @@ void Parser::load_state()
     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
 {
     return token.text();
@@ -906,7 +910,7 @@ NonnullRefPtr<EnumDeclaration> Parser::parse_enum_declaration(ASTNode& parent)
     auto name_token = consume(Token::Type::Identifier);
     enum_decl->m_name = text_of_token(name_token);
     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)));
         if (peek().type() != Token::Type::Comma) {
             break;
@@ -962,7 +966,7 @@ NonnullRefPtr<StructOrClassDeclaration> Parser::parse_struct_or_class_declaratio
 
     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));
     }
 
@@ -1073,7 +1077,7 @@ Vector<StringView> Parser::parse_type_qualifiers()
 {
     SCOPE_LOGGER();
     Vector<StringView> qualifiers;
-    while (!done()) {
+    while (!eof()) {
         auto token = peek();
         if (token.type() != Token::Type::Keyword)
             break;
@@ -1096,7 +1100,7 @@ void Parser::consume_attribute_specification()
     consume(); // __attribute__
     consume(Token::Type::LeftParen);
     size_t left_count = 1;
-    while (!done()) {
+    while (!eof()) {
         auto token = consume();
         if (token.type() == Token::Type::LeftParen) {
             ++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;
+}
+
 }

+ 6 - 10
Userland/Libraries/LibCpp/Parser.h

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