From 3cd04f40e125dda1492b9520422f45c24baef3a8 Mon Sep 17 00:00:00 2001 From: Poseydon42 Date: Thu, 26 Jan 2023 23:17:57 +0000 Subject: [PATCH] LibCpp: Parse 'using namespace' declarations This gets us a little bit closer to a fully capable C++ parser. --- Userland/Libraries/LibCpp/AST.cpp | 7 ++++ Userland/Libraries/LibCpp/AST.h | 12 ++++++ Userland/Libraries/LibCpp/Parser.cpp | 37 +++++++++++++++++++ Userland/Libraries/LibCpp/Parser.h | 3 ++ .../LibCpp/Tests/parser/using-namespace.ast | 3 ++ .../LibCpp/Tests/parser/using-namespace.cpp | 2 + 6 files changed, 64 insertions(+) create mode 100644 Userland/Libraries/LibCpp/Tests/parser/using-namespace.ast create mode 100644 Userland/Libraries/LibCpp/Tests/parser/using-namespace.cpp diff --git a/Userland/Libraries/LibCpp/AST.cpp b/Userland/Libraries/LibCpp/AST.cpp index 21419bd889..36b2bd25f1 100644 --- a/Userland/Libraries/LibCpp/AST.cpp +++ b/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()); +} + } diff --git a/Userland/Libraries/LibCpp/AST.h b/Userland/Libraries/LibCpp/AST.h index 1b997c0531..b0ec6c8de9 100644 --- a/Userland/Libraries/LibCpp/AST.h +++ b/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 start, Optional end, DeprecatedString const& filename) + : Declaration(parent, start, end, filename) + { + } +}; + template<> inline bool ASTNode::fast_is() const { return is_identifier(); } template<> diff --git a/Userland/Libraries/LibCpp/Parser.cpp b/Userland/Libraries/LibCpp/Parser.cpp index 9976c73ac7..89ed2a79e2 100644 --- a/Userland/Libraries/LibCpp/Parser.cpp +++ b/Userland/Libraries/LibCpp/Parser.cpp @@ -91,6 +91,8 @@ NonnullRefPtr 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(parent, position(), position()); @@ -624,6 +626,8 @@ Optional 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 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 Parser::parse_using_namespace_declaration(ASTNode& parent) +{ + auto decl = create_ast_node(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; +} + } diff --git a/Userland/Libraries/LibCpp/Parser.h b/Userland/Libraries/LibCpp/Parser.h index aee83299f5..a15dc2da19 100644 --- a/Userland/Libraries/LibCpp/Parser.h +++ b/Userland/Libraries/LibCpp/Parser.h @@ -49,6 +49,7 @@ private: Namespace, Constructor, Destructor, + UsingNamespace, }; Optional 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> parse_parameter_list(ASTNode& parent); Optional consume_whitespace(); @@ -121,6 +123,7 @@ private: NonnullRefPtrVector parse_class_members(StructOrClassDeclaration& parent); NonnullRefPtr parse_constructor(ASTNode& parent); NonnullRefPtr parse_destructor(ASTNode& parent); + NonnullRefPtr parse_using_namespace_declaration(ASTNode& parent); bool match(Token::Type); Token consume(Token::Type); diff --git a/Userland/Libraries/LibCpp/Tests/parser/using-namespace.ast b/Userland/Libraries/LibCpp/Tests/parser/using-namespace.ast new file mode 100644 index 0000000000..8d4efa999e --- /dev/null +++ b/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 diff --git a/Userland/Libraries/LibCpp/Tests/parser/using-namespace.cpp b/Userland/Libraries/LibCpp/Tests/parser/using-namespace.cpp new file mode 100644 index 0000000000..bf15c1c911 --- /dev/null +++ b/Userland/Libraries/LibCpp/Tests/parser/using-namespace.cpp @@ -0,0 +1,2 @@ +using namespace a::b::c; +