فهرست منبع

LibCpp: Parse C++ cast expressions

parse static_cast, reinterpret_cast, dynamic_cast & const_cast
Itamar 4 سال پیش
والد
کامیت
8962581c9c
4فایلهای تغییر یافته به همراه74 افزوده شده و 1 حذف شده
  1. 17 0
      Userland/Libraries/LibCpp/AST.cpp
  2. 16 0
      Userland/Libraries/LibCpp/AST.h
  3. 39 1
      Userland/Libraries/LibCpp/Parser.cpp
  4. 2 0
      Userland/Libraries/LibCpp/Parser.h

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

@@ -501,7 +501,24 @@ void TemplatizedFunctionCall::dump(size_t indent) const
     for (const auto& arg : m_arguments) {
         arg.dump(indent + 1);
     }
+}
+
+void CppCastExpression::dump(size_t indent) const
+{
+    ASTNode::dump(indent);
+
+    print_indent(indent);
+    outln("{}", m_cast_type);
+
+    print_indent(indent + 1);
+    outln("<");
+    if (m_type)
+        m_type->dump(indent + 1);
+    print_indent(indent + 1);
+    outln(">");
 
+    if (m_expression)
+        m_expression->dump(indent + 1);
 }
 
 }

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

@@ -696,4 +696,20 @@ public:
     NonnullRefPtrVector<Declaration> m_declarations;
 };
 
+class CppCastExpression : public Expression {
+public:
+    CppCastExpression(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename)
+        : Expression(parent, start, end, filename)
+    {
+    }
+
+    virtual ~CppCastExpression() override = default;
+    virtual const char* class_name() const override { return "CppCastExpression"; }
+    virtual void dump(size_t indent) const override;
+
+    StringView m_cast_type;
+    RefPtr<Type> m_type;
+    RefPtr<Expression> m_expression;
+};
+
 }

+ 39 - 1
Userland/Libraries/LibCpp/Parser.cpp

@@ -440,6 +440,9 @@ NonnullRefPtr<Expression> Parser::parse_primary_expression(ASTNode& parent)
         return parse_literal(parent);
     }
 
+    if (match_cpp_cast_expression())
+        return parse_cpp_cast_expression(parent);
+
     if (match_name()) {
         if (match_function_call() != TemplatizedMatchResult::NoMatch)
             return parse_function_call(parent);
@@ -827,7 +830,8 @@ bool Parser::match_expression()
     auto token_type = peek().type();
     return match_literal()
         || token_type == Token::Type::Identifier
-        || match_unary_expression();
+        || match_unary_expression()
+        || match_cpp_cast_expression();
 }
 
 bool Parser::eof() const
@@ -1341,4 +1345,38 @@ NonnullRefPtr<Name> Parser::parse_name(ASTNode& parent)
     return name_node;
 }
 
+bool Parser::match_cpp_cast_expression()
+{
+    save_state();
+    ScopeGuard state_guard = [this] { load_state(); };
+
+    auto token = consume();
+    if (token.type() != Token::Type::Keyword)
+        return false;
+
+    auto text = token.text();
+    if (text == "static_cast" || text == "reinterpret_cast" || text == "dynamic_cast" || text == "const_cast")
+        return true;
+    return false;
+}
+
+NonnullRefPtr<CppCastExpression> Parser::parse_cpp_cast_expression(ASTNode& parent)
+{
+    auto cast_expression = create_ast_node<CppCastExpression>(parent, position(), {});
+
+    cast_expression->m_cast_type = consume(Token::Type::Keyword).text();
+
+    consume(Token::Type::Less);
+    cast_expression->m_type = parse_type(*cast_expression);
+    consume(Token::Type::Greater);
+
+    consume(Token::Type::LeftParen);
+    cast_expression->m_expression = parse_expression(*cast_expression);
+    consume(Token::Type::RightParen);
+
+    cast_expression->set_end(position());
+
+    return cast_expression;
+}
+
 }

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

@@ -89,6 +89,7 @@ private:
     bool match_namespace_declaration();
     bool match_template_arguments();
     bool match_name();
+    bool match_cpp_cast_expression();
 
     enum class TemplatizedMatchResult {
         NoMatch,
@@ -131,6 +132,7 @@ private:
     RefPtr<Declaration> parse_single_declaration_in_translation_unit(ASTNode& parent);
     NonnullRefPtrVector<Type> parse_template_arguments(ASTNode& parent);
     NonnullRefPtr<Name> parse_name(ASTNode& parent);
+    NonnullRefPtr<CppCastExpression> parse_cpp_cast_expression(ASTNode& parent);
 
     bool match(Token::Type);
     Token consume(Token::Type);