From 10cad8a87418a4507b5385d69f66eef349b0561d Mon Sep 17 00:00:00 2001 From: Itamar Date: Sat, 26 Jun 2021 17:23:56 +0300 Subject: LibCpp: Add LOG_SCOPE() macro for debugging the parser's flow LOG_SCOPE() uses ScopeLogger and additionally shows the current token in the parser's state. --- Userland/Libraries/LibCpp/Parser.cpp | 60 ++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/Userland/Libraries/LibCpp/Parser.cpp b/Userland/Libraries/LibCpp/Parser.cpp index 044885c680..6e5f825a32 100644 --- a/Userland/Libraries/LibCpp/Parser.cpp +++ b/Userland/Libraries/LibCpp/Parser.cpp @@ -11,6 +11,8 @@ #include #include +#define LOG_SCOPE() ScopeLogger logger(String::formatted("'{}' - {} ({})", peek().text(), peek().type_as_string(), m_state.token_index)) + namespace Cpp { Parser::Parser(const StringView& program, const String& filename, Preprocessor::Definitions&& definitions) @@ -20,8 +22,8 @@ Parser::Parser(const StringView& program, const String& filename, Preprocessor:: initialize_program_tokens(program); if constexpr (CPP_DEBUG) { dbgln("Tokens:"); - for (auto& token : m_tokens) { - dbgln("{}", token.to_string()); + for (size_t i = 0; i < m_tokens.size(); ++i) { + dbgln("{}- {}", i, m_tokens[i].to_string()); } } } @@ -45,7 +47,7 @@ void Parser::initialize_program_tokens(const StringView& program) NonnullRefPtr Parser::parse() { - ScopeLogger logger; + LOG_SCOPE(); if (m_tokens.is_empty()) return create_root_ast_node({}, {}); auto unit = create_root_ast_node(m_tokens.first().start(), m_tokens.last().end()); @@ -149,7 +151,7 @@ NonnullRefPtr Parser::parse_function_declaration(ASTNode& p NonnullRefPtr Parser::parse_function_definition(ASTNode& parent) { - ScopeLogger logger; + LOG_SCOPE(); auto func = create_ast_node(parent, position(), {}); consume(Token::Type::LeftCurly); while (!eof() && peek().type() != Token::Type::RightCurly) { @@ -163,7 +165,7 @@ NonnullRefPtr Parser::parse_function_definition(ASTNode& par NonnullRefPtr Parser::parse_statement(ASTNode& parent) { - ScopeLogger logger; + LOG_SCOPE(); ArmedScopeGuard consume_semicolon([this]() { consume(Token::Type::Semicolon); }); @@ -215,7 +217,7 @@ bool Parser::match_block_statement() NonnullRefPtr Parser::parse_block_statement(ASTNode& parent) { - ScopeLogger logger; + LOG_SCOPE(); auto block_statement = create_ast_node(parent, position(), {}); consume(Token::Type::LeftCurly); while (!eof() && peek().type() != Token::Type::RightCurly) { @@ -266,7 +268,7 @@ bool Parser::match_template_arguments() NonnullRefPtrVector Parser::parse_template_arguments(ASTNode& parent) { - ScopeLogger logger; + LOG_SCOPE(); consume(Token::Type::Less); @@ -282,7 +284,7 @@ NonnullRefPtrVector Parser::parse_template_arguments(ASTNode& parent) bool Parser::match_variable_declaration() { - ScopeLogger logger; + LOG_SCOPE(); save_state(); ScopeGuard state_guard = [this] { load_state(); }; @@ -316,7 +318,7 @@ bool Parser::match_variable_declaration() NonnullRefPtr Parser::parse_variable_declaration(ASTNode& parent, bool expect_semicolon) { - ScopeLogger logger; + LOG_SCOPE(); auto var = create_ast_node(parent, position(), {}); if (!match_variable_declaration()) { error("unexpected token for variable type"); @@ -348,7 +350,7 @@ NonnullRefPtr Parser::parse_variable_declaration(ASTNode& p NonnullRefPtr Parser::parse_expression(ASTNode& parent) { - ScopeLogger logger; + LOG_SCOPE(); auto expression = parse_primary_expression(parent); // TODO: remove eof() logic, should still work without it if (eof() || match(Token::Type::Semicolon)) { @@ -410,7 +412,7 @@ bool Parser::match_secondary_expression() NonnullRefPtr Parser::parse_primary_expression(ASTNode& parent) { - ScopeLogger logger; + LOG_SCOPE(); // TODO: remove eof() logic, should still work without it if (eof()) { auto node = create_ast_node(parent, position(), position()); @@ -540,7 +542,7 @@ NonnullRefPtr Parser::parse_literal(ASTNode& parent) NonnullRefPtr Parser::parse_secondary_expression(ASTNode& parent, NonnullRefPtr lhs) { - ScopeLogger logger; + LOG_SCOPE(); switch (peek().type()) { case Token::Type::Plus: return parse_binary_expression(parent, lhs, BinaryOp::Addition); @@ -732,7 +734,7 @@ bool Parser::match_function_declaration() Optional> Parser::parse_parameter_list(ASTNode& parent) { - ScopeLogger logger; + LOG_SCOPE(); NonnullRefPtrVector parameters; while (peek().type() != Token::Type::RightParen && !eof()) { if (match_ellipsis()) { @@ -782,7 +784,7 @@ bool Parser::match_preprocessor() void Parser::consume_preprocessor() { - ScopeLogger logger; + LOG_SCOPE(); switch (peek().type()) { case Token::Type::PreprocessorStatement: consume(); @@ -799,7 +801,7 @@ void Parser::consume_preprocessor() Optional Parser::consume_whitespace() { - ScopeLogger logger; + LOG_SCOPE(); return consume(Token::Type::Whitespace); } @@ -875,7 +877,7 @@ String Parser::text_in_range(Position start, Position end) const void Parser::error(StringView message) { - ScopeLogger logger; + LOG_SCOPE(); if (message.is_null() || message.is_empty()) message = ""; String formatted_message; @@ -910,8 +912,12 @@ bool Parser::eof() const Position Parser::position() const { + if (m_tokens.is_empty()) + return {}; + if (eof()) return m_tokens.last().end(); + return peek().start(); } @@ -992,7 +998,7 @@ Vector Parser::get_todo_entries() const NonnullRefPtr Parser::parse_string_literal(ASTNode& parent) { - ScopeLogger logger; + LOG_SCOPE(); Optional start_token_index; Optional end_token_index; while (!eof()) { @@ -1026,7 +1032,7 @@ NonnullRefPtr Parser::parse_string_literal(ASTNode& parent) NonnullRefPtr Parser::parse_return_statement(ASTNode& parent) { - ScopeLogger logger; + LOG_SCOPE(); auto return_statement = create_ast_node(parent, position(), {}); consume(Token::Type::Keyword); if (!peek(Token::Type::Semicolon).has_value()) { @@ -1039,7 +1045,7 @@ NonnullRefPtr Parser::parse_return_statement(ASTNode& parent) NonnullRefPtr Parser::parse_enum_declaration(ASTNode& parent) { - ScopeLogger logger; + LOG_SCOPE(); auto enum_decl = create_ast_node(parent, position(), {}); consume_keyword("enum"); @@ -1094,7 +1100,7 @@ bool Parser::match_keyword(const String& keyword) NonnullRefPtr Parser::parse_class_declaration(ASTNode& parent) { - ScopeLogger logger; + LOG_SCOPE(); auto type_token = consume(Token::Type::Keyword); StructOrClassDeclaration::Type type {}; @@ -1123,7 +1129,7 @@ NonnullRefPtr Parser::parse_class_declaration(ASTNode& NonnullRefPtr Parser::parse_boolean_literal(ASTNode& parent) { - ScopeLogger logger; + LOG_SCOPE(); auto token = consume(Token::Type::Keyword); auto text = text_of_token(token); // text == "true" || text == "false"; @@ -1177,7 +1183,8 @@ NonnullRefPtr Parser::parse_type(ASTNode& parent) auto ptr = create_ast_node(parent, asterisk.start(), asterisk.end()); type->set_parent(*ptr); ptr->m_pointee = type; - type = ptr; + ptr->set_end(position()); + return ptr; } type->set_end(position()); @@ -1186,7 +1193,7 @@ NonnullRefPtr Parser::parse_type(ASTNode& parent) NonnullRefPtr Parser::parse_for_statement(ASTNode& parent) { - ScopeLogger logger; + LOG_SCOPE(); auto for_statement = create_ast_node(parent, position(), {}); consume(Token::Type::Keyword); consume(Token::Type::LeftParen); @@ -1210,7 +1217,7 @@ NonnullRefPtr Parser::parse_for_statement(ASTNode& parent) NonnullRefPtr Parser::parse_if_statement(ASTNode& parent) { - ScopeLogger logger; + LOG_SCOPE(); auto if_statement = create_ast_node(parent, position(), {}); consume(Token::Type::Keyword); consume(Token::Type::LeftParen); @@ -1228,7 +1235,7 @@ NonnullRefPtr Parser::parse_if_statement(ASTNode& parent) } Vector Parser::parse_type_qualifiers() { - ScopeLogger logger; + LOG_SCOPE(); Vector qualifiers; while (!eof()) { auto token = peek(); @@ -1247,7 +1254,7 @@ Vector Parser::parse_type_qualifiers() Vector Parser::parse_function_qualifiers() { - ScopeLogger logger; + LOG_SCOPE(); Vector qualifiers; while (!eof()) { auto token = peek(); @@ -1346,6 +1353,7 @@ bool Parser::match_name() NonnullRefPtr Parser::parse_name(ASTNode& parent) { + LOG_SCOPE(); NonnullRefPtr name_node = create_ast_node(parent, position(), {}); while (!eof() && (peek().type() == Token::Type::Identifier || peek().type() == Token::Type::KnownType) && peek(1).type() == Token::Type::ColonColon) { auto token = consume(); -- cgit v1.2.3