Prechádzať zdrojové kódy

LibCpp: Add support for type aliases with typedef/using

Ali Mohammad Pur 2 rokov pred
rodič
commit
543ccecc0b

+ 9 - 0
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);
+}
+
 }

+ 17 - 0
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<Position> start, Optional<Position> 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<Type const> m_alias;
+};
 template<>
 inline bool ASTNode::fast_is<Identifier>() const { return is_identifier(); }
 template<>

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

@@ -93,6 +93,10 @@ NonnullRefPtr<Declaration const> 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<InvalidDeclaration>(parent, position(), position());
@@ -641,6 +645,10 @@ Optional<Parser::DeclarationType> 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<UsingNamespaceDeclaration const> Parser::parse_using_namespace_declaration(ASTNode const& parent)
 {
     auto decl = create_ast_node<UsingNamespaceDeclaration>(parent, position(), {});
@@ -1778,4 +1821,44 @@ NonnullRefPtr<UsingNamespaceDeclaration const> Parser::parse_using_namespace_dec
     return decl;
 }
 
+NonnullRefPtr<TypedefDeclaration const> Parser::parse_typedef_declaration(Cpp::ASTNode const& parent)
+{
+    auto decl = create_ast_node<TypedefDeclaration>(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<TypedefDeclaration const> Parser::parse_using_type_declaration(Cpp::ASTNode const& parent)
+{
+    auto decl = create_ast_node<TypedefDeclaration>(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;
+}
+
 }

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

@@ -50,6 +50,8 @@ private:
         Constructor,
         Destructor,
         UsingNamespace,
+        Typedef,
+        UsingType,
     };
 
     Optional<DeclarationType> 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<Vector<NonnullRefPtr<Parameter const>>> parse_parameter_list(ASTNode const& parent);
     Optional<Token> consume_whitespace();
@@ -122,6 +126,8 @@ private:
     NonnullRefPtr<Constructor const> parse_constructor(ASTNode const& parent);
     NonnullRefPtr<Destructor const> parse_destructor(ASTNode const& parent);
     NonnullRefPtr<UsingNamespaceDeclaration const> parse_using_namespace_declaration(ASTNode const& parent);
+    NonnullRefPtr<TypedefDeclaration const> parse_typedef_declaration(ASTNode const& parent);
+    NonnullRefPtr<TypedefDeclaration const> parse_using_type_declaration(ASTNode const& parent);
 
     bool match(Token::Type);
     Token consume(Token::Type);