mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 14:47:44 +00:00
LibCpp: Parse basic constructors and destructors
This commit is contained in:
parent
fd851ec5c9
commit
7de6c1489b
4 changed files with 185 additions and 5 deletions
|
@ -533,4 +533,36 @@ void CStyleCastExpression::dump(FILE* output, size_t indent) const
|
||||||
m_expression->dump(output, indent + 1);
|
m_expression->dump(output, indent + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Constructor::dump(FILE* output, size_t indent) const
|
||||||
|
{
|
||||||
|
print_indent(output, indent);
|
||||||
|
outln(output, "C'tor");
|
||||||
|
print_indent(output, indent + 1);
|
||||||
|
outln(output, "(");
|
||||||
|
for (const auto& arg : m_parameters) {
|
||||||
|
arg.dump(output, indent + 1);
|
||||||
|
}
|
||||||
|
print_indent(output, indent + 1);
|
||||||
|
outln(output, ")");
|
||||||
|
if (!m_definition.is_null()) {
|
||||||
|
m_definition->dump(output, indent + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Destructor::dump(FILE* output, size_t indent) const
|
||||||
|
{
|
||||||
|
print_indent(output, indent);
|
||||||
|
outln(output, "D'tor");
|
||||||
|
print_indent(output, indent + 1);
|
||||||
|
outln(output, "(");
|
||||||
|
for (const auto& arg : m_parameters) {
|
||||||
|
arg.dump(output, indent + 1);
|
||||||
|
}
|
||||||
|
print_indent(output, indent + 1);
|
||||||
|
outln(output, ")");
|
||||||
|
if (!m_definition.is_null()) {
|
||||||
|
m_definition->dump(output, indent + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,6 +146,8 @@ public:
|
||||||
virtual const char* class_name() const override { return "FunctionDeclaration"; }
|
virtual const char* class_name() const override { return "FunctionDeclaration"; }
|
||||||
virtual void dump(FILE* = stdout, size_t indent = 0) const override;
|
virtual void dump(FILE* = stdout, size_t indent = 0) const override;
|
||||||
virtual bool is_function() const override { return true; }
|
virtual bool is_function() const override { return true; }
|
||||||
|
virtual bool is_constructor() const { return false; }
|
||||||
|
virtual bool is_destructor() const { return false; }
|
||||||
RefPtr<FunctionDefinition> definition() { return m_definition; }
|
RefPtr<FunctionDefinition> definition() { return m_definition; }
|
||||||
|
|
||||||
FunctionDeclaration(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename)
|
FunctionDeclaration(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename)
|
||||||
|
@ -721,4 +723,31 @@ public:
|
||||||
virtual const char* class_name() const override { return "DummyAstNode"; }
|
virtual const char* class_name() const override { return "DummyAstNode"; }
|
||||||
virtual void dump(FILE* = stdout, size_t = 0) const override { }
|
virtual void dump(FILE* = stdout, size_t = 0) const override { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Constructor : public FunctionDeclaration {
|
||||||
|
public:
|
||||||
|
virtual ~Constructor() override = default;
|
||||||
|
virtual const char* class_name() const override { return "Constructor"; }
|
||||||
|
virtual void dump(FILE* = stdout, size_t indent = 0) const override;
|
||||||
|
virtual bool is_constructor() const override { return true; }
|
||||||
|
|
||||||
|
Constructor(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename)
|
||||||
|
: FunctionDeclaration(parent, start, end, filename)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Destructor : public FunctionDeclaration {
|
||||||
|
public:
|
||||||
|
virtual ~Destructor() override = default;
|
||||||
|
virtual const char* class_name() const override { return "Destructor"; }
|
||||||
|
virtual void dump(FILE* = stdout, size_t indent = 0) const override;
|
||||||
|
virtual bool is_destructor() const override { return true; }
|
||||||
|
|
||||||
|
Destructor(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename)
|
||||||
|
: FunctionDeclaration(parent, start, end, filename)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,10 @@ NonnullRefPtr<Declaration> Parser::parse_declaration(ASTNode& parent, Declaratio
|
||||||
return parse_class_declaration(parent);
|
return parse_class_declaration(parent);
|
||||||
case DeclarationType::Namespace:
|
case DeclarationType::Namespace:
|
||||||
return parse_namespace_declaration(parent);
|
return parse_namespace_declaration(parent);
|
||||||
|
case DeclarationType::Constructor:
|
||||||
|
return parse_constructor(parent);
|
||||||
|
case DeclarationType::Destructor:
|
||||||
|
return parse_destructor(parent);
|
||||||
default:
|
default:
|
||||||
error("unexpected declaration type");
|
error("unexpected declaration type");
|
||||||
return create_ast_node<InvalidDeclaration>(parent, position(), position());
|
return create_ast_node<InvalidDeclaration>(parent, position(), position());
|
||||||
|
@ -631,7 +635,7 @@ Optional<Parser::DeclarationType> Parser::match_declaration_in_translation_unit(
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<Parser::DeclarationType> Parser::match_class_member()
|
Optional<Parser::DeclarationType> Parser::match_class_member(const StringView& class_name)
|
||||||
{
|
{
|
||||||
if (match_function_declaration())
|
if (match_function_declaration())
|
||||||
return DeclarationType::Function;
|
return DeclarationType::Function;
|
||||||
|
@ -641,6 +645,10 @@ Optional<Parser::DeclarationType> Parser::match_class_member()
|
||||||
return DeclarationType::Class;
|
return DeclarationType::Class;
|
||||||
if (match_variable_declaration())
|
if (match_variable_declaration())
|
||||||
return DeclarationType::Variable;
|
return DeclarationType::Variable;
|
||||||
|
if (match_constructor(class_name))
|
||||||
|
return DeclarationType::Constructor;
|
||||||
|
if (match_destructor(class_name))
|
||||||
|
return DeclarationType::Destructor;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1436,13 +1444,15 @@ 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> Parser::parse_class_members(StructOrClassDeclaration& parent)
|
||||||
{
|
{
|
||||||
|
auto& class_name = parent.name();
|
||||||
|
|
||||||
NonnullRefPtrVector<Declaration> members;
|
NonnullRefPtrVector<Declaration> members;
|
||||||
while (!eof() && peek().type() != Token::Type::RightCurly) {
|
while (!eof() && peek().type() != Token::Type::RightCurly) {
|
||||||
if (match_access_specifier())
|
if (match_access_specifier())
|
||||||
consume_access_specifier(); // FIXME: Do not ignore access specifiers
|
consume_access_specifier(); // FIXME: Do not ignore access specifiers
|
||||||
auto member_type = match_class_member();
|
auto member_type = match_class_member(class_name);
|
||||||
if (member_type.has_value()) {
|
if (member_type.has_value()) {
|
||||||
members.append(parse_declaration(parent, member_type.value()));
|
members.append(parse_declaration(parent, member_type.value()));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1467,4 +1477,100 @@ void Parser::consume_access_specifier()
|
||||||
consume(Token::Type::Colon);
|
consume(Token::Type::Colon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Parser::match_constructor(const StringView& class_name)
|
||||||
|
{
|
||||||
|
save_state();
|
||||||
|
ScopeGuard state_guard = [this] { load_state(); };
|
||||||
|
|
||||||
|
auto token = consume();
|
||||||
|
if (token.text() != class_name)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!peek(Token::Type::LeftParen).has_value())
|
||||||
|
return false;
|
||||||
|
consume();
|
||||||
|
|
||||||
|
while (consume().type() != Token::Type::RightParen && !eof()) { };
|
||||||
|
|
||||||
|
return (peek(Token::Type::Semicolon).has_value() || peek(Token::Type::LeftCurly).has_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Parser::match_destructor(const StringView& class_name)
|
||||||
|
{
|
||||||
|
save_state();
|
||||||
|
ScopeGuard state_guard = [this] { load_state(); };
|
||||||
|
|
||||||
|
if (!match(Token::Type::Tilde))
|
||||||
|
return false;
|
||||||
|
consume();
|
||||||
|
|
||||||
|
auto token = peek();
|
||||||
|
|
||||||
|
if (token.text() != class_name)
|
||||||
|
return false;
|
||||||
|
consume();
|
||||||
|
|
||||||
|
if (!peek(Token::Type::LeftParen).has_value())
|
||||||
|
return false;
|
||||||
|
consume();
|
||||||
|
|
||||||
|
while (consume().type() != Token::Type::RightParen && !eof()) { };
|
||||||
|
|
||||||
|
return (peek(Token::Type::Semicolon).has_value() || peek(Token::Type::LeftCurly).has_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parser::parse_constructor_or_destructor_impl(FunctionDeclaration& func, CtorOrDtor type)
|
||||||
|
{
|
||||||
|
if (type == CtorOrDtor::Dtor)
|
||||||
|
consume(Token::Type::Tilde);
|
||||||
|
|
||||||
|
auto name_token = consume();
|
||||||
|
if (name_token.type() != Token::Type::Identifier && name_token.type() != Token::Type::KnownType) {
|
||||||
|
error("Unexpected constructor name");
|
||||||
|
}
|
||||||
|
func.m_name = name_token.text();
|
||||||
|
|
||||||
|
consume(Token::Type::LeftParen);
|
||||||
|
auto parameters = parse_parameter_list(func);
|
||||||
|
if (parameters.has_value()) {
|
||||||
|
if (type == CtorOrDtor::Dtor && !parameters->is_empty())
|
||||||
|
error("Destructor declaration that takes parameters");
|
||||||
|
else
|
||||||
|
func.m_parameters = move(parameters.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
consume(Token::Type::RightParen);
|
||||||
|
|
||||||
|
// TODO: Parse =default, =delete.
|
||||||
|
|
||||||
|
RefPtr<FunctionDefinition> body;
|
||||||
|
Position ctor_end {};
|
||||||
|
if (peek(Token::Type::LeftCurly).has_value()) {
|
||||||
|
body = parse_function_definition(func);
|
||||||
|
ctor_end = body->end();
|
||||||
|
} else {
|
||||||
|
ctor_end = position();
|
||||||
|
if (match_attribute_specification())
|
||||||
|
consume_attribute_specification(); // we don't use the value of __attribute__
|
||||||
|
consume(Token::Type::Semicolon);
|
||||||
|
}
|
||||||
|
|
||||||
|
func.m_definition = move(body);
|
||||||
|
func.set_end(ctor_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
NonnullRefPtr<Constructor> Parser::parse_constructor(ASTNode& parent)
|
||||||
|
{
|
||||||
|
auto ctor = create_ast_node<Constructor>(parent, position(), {});
|
||||||
|
parse_constructor_or_destructor_impl(*ctor, CtorOrDtor::Ctor);
|
||||||
|
return ctor;
|
||||||
|
}
|
||||||
|
|
||||||
|
NonnullRefPtr<Destructor> Parser::parse_destructor(ASTNode& parent)
|
||||||
|
{
|
||||||
|
auto ctor = create_ast_node<Destructor>(parent, position(), {});
|
||||||
|
parse_constructor_or_destructor_impl(*ctor, CtorOrDtor::Dtor);
|
||||||
|
return ctor;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,10 +49,13 @@ private:
|
||||||
Enum,
|
Enum,
|
||||||
Class,
|
Class,
|
||||||
Namespace,
|
Namespace,
|
||||||
|
Constructor,
|
||||||
|
Destructor,
|
||||||
};
|
};
|
||||||
|
|
||||||
Optional<DeclarationType> match_declaration_in_translation_unit();
|
Optional<DeclarationType> match_declaration_in_translation_unit();
|
||||||
Optional<Parser::DeclarationType> match_class_member();
|
Optional<Parser::DeclarationType> match_class_member(const StringView& class_name);
|
||||||
|
|
||||||
bool match_function_declaration();
|
bool match_function_declaration();
|
||||||
bool match_comment();
|
bool match_comment();
|
||||||
bool match_preprocessor();
|
bool match_preprocessor();
|
||||||
|
@ -76,6 +79,8 @@ private:
|
||||||
bool match_braced_init_list();
|
bool match_braced_init_list();
|
||||||
bool match_type();
|
bool match_type();
|
||||||
bool match_access_specifier();
|
bool match_access_specifier();
|
||||||
|
bool match_constructor(const StringView& class_name);
|
||||||
|
bool match_destructor(const StringView& class_name);
|
||||||
|
|
||||||
Optional<NonnullRefPtrVector<Parameter>> parse_parameter_list(ASTNode& parent);
|
Optional<NonnullRefPtrVector<Parameter>> parse_parameter_list(ASTNode& parent);
|
||||||
Optional<Token> consume_whitespace();
|
Optional<Token> consume_whitespace();
|
||||||
|
@ -113,7 +118,9 @@ 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);
|
NonnullRefPtrVector<Declaration> parse_class_members(StructOrClassDeclaration& parent);
|
||||||
|
NonnullRefPtr<Constructor> parse_constructor(ASTNode& parent);
|
||||||
|
NonnullRefPtr<Destructor> parse_destructor(ASTNode& parent);
|
||||||
|
|
||||||
bool match(Token::Type);
|
bool match(Token::Type);
|
||||||
Token consume(Token::Type);
|
Token consume(Token::Type);
|
||||||
|
@ -170,6 +177,12 @@ private:
|
||||||
Vector<StringView> parse_type_qualifiers();
|
Vector<StringView> parse_type_qualifiers();
|
||||||
Vector<StringView> parse_function_qualifiers();
|
Vector<StringView> parse_function_qualifiers();
|
||||||
|
|
||||||
|
enum class CtorOrDtor {
|
||||||
|
Ctor,
|
||||||
|
Dtor,
|
||||||
|
};
|
||||||
|
void parse_constructor_or_destructor_impl(FunctionDeclaration&, CtorOrDtor);
|
||||||
|
|
||||||
Preprocessor::Definitions m_preprocessor_definitions;
|
Preprocessor::Definitions m_preprocessor_definitions;
|
||||||
String m_filename;
|
String m_filename;
|
||||||
Vector<Token> m_tokens;
|
Vector<Token> m_tokens;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue