Browse Source

LibCpp: Parse 'using namespace' declarations

This gets us a little bit closer to a fully capable C++ parser.
Poseydon42 2 years ago
parent
commit
3cd04f40e1

+ 7 - 0
Userland/Libraries/LibCpp/AST.cpp

@@ -658,4 +658,11 @@ StringView Declaration::full_name() const
     return *m_full_name;
 }
 
+void UsingNamespaceDeclaration::dump(FILE* output, size_t indent) const
+{
+    ASTNode::dump(output, indent);
+    print_indent(output, indent + 1);
+    outln(output, "{}", full_name());
+}
+
 }

+ 12 - 0
Userland/Libraries/LibCpp/AST.h

@@ -976,6 +976,18 @@ public:
     }
 };
 
+class UsingNamespaceDeclaration : public Declaration {
+public:
+    virtual ~UsingNamespaceDeclaration() override = default;
+    virtual StringView class_name() const override { return "UsingNamespaceDeclaration"sv; }
+    virtual void dump(FILE* = stdout, size_t indent = 0) const override;
+
+    UsingNamespaceDeclaration(ASTNode* parent, Optional<Position> start, Optional<Position> end, DeprecatedString const& filename)
+        : Declaration(parent, start, end, filename)
+    {
+    }
+};
+
 template<>
 inline bool ASTNode::fast_is<Identifier>() const { return is_identifier(); }
 template<>

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

@@ -91,6 +91,8 @@ NonnullRefPtr<Declaration> Parser::parse_declaration(ASTNode& parent, Declaratio
         return parse_constructor(parent);
     case DeclarationType::Destructor:
         return parse_destructor(parent);
+    case DeclarationType::UsingNamespace:
+        return parse_using_namespace_declaration(parent);
     default:
         error("unexpected declaration type"sv);
         return create_ast_node<InvalidDeclaration>(parent, position(), position());
@@ -624,6 +626,8 @@ Optional<Parser::DeclarationType> Parser::match_declaration_in_translation_unit(
         return DeclarationType::Namespace;
     if (match_variable_declaration())
         return DeclarationType::Variable;
+    if (match_using_namespace_declaration())
+        return DeclarationType::UsingNamespace;
     return {};
 }
 
@@ -1703,4 +1707,37 @@ NonnullRefPtr<Destructor> Parser::parse_destructor(ASTNode& parent)
     return ctor;
 }
 
+bool Parser::match_using_namespace_declaration()
+{
+    save_state();
+    ScopeGuard state_guard = [this] { load_state(); };
+
+    if (!match_keyword("using"))
+        return false;
+    consume();
+
+    if (!match_keyword("namespace"))
+        return false;
+    consume();
+
+    return true;
+}
+
+NonnullRefPtr<UsingNamespaceDeclaration> Parser::parse_using_namespace_declaration(ASTNode& parent)
+{
+    auto decl = create_ast_node<UsingNamespaceDeclaration>(parent, position(), {});
+
+    consume_keyword("using");
+    consume_keyword("namespace");
+
+    auto name = parse_name(*decl);
+
+    decl->set_end(position());
+    consume(Token::Type::Semicolon);
+
+    decl->set_name(name);
+
+    return decl;
+}
+
 }

+ 3 - 0
Userland/Libraries/LibCpp/Parser.h

@@ -49,6 +49,7 @@ private:
         Namespace,
         Constructor,
         Destructor,
+        UsingNamespace,
     };
 
     Optional<DeclarationType> match_declaration_in_translation_unit();
@@ -80,6 +81,7 @@ private:
     bool match_access_specifier();
     bool match_constructor(StringView class_name);
     bool match_destructor(StringView class_name);
+    bool match_using_namespace_declaration();
 
     Optional<NonnullRefPtrVector<Parameter>> parse_parameter_list(ASTNode& parent);
     Optional<Token> consume_whitespace();
@@ -121,6 +123,7 @@ private:
     NonnullRefPtrVector<Declaration> parse_class_members(StructOrClassDeclaration& parent);
     NonnullRefPtr<Constructor> parse_constructor(ASTNode& parent);
     NonnullRefPtr<Destructor> parse_destructor(ASTNode& parent);
+    NonnullRefPtr<UsingNamespaceDeclaration> parse_using_namespace_declaration(ASTNode& parent);
 
     bool match(Token::Type);
     Token consume(Token::Type);

+ 3 - 0
Userland/Libraries/LibCpp/Tests/parser/using-namespace.ast

@@ -0,0 +1,3 @@
+TranslationUnit[0:0->0:23]
+  UsingNamespaceDeclaration[0:0->0:23]
+    a::b::c

+ 2 - 0
Userland/Libraries/LibCpp/Tests/parser/using-namespace.cpp

@@ -0,0 +1,2 @@
+using namespace a::b::c;
+