From 543ccecc0b783f65f598bae5cca838b84953a8d4 Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Sat, 17 Jun 2023 22:41:30 +0330 Subject: [PATCH] LibCpp: Add support for type aliases with typedef/using --- Userland/Libraries/LibCpp/AST.cpp | 9 +++ Userland/Libraries/LibCpp/AST.h | 17 ++++++ Userland/Libraries/LibCpp/Parser.cpp | 83 ++++++++++++++++++++++++++++ Userland/Libraries/LibCpp/Parser.h | 6 ++ 4 files changed, 115 insertions(+) diff --git a/Userland/Libraries/LibCpp/AST.cpp b/Userland/Libraries/LibCpp/AST.cpp index 92c666b9a0..8370b94796 100644 --- a/Userland/Libraries/LibCpp/AST.cpp +++ b/Userland/Libraries/LibCpp/AST.cpp @@ -683,4 +683,13 @@ void UsingNamespaceDeclaration::dump(FILE* output, size_t indent) const outln(output, "{}", full_name()); } +void TypedefDeclaration::dump(FILE* output, size_t indent) const +{ + ASTNode::dump(output, indent); + print_indent(output, indent + 1); + outln(output, "{}", full_name()); + if (m_alias) + m_alias->dump(output, indent + 1); +} + } diff --git a/Userland/Libraries/LibCpp/AST.h b/Userland/Libraries/LibCpp/AST.h index 072ffc8382..d0f3c5725c 100644 --- a/Userland/Libraries/LibCpp/AST.h +++ b/Userland/Libraries/LibCpp/AST.h @@ -1007,6 +1007,23 @@ public: } }; +class TypedefDeclaration : public Declaration { +public: + virtual ~TypedefDeclaration() override = default; + virtual StringView class_name() const override { return "TypedefDeclaration"sv; } + virtual void dump(FILE* = stdout, size_t indent = 0) const override; + + TypedefDeclaration(ASTNode const* parent, Optional start, Optional end, DeprecatedString const& filename) + : Declaration(parent, start, end, filename) + { + } + + void set_alias(Type const& alias) { m_alias = alias; } + Type const* alias() const { return m_alias.ptr(); } + +private: + RefPtr m_alias; +}; 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 69250b4b26..d39c30a0b2 100644 --- a/Userland/Libraries/LibCpp/Parser.cpp +++ b/Userland/Libraries/LibCpp/Parser.cpp @@ -93,6 +93,10 @@ NonnullRefPtr Parser::parse_declaration(ASTNode const& parent return parse_destructor(parent); case DeclarationType::UsingNamespace: return parse_using_namespace_declaration(parent); + case DeclarationType::UsingType: + return parse_using_type_declaration(parent); + case DeclarationType::Typedef: + return parse_typedef_declaration(parent); default: error("unexpected declaration type"sv); return create_ast_node(parent, position(), position()); @@ -641,6 +645,10 @@ Optional Parser::match_declaration_in_translation_unit( return DeclarationType::Variable; if (match_using_namespace_declaration()) return DeclarationType::UsingNamespace; + if (match_using_type_declaration()) + return DeclarationType::UsingType; + if (match_typedef_declaration()) + return DeclarationType::Typedef; return {}; } @@ -1761,6 +1769,41 @@ bool Parser::match_using_namespace_declaration() return true; } +bool Parser::match_using_type_declaration() +{ + save_state(); + ScopeGuard state_guard = [this] { load_state(); }; + + if (!match_keyword("using")) + return false; + consume(); + + if (!match(Token::Type::Identifier)) + return false; + + return true; +} + +bool Parser::match_typedef_declaration() +{ + save_state(); + ScopeGuard state_guard = [this] { load_state(); }; + + if (!match_keyword("typedef")) + return false; + consume(); + + // FIXME: typedef void (*fn)() + + if (!match_type()) + return false; + + if (!match(Token::Type::Identifier)) + return false; + + return true; +} + NonnullRefPtr Parser::parse_using_namespace_declaration(ASTNode const& parent) { auto decl = create_ast_node(parent, position(), {}); @@ -1778,4 +1821,44 @@ NonnullRefPtr Parser::parse_using_namespace_dec return decl; } +NonnullRefPtr Parser::parse_typedef_declaration(Cpp::ASTNode const& parent) +{ + auto decl = create_ast_node(parent, position(), {}); + + consume_keyword("typedef"); + + auto type = parse_type(*decl); + decl->set_alias(type); + + auto name = parse_name(*decl); + decl->set_name(name); + + decl->set_end(position()); + consume(Token::Type::Semicolon); + + return decl; +} + +NonnullRefPtr Parser::parse_using_type_declaration(Cpp::ASTNode const& parent) +{ + auto decl = create_ast_node(parent, position(), {}); + + // FIXME: These can also be templated. + consume_keyword("using"); + + auto name = parse_name(*decl); + decl->set_name(name); + + if (match(Token::Type::Equals)) { + consume(); + auto type = parse_type(*decl); + decl->set_alias(type); + } + + decl->set_end(position()); + consume(Token::Type::Semicolon); + + return decl; +} + } diff --git a/Userland/Libraries/LibCpp/Parser.h b/Userland/Libraries/LibCpp/Parser.h index 6ced38a294..e43f238d88 100644 --- a/Userland/Libraries/LibCpp/Parser.h +++ b/Userland/Libraries/LibCpp/Parser.h @@ -50,6 +50,8 @@ private: Constructor, Destructor, UsingNamespace, + Typedef, + UsingType, }; Optional match_declaration_in_translation_unit(); @@ -82,6 +84,8 @@ private: bool match_constructor(StringView class_name); bool match_destructor(StringView class_name); bool match_using_namespace_declaration(); + bool match_typedef_declaration(); + bool match_using_type_declaration(); Optional>> parse_parameter_list(ASTNode const& parent); Optional consume_whitespace(); @@ -122,6 +126,8 @@ private: NonnullRefPtr parse_constructor(ASTNode const& parent); NonnullRefPtr parse_destructor(ASTNode const& parent); NonnullRefPtr parse_using_namespace_declaration(ASTNode const& parent); + NonnullRefPtr parse_typedef_declaration(ASTNode const& parent); + NonnullRefPtr parse_using_type_declaration(ASTNode const& parent); bool match(Token::Type); Token consume(Token::Type);