mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 09:57:35 +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:
parent
8f074222e8
commit
dcdb0c7035
6 changed files with 71 additions and 77 deletions
|
@ -293,7 +293,9 @@ Vector<CppComprehensionEngine::PropertyInfo> CppComprehensionEngine::properties_
|
||||||
|
|
||||||
Vector<PropertyInfo> properties;
|
Vector<PropertyInfo> properties;
|
||||||
for (auto& member : struct_or_class.m_members) {
|
for (auto& member : struct_or_class.m_members) {
|
||||||
properties.append({ member.m_name, member.m_type });
|
if (!member.is_variable_declaration())
|
||||||
|
continue;
|
||||||
|
properties.append({ member.m_name, ((VariableDeclaration&)member).m_type });
|
||||||
}
|
}
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -453,7 +455,7 @@ RefPtr<Declaration> CppComprehensionEngine::find_declaration_of(const DocumentDa
|
||||||
bool match_function = target_decl.value().type == TargetDeclaration::Function && symbol.declaration->is_function();
|
bool match_function = target_decl.value().type == TargetDeclaration::Function && symbol.declaration->is_function();
|
||||||
bool match_variable = target_decl.value().type == TargetDeclaration::Variable && symbol.declaration->is_variable_declaration();
|
bool match_variable = target_decl.value().type == TargetDeclaration::Variable && symbol.declaration->is_variable_declaration();
|
||||||
bool match_type = target_decl.value().type == TargetDeclaration::Type && symbol.declaration->is_struct_or_class();
|
bool match_type = target_decl.value().type == TargetDeclaration::Type && symbol.declaration->is_struct_or_class();
|
||||||
bool match_property = target_decl.value().type == TargetDeclaration::Property && symbol.declaration->is_member();
|
bool match_property = target_decl.value().type == TargetDeclaration::Property && symbol.declaration->parent()->is_declaration() && ((Declaration*)symbol.declaration->parent())->is_struct_or_class();
|
||||||
bool match_parameter = target_decl.value().type == TargetDeclaration::Variable && symbol.declaration->is_parameter();
|
bool match_parameter = target_decl.value().type == TargetDeclaration::Variable && symbol.declaration->is_parameter();
|
||||||
|
|
||||||
if (match_property) {
|
if (match_property) {
|
||||||
|
|
|
@ -308,17 +308,6 @@ NonnullRefPtrVector<Declaration> StructOrClassDeclaration::declarations() const
|
||||||
return declarations;
|
return declarations;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemberDeclaration::dump(FILE* output, size_t indent) const
|
|
||||||
{
|
|
||||||
ASTNode::dump(output, indent);
|
|
||||||
m_type->dump(output, indent + 1);
|
|
||||||
print_indent(output, indent + 1);
|
|
||||||
outln(output, "{}", m_name);
|
|
||||||
if (m_initial_value) {
|
|
||||||
m_initial_value->dump(output, indent + 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnaryExpression::dump(FILE* output, size_t indent) const
|
void UnaryExpression::dump(FILE* output, size_t indent) const
|
||||||
{
|
{
|
||||||
ASTNode::dump(output, indent);
|
ASTNode::dump(output, indent);
|
||||||
|
|
|
@ -506,22 +506,6 @@ public:
|
||||||
Vector<StringView> m_entries;
|
Vector<StringView> m_entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MemberDeclaration : public Declaration {
|
|
||||||
public:
|
|
||||||
virtual ~MemberDeclaration() override = default;
|
|
||||||
virtual const char* class_name() const override { return "MemberDeclaration"; }
|
|
||||||
virtual void dump(FILE* = stdout, size_t indent = 0) const override;
|
|
||||||
virtual bool is_member() const override { return true; }
|
|
||||||
|
|
||||||
MemberDeclaration(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename)
|
|
||||||
: Declaration(parent, start, end, filename)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<Type> m_type;
|
|
||||||
RefPtr<Expression> m_initial_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
class StructOrClassDeclaration : public Declaration {
|
class StructOrClassDeclaration : public Declaration {
|
||||||
public:
|
public:
|
||||||
virtual ~StructOrClassDeclaration() override = default;
|
virtual ~StructOrClassDeclaration() override = default;
|
||||||
|
@ -544,7 +528,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
StructOrClassDeclaration::Type m_type;
|
StructOrClassDeclaration::Type m_type;
|
||||||
NonnullRefPtrVector<MemberDeclaration> m_members;
|
NonnullRefPtrVector<Declaration> m_members;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class UnaryOp {
|
enum class UnaryOp {
|
||||||
|
|
|
@ -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);
|
return parse_class_declaration(parent);
|
||||||
case DeclarationType::Struct:
|
|
||||||
return parse_struct_or_class_declaration(parent, StructOrClassDeclaration::Type::Struct);
|
|
||||||
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()
|
if (!match_keyword("struct") && !match_keyword("class"))
|
||||||
{
|
return false;
|
||||||
return match_keyword("struct");
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,12 +47,12 @@ private:
|
||||||
Function,
|
Function,
|
||||||
Variable,
|
Variable,
|
||||||
Enum,
|
Enum,
|
||||||
Struct,
|
|
||||||
Namespace,
|
|
||||||
Class,
|
Class,
|
||||||
|
Namespace,
|
||||||
};
|
};
|
||||||
|
|
||||||
Optional<DeclarationType> match_declaration_in_translation_unit();
|
Optional<DeclarationType> match_declaration_in_translation_unit();
|
||||||
|
Optional<Parser::DeclarationType> match_class_member();
|
||||||
bool match_function_declaration();
|
bool match_function_declaration();
|
||||||
bool match_comment();
|
bool match_comment();
|
||||||
bool match_preprocessor();
|
bool match_preprocessor();
|
||||||
|
@ -62,7 +62,6 @@ private:
|
||||||
bool match_secondary_expression();
|
bool match_secondary_expression();
|
||||||
bool match_enum_declaration();
|
bool match_enum_declaration();
|
||||||
bool match_class_declaration();
|
bool match_class_declaration();
|
||||||
bool match_struct_declaration();
|
|
||||||
bool match_literal();
|
bool match_literal();
|
||||||
bool match_unary_expression();
|
bool match_unary_expression();
|
||||||
bool match_boolean_literal();
|
bool match_boolean_literal();
|
||||||
|
@ -93,8 +92,7 @@ private:
|
||||||
NonnullRefPtr<StringLiteral> parse_string_literal(ASTNode& parent);
|
NonnullRefPtr<StringLiteral> parse_string_literal(ASTNode& parent);
|
||||||
NonnullRefPtr<ReturnStatement> parse_return_statement(ASTNode& parent);
|
NonnullRefPtr<ReturnStatement> parse_return_statement(ASTNode& parent);
|
||||||
NonnullRefPtr<EnumDeclaration> parse_enum_declaration(ASTNode& parent);
|
NonnullRefPtr<EnumDeclaration> parse_enum_declaration(ASTNode& parent);
|
||||||
NonnullRefPtr<StructOrClassDeclaration> parse_struct_or_class_declaration(ASTNode& parent, StructOrClassDeclaration::Type);
|
NonnullRefPtr<StructOrClassDeclaration> parse_class_declaration(ASTNode& parent);
|
||||||
NonnullRefPtr<MemberDeclaration> parse_member_declaration(ASTNode& parent);
|
|
||||||
NonnullRefPtr<Expression> parse_literal(ASTNode& parent);
|
NonnullRefPtr<Expression> parse_literal(ASTNode& parent);
|
||||||
NonnullRefPtr<UnaryExpression> parse_unary_expression(ASTNode& parent);
|
NonnullRefPtr<UnaryExpression> parse_unary_expression(ASTNode& parent);
|
||||||
NonnullRefPtr<BooleanLiteral> parse_boolean_literal(ASTNode& parent);
|
NonnullRefPtr<BooleanLiteral> parse_boolean_literal(ASTNode& parent);
|
||||||
|
@ -114,6 +112,7 @@ private:
|
||||||
NonnullRefPtr<SizeofExpression> parse_sizeof_expression(ASTNode& parent);
|
NonnullRefPtr<SizeofExpression> parse_sizeof_expression(ASTNode& parent);
|
||||||
NonnullRefPtr<BracedInitList> parse_braced_init_list(ASTNode& parent);
|
NonnullRefPtr<BracedInitList> parse_braced_init_list(ASTNode& parent);
|
||||||
NonnullRefPtr<CStyleCastExpression> parse_c_style_cast_expression(ASTNode& parent);
|
NonnullRefPtr<CStyleCastExpression> parse_c_style_cast_expression(ASTNode& parent);
|
||||||
|
NonnullRefPtrVector<Declaration> parse_class_members(ASTNode& parent);
|
||||||
|
|
||||||
bool match(Token::Type);
|
bool match(Token::Type);
|
||||||
Token consume(Token::Type);
|
Token consume(Token::Type);
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
TranslationUnit[1:0->12:0]
|
TranslationUnit[1:0->12:0]
|
||||||
StructOrClassDeclaration[1:0->7:0]
|
StructOrClassDeclaration[1:7->7:0]
|
||||||
MyStruct
|
MyStruct
|
||||||
MemberDeclaration[3:4->4:4]
|
VariableDeclaration[3:4->4:4]
|
||||||
Type[3:4->3:8]
|
Type[3:4->3:8]
|
||||||
int
|
int
|
||||||
x
|
x
|
||||||
MemberDeclaration[4:4->5:0]
|
VariableDeclaration[4:4->5:0]
|
||||||
Pointer[4:12->4:14]
|
Pointer[4:12->4:14]
|
||||||
Type[4:4->4:12]
|
Type[4:4->4:12]
|
||||||
s
|
s
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue