mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 13:37:45 +00:00
LibCpp: Parse Namespace declaration
Also, remove unused State::Context
This commit is contained in:
parent
505c84fdf0
commit
b5cab861e3
4 changed files with 111 additions and 57 deletions
|
@ -43,7 +43,7 @@ void ASTNode::dump(size_t indent) const
|
||||||
void TranslationUnit::dump(size_t indent) const
|
void TranslationUnit::dump(size_t indent) const
|
||||||
{
|
{
|
||||||
ASTNode::dump(indent);
|
ASTNode::dump(indent);
|
||||||
for (const auto& child : m_children) {
|
for (const auto& child : m_declarations) {
|
||||||
child.dump(indent + 1);
|
child.dump(indent + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -413,4 +413,14 @@ NonnullRefPtrVector<Declaration> IfStatement::declarations() const
|
||||||
declarations.append(m_else->declarations());
|
declarations.append(m_else->declarations());
|
||||||
return declarations;
|
return declarations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NamespaceDeclaration::dump(size_t indent) const
|
||||||
|
{
|
||||||
|
ASTNode::dump(indent);
|
||||||
|
print_indent(indent + 1);
|
||||||
|
outln("{}", m_name);
|
||||||
|
for (auto& decl : m_declarations)
|
||||||
|
decl.dump(indent + 1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,23 +96,16 @@ class TranslationUnit : public ASTNode {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~TranslationUnit() override = default;
|
virtual ~TranslationUnit() override = default;
|
||||||
const NonnullRefPtrVector<Declaration>& children() const { return m_children; }
|
|
||||||
virtual const char* class_name() const override { return "TranslationUnit"; }
|
virtual const char* class_name() const override { return "TranslationUnit"; }
|
||||||
virtual void dump(size_t indent) const override;
|
virtual void dump(size_t indent) const override;
|
||||||
void append(NonnullRefPtr<Declaration> child)
|
virtual NonnullRefPtrVector<Declaration> declarations() const override { return m_declarations; }
|
||||||
{
|
|
||||||
m_children.append(move(child));
|
|
||||||
}
|
|
||||||
virtual NonnullRefPtrVector<Declaration> declarations() const override { return m_children; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
TranslationUnit(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename)
|
TranslationUnit(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename)
|
||||||
: ASTNode(parent, start, end, filename)
|
: ASTNode(parent, start, end, filename)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
NonnullRefPtrVector<Declaration> m_declarations;
|
||||||
NonnullRefPtrVector<Declaration> m_children;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Statement : public ASTNode {
|
class Statement : public ASTNode {
|
||||||
|
@ -140,6 +133,7 @@ public:
|
||||||
virtual bool is_struct() const { return false; }
|
virtual bool is_struct() const { return false; }
|
||||||
virtual bool is_class() const { return false; }
|
virtual bool is_class() const { return false; }
|
||||||
virtual bool is_function() const { return false; }
|
virtual bool is_function() const { return false; }
|
||||||
|
virtual bool is_namespace() const { return false; }
|
||||||
const StringView& name() const { return m_name; }
|
const StringView& name() const { return m_name; }
|
||||||
|
|
||||||
StringView m_name;
|
StringView m_name;
|
||||||
|
@ -618,4 +612,22 @@ public:
|
||||||
RefPtr<Statement> m_else;
|
RefPtr<Statement> m_else;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NamespaceDeclaration : public Declaration {
|
||||||
|
public:
|
||||||
|
virtual ~NamespaceDeclaration() override = default;
|
||||||
|
virtual const char* class_name() const override { return "NamespaceDeclaration"; }
|
||||||
|
virtual void dump(size_t indent) const override;
|
||||||
|
virtual bool is_namespace() const override { return true; }
|
||||||
|
|
||||||
|
NamespaceDeclaration(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename)
|
||||||
|
: Declaration(parent, start, end, filename)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual NonnullRefPtrVector<Declaration> declarations() const override { return m_declarations; }
|
||||||
|
|
||||||
|
StringView m_name;
|
||||||
|
NonnullRefPtrVector<Declaration> m_declarations;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,28 @@ NonnullRefPtr<TranslationUnit> Parser::parse()
|
||||||
if (m_tokens.is_empty())
|
if (m_tokens.is_empty())
|
||||||
return create_root_ast_node({}, {});
|
return create_root_ast_node({}, {});
|
||||||
auto unit = create_root_ast_node(m_tokens.first().start(), m_tokens.last().end());
|
auto unit = create_root_ast_node(m_tokens.first().start(), m_tokens.last().end());
|
||||||
while (!done()) {
|
unit->m_declarations = parse_declarations_in_translation_unit(*unit);
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
NonnullRefPtrVector<Declaration> Parser::parse_declarations_in_translation_unit(ASTNode& parent)
|
||||||
|
{
|
||||||
|
NonnullRefPtrVector<Declaration> declarations;
|
||||||
|
while (!eof()) {
|
||||||
|
auto declaration = parse_single_declaration_in_translation_unit(parent);
|
||||||
|
if (declaration) {
|
||||||
|
declarations.append(declaration.release_nonnull());
|
||||||
|
} else {
|
||||||
|
error("unexpected token");
|
||||||
|
consume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return declarations;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<Declaration> Parser::parse_single_declaration_in_translation_unit(ASTNode& parent)
|
||||||
|
{
|
||||||
|
while (!eof()) {
|
||||||
if (match_comment()) {
|
if (match_comment()) {
|
||||||
consume(Token::Type::Comment);
|
consume(Token::Type::Comment);
|
||||||
continue;
|
continue;
|
||||||
|
@ -89,29 +110,13 @@ NonnullRefPtr<TranslationUnit> Parser::parse()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto declaration = match_declaration();
|
auto declaration = match_declaration_in_translation_unit();
|
||||||
if (declaration.has_value()) {
|
if (declaration.has_value()) {
|
||||||
unit->append(parse_declaration(*unit, declaration.value()));
|
return parse_declaration(parent, declaration.value());
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error("unexpected token");
|
|
||||||
consume();
|
|
||||||
}
|
|
||||||
return unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<Parser::DeclarationType> Parser::match_declaration()
|
|
||||||
{
|
|
||||||
switch (m_state.context) {
|
|
||||||
case Context::InTranslationUnit:
|
|
||||||
return match_declaration_in_translation_unit();
|
|
||||||
case Context::InFunctionDefinition:
|
|
||||||
return match_declaration_in_function_definition();
|
|
||||||
default:
|
|
||||||
error("unexpected context");
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<Declaration> Parser::parse_declaration(ASTNode& parent, DeclarationType declaration_type)
|
NonnullRefPtr<Declaration> Parser::parse_declaration(ASTNode& parent, DeclarationType declaration_type)
|
||||||
|
@ -125,6 +130,8 @@ NonnullRefPtr<Declaration> Parser::parse_declaration(ASTNode& parent, Declaratio
|
||||||
return parse_enum_declaration(parent);
|
return parse_enum_declaration(parent);
|
||||||
case DeclarationType::Struct:
|
case DeclarationType::Struct:
|
||||||
return parse_struct_or_class_declaration(parent, StructOrClassDeclaration::Type::Struct);
|
return parse_struct_or_class_declaration(parent, StructOrClassDeclaration::Type::Struct);
|
||||||
|
case DeclarationType::Namespace:
|
||||||
|
return parse_namespace_declaration(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());
|
||||||
|
@ -233,7 +240,7 @@ NonnullRefPtr<BlockStatement> Parser::parse_block_statement(ASTNode& parent)
|
||||||
SCOPE_LOGGER();
|
SCOPE_LOGGER();
|
||||||
auto block_statement = create_ast_node<BlockStatement>(parent, position(), {});
|
auto block_statement = create_ast_node<BlockStatement>(parent, position(), {});
|
||||||
consume(Token::Type::LeftCurly);
|
consume(Token::Type::LeftCurly);
|
||||||
while (peek().type() != Token::Type::RightCurly) {
|
while (!eof() && peek().type() != Token::Type::RightCurly) {
|
||||||
block_statement->m_statements.append(parse_statement(*block_statement));
|
block_statement->m_statements.append(parse_statement(*block_statement));
|
||||||
}
|
}
|
||||||
consume(Token::Type::RightCurly);
|
consume(Token::Type::RightCurly);
|
||||||
|
@ -524,17 +531,24 @@ Optional<Parser::DeclarationType> Parser::match_declaration_in_translation_unit(
|
||||||
return DeclarationType::Enum;
|
return DeclarationType::Enum;
|
||||||
if (match_struct_declaration())
|
if (match_struct_declaration())
|
||||||
return DeclarationType::Struct;
|
return DeclarationType::Struct;
|
||||||
|
if (match_namespace_declaration())
|
||||||
|
return DeclarationType::Namespace;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::match_enum_declaration()
|
bool Parser::match_enum_declaration()
|
||||||
{
|
{
|
||||||
return peek().type() == Token::Type::Keyword && text_of_token(peek()) == "enum";
|
return match_keyword("enum");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::match_struct_declaration()
|
bool Parser::match_struct_declaration()
|
||||||
{
|
{
|
||||||
return peek().type() == Token::Type::Keyword && text_of_token(peek()) == "struct";
|
return match_keyword("struct");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Parser::match_namespace_declaration()
|
||||||
|
{
|
||||||
|
return match_keyword("namespace");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::match_function_declaration()
|
bool Parser::match_function_declaration()
|
||||||
|
@ -687,16 +701,6 @@ void Parser::load_state()
|
||||||
m_state = m_saved_states.take_last();
|
m_state = m_saved_states.take_last();
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<Parser::DeclarationType> Parser::match_declaration_in_function_definition()
|
|
||||||
{
|
|
||||||
VERIFY_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Parser::done()
|
|
||||||
{
|
|
||||||
return m_state.token_index == m_tokens.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
StringView Parser::text_of_token(const Cpp::Token& token) const
|
StringView Parser::text_of_token(const Cpp::Token& token) const
|
||||||
{
|
{
|
||||||
return token.text();
|
return token.text();
|
||||||
|
@ -906,7 +910,7 @@ NonnullRefPtr<EnumDeclaration> Parser::parse_enum_declaration(ASTNode& parent)
|
||||||
auto name_token = consume(Token::Type::Identifier);
|
auto name_token = consume(Token::Type::Identifier);
|
||||||
enum_decl->m_name = text_of_token(name_token);
|
enum_decl->m_name = text_of_token(name_token);
|
||||||
consume(Token::Type::LeftCurly);
|
consume(Token::Type::LeftCurly);
|
||||||
while (peek().type() != Token::Type::RightCurly && !eof()) {
|
while (!eof() && peek().type() != Token::Type::RightCurly) {
|
||||||
enum_decl->m_entries.append(text_of_token(consume(Token::Type::Identifier)));
|
enum_decl->m_entries.append(text_of_token(consume(Token::Type::Identifier)));
|
||||||
if (peek().type() != Token::Type::Comma) {
|
if (peek().type() != Token::Type::Comma) {
|
||||||
break;
|
break;
|
||||||
|
@ -962,7 +966,7 @@ NonnullRefPtr<StructOrClassDeclaration> Parser::parse_struct_or_class_declaratio
|
||||||
|
|
||||||
consume(Token::Type::LeftCurly);
|
consume(Token::Type::LeftCurly);
|
||||||
|
|
||||||
while (peek().type() != Token::Type::RightCurly && !eof()) {
|
while (!eof() && peek().type() != Token::Type::RightCurly) {
|
||||||
decl->m_members.append(parse_member_declaration(*decl));
|
decl->m_members.append(parse_member_declaration(*decl));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1073,7 +1077,7 @@ Vector<StringView> Parser::parse_type_qualifiers()
|
||||||
{
|
{
|
||||||
SCOPE_LOGGER();
|
SCOPE_LOGGER();
|
||||||
Vector<StringView> qualifiers;
|
Vector<StringView> qualifiers;
|
||||||
while (!done()) {
|
while (!eof()) {
|
||||||
auto token = peek();
|
auto token = peek();
|
||||||
if (token.type() != Token::Type::Keyword)
|
if (token.type() != Token::Type::Keyword)
|
||||||
break;
|
break;
|
||||||
|
@ -1096,7 +1100,7 @@ void Parser::consume_attribute_specification()
|
||||||
consume(); // __attribute__
|
consume(); // __attribute__
|
||||||
consume(Token::Type::LeftParen);
|
consume(Token::Type::LeftParen);
|
||||||
size_t left_count = 1;
|
size_t left_count = 1;
|
||||||
while (!done()) {
|
while (!eof()) {
|
||||||
auto token = consume();
|
auto token = consume();
|
||||||
if (token.type() == Token::Type::LeftParen) {
|
if (token.type() == Token::Type::LeftParen) {
|
||||||
++left_count;
|
++left_count;
|
||||||
|
@ -1129,4 +1133,36 @@ void Parser::add_tokens_for_preprocessor(Token& replaced_token, Preprocessor::De
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NonnullRefPtr<NamespaceDeclaration> Parser::parse_namespace_declaration(ASTNode& parent, bool is_nested_namespace)
|
||||||
|
{
|
||||||
|
auto namespace_decl = create_ast_node<NamespaceDeclaration>(parent, position(), {});
|
||||||
|
|
||||||
|
if (!is_nested_namespace)
|
||||||
|
consume(Token::Type::Keyword);
|
||||||
|
|
||||||
|
auto name_token = consume(Token::Type::Identifier);
|
||||||
|
namespace_decl->m_name = name_token.text();
|
||||||
|
|
||||||
|
if (peek().type() == Token::Type::ColonColon) {
|
||||||
|
consume(Token::Type::ColonColon);
|
||||||
|
namespace_decl->m_declarations.append(parse_namespace_declaration(*namespace_decl, true));
|
||||||
|
namespace_decl->set_end(position());
|
||||||
|
return namespace_decl;
|
||||||
|
}
|
||||||
|
|
||||||
|
consume(Token::Type::LeftCurly);
|
||||||
|
while (!eof() && peek().type() != Token::Type::RightCurly) {
|
||||||
|
auto declaration = parse_single_declaration_in_translation_unit(*namespace_decl);
|
||||||
|
if (declaration) {
|
||||||
|
namespace_decl->m_declarations.append(declaration.release_nonnull());
|
||||||
|
} else {
|
||||||
|
error("unexpected token");
|
||||||
|
consume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
consume(Token::Type::RightCurly);
|
||||||
|
namespace_decl->set_end(position());
|
||||||
|
return namespace_decl;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,13 +68,10 @@ private:
|
||||||
Variable,
|
Variable,
|
||||||
Enum,
|
Enum,
|
||||||
Struct,
|
Struct,
|
||||||
|
Namespace,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool done();
|
|
||||||
|
|
||||||
Optional<DeclarationType> match_declaration();
|
|
||||||
Optional<DeclarationType> match_declaration_in_translation_unit();
|
Optional<DeclarationType> match_declaration_in_translation_unit();
|
||||||
Optional<DeclarationType> match_declaration_in_function_definition();
|
|
||||||
bool match_function_declaration();
|
bool match_function_declaration();
|
||||||
bool match_comment();
|
bool match_comment();
|
||||||
bool match_preprocessor();
|
bool match_preprocessor();
|
||||||
|
@ -90,6 +87,7 @@ private:
|
||||||
bool match_boolean_literal();
|
bool match_boolean_literal();
|
||||||
bool match_keyword(const String&);
|
bool match_keyword(const String&);
|
||||||
bool match_block_statement();
|
bool match_block_statement();
|
||||||
|
bool match_namespace_declaration();
|
||||||
|
|
||||||
Optional<NonnullRefPtrVector<Parameter>> parse_parameter_list(ASTNode& parent);
|
Optional<NonnullRefPtrVector<Parameter>> parse_parameter_list(ASTNode& parent);
|
||||||
Optional<Token> consume_whitespace();
|
Optional<Token> consume_whitespace();
|
||||||
|
@ -119,6 +117,10 @@ private:
|
||||||
NonnullRefPtr<BlockStatement> parse_block_statement(ASTNode& parent);
|
NonnullRefPtr<BlockStatement> parse_block_statement(ASTNode& parent);
|
||||||
NonnullRefPtr<Comment> parse_comment(ASTNode& parent);
|
NonnullRefPtr<Comment> parse_comment(ASTNode& parent);
|
||||||
NonnullRefPtr<IfStatement> parse_if_statement(ASTNode& parent);
|
NonnullRefPtr<IfStatement> parse_if_statement(ASTNode& parent);
|
||||||
|
NonnullRefPtr<NamespaceDeclaration> parse_namespace_declaration(ASTNode& parent, bool is_nested_namespace = false);
|
||||||
|
NonnullRefPtrVector<Declaration> parse_declarations_in_translation_unit(ASTNode& parent);
|
||||||
|
RefPtr<Declaration> parse_single_declaration_in_translation_unit(ASTNode& parent);
|
||||||
|
|
||||||
|
|
||||||
bool match(Token::Type);
|
bool match(Token::Type);
|
||||||
Token consume(Token::Type);
|
Token consume(Token::Type);
|
||||||
|
@ -132,13 +134,7 @@ private:
|
||||||
void save_state();
|
void save_state();
|
||||||
void load_state();
|
void load_state();
|
||||||
|
|
||||||
enum class Context {
|
|
||||||
InTranslationUnit,
|
|
||||||
InFunctionDefinition,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
Context context { Context::InTranslationUnit };
|
|
||||||
size_t token_index { 0 };
|
size_t token_index { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue