1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 11:38:11 +00:00

LibCpp: Support non-field class members

Previously, we had a special ASTNode for class members,
"MemberDeclaration", which only represented fields.

This commit removes MemberDeclaration and instead uses regular
Declaration nodes for representing the members of a class.

This means that we can now also parse methods, inner-classes, and other
declarations that appear inside of a class.
This commit is contained in:
Itamar 2021-06-05 17:57:13 +03:00 committed by Andreas Kling
parent 8f074222e8
commit dcdb0c7035
6 changed files with 71 additions and 77 deletions

View file

@ -100,9 +100,7 @@ NonnullRefPtr<Declaration> Parser::parse_declaration(ASTNode& parent, Declaratio
case DeclarationType::Enum:
return parse_enum_declaration(parent);
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:
return parse_namespace_declaration(parent);
default:
@ -306,6 +304,9 @@ bool Parser::match_variable_declaration()
return true;
}
if (match_braced_init_list())
parse_braced_init_list(get_dummy_node());
return match(Token::Type::Semicolon);
}
@ -327,6 +328,10 @@ NonnullRefPtr<VariableDeclaration> Parser::parse_variable_declaration(ASTNode& p
initial_value = parse_expression(var);
}
if (match_braced_init_list()) {
initial_value = parse_braced_init_list(var);
}
if (expect_semicolon)
consume(Token::Type::Semicolon);
@ -619,8 +624,6 @@ Optional<Parser::DeclarationType> Parser::match_declaration_in_translation_unit(
return DeclarationType::Enum;
if (match_class_declaration())
return DeclarationType::Class;
if (match_struct_declaration())
return DeclarationType::Struct;
if (match_namespace_declaration())
return DeclarationType::Namespace;
if (match_variable_declaration())
@ -628,6 +631,19 @@ Optional<Parser::DeclarationType> Parser::match_declaration_in_translation_unit(
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()
{
return match_keyword("enum");
@ -635,12 +651,19 @@ bool Parser::match_enum_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()
@ -1023,25 +1046,27 @@ bool Parser::match_keyword(const String& keyword)
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;
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);
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);
decl->m_name = text_of_token(name_token);
consume(Token::Type::LeftCurly);
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);
@ -1050,25 +1075,6 @@ NonnullRefPtr<StructOrClassDeclaration> Parser::parse_struct_or_class_declaratio
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)
{
ScopeLogger<CPP_DEBUG> logger;
@ -1429,5 +1435,19 @@ NonnullRefPtr<BracedInitList> Parser::parse_braced_init_list(ASTNode& parent)
init_list->set_end(position());
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;
}
}