Browse Source

LibCpp: Support parsing function qualifiers

Itamar 4 years ago
parent
commit
1f9f6ea9d6

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

@@ -51,6 +51,13 @@ void TranslationUnit::dump(size_t indent) const
 void FunctionDeclaration::dump(size_t indent) const
 {
     ASTNode::dump(indent);
+
+    String qualifiers_string;
+    if (!m_qualifiers.is_empty()) {
+        print_indent(indent+1);
+        outln("[{}]", String::join(" ", m_qualifiers));
+    }
+
     m_return_type->dump(indent + 1);
     if (!m_name.is_null()) {
         print_indent(indent + 1);

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

@@ -171,6 +171,7 @@ public:
 
     virtual NonnullRefPtrVector<Declaration> declarations() const override;
 
+    Vector<StringView> m_qualifiers;
     RefPtr<Type> m_return_type;
     NonnullRefPtrVector<Parameter> m_parameters;
     RefPtr<FunctionDefinition> m_definition;

+ 48 - 10
Userland/Libraries/LibCpp/Parser.cpp

@@ -142,10 +142,17 @@ NonnullRefPtr<FunctionDeclaration> Parser::parse_function_declaration(ASTNode& p
 {
     auto func = create_ast_node<FunctionDeclaration>(parent, position(), {});
 
-    auto return_type_token = consume(Token::Type::KnownType);
+    func->m_qualifiers = parse_function_qualifiers();
+    func->m_return_type = parse_type(*func);
+
     auto function_name = consume(Token::Type::Identifier);
+    func->m_name = text_of_token(function_name);
+
     consume(Token::Type::LeftParen);
     auto parameters = parse_parameter_list(*func);
+    if (parameters.has_value())
+        func->m_parameters = move(parameters.value());
+
     consume(Token::Type::RightParen);
 
     RefPtr<FunctionDefinition> body;
@@ -160,10 +167,6 @@ NonnullRefPtr<FunctionDeclaration> Parser::parse_function_declaration(ASTNode& p
         consume(Token::Type::Semicolon);
     }
 
-    func->m_name = text_of_token(function_name);
-    func->m_return_type = create_ast_node<Type>(*func, return_type_token.start(), return_type_token.end(), text_of_token(return_type_token));
-    if (parameters.has_value())
-        func->m_parameters = move(parameters.value());
     func->m_definition = move(body);
     func->set_end(func_end);
     return func;
@@ -248,9 +251,8 @@ NonnullRefPtr<BlockStatement> Parser::parse_block_statement(ASTNode& parent)
     return block_statement;
 }
 
-bool Parser::match_variable_declaration()
+bool Parser::match_type()
 {
-    SCOPE_LOGGER();
     save_state();
     ScopeGuard state_guard = [this] { load_state(); };
 
@@ -258,7 +260,19 @@ bool Parser::match_variable_declaration()
     // Type
     if (!peek(Token::Type::KnownType).has_value() && !peek(Token::Type::Identifier).has_value())
         return false;
-    consume();
+    return true;
+}
+
+bool Parser::match_variable_declaration()
+{
+    SCOPE_LOGGER();
+    save_state();
+    ScopeGuard state_guard = [this] { load_state(); };
+
+    if (!match_type())
+        return false;
+    VERIFY(m_root_node);
+    parse_type(*m_root_node);
 
     // Identifier
     if (!peek(Token::Type::Identifier).has_value())
@@ -561,9 +575,12 @@ bool Parser::match_function_declaration()
     save_state();
     ScopeGuard state_guard = [this] { load_state(); };
 
-    if (!peek(Token::Type::KnownType).has_value())
+    parse_function_qualifiers();
+
+    if (!match_type())
         return false;
-    consume();
+    VERIFY(m_root_node);
+    parse_type(*m_root_node);
 
     if (!peek(Token::Type::Identifier).has_value())
         return false;
@@ -1098,6 +1115,27 @@ Vector<StringView> Parser::parse_type_qualifiers()
     }
     return qualifiers;
 }
+
+Vector<StringView> Parser::parse_function_qualifiers()
+{
+    SCOPE_LOGGER();
+    Vector<StringView> qualifiers;
+    while (!eof()) {
+        auto token = peek();
+        if (token.type() != Token::Type::Keyword)
+            break;
+        auto text = text_of_token(token);
+        if (text == "static" || text == "inline") {
+            qualifiers.append(text);
+            consume();
+        } else {
+            break;
+        }
+    }
+    return qualifiers;
+}
+
+
 bool Parser::match_attribute_specification()
 {
     return text_of_token(peek()) == "__attribute__";

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

@@ -88,6 +88,7 @@ private:
     bool match_keyword(const String&);
     bool match_block_statement();
     bool match_namespace_declaration();
+    bool match_type();
 
     Optional<NonnullRefPtrVector<Parameter>> parse_parameter_list(ASTNode& parent);
     Optional<Token> consume_whitespace();
@@ -163,6 +164,7 @@ private:
     void initialize_program_tokens(const StringView& program);
     void add_tokens_for_preprocessor(Token& replaced_token, Preprocessor::DefinedValue&);
     Vector<StringView> parse_type_qualifiers();
+    Vector<StringView> parse_function_qualifiers();
 
     Preprocessor::Definitions m_definitions;
     String m_filename;