|
@@ -100,9 +100,7 @@ NonnullRefPtr<Declaration> Parser::parse_declaration(ASTNode& parent, Declaratio
|
|
case DeclarationType::Enum:
|
|
case DeclarationType::Enum:
|
|
return parse_enum_declaration(parent);
|
|
return parse_enum_declaration(parent);
|
|
case DeclarationType::Class:
|
|
case DeclarationType::Class:
|
|
- return parse_struct_or_class_declaration(parent, StructOrClassDeclaration::Type::Class);
|
|
|
|
- case DeclarationType::Struct:
|
|
|
|
- return parse_struct_or_class_declaration(parent, StructOrClassDeclaration::Type::Struct);
|
|
|
|
|
|
+ return parse_class_declaration(parent);
|
|
case DeclarationType::Namespace:
|
|
case DeclarationType::Namespace:
|
|
return parse_namespace_declaration(parent);
|
|
return parse_namespace_declaration(parent);
|
|
default:
|
|
default:
|
|
@@ -306,6 +304,9 @@ bool Parser::match_variable_declaration()
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (match_braced_init_list())
|
|
|
|
+ parse_braced_init_list(get_dummy_node());
|
|
|
|
+
|
|
return match(Token::Type::Semicolon);
|
|
return match(Token::Type::Semicolon);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -327,6 +328,10 @@ NonnullRefPtr<VariableDeclaration> Parser::parse_variable_declaration(ASTNode& p
|
|
initial_value = parse_expression(var);
|
|
initial_value = parse_expression(var);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (match_braced_init_list()) {
|
|
|
|
+ initial_value = parse_braced_init_list(var);
|
|
|
|
+ }
|
|
|
|
+
|
|
if (expect_semicolon)
|
|
if (expect_semicolon)
|
|
consume(Token::Type::Semicolon);
|
|
consume(Token::Type::Semicolon);
|
|
|
|
|
|
@@ -619,8 +624,6 @@ Optional<Parser::DeclarationType> Parser::match_declaration_in_translation_unit(
|
|
return DeclarationType::Enum;
|
|
return DeclarationType::Enum;
|
|
if (match_class_declaration())
|
|
if (match_class_declaration())
|
|
return DeclarationType::Class;
|
|
return DeclarationType::Class;
|
|
- if (match_struct_declaration())
|
|
|
|
- return DeclarationType::Struct;
|
|
|
|
if (match_namespace_declaration())
|
|
if (match_namespace_declaration())
|
|
return DeclarationType::Namespace;
|
|
return DeclarationType::Namespace;
|
|
if (match_variable_declaration())
|
|
if (match_variable_declaration())
|
|
@@ -628,6 +631,19 @@ Optional<Parser::DeclarationType> Parser::match_declaration_in_translation_unit(
|
|
return {};
|
|
return {};
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+Optional<Parser::DeclarationType> Parser::match_class_member()
|
|
|
|
+{
|
|
|
|
+ if (match_function_declaration())
|
|
|
|
+ return DeclarationType::Function;
|
|
|
|
+ if (match_enum_declaration())
|
|
|
|
+ return DeclarationType::Enum;
|
|
|
|
+ if (match_class_declaration())
|
|
|
|
+ return DeclarationType::Class;
|
|
|
|
+ if (match_variable_declaration())
|
|
|
|
+ return DeclarationType::Variable;
|
|
|
|
+ return {};
|
|
|
|
+}
|
|
|
|
+
|
|
bool Parser::match_enum_declaration()
|
|
bool Parser::match_enum_declaration()
|
|
{
|
|
{
|
|
return match_keyword("enum");
|
|
return match_keyword("enum");
|
|
@@ -635,12 +651,19 @@ bool Parser::match_enum_declaration()
|
|
|
|
|
|
bool Parser::match_class_declaration()
|
|
bool Parser::match_class_declaration()
|
|
{
|
|
{
|
|
- return match_keyword("class");
|
|
|
|
-}
|
|
|
|
|
|
+ save_state();
|
|
|
|
+ ScopeGuard state_guard = [this] { load_state(); };
|
|
|
|
|
|
-bool Parser::match_struct_declaration()
|
|
|
|
-{
|
|
|
|
- return match_keyword("struct");
|
|
|
|
|
|
+ if (!match_keyword("struct") && !match_keyword("class"))
|
|
|
|
+ return false;
|
|
|
|
+ consume(Token::Type::Keyword);
|
|
|
|
+
|
|
|
|
+ if (!match(Token::Type::Identifier))
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ consume(Token::Type::Identifier);
|
|
|
|
+
|
|
|
|
+ return match(Token::Type::LeftCurly);
|
|
}
|
|
}
|
|
|
|
|
|
bool Parser::match_namespace_declaration()
|
|
bool Parser::match_namespace_declaration()
|
|
@@ -1023,25 +1046,27 @@ bool Parser::match_keyword(const String& keyword)
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
-NonnullRefPtr<StructOrClassDeclaration> Parser::parse_struct_or_class_declaration(ASTNode& parent, StructOrClassDeclaration::Type type)
|
|
|
|
|
|
+NonnullRefPtr<StructOrClassDeclaration> Parser::parse_class_declaration(ASTNode& parent)
|
|
{
|
|
{
|
|
ScopeLogger<CPP_DEBUG> logger;
|
|
ScopeLogger<CPP_DEBUG> logger;
|
|
|
|
+
|
|
|
|
+ auto type_token = consume(Token::Type::Keyword);
|
|
|
|
+ StructOrClassDeclaration::Type type {};
|
|
|
|
+
|
|
|
|
+ if (type_token.text() == "struct")
|
|
|
|
+ type = StructOrClassDeclaration::Type::Struct;
|
|
|
|
+ if (type_token.text() == "class")
|
|
|
|
+ type = StructOrClassDeclaration::Type::Class;
|
|
|
|
+
|
|
auto decl = create_ast_node<StructOrClassDeclaration>(parent, position(), {}, type);
|
|
auto decl = create_ast_node<StructOrClassDeclaration>(parent, position(), {}, type);
|
|
- switch (type) {
|
|
|
|
- case StructOrClassDeclaration::Type::Struct:
|
|
|
|
- consume_keyword("struct");
|
|
|
|
- break;
|
|
|
|
- case StructOrClassDeclaration::Type::Class:
|
|
|
|
- consume_keyword("class");
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
auto name_token = consume(Token::Type::Identifier);
|
|
auto name_token = consume(Token::Type::Identifier);
|
|
decl->m_name = text_of_token(name_token);
|
|
decl->m_name = text_of_token(name_token);
|
|
|
|
|
|
consume(Token::Type::LeftCurly);
|
|
consume(Token::Type::LeftCurly);
|
|
|
|
|
|
while (!eof() && peek().type() != Token::Type::RightCurly) {
|
|
while (!eof() && peek().type() != Token::Type::RightCurly) {
|
|
- decl->m_members.append(parse_member_declaration(*decl));
|
|
|
|
|
|
+ decl->m_members = parse_class_members(*decl);
|
|
}
|
|
}
|
|
|
|
|
|
consume(Token::Type::RightCurly);
|
|
consume(Token::Type::RightCurly);
|
|
@@ -1050,25 +1075,6 @@ NonnullRefPtr<StructOrClassDeclaration> Parser::parse_struct_or_class_declaratio
|
|
return decl;
|
|
return decl;
|
|
}
|
|
}
|
|
|
|
|
|
-NonnullRefPtr<MemberDeclaration> Parser::parse_member_declaration(ASTNode& parent)
|
|
|
|
-{
|
|
|
|
- ScopeLogger<CPP_DEBUG> logger;
|
|
|
|
- auto member_decl = create_ast_node<MemberDeclaration>(parent, position(), {});
|
|
|
|
- member_decl->m_type = parse_type(*member_decl);
|
|
|
|
-
|
|
|
|
- auto identifier_token = consume(Token::Type::Identifier);
|
|
|
|
- member_decl->m_name = text_of_token(identifier_token);
|
|
|
|
-
|
|
|
|
- if (match_braced_init_list()) {
|
|
|
|
- member_decl->m_initial_value = parse_braced_init_list(*member_decl);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- consume(Token::Type::Semicolon);
|
|
|
|
- member_decl->set_end(position());
|
|
|
|
-
|
|
|
|
- return member_decl;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
NonnullRefPtr<BooleanLiteral> Parser::parse_boolean_literal(ASTNode& parent)
|
|
NonnullRefPtr<BooleanLiteral> Parser::parse_boolean_literal(ASTNode& parent)
|
|
{
|
|
{
|
|
ScopeLogger<CPP_DEBUG> logger;
|
|
ScopeLogger<CPP_DEBUG> logger;
|
|
@@ -1429,5 +1435,19 @@ NonnullRefPtr<BracedInitList> Parser::parse_braced_init_list(ASTNode& parent)
|
|
init_list->set_end(position());
|
|
init_list->set_end(position());
|
|
return init_list;
|
|
return init_list;
|
|
}
|
|
}
|
|
|
|
+NonnullRefPtrVector<Declaration> Parser::parse_class_members(ASTNode& parent)
|
|
|
|
+{
|
|
|
|
+ NonnullRefPtrVector<Declaration> members;
|
|
|
|
+ while (!eof() && peek().type() != Token::Type::RightCurly) {
|
|
|
|
+ auto member_type = match_class_member();
|
|
|
|
+ if (member_type.has_value()) {
|
|
|
|
+ members.append(parse_declaration(parent, member_type.value()));
|
|
|
|
+ } else {
|
|
|
|
+ error("Expected class member");
|
|
|
|
+ consume();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return members;
|
|
|
|
+}
|
|
|
|
|
|
}
|
|
}
|