From 7d9b966bc7b176afb574c79445308df8154833ef Mon Sep 17 00:00:00 2001 From: csh Date: Sun, 26 Oct 2025 22:51:52 +0800 Subject: [PATCH] improve ast --- lsp-server/src/language/ast/deserializer.cpp | 8 +- lsp-server/src/language/ast/detail.cpp | 634 ++-- lsp-server/src/language/ast/types.hpp | 80 +- lsp-server/test/test_ast/debug_printer.cpp | 3512 +++++++++--------- lsp-server/test/test_ast/debug_printer.hpp | 6 +- lsp-server/test/test_ast/test.sh | 86 + lsp-server/test/test_ast/test.tsf | 22 +- 7 files changed, 2124 insertions(+), 2224 deletions(-) create mode 100644 lsp-server/test/test_ast/test.sh diff --git a/lsp-server/src/language/ast/deserializer.cpp b/lsp-server/src/language/ast/deserializer.cpp index 3b9b399..0932660 100644 --- a/lsp-server/src/language/ast/deserializer.cpp +++ b/lsp-server/src/language/ast/deserializer.cpp @@ -1,4 +1,3 @@ -#include #include "./detail.hpp" #include "./tree_sitter_utils.hpp" #include "./deserializer.hpp" @@ -19,8 +18,7 @@ namespace lsp::language::ast detail::ParseContext ctx(source, result.errors); auto program = std::make_unique(); - program->location = ts::NodeLocation(root); - program->node_type_name = "program"; + program->span = ts::NodeLocation(root); uint32_t count = ts_node_child_count(root); for (uint32_t i = 0; i < count; i++) @@ -53,8 +51,7 @@ namespace lsp::language::ast detail::ParseContext ctx(source, result.result.errors); auto program = std::make_unique(); - program->location = ts::NodeLocation(root); - program->node_type_name = "program"; + program->span = ts::NodeLocation(root); uint32_t count = ts_node_child_count(root); for (uint32_t i = 0; i < count; i++) @@ -75,6 +72,7 @@ namespace lsp::language::ast program->statements.push_back(std::move(stmt)); } + result.result.root = std::move(program); auto syntax_errors = detail::CollectSyntaxErrors(root, source); result.result.errors.insert(result.result.errors.end(), std::make_move_iterator(syntax_errors.begin()), diff --git a/lsp-server/src/language/ast/detail.cpp b/lsp-server/src/language/ast/detail.cpp index 0e502a0..650b77b 100644 --- a/lsp-server/src/language/ast/detail.cpp +++ b/lsp-server/src/language/ast/detail.cpp @@ -48,8 +48,7 @@ namespace lsp::language::ast::detail Location loc = ts::NodeLocation(n); auto stmt = MakeNode(); stmt->kind = NodeKind::kExpressionStatement; - stmt->location = loc; - stmt->node_type_name = "expression_statement"; + stmt->span = loc; stmt->expression = std::move(expr); return stmt; }); @@ -251,13 +250,12 @@ namespace lsp::language::ast::detail TSNode params_node = ts_node_child_by_field_name(node, "parameters", 10); if (!ts_node_is_null(params_node)) sig.parameters = ParseParameters(params_node, ctx); - TSNode return_node = ts_node_child_by_field_name(node, "return_type", 11); if (!ts_node_is_null(return_node)) { TSNode type_name_node = ts_node_child_by_field_name(return_node, "type_name", 9); if (!ts_node_is_null(type_name_node)) - sig.return_type = ts::Text(type_name_node, ctx.Source()); + sig.return_type = TypeAnnotation{ .name = ts::Text(type_name_node, ctx.Source()), .location = ts::NodeLocation(type_name_node) }; } return sig; @@ -289,16 +287,6 @@ namespace lsp::language::ast::detail is_out = true; } - std::optional type_name; - TSNode type_node = ts_node_child_by_field_name(param_node, "type_name", 9); - if (!ts_node_is_null(type_node)) - type_name = ts::Text(type_node, ctx.Source()); - - ExpressionPtr default_value; - TSNode default_node = ts_node_child_by_field_name(param_node, "default", 7); - if (!ts_node_is_null(default_node)) - default_value = ParseExpression(default_node, ctx); - for (uint32_t j = 0; j < param_count; j++) { const char* field = ts_node_field_name_for_child(param_node, j); @@ -310,7 +298,7 @@ namespace lsp::language::ast::detail Parameter param; param.name = ts::Text(child, ctx.Source()); - param.type_name = std::nullopt; + param.type = std::nullopt; param.is_var = is_var; param.is_out = is_out; param.location = ts::NodeLocation(child); @@ -320,8 +308,12 @@ namespace lsp::language::ast::detail if (!all_params.empty()) { - all_params.back().type_name = type_name; - all_params.back().default_value = std::move(default_value); + TSNode type_node = ts_node_child_by_field_name(param_node, "type_name", 9); + if (!ts_node_is_null(type_node)) + all_params.back().type = TypeAnnotation{ .name = ts::Text(type_node, ctx.Source()), .location = ts::NodeLocation(type_node) }; + TSNode default_node = ts_node_child_by_field_name(param_node, "default", 7); + if (!ts_node_is_null(default_node)) + all_params.back().default_value = ParseExpression(default_node, ctx); } } @@ -422,8 +414,7 @@ namespace lsp::language::ast::detail Location loc = ts::NodeLocation(node); auto expr = MakeNode(); - expr->location = loc; - expr->node_type_name = node_type; + expr->span = loc; expr->raw_sql = ts::Text(node, ctx.Source()); // 根据节点类型设置SQL类型 @@ -449,18 +440,17 @@ namespace lsp::language::ast::detail ExpressionPtr ParseEchoExpression(TSNode node, ParseContext& ctx) { - Location loc = ts::NodeLocation(node); - - auto echo_id = MakeNode(); - echo_id->kind = NodeKind::kIdentifier; - echo_id->location = loc; - echo_id->node_type_name = "identifier"; - echo_id->name = "echo"; - auto call = MakeNode(); call->kind = NodeKind::kCallExpression; - call->location = loc; - call->node_type_name = "call_expression"; + call->span = ts::NodeLocation(node); + + TSNode echo_node = ts_node_child(node, 0); + auto echo_id = MakeNode(); + echo_id->kind = NodeKind::kIdentifier; + echo_id->span = ts::NodeLocation(echo_node); + echo_id->name = "echo"; + echo_id->location = ts::NodeLocation(echo_node); + call->callee = std::move(echo_id); uint32_t count = ts_node_child_count(node); @@ -484,18 +474,17 @@ namespace lsp::language::ast::detail ExpressionPtr ParseRaiseExpression(TSNode node, ParseContext& ctx) { - Location loc = ts::NodeLocation(node); - - auto raise_id = MakeNode(); - raise_id->kind = NodeKind::kIdentifier; - raise_id->location = loc; - raise_id->node_type_name = "identifier"; - raise_id->name = "raise"; - auto call = MakeNode(); call->kind = NodeKind::kCallExpression; - call->location = loc; - call->node_type_name = "call_expression"; + call->span = ts::NodeLocation(node); + + TSNode raise_node = ts_node_child(node, 0); + auto raise_id = MakeNode(); + raise_id->kind = NodeKind::kIdentifier; + raise_id->span = ts::NodeLocation(raise_node); + raise_id->name = "raise"; + raise_id->location = ts::NodeLocation(raise_node); + call->callee = std::move(raise_id); TSNode exception_node = ts_node_child_by_field_name(node, "exception", 9); @@ -514,18 +503,17 @@ namespace lsp::language::ast::detail ExpressionPtr ParseNewExpression(TSNode node, ParseContext& ctx) { - Location loc = ts::NodeLocation(node); - - auto new_id = MakeNode(); - new_id->kind = NodeKind::kIdentifier; - new_id->location = loc; - new_id->node_type_name = "identifier"; - new_id->name = "new"; - auto call = MakeNode(); call->kind = NodeKind::kCallExpression; - call->location = loc; - call->node_type_name = "call_expression"; + call->span = ts::NodeLocation(node); + + TSNode new_node = ts_node_child(node, 0); + auto new_id = MakeNode(); + new_id->kind = NodeKind::kIdentifier; + new_id->span = ts::NodeLocation(new_node); + new_id->name = "new"; + new_id->location = ts::NodeLocation(new_node); + call->callee = std::move(new_id); TSNode exception_node = ts_node_child_by_field_name(node, "class", 5); @@ -545,19 +533,18 @@ namespace lsp::language::ast::detail ExpressionPtr ParseInheritedExpression(TSNode node, ParseContext& ctx) { - Location loc = ts::NodeLocation(node); - - auto new_id = MakeNode(); - new_id->kind = NodeKind::kIdentifier; - new_id->location = loc; - new_id->node_type_name = "identifier"; - new_id->name = "inherited"; - auto call = MakeNode(); call->kind = NodeKind::kCallExpression; - call->location = loc; - call->node_type_name = "call_expression"; - call->callee = std::move(new_id); + call->span = ts::NodeLocation(node); + + TSNode inherited_node = ts_node_child(node, 0); + auto inherited_id = MakeNode(); + inherited_id->kind = NodeKind::kIdentifier; + inherited_id->span = ts::NodeLocation(inherited_node); + inherited_id->name = "inherited"; + inherited_id->location = ts::NodeLocation(inherited_node); + + call->callee = std::move(inherited_id); TSNode exception_node = ts_node_child_by_field_name(node, "class", 5); if (!ts_node_is_null(exception_node)) @@ -598,8 +585,8 @@ namespace lsp::language::ast::detail std::string name = ts::Text(node, ctx.Source()); auto id = MakeNode(); id->kind = NodeKind::kIdentifier; - id->location = loc; - id->node_type_name = node_type; + id->span = loc; + id->name = std::move(name); return id; } @@ -607,37 +594,34 @@ namespace lsp::language::ast::detail // 字面量 if (node_type == "number") { - std::string value = ts::Text(node, ctx.Source()); auto lit = MakeNode(); lit->kind = NodeKind::kLiteral; - lit->location = loc; - lit->node_type_name = "literal"; + lit->span = loc; lit->literal_kind = LiteralKind::kNumber; - lit->value = std::move(value); + lit->name = ts::Text(node, ctx.Source()); + lit->location = loc; return lit; } if (node_type == "string") { - std::string value = ts::Text(node, ctx.Source()); auto lit = MakeNode(); lit->kind = NodeKind::kLiteral; - lit->location = loc; - lit->node_type_name = "literal"; + lit->span = loc; lit->literal_kind = LiteralKind::kString; - lit->value = std::move(value); + lit->name = ts::Text(node, ctx.Source()); + lit->location = loc; return lit; } if (node_type == "boolean") { - std::string value = ts::Text(node, ctx.Source()); auto lit = MakeNode(); lit->kind = NodeKind::kLiteral; - lit->location = loc; - lit->node_type_name = "literal"; + lit->span = loc; lit->literal_kind = LiteralKind::kBoolean; - lit->value = std::move(value); + lit->name = ts::Text(node, ctx.Source()); + lit->location = loc; return lit; } @@ -645,22 +629,21 @@ namespace lsp::language::ast::detail { auto lit = MakeNode(); lit->kind = NodeKind::kLiteral; - lit->location = loc; - lit->node_type_name = "literal"; + lit->span = loc; lit->literal_kind = LiteralKind::kNil; - lit->value = "nil"; + lit->name = "nil"; + lit->location = loc; return lit; } if (node_type == "infinity") { - std::string value = ts::Text(node, ctx.Source()); auto lit = MakeNode(); lit->kind = NodeKind::kLiteral; - lit->location = loc; - lit->node_type_name = "literal"; + lit->span = loc; lit->literal_kind = LiteralKind::kInfinity; - lit->value = std::move(value); + lit->name = ts::Text(node, ctx.Source()); + lit->location = loc; return lit; } @@ -668,10 +651,10 @@ namespace lsp::language::ast::detail { auto lit = MakeNode(); lit->kind = NodeKind::kLiteral; - lit->location = loc; - lit->node_type_name = "literal"; + lit->span = loc; lit->literal_kind = LiteralKind::kEllipsis; - lit->value = "..."; + lit->name = "..."; + lit->location = loc; return lit; } @@ -681,8 +664,8 @@ namespace lsp::language::ast::detail { auto id = MakeNode(); id->kind = NodeKind::kIdentifier; - id->location = loc; - id->node_type_name = "identifier"; + id->span = loc; + id->name = std::move(text); return id; } @@ -723,8 +706,8 @@ namespace lsp::language::ast::detail auto expr = MakeNode(); expr->kind = NodeKind::kBinaryExpression; - expr->location = loc; - expr->node_type_name = "binary_expression"; + expr->span = loc; + expr->op = op; expr->left = std::move(left); expr->right = std::move(right); @@ -743,8 +726,8 @@ namespace lsp::language::ast::detail auto arg = ParseExpression(arg_node, ctx); auto expr = MakeNode(); expr->kind = NodeKind::kPrefixIncrementExpression; - expr->location = loc; - expr->node_type_name = "prefix_increment_expression"; + expr->span = loc; + expr->argument = std::move(arg); return expr; } @@ -755,8 +738,8 @@ namespace lsp::language::ast::detail auto arg = ParseExpression(arg_node, ctx); auto expr = MakeNode(); expr->kind = NodeKind::kPrefixDecrementExpression; - expr->location = loc; - expr->node_type_name = "prefix_decrement_expression"; + expr->span = loc; + expr->argument = std::move(arg); return expr; } @@ -768,8 +751,8 @@ namespace lsp::language::ast::detail auto arg = ParseExpression(arg_node, ctx); auto expr = MakeNode(); expr->kind = NodeKind::kPostfixIncrementExpression; - expr->location = loc; - expr->node_type_name = "postfix_increment_expression"; + expr->span = loc; + expr->argument = std::move(arg); return expr; } @@ -780,8 +763,8 @@ namespace lsp::language::ast::detail auto arg = ParseExpression(arg_node, ctx); auto expr = MakeNode(); expr->kind = NodeKind::kPostfixDecrementExpression; - expr->location = loc; - expr->node_type_name = "postfix_decrement_expression"; + expr->span = loc; + expr->argument = std::move(arg); return expr; } @@ -793,8 +776,8 @@ namespace lsp::language::ast::detail auto arg = ParseExpression(arg_node, ctx); auto expr = MakeNode(); expr->kind = NodeKind::kFunctionPointerExpression; - expr->location = loc; - expr->node_type_name = "function_pointer_expression"; + expr->span = loc; + expr->argument = std::move(arg); return expr; } @@ -818,8 +801,8 @@ namespace lsp::language::ast::detail auto expr = MakeNode(); expr->kind = NodeKind::kUnaryExpression; - expr->location = loc; - expr->node_type_name = "unary_expression"; + expr->span = loc; + expr->op = op; expr->argument = std::move(arg); return expr; @@ -848,8 +831,8 @@ namespace lsp::language::ast::detail auto expr = MakeNode(); expr->kind = NodeKind::kTernaryExpression; - expr->location = loc; - expr->node_type_name = "ternary_expression"; + expr->span = loc; + expr->condition = std::move(condition); expr->consequence = std::move(consequence); expr->alternative = std::move(alternative); @@ -858,84 +841,72 @@ namespace lsp::language::ast::detail ExpressionPtr ParseCallExpression(TSNode node, ParseContext& ctx) { - Location loc = ts::NodeLocation(node); - - TSNode callee_node = ts_node_child_by_field_name(node, "function", 8); - - if (ts_node_is_null(callee_node)) - return ctx.ReportNullNode(loc, "function callee"); - - auto callee = ParseExpression(callee_node, ctx); - - if (!callee) - return ctx.ReportParseFailed(loc, "call_expression", "failed to parse callee"); - - std::vector arguments; - - uint32_t count = ts_node_child_count(node); - for (uint32_t i = 0; i < count; i++) - { - const char* field = ts_node_field_name_for_child(node, i); - if (!field || std::string_view(field) != "argument") - continue; - - TSNode argument_node = ts_node_child(node, i); - - TSNode child = ts_node_child(argument_node, 0); - std::string_view child_node_type = ts_node_type(child); - - CallExpression::Argument arg; - if (child_node_type == "expression") - { - arg.value = ParseExpression(child, ctx); - } - else if (child_node_type == "named_argument") - { - TSNode name_node = ts_node_child_by_field_name(child, "name", 4); - if (!ts_node_is_null(name_node)) - arg.name = ts::Text(name_node, ctx.Source()); - - TSNode value_node = ts_node_child_by_field_name(child, "value", 5); - if (!ts_node_is_null(value_node)) - arg.value = ParseExpression(value_node, ctx); - } - arguments.push_back(std::move(arg)); - } - auto expr = MakeNode(); expr->kind = NodeKind::kCallExpression; - expr->location = loc; - expr->node_type_name = "call_expression"; - expr->callee = std::move(callee); - expr->arguments = std::move(arguments); + expr->span = ts::NodeLocation(node); + + TSNode callee_node = ts_node_child_by_field_name(node, "function", 8); + if (!ts_node_is_null(callee_node)) + { + auto callee = ParseExpression(callee_node, ctx); + std::vector arguments; + uint32_t count = ts_node_child_count(node); + for (uint32_t i = 0; i < count; i++) + { + const char* field = ts_node_field_name_for_child(node, i); + if (!field || std::string_view(field) != "argument") + continue; + + TSNode argument_node = ts_node_child(node, i); + + TSNode child = ts_node_child(argument_node, 0); + std::string_view child_node_type = ts_node_type(child); + + CallExpression::Argument arg; + if (child_node_type == "expression") + { + arg.value = ParseExpression(child, ctx); + } + else if (child_node_type == "named_argument") + { + TSNode name_node = ts_node_child_by_field_name(child, "name", 4); + if (!ts_node_is_null(name_node)) + { + arg.name = ts::Text(name_node, ctx.Source()); + arg.location = ts::NodeLocation(name_node); + } + + TSNode value_node = ts_node_child_by_field_name(child, "value", 5); + if (!ts_node_is_null(value_node)) + arg.value = ParseExpression(value_node, ctx); + } + arguments.push_back(std::move(arg)); + } + expr->callee = std::move(callee); + expr->arguments = std::move(arguments); + } return expr; } ExpressionPtr ParseAttributeExpression(TSNode node, ParseContext& ctx) { - Location loc = ts::NodeLocation(node); + auto expr = MakeNode(); + expr->kind = NodeKind::kAttributeExpression; + expr->span = ts::NodeLocation(node); TSNode obj_node = ts_node_child_by_field_name(node, "object", 6); TSNode attr_node = ts_node_child_by_field_name(node, "attribute", 9); - if (ts_node_is_null(obj_node)) - return ctx.ReportNullNode(loc, "object"); - - if (ts_node_is_null(attr_node)) - return ctx.ReportNullNode(loc, "attribute"); - - auto object = ParseExpression(obj_node, ctx); - if (!object) - return ctx.ReportParseFailed(loc, "attribute_expression", "failed to parse object"); - - std::string attribute = ts::Text(attr_node, ctx.Source()); - - auto expr = MakeNode(); - expr->kind = NodeKind::kAttributeExpression; - expr->location = loc; - expr->node_type_name = "attribute_expression"; - expr->object = std::move(object); - expr->attribute = std::move(attribute); + if (!ts_node_is_null(obj_node)) + { + auto object = ParseExpression(obj_node, ctx); + expr->object = std::move(object); + } + if (!ts_node_is_null(attr_node)) + { + expr->name = ts::Text(attr_node, ctx.Source()); + expr->location = ts::NodeLocation(attr_node); + } return expr; } @@ -1012,8 +983,8 @@ namespace lsp::language::ast::detail auto expr = MakeNode(); expr->kind = NodeKind::kSubscriptExpression; - expr->location = loc; - expr->node_type_name = "subscript_expression"; + expr->span = loc; + expr->value = std::move(value); expr->indices = std::move(indices); return expr; @@ -1067,8 +1038,8 @@ namespace lsp::language::ast::detail auto expr = MakeNode(); expr->kind = NodeKind::kArrayExpression; - expr->location = loc; - expr->node_type_name = "array_expression"; + expr->span = loc; + expr->elements = std::move(elements); return expr; } @@ -1084,8 +1055,8 @@ namespace lsp::language::ast::detail auto expr = MakeNode(); expr->kind = NodeKind::kAnonymousFunctionExpression; - expr->location = loc; - expr->node_type_name = "anonymous_function_expression"; + expr->span = loc; + expr->signature = std::move(sig); expr->body = std::move(body); return expr; @@ -1099,8 +1070,8 @@ namespace lsp::language::ast::detail { auto id = MakeNode(); id->kind = NodeKind::kIdentifier; - id->location = ts::NodeLocation(node); - id->node_type_name = "identifier"; + id->span = ts::NodeLocation(node); + id->name = ""; return id; } @@ -1115,8 +1086,8 @@ namespace lsp::language::ast::detail Location loc = ts::NodeLocation(node); auto id = MakeNode(); id->kind = NodeKind::kIdentifier; - id->location = loc; - id->node_type_name = "identifier"; + id->span = loc; + id->name = std::move(name); return id; } @@ -1143,8 +1114,8 @@ namespace lsp::language::ast::detail auto id = MakeNode(); id->kind = NodeKind::kIdentifier; - id->location = ts::NodeLocation(node); - id->node_type_name = "identifier"; + id->span = ts::NodeLocation(node); + id->name = ts::Text(node, ctx.Source()); return id; } @@ -1164,8 +1135,8 @@ namespace lsp::language::ast::detail auto pattern = MakeNode(); pattern->kind = NodeKind::kUnpackPattern; - pattern->location = loc; - pattern->node_type_name = "unpack_pattern"; + pattern->span = loc; + pattern->names = std::move(names); return pattern; } @@ -1221,8 +1192,8 @@ namespace lsp::language::ast::detail auto block = MakeNode(); block->kind = NodeKind::kBlockStatement; - block->location = loc; - block->node_type_name = "block_suit"; + block->span = loc; + block->statements = std::move(statements); return block; } @@ -1247,8 +1218,8 @@ namespace lsp::language::ast::detail auto stmt = MakeNode(); stmt->kind = NodeKind::kExpressionStatement; - stmt->location = loc; - stmt->node_type_name = "expression_statement"; + stmt->span = loc; + stmt->expression = std::move(expr); return stmt; } @@ -1256,7 +1227,6 @@ namespace lsp::language::ast::detail ExpressionPtr ParseAssignmentExpression(TSNode node, ParseContext& ctx) { Location loc = ts::NodeLocation(node); - std::string_view node_type = ts_node_type(node); TSNode left_node = ts_node_child_by_field_name(node, "left", 4); TSNode op_node = ts_node_child_by_field_name(node, "operator", 8); @@ -1280,8 +1250,8 @@ namespace lsp::language::ast::detail auto expr = MakeNode(); expr->kind = NodeKind::kAssignmentExpression; - expr->location = loc; - expr->node_type_name = node_type; + expr->span = loc; + expr->left = std::move(left); expr->op = op; expr->right = std::move(right); @@ -1331,8 +1301,8 @@ namespace lsp::language::ast::detail auto stmt = MakeNode(); stmt->kind = NodeKind::kAssignmentStatement; - stmt->location = loc; - stmt->node_type_name = "assignment_statement"; + stmt->span = loc; + stmt->left = std::move(left); stmt->op = op; stmt->right = std::move(right); @@ -1342,7 +1312,7 @@ namespace lsp::language::ast::detail // ===== 通用声明解析模板 ===== template - StatementPtr ParseDeclarationStatement(TSNode node, ParseContext& ctx, NodeKind decl_kind, NodeKind stmt_kind, const std::string& keyword) + StatementPtr ParseDeclarationStatement(TSNode node, ParseContext& ctx, NodeKind decl_kind, NodeKind stmt_kind) { Location loc = ts::NodeLocation(node); std::vector> declarations; @@ -1350,12 +1320,6 @@ namespace lsp::language::ast::detail TSNode decl_node = ts_node_child_by_field_name(node, "declaration", 11); if (!ts_node_is_null(decl_node)) { - std::optional type_name; - - TSNode type_node = ts_node_child_by_field_name(decl_node, "type_name", 9); - if (!ts_node_is_null(type_node)) - type_name = ts::Text(type_node, ctx.Source()); - uint32_t count = ts_node_child_count(decl_node); for (uint32_t i = 0; i < count; i++) { @@ -1369,10 +1333,10 @@ namespace lsp::language::ast::detail auto decl = MakeNode(); decl->kind = decl_kind; - decl->location = name_loc; - decl->node_type_name = keyword + "_declaration"; + decl->span = name_loc; + decl->name = std::move(name); - decl->type_name = type_name; + decl->type = std::nullopt; decl->initial_value = nullptr; declarations.push_back(std::move(decl)); } @@ -1380,12 +1344,15 @@ namespace lsp::language::ast::detail TSNode initial_node = ts_node_child_by_field_name(decl_node, "initial_value", 13); if (!ts_node_is_null(initial_node)) declarations.back()->initial_value = ParseExpression(initial_node, ctx); + + TSNode type_node = ts_node_child_by_field_name(decl_node, "type_name", 9); + if (!declarations.empty() && !ts_node_is_null(type_node)) + declarations.back()->type = TypeAnnotation{ .name = ts::Text(type_node, ctx.Source()), .location = ts::NodeLocation(type_node) }; } auto stmt = MakeNode(); stmt->kind = stmt_kind; - stmt->location = loc; - stmt->node_type_name = keyword + "_statement"; + stmt->span = loc; stmt->declarations = std::move(declarations); return stmt; } @@ -1393,19 +1360,19 @@ namespace lsp::language::ast::detail StatementPtr ParseVarStatement(TSNode node, ParseContext& ctx) { return ParseDeclarationStatement( - node, ctx, NodeKind::kVarDeclaration, NodeKind::kVarStatement, "var"); + node, ctx, NodeKind::kVarDeclaration, NodeKind::kVarStatement); } StatementPtr ParseStaticStatement(TSNode node, ParseContext& ctx) { return ParseDeclarationStatement( - node, ctx, NodeKind::kStaticDeclaration, NodeKind::kStaticStatement, "static"); + node, ctx, NodeKind::kStaticDeclaration, NodeKind::kStaticStatement); } StatementPtr ParseGlobalStatement(TSNode node, ParseContext& ctx) { return ParseDeclarationStatement( - node, ctx, NodeKind::kGlobalDeclaration, NodeKind::kGlobalStatement, "global"); + node, ctx, NodeKind::kGlobalDeclaration, NodeKind::kGlobalStatement); } StatementPtr ParseConstStatement(TSNode node, ParseContext& ctx) @@ -1427,8 +1394,8 @@ namespace lsp::language::ast::detail auto stmt = MakeNode(); stmt->kind = NodeKind::kConstStatement; - stmt->location = loc; - stmt->node_type_name = "const_statement"; + stmt->span = loc; + stmt->name = std::move(name); stmt->type_name = type_name; stmt->value = std::move(value); @@ -1481,8 +1448,8 @@ namespace lsp::language::ast::detail auto stmt = MakeNode(); stmt->kind = NodeKind::kIfStatement; - stmt->location = loc; - stmt->node_type_name = "if_statement"; + stmt->span = loc; + stmt->branches = std::move(branches); return stmt; } @@ -1503,8 +1470,8 @@ namespace lsp::language::ast::detail auto stmt = MakeNode(); stmt->kind = NodeKind::kForInStatement; - stmt->location = loc; - stmt->node_type_name = "for_in_statement"; + stmt->span = loc; + stmt->key = std::move(key); stmt->value = std::move(value); stmt->collection = std::move(collection); @@ -1537,8 +1504,8 @@ namespace lsp::language::ast::detail auto stmt = MakeNode(); stmt->kind = NodeKind::kForToStatement; - stmt->location = loc; - stmt->node_type_name = "for_to_statement"; + stmt->span = loc; + stmt->counter = std::move(counter); stmt->start = std::move(start); stmt->end = std::move(end); @@ -1559,8 +1526,8 @@ namespace lsp::language::ast::detail auto stmt = MakeNode(); stmt->kind = NodeKind::kWhileStatement; - stmt->location = loc; - stmt->node_type_name = "while_statement"; + stmt->span = loc; + stmt->condition = std::move(condition); stmt->body = std::move(body); return stmt; @@ -1578,7 +1545,7 @@ namespace lsp::language::ast::detail for (uint32_t i = 0; i < count; i++) { const char* field = ts_node_field_name_for_child(node, i); - if (!field || name != field) + if (!field || std::string_view(field) != "body") continue; TSNode child = ts_node_child(node, i); @@ -1591,8 +1558,8 @@ namespace lsp::language::ast::detail auto stmt = MakeNode(); stmt->kind = NodeKind::kRepeatStatement; - stmt->location = loc; - stmt->node_type_name = "repeat_statement"; + stmt->span = loc; + stmt->body = std::move(body_statements); stmt->condition = std::move(condition); return stmt; @@ -1607,12 +1574,11 @@ namespace lsp::language::ast::detail std::vector branches; - std::string name = "branches"; uint32_t count = ts_node_child_count(node); for (uint32_t i = 0; i < count; i++) { const char* field = ts_node_field_name_for_child(node, i); - if (!field || name != field) + if (!field || std::string_view(field) != "branches") continue; TSNode branch_node = ts_node_child(node, i); @@ -1648,8 +1614,8 @@ namespace lsp::language::ast::detail auto stmt = MakeNode(); stmt->kind = NodeKind::kCaseStatement; - stmt->location = loc; - stmt->node_type_name = "case_statement"; + stmt->span = loc; + stmt->discriminant = std::move(discriminant); stmt->branches = std::move(branches); stmt->default_case = std::move(default_case); @@ -1668,8 +1634,8 @@ namespace lsp::language::ast::detail auto stmt = MakeNode(); stmt->kind = NodeKind::kTryStatement; - stmt->location = loc; - stmt->node_type_name = "try_statement"; + stmt->span = loc; + stmt->try_body = std::move(try_body); stmt->except_body = std::move(except_body); return stmt; @@ -1680,8 +1646,8 @@ namespace lsp::language::ast::detail Location loc = ts::NodeLocation(node); auto stmt = MakeNode(); stmt->kind = NodeKind::kBreakStatement; - stmt->location = loc; - stmt->node_type_name = "break_statement"; + stmt->span = loc; + return stmt; } @@ -1690,8 +1656,8 @@ namespace lsp::language::ast::detail Location loc = ts::NodeLocation(node); auto stmt = MakeNode(); stmt->kind = NodeKind::kContinueStatement; - stmt->location = loc; - stmt->node_type_name = "continue_statement"; + stmt->span = loc; + return stmt; } @@ -1701,8 +1667,7 @@ namespace lsp::language::ast::detail auto stmt = MakeNode(); stmt->kind = NodeKind::kReturnStatement; - stmt->location = loc; - stmt->node_type_name = "return_statement"; + stmt->span = loc; TSNode value_node = ts_node_child_by_field_name(node, "value", 5); if (!ts_node_is_null(value_node)) @@ -1720,8 +1685,7 @@ namespace lsp::language::ast::detail auto uses = MakeNode(); uses->kind = NodeKind::kUsesStatement; - uses->location = loc; - uses->node_type_name = "uses_statement"; + uses->span = loc; uint32_t count = ts_node_child_count(node); for (uint32_t i = 0; i < count; i++) @@ -1747,36 +1711,43 @@ namespace lsp::language::ast::detail auto stmt = MakeNode(); stmt->kind = NodeKind::kExpressionStatement; - stmt->location = loc; - stmt->node_type_name = "inherited_statement"; + stmt->span = loc; + stmt->expression = std::move(expr); return stmt; } StatementPtr ParseFunctionDeclaration(TSNode node, ParseContext& ctx) { - Location loc = ts::NodeLocation(node); - - TSNode name_node = ts_node_child_by_field_name(node, "name", 4); - std::string name = ts_node_is_null(name_node) ? "" : ts::Text(name_node, ctx.Source()); - - Signature sig = ParseSignature(node, ctx); - auto stmt = MakeNode(); stmt->kind = NodeKind::kFunctionDeclaration; - stmt->location = loc; - stmt->node_type_name = "function_declaration"; - stmt->name = std::move(name); + stmt->span = ts::NodeLocation(node); + TSNode name_node = ts_node_child_by_field_name(node, "name", 4); + if (!ts_node_is_null(name_node)) + { + stmt->name = ts::Text(name_node, ctx.Source()); + stmt->location = ts::NodeLocation(name_node); + } + + Signature sig = ParseSignature(node, ctx); stmt->signature = std::move(sig); + return stmt; } StatementPtr ParseFunctionDefinition(TSNode node, ParseContext& ctx) { - Location loc = ts::NodeLocation(node); + auto stmt = MakeNode(); + stmt->kind = NodeKind::kFunctionDefinition; + stmt->span = ts::NodeLocation(node); TSNode name_node = ts_node_child_by_field_name(node, "name", 4); - std::string name = ts_node_is_null(name_node) ? "" : ts::Text(name_node, ctx.Source()); + if (!ts_node_is_null(name_node)) + { + std::string name = ts::Text(name_node, ctx.Source()); + stmt->name = std::move(name); + stmt->location = ts::NodeLocation(name_node); + } Signature sig = ParseSignature(node, ctx); @@ -1786,11 +1757,6 @@ namespace lsp::language::ast::detail std::string_view node_type = ts_node_type(node); bool is_overload = (node_type == "function_definition_with_overload_statement"); - auto stmt = MakeNode(); - stmt->kind = NodeKind::kFunctionDefinition; - stmt->location = loc; - stmt->node_type_name = "function_definition"; - stmt->name = std::move(name); stmt->signature = std::move(sig); stmt->body = std::move(body); stmt->is_overload = is_overload; @@ -1799,18 +1765,15 @@ namespace lsp::language::ast::detail StatementPtr ParseMatrixIterationStatement(TSNode node, ParseContext& ctx) { - Location loc = ts::NodeLocation(node); + auto stmt = MakeNode(); + stmt->kind = NodeKind::kWhileStatement; + stmt->span = ts::NodeLocation(node); TSNode target_node = ts_node_child_by_field_name(node, "target", 6); TSNode body_node = ts_node_child_by_field_name(node, "body", 4); auto target = ParseExpression(target_node, ctx); auto body = ParseStatement(body_node, ctx); - - auto stmt = MakeNode(); - stmt->kind = NodeKind::kWhileStatement; - stmt->location = loc; - stmt->node_type_name = "matrix_iteration_statement"; stmt->condition = std::move(target); stmt->body = std::move(body); return stmt; @@ -1823,8 +1786,8 @@ namespace lsp::language::ast::detail Location loc = ts::NodeLocation(node); auto block = MakeNode(); block->kind = NodeKind::kBlockStatement; - block->location = loc; - block->node_type_name = "tslx_open_tag"; + block->span = loc; + return block; } @@ -1833,8 +1796,8 @@ namespace lsp::language::ast::detail Location loc = ts::NodeLocation(node); auto block = MakeNode(); block->kind = NodeKind::kBlockStatement; - block->location = loc; - block->node_type_name = "tslx_close_tag"; + block->span = loc; + return block; } @@ -1857,15 +1820,14 @@ namespace lsp::language::ast::detail auto block = MakeNode(); block->kind = NodeKind::kBlockStatement; - block->location = loc; - block->node_type_name = "tslx_output_tag"; + block->span = loc; for (auto& expr : expressions) { auto expr_stmt = MakeNode(); expr_stmt->kind = NodeKind::kExpressionStatement; - expr_stmt->location = expr->location; - expr_stmt->node_type_name = "expression_statement"; + expr_stmt->span = expr->span; + expr_stmt->expression = std::move(expr); block->statements.push_back(std::move(expr_stmt)); } @@ -1895,8 +1857,8 @@ namespace lsp::language::ast::detail auto block = MakeNode(); block->kind = NodeKind::kBlockStatement; - block->location = loc; - block->node_type_name = "tslx_expression_tag"; + block->span = loc; + block->statements = std::move(statements); return block; } @@ -1906,8 +1868,8 @@ namespace lsp::language::ast::detail Location loc = ts::NodeLocation(node); auto block = MakeNode(); block->kind = NodeKind::kBlockStatement; - block->location = loc; - block->node_type_name = "html_self_closing_tag"; + block->span = loc; + return block; } @@ -1934,8 +1896,8 @@ namespace lsp::language::ast::detail auto block = MakeNode(); block->kind = NodeKind::kBlockStatement; - block->location = loc; - block->node_type_name = "html_paired_tag"; + block->span = loc; + block->statements = std::move(content); return block; } @@ -1945,23 +1907,23 @@ namespace lsp::language::ast::detail Location loc = ts::NodeLocation(node); auto block = MakeNode(); block->kind = NodeKind::kBlockStatement; - block->location = loc; - block->node_type_name = "html_comment"; + block->span = loc; + return block; } StatementPtr ParseUnitDefinition(TSNode node, ParseContext& ctx) { - Location loc = ts::NodeLocation(node); - - TSNode name_node = ts_node_child_by_field_name(node, "name", 4); - std::string unit_name = ts_node_is_null(name_node) ? "" : ts::Text(name_node, ctx.Source()); - auto unit = MakeNode(); unit->kind = NodeKind::kUnitDefinition; - unit->location = loc; - unit->node_type_name = "unit_definition"; - unit->name = std::move(unit_name); + unit->span = ts::NodeLocation(node); + + TSNode name_node = ts_node_child_by_field_name(node, "name", 4); + if (!ts_node_is_null(name_node)) + { + unit->name = ts::Text(name_node, ctx.Source()); + unit->location = ts::NodeLocation(name_node); + } TSNode interface_node = ts_node_child_by_field_name(node, "interface", 9); if (!ts_node_is_null(interface_node)) @@ -1978,7 +1940,6 @@ namespace lsp::language::ast::detail std::string_view child_type = ts_node_type(child); if (child_type == "interface") continue; - auto stmt = ParseStatement(child, ctx); if (stmt) unit->interface_statements.push_back(std::move(stmt)); @@ -2102,8 +2063,7 @@ namespace lsp::language::ast::detail auto method = MakeNode(); method->kind = NodeKind::kMethodDeclaration; - method->location = loc; - method->node_type_name = "method_declaration"; + method->span = loc; uint32_t count = ts_node_child_count(node); for (uint32_t i = 0; i < count; i++) @@ -2126,11 +2086,15 @@ namespace lsp::language::ast::detail method->is_operator_overload = true; TSNode op_node = ts_node_child_by_field_name(name_node, "operator", 8); if (!ts_node_is_null(op_node)) - method->operator_symbol = ts::Text(op_node, ctx.Source()); + { + method->name = ts::Text(op_node, ctx.Source()); + method->location = ts::NodeLocation(op_node); + } } else { method->name = ts::Text(name_node, ctx.Source()); + method->location = ts::NodeLocation(name_node); } } @@ -2158,12 +2122,14 @@ namespace lsp::language::ast::detail auto prop = MakeNode(); prop->kind = NodeKind::kPropertyDeclaration; - prop->location = loc; - prop->node_type_name = "property_declaration"; + prop->span = loc; TSNode name_node = ts_node_child_by_field_name(node, "name", 4); if (!ts_node_is_null(name_node)) + { prop->name = ts::Text(name_node, ctx.Source()); + prop->location = ts::NodeLocation(name_node); + } TSNode type_node = ts_node_child_by_field_name(node, "type_name", 9); if (!ts_node_is_null(type_node)) @@ -2238,16 +2204,6 @@ namespace lsp::language::ast::detail if (ts_node_is_null(member_var_node)) return results; - std::optional type_name; - TSNode type_node = ts_node_child_by_field_name(member_var_node, "type_name", 9); - if (!ts_node_is_null(type_node)) - type_name = ts::Text(type_node, ctx.Source()); - - ExpressionPtr initial_value; - TSNode value_node = ts_node_child_by_field_name(member_var_node, "initial_value", 13); - if (!ts_node_is_null(value_node)) - initial_value = ParseExpression(value_node, ctx); - uint32_t count = ts_node_child_count(member_var_node); for (uint32_t i = 0; i < count; i++) { @@ -2261,16 +2217,15 @@ namespace lsp::language::ast::detail auto member = MakeNode(); member->kind = NodeKind::kClassMember; - member->location = name_loc; - member->node_type_name = "class_member"; + member->span = name_loc; member->access_modifier = current_access; if (is_static) { auto decl = MakeNode(); decl->kind = NodeKind::kStaticDeclaration; - decl->location = name_loc; - decl->node_type_name = "static_declaration"; + decl->span = name_loc; + decl->name = name; decl->reference_modifier = ref_flag ? ParseReferenceModifier(ref_node, ctx) : current_reference; @@ -2280,8 +2235,8 @@ namespace lsp::language::ast::detail { auto decl = MakeNode(); decl->kind = NodeKind::kFieldDeclaration; - decl->location = name_loc; - decl->node_type_name = "field_declaration"; + decl->span = name_loc; + decl->name = name; decl->reference_modifier = ref_flag ? ParseReferenceModifier(ref_node, ctx) : current_reference; @@ -2293,6 +2248,12 @@ namespace lsp::language::ast::detail results.push_back(std::move(result)); } + ExpressionPtr initial_value; + TSNode value_node = ts_node_child_by_field_name(member_var_node, "initial_value", 13); + if (!ts_node_is_null(value_node)) + initial_value = ParseExpression(value_node, ctx); + + TSNode type_node = ts_node_child_by_field_name(member_var_node, "type_name", 9); if (!results.empty()) { auto& last_member = results.back().member; @@ -2303,7 +2264,8 @@ namespace lsp::language::ast::detail if constexpr (std::is_same_v || std::is_same_v) { - decl_ptr->type_name = type_name; + if (!ts_node_is_null(type_node)) + decl_ptr->type = TypeAnnotation{ .name = ts::Text(type_node, ctx.Source()), .location = ts::NodeLocation(type_node) }; decl_ptr->initial_value = std::move(initial_value); } }, @@ -2317,8 +2279,8 @@ namespace lsp::language::ast::detail { auto member = MakeNode(); member->kind = NodeKind::kClassMember; - member->location = loc; - member->node_type_name = "class_member"; + member->span = loc; + member->access_modifier = current_access; auto method = ParseMethodDeclaration(node, ctx); @@ -2332,8 +2294,8 @@ namespace lsp::language::ast::detail { auto member = MakeNode(); member->kind = NodeKind::kClassMember; - member->location = loc; - member->node_type_name = "class_member"; + member->span = loc; + member->access_modifier = current_access; auto prop = ParsePropertyDeclaration(node, ctx); @@ -2349,35 +2311,51 @@ namespace lsp::language::ast::detail StatementPtr ParseClassDefinition(TSNode node, ParseContext& ctx) { - Location loc = ts::NodeLocation(node); - auto class_def = MakeNode(); class_def->kind = NodeKind::kClassDefinition; - class_def->location = loc; - class_def->node_type_name = "class_definition"; + class_def->span = ts::NodeLocation(node); TSNode name_node = ts_node_child_by_field_name(node, "name", 4); if (!ts_node_is_null(name_node)) + { class_def->name = ts::Text(name_node, ctx.Source()); + class_def->location = ts::NodeLocation(name_node); + } - std::string name = "parent"; uint32_t count = ts_node_child_count(node); for (uint32_t i = 0; i < count; i++) { const char* field = ts_node_field_name_for_child(node, i); - if (!field || name != field) + if (!field || std::string_view(field) != "parent") continue; TSNode parent_node = ts_node_child(node, i); std::string parent_name; std::string_view parent_type = ts_node_type(parent_node); + ClassDefinition::ParentClass parent; if (parent_type == "attribute") - parent_name = ts::Text(parent_node, ctx.Source()); + { + auto attr = ParseAttributeExpression(parent_node, ctx); + auto attr_expr = dynamic_cast(attr.get()); + if (!attr_expr->name.empty()) + { + parent.name = attr_expr->name; + parent.location = attr_expr->location; + } + if (attr_expr->object) + { + auto identifier = dynamic_cast(attr_expr->object.get()); + parent.qualifier = identifier->name; + parent.qualifier_location = identifier->location; + } + } else - parent_name = ts::Text(parent_node, ctx.Source()); - - class_def->parent_classes.push_back(parent_name); + { + parent.name = ts::Text(parent_node, ctx.Source()); + parent.location = ts::NodeLocation(parent_node); + } + class_def->parent_classes.push_back(std::move(parent)); } TSNode body_node = ts_node_child_by_field_name(node, "body", 4); @@ -2439,28 +2417,32 @@ namespace lsp::language::ast::detail StatementPtr ParseExternalMethodStatement(TSNode node, ParseContext& ctx) { - Location loc = ts::NodeLocation(node); - auto ext_method = MakeNode(); ext_method->kind = NodeKind::kExternalMethodDefinition; - ext_method->location = loc; - ext_method->node_type_name = "external_method_definition"; + ext_method->span = ts::NodeLocation(node); TSNode class_node = ts_node_child_by_field_name(node, "class_name", 10); if (!ts_node_is_null(class_node)) - ext_method->owner_class = ts::Text(class_node, ctx.Source()); + { + ext_method->owner_class.name = ts::Text(class_node, ctx.Source()); + ext_method->owner_class.location = ts::NodeLocation(class_node); + } TSNode op_node = ts_node_child_by_field_name(node, "operator", 8); if (!ts_node_is_null(op_node)) { ext_method->is_operator_overload = true; - ext_method->operator_symbol = ts::Text(op_node, ctx.Source()); + ext_method->name = ts::Text(op_node, ctx.Source()); + ext_method->location = ts::NodeLocation(op_node); } else { TSNode method_node = ts_node_child_by_field_name(node, "method_name", 11); if (!ts_node_is_null(method_node)) + { ext_method->name = ts::Text(method_node, ctx.Source()); + ext_method->location = ts::NodeLocation(method_node); + } } uint32_t count = ts_node_child_count(node); diff --git a/lsp-server/src/language/ast/types.hpp b/lsp-server/src/language/ast/types.hpp index cfef51d..8966fe6 100644 --- a/lsp-server/src/language/ast/types.hpp +++ b/lsp-server/src/language/ast/types.hpp @@ -91,6 +91,8 @@ namespace lsp::language::ast kUnpackPattern, kCaseBranch, kClassMember, + + kMatrixIterationStatement, }; // ===== 枚举类型 ===== @@ -300,6 +302,7 @@ namespace lsp::language::ast class ClassDefinition; class UnitDefinition; class TSSQLExpression; + class MatrixIterationStatement; using ASTNodePtr = std::unique_ptr; using ExpressionPtr = std::unique_ptr; @@ -362,6 +365,13 @@ namespace lsp::language::ast virtual void VisitFieldDeclaration(FieldDeclaration& node) = 0; virtual void VisitTSSQLExpression(TSSQLExpression& node) = 0; virtual void VisitUnpackPattern(UnpackPattern& node) = 0; + virtual void VisitMatrixIterationStatement(MatrixIterationStatement& node) = 0; + }; + + struct TypeAnnotation + { + std::string name; + Location location; }; // ===== 基类 ASTNode ===== @@ -373,8 +383,7 @@ namespace lsp::language::ast public: NodeKind kind; - Location location; - std::string node_type_name; + Location span; }; // ===== Expression 基类 ===== @@ -395,6 +404,7 @@ namespace lsp::language::ast public: std::string name; + Location location; }; class Literal : public Expression @@ -405,7 +415,8 @@ namespace lsp::language::ast public: LiteralKind literal_kind; - std::string value; + std::string name; + Location location; }; class BinaryExpression : public Expression @@ -466,8 +477,8 @@ namespace lsp::language::ast struct Argument { std::optional name; + std::optional location; ExpressionPtr value; - bool is_spread = false; }; CallExpression() { kind = NodeKind::kCallExpression; } @@ -485,8 +496,9 @@ namespace lsp::language::ast void Accept(ASTVisitor& visitor) override { visitor.VisitAttributeExpression(*this); } public: + std::string name; + Location location; ExpressionPtr object; - std::string attribute; }; class SubscriptExpression : public Expression @@ -594,7 +606,8 @@ namespace lsp::language::ast public: std::string name; - std::optional type_name; + Location location; + std::optional type; ExpressionPtr initial_value; }; @@ -605,10 +618,11 @@ namespace lsp::language::ast void Accept(ASTVisitor& visitor) override { visitor.VisitStaticDeclaration(*this); } public: - std::string name; - std::optional type_name; - ExpressionPtr initial_value; ReferenceModifier reference_modifier = ReferenceModifier::kNone; + std::string name; + Location location; + std::optional type; + ExpressionPtr initial_value; }; class GlobalDeclaration : public ASTNode @@ -619,7 +633,8 @@ namespace lsp::language::ast public: std::string name; - std::optional type_name; + Location location; + std::optional type; ExpressionPtr initial_value; }; @@ -631,7 +646,7 @@ namespace lsp::language::ast public: std::string name; - std::optional type_name; + std::optional type; ExpressionPtr initial_value; ReferenceModifier reference_modifier = ReferenceModifier::kNone; }; @@ -880,17 +895,17 @@ namespace lsp::language::ast struct Parameter { std::string name; - std::optional type_name; + Location location; + std::optional type; ExpressionPtr default_value; bool is_var = false; bool is_out = false; - Location location; }; struct Signature { std::vector parameters; - std::optional return_type; + std::optional return_type; }; class FunctionDefinition : public Statement @@ -901,6 +916,7 @@ namespace lsp::language::ast public: std::string name; + Location location; Signature signature; StatementPtr body; bool is_overload; @@ -914,6 +930,7 @@ namespace lsp::language::ast public: std::string name; + Location location; Signature signature; bool is_overload; }; @@ -937,13 +954,13 @@ namespace lsp::language::ast public: std::string name; + Location location; Signature signature; StatementPtr body; MethodModifier modifier = MethodModifier::kNone; MethodType method_type = MethodType::kNormal; bool is_class_method = false; bool is_operator_overload = false; - std::string operator_symbol; }; class PropertyDeclaration : public Statement @@ -954,6 +971,7 @@ namespace lsp::language::ast public: std::string name; + Location location; std::optional type_name; std::optional index_value; std::optional read_accessor; @@ -982,9 +1000,19 @@ namespace lsp::language::ast ClassDefinition() { kind = NodeKind::kClassDefinition; } void Accept(ASTVisitor& visitor) override { visitor.VisitClassDefinition(*this); } + struct ParentClass + { + std::optional qualifier; + std::optional qualifier_location; + + std::string name; + Location location; + }; + public: std::string name; - std::vector parent_classes; + Location location; + std::vector parent_classes; std::vector> members; }; @@ -996,6 +1024,7 @@ namespace lsp::language::ast public: std::string name; + Location location; std::vector interface_statements; std::vector implementation_statements; std::vector initialization_statements; @@ -1009,15 +1038,30 @@ namespace lsp::language::ast void Accept(ASTVisitor& visitor) override { visitor.VisitExternalMethodDefinition(*this); } public: - std::string owner_class; + struct + { + std::string name; + Location location; + } owner_class; std::string name; + Location location; Signature signature; StatementPtr body; MethodModifier modifier = MethodModifier::kNone; MethodType method_type = MethodType::kNormal; bool is_operator_overload = false; bool is_class_method = false; - std::string operator_symbol; + }; + + class MatrixIterationStatement : public Statement + { + public: + MatrixIterationStatement() { kind = NodeKind::kMatrixIterationStatement; } + void Accept(ASTVisitor& visitor) override { visitor.VisitMatrixIterationStatement(*this); } + + public: + ExpressionPtr target; + StatementPtr body; }; class Program : public ASTNode diff --git a/lsp-server/test/test_ast/debug_printer.cpp b/lsp-server/test/test_ast/debug_printer.cpp index 900b981..8423da8 100644 --- a/lsp-server/test/test_ast/debug_printer.cpp +++ b/lsp-server/test/test_ast/debug_printer.cpp @@ -1,1869 +1,19 @@ #include -#include +#include #include "./debug_printer.hpp" namespace lsp::language::ast { - // ===== 辅助函数实现 ===== - - const char* DebugPrinter::GetColor(const char* color) const - { - return options_.use_colors ? color : ""; - } - - void DebugPrinter::PrintColored(const std::string& text, const char* color) - { - os_ << GetColor(color) << text << GetColor(Color::Reset); - } - - std::string DebugPrinter::GetIndent() const - { - return std::string(current_indent_, ' '); - } - - void DebugPrinter::PrintIndent(bool is_last) - { - if (options_.use_tree_chars && current_indent_ > 0) - { - PrintTreePrefix(is_last); - } - else - { - os_ << GetIndent(); - } - } - - void DebugPrinter::PrintTreePrefix(bool is_last) - { - std::string prefix; - for (size_t i = 0; i < is_last_child_stack_.size(); ++i) - { - if (is_last_child_stack_[i]) - { - prefix += " "; - } - else - { - prefix += "│ "; - } - } - - if (is_last) - { - prefix += "└── "; - } - else - { - prefix += "├── "; - } - - os_ << GetColor(Color::Gray) << prefix << GetColor(Color::Reset); - } - - std::string DebugPrinter::EscapeString(const std::string& str) const - { - std::string result; - for (char c : str) - { - switch (c) - { - case '\n': - result += "\\n"; - break; - case '\r': - result += "\\r"; - break; - case '\t': - result += "\\t"; - break; - case '\\': - result += "\\\\"; - break; - case '"': - result += "\\\""; - break; - default: - if (c >= 32 && c < 127) - result += c; - else - { - char buf[5]; - snprintf(buf, sizeof(buf), "\\x%02x", static_cast(c)); - result += buf; - } - } - } - return result; - } - - std::string DebugPrinter::TruncateString(const std::string& str, size_t max_len) const - { - if (str.length() <= max_len) - return str; - return str.substr(0, max_len - 3) + "..."; - } - - std::string DebugPrinter::GetSourceText(const Location& loc) const - { - if (!source_code_ || source_code_->empty()) - return ""; - - size_t start = loc.start_byte; - size_t end = loc.end_byte; - - if (start >= source_code_->length() || end > source_code_->length() || start >= end) - return ""; - - std::string text = source_code_->substr(start, end - start); - - // 移除首尾空白 - size_t first = text.find_first_not_of(" \t\n\r"); - if (first == std::string::npos) - return ""; - size_t last = text.find_last_not_of(" \t\n\r"); - text = text.substr(first, last - first + 1); - - // 压缩多个空白为单个空格 - bool prev_space = false; - std::string result; - for (char c : text) - { - if (std::isspace(c)) - { - if (!prev_space) - result += ' '; - prev_space = true; - } - else - { - result += c; - prev_space = false; - } - } - - return TruncateString(result, options_.max_source_length); - } - - void DebugPrinter::PrintLocation(const Location& loc) - { - if (!options_.show_location) - return; - - os_ << GetColor(Color::Gray) << "@"; - os_ << loc.start_line << ":" << loc.start_column; - if (loc.end_line != loc.start_line || loc.end_column != loc.start_column) - { - os_ << "-" << loc.end_line << ":" << loc.end_column; - } - os_ << GetColor(Color::Reset); - } - - void DebugPrinter::PrintSourceSnippet(const Location& loc) - { - if (!options_.show_source_code) - return; - - std::string source = GetSourceText(loc); - if (!source.empty()) - { - os_ << " " << GetColor(Color::Dim) << "«" << source << "»" << GetColor(Color::Reset); - } - } - - void DebugPrinter::PrintNodeHeader(const std::string& type_name, const Location& loc) - { - PrintIndent(); - - // 打印节点类型 - PrintColored(type_name, Color::BrightCyan); - - // 打印位置 - if (options_.show_location || options_.show_source_code) - { - os_ << " "; - PrintLocation(loc); - PrintSourceSnippet(loc); - } - - os_ << "\n"; - } - - void DebugPrinter::PrintKeyValue(const std::string& key, const std::string& value, const char* value_color) - { - if (options_.compact_mode && value.empty()) - return; - - PrintIndent(); - PrintColored(key + ": ", Color::Yellow); - - if (value_color) - PrintColored(value, value_color); - else - os_ << value; - - os_ << "\n"; - } - - void DebugPrinter::PrintKeyValue(const std::string& key, int value) - { - PrintIndent(); - PrintColored(key + ": ", Color::Yellow); - PrintColored(std::to_string(value), Color::BrightGreen); - os_ << "\n"; - } - - void DebugPrinter::PrintKeyValue(const std::string& key, bool value) - { - PrintIndent(); - PrintColored(key + ": ", Color::Yellow); - PrintColored(value ? "true" : "false", value ? Color::Green : Color::Red); - os_ << "\n"; - } - - // ===== 打印主函数 ===== - - void DebugPrinter::Print(const ASTNode* node) - { - if (!node) - { - os_ << GetColor(Color::Red) << "(null)" << GetColor(Color::Reset) << "\n"; - return; - } - const_cast(node)->Accept(*this); - } - - void DebugPrinter::PrintStatements(const std::vector& statements) - { - for (size_t i = 0; i < statements.size(); ++i) - { - if (statements[i]) - { - bool is_last = (i == statements.size() - 1); - if (options_.use_tree_chars) - { - is_last_child_stack_.push_back(is_last); - statements[i]->Accept(*this); - is_last_child_stack_.pop_back(); - } - else - { - statements[i]->Accept(*this); - } - } - } - } - - void DebugPrinter::PrintParseResult(const ParseResult& result) - { - // 打印头部 - PrintColored("╔═══════════════════════════════════════════════════════════════\n", Color::BrightBlue); - PrintColored("║ ", Color::BrightBlue); - PrintColored("AST Parse Result", Color::BrightCyan); - os_ << "\n"; - PrintColored("╠═══════════════════════════════════════════════════════════════\n", Color::BrightBlue); - - // 打印统计信息 - if (result.root) - { - PrintColored("║ ", Color::BrightBlue); - PrintColored("Statements: ", Color::Yellow); - PrintColored(std::to_string(result.root->statements.size()), Color::BrightGreen); - os_ << "\n"; - } - - PrintColored("║ ", Color::BrightBlue); - PrintColored("Errors: ", Color::Yellow); - if (result.errors.empty()) - { - PrintColored("0", Color::Green); - os_ << " "; - PrintColored("✓", Color::BrightGreen); - } - else - { - PrintColored(std::to_string(result.errors.size()), Color::BrightRed); - os_ << " "; - PrintColored("✗", Color::BrightRed); - } - os_ << "\n"; - - PrintColored("╚═══════════════════════════════════════════════════════════════\n", Color::BrightBlue); - - // 打印错误 - if (!result.errors.empty()) - { - os_ << "\n"; - PrintColored("Errors:\n", Color::BrightRed); - for (const auto& error : result.errors) - { - PrintError(error); - } - os_ << "\n"; - } - - // 打印AST - if (result.root) - { - os_ << "\n"; - PrintColored("AST Tree:\n", Color::BrightCyan); - Print(result.root.get()); - } - } - - void DebugPrinter::PrintError(const ParseError& error) - { - PrintIndent(); - - // 错误级别 - const char* severity_color = Color::Red; - std::string severity_text = "ERROR"; - - switch (error.severity) - { - case ErrorSeverity::Warning: - severity_color = Color::Yellow; - severity_text = "WARNING"; - break; - case ErrorSeverity::Fatal: - severity_color = Color::BrightRed; - severity_text = "FATAL"; - break; - default: - break; - } - - PrintColored(severity_text, severity_color); - os_ << " "; - - // 位置 - PrintLocation(error.location); - os_ << " "; - - // 消息 - os_ << error.message << "\n"; - } - - void DebugPrinter::PrintExpression(const Expression* expr, const std::string& label, bool is_last) - { - if (!label.empty()) - { - PrintIndent(); - PrintColored(label + ":\n", Color::Yellow); - } - - IncreaseIndent(); - if (expr) - { - if (options_.use_tree_chars) - { - is_last_child_stack_.push_back(is_last); - const_cast(expr)->Accept(*this); - is_last_child_stack_.pop_back(); - } - else - { - const_cast(expr)->Accept(*this); - } - } - else - { - if (options_.use_tree_chars) - { - is_last_child_stack_.push_back(is_last); - } - PrintIndent(is_last); - PrintColored("(null)", Color::Red); - os_ << "\n"; - if (options_.use_tree_chars) - { - is_last_child_stack_.pop_back(); - } - } - DecreaseIndent(); - } - - void DebugPrinter::PrintStatement(const Statement* stmt, const std::string& label, bool is_last) - { - if (!label.empty()) - { - PrintIndent(); - PrintColored(label + ":\n", Color::Yellow); - } - - IncreaseIndent(); - if (stmt) - { - if (options_.use_tree_chars) - { - is_last_child_stack_.push_back(is_last); - const_cast(stmt)->Accept(*this); - is_last_child_stack_.pop_back(); - } - else - { - const_cast(stmt)->Accept(*this); - } - } - else - { - if (options_.use_tree_chars) - { - is_last_child_stack_.push_back(is_last); - } - PrintIndent(is_last); - PrintColored("(null)", Color::Red); - os_ << "\n"; - if (options_.use_tree_chars) - { - is_last_child_stack_.pop_back(); - } - } - DecreaseIndent(); - } - - void DebugPrinter::PrintSignature(const Signature& sig) - { - if (!sig.parameters.empty()) - { - PrintIndent(); - PrintColored("parameters", Color::Yellow); - PrintColored(" (" + std::to_string(sig.parameters.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - for (size_t i = 0; i < sig.parameters.size(); ++i) - { - bool is_last = (i == sig.parameters.size() - 1); - if (options_.use_tree_chars) - { - is_last_child_stack_.push_back(is_last); - PrintParameter(sig.parameters[i], is_last); - is_last_child_stack_.pop_back(); - } - else - { - PrintParameter(sig.parameters[i], is_last); - } - } - DecreaseIndent(); - } - - if (sig.return_type) - { - PrintKeyValue("return_type", *sig.return_type, Color::BrightMagenta); - } - } - - void DebugPrinter::PrintParameter(const Parameter& param, bool is_last) - { - PrintIndent(is_last); - PrintColored(param.name, Color::BrightGreen); - - if (param.is_var) - os_ << " " << GetColor(Color::Cyan) << "[var]" << GetColor(Color::Reset); - if (param.is_out) - os_ << " " << GetColor(Color::Cyan) << "[out]" << GetColor(Color::Reset); - - if (param.type_name) - os_ << GetColor(Color::Gray) << ": " << GetColor(Color::BrightMagenta) - << *param.type_name << GetColor(Color::Reset); - - if (param.default_value) - { - os_ << " " << GetColor(Color::Gray) << "= " << GetColor(Color::Reset); - os_ << "..."; // 简化显示 - } - - os_ << "\n"; - } - - void DebugPrinter::PrintLeftHandSide(const LeftHandSide& lhs, const std::string& label, bool is_last) - { - if (!label.empty()) - { - PrintIndent(); - PrintColored(label + ":\n", Color::Yellow); - IncreaseIndent(); - } - - if (options_.use_tree_chars) - { - is_last_child_stack_.push_back(is_last); - } - - std::visit([this](auto&& arg) { - using T = std::decay_t; - if constexpr (std::is_same_v> || - std::is_same_v> || - std::is_same_v> || - std::is_same_v> || - std::is_same_v> || - std::is_same_v> || - std::is_same_v> || - std::is_same_v>) - { - if (arg) - { - arg->Accept(*this); - } - else - { - PrintIndent(); - PrintColored("(null)", Color::Red); - os_ << "\n"; - } - } - }, - lhs); - - if (options_.use_tree_chars) - { - is_last_child_stack_.pop_back(); - } - - if (!label.empty()) - { - DecreaseIndent(); - } - } - - // ===== 枚举打印实现 ===== - - void DebugPrinter::PrintOperator(BinaryOperator op) - { - PrintColored(GetBinaryOperatorSymbol(op), Color::BrightYellow); - } - - void DebugPrinter::PrintOperator(UnaryOperator op) - { - const char* symbol = ""; - switch (op) - { - case UnaryOperator::kPlus: - symbol = "+"; - break; - case UnaryOperator::kMinus: - symbol = "-"; - break; - case UnaryOperator::kNot: - symbol = "not"; - break; - case UnaryOperator::kBitwiseNot: - symbol = ".!"; - break; - case UnaryOperator::kDotNot: - symbol = ".!!"; - break; - case UnaryOperator::kMatrixTranspose: - symbol = "`"; - break; - case UnaryOperator::kDerivative: - symbol = "!"; - break; - case UnaryOperator::kExprAt: - symbol = "@"; - break; - case UnaryOperator::kExprRef: - symbol = "&"; - break; - } - PrintColored(symbol, Color::BrightYellow); - } - - void DebugPrinter::PrintOperator(AssignmentOperator op) - { - PrintColored(GetAssignmentOperatorSymbol(op), Color::BrightYellow); - } - - void DebugPrinter::PrintLiteralKind(LiteralKind kind) - { - const char* kind_str = ""; - const char* color = Color::Magenta; - - switch (kind) - { - case LiteralKind::kNumber: - kind_str = "number"; - break; - case LiteralKind::kString: - kind_str = "string"; - color = Color::Green; - break; - case LiteralKind::kBoolean: - kind_str = "boolean"; - break; - case LiteralKind::kNil: - kind_str = "nil"; - color = Color::Gray; - break; - case LiteralKind::kInfinity: - kind_str = "infinity"; - break; - case LiteralKind::kEllipsis: - kind_str = "ellipsis"; - break; - } - - PrintColored(kind_str, color); - } - - void DebugPrinter::PrintAccessModifier(AccessModifier modifier) - { - const char* mod_str = ""; - const char* color = Color::Cyan; - - switch (modifier) - { - case AccessModifier::kPublic: - mod_str = "public"; - break; - case AccessModifier::kProtected: - mod_str = "protected"; - color = Color::Yellow; - break; - case AccessModifier::kPrivate: - mod_str = "private"; - color = Color::Red; - break; - } - - PrintColored(mod_str, color); - } - - void DebugPrinter::PrintMethodModifier(MethodModifier modifier) - { - const char* mod_str = ""; - - switch (modifier) - { - case MethodModifier::kNone: - mod_str = "none"; - break; - case MethodModifier::kVirtual: - mod_str = "virtual"; - break; - case MethodModifier::kOverride: - mod_str = "override"; - break; - case MethodModifier::kOverload: - mod_str = "overload"; - break; - } - - PrintColored(mod_str, Color::Magenta); - } - - void DebugPrinter::PrintReferenceModifier(ReferenceModifier modifier) - { - const char* mod_str = ""; - - switch (modifier) - { - case ReferenceModifier::kNone: - mod_str = "none"; - break; - case ReferenceModifier::kWeakRef: - mod_str = "weakref"; - break; - case ReferenceModifier::kAutoRef: - mod_str = "autoref"; - break; - } - - PrintColored(mod_str, Color::Cyan); - } - - // ===== Visitor 实现 ===== - - void DebugPrinter::VisitProgram(Program& node) - { - PrintNodeHeader("Program", node.location); - - if (!node.statements.empty()) - { - IncreaseIndent(); - PrintIndent(); - PrintColored("statements ", Color::Yellow); - PrintColored("(" + std::to_string(node.statements.size()) + "):\n", Color::Gray); - IncreaseIndent(); - PrintStatements(node.statements); - DecreaseIndent(); - DecreaseIndent(); - } - } - - void DebugPrinter::VisitIdentifier(Identifier& node) - { - PrintNodeHeader("Identifier", node.location); - IncreaseIndent(); - PrintKeyValue("name", node.name, Color::BrightGreen); - DecreaseIndent(); - } - - void DebugPrinter::VisitLiteral(Literal& node) - { - PrintNodeHeader("Literal", node.location); - IncreaseIndent(); - - PrintIndent(); - PrintColored("kind: ", Color::Yellow); - PrintLiteralKind(node.literal_kind); - os_ << "\n"; - - PrintIndent(); - PrintColored("value: ", Color::Yellow); - - if (node.literal_kind == LiteralKind::kString) - { - PrintColored("\"" + EscapeString(node.value) + "\"", Color::Green); - } - else - { - PrintColored(node.value, Color::BrightGreen); - } - os_ << "\n"; - - DecreaseIndent(); - } - - void DebugPrinter::VisitBinaryExpression(BinaryExpression& node) - { - PrintNodeHeader("BinaryExpression", node.location); - IncreaseIndent(); - - PrintIndent(); - PrintColored("operator: ", Color::Yellow); - PrintOperator(node.op); - os_ << "\n"; - - PrintExpression(node.left.get(), "left", false); - PrintExpression(node.right.get(), "right", true); - - DecreaseIndent(); - } - - void DebugPrinter::VisitComparisonExpression(ComparisonExpression& node) - { - PrintNodeHeader("ComparisonExpression", node.location); - IncreaseIndent(); - - PrintExpression(node.left.get(), "left", false); - - if (!node.comparisons.empty()) - { - PrintIndent(); - PrintColored("comparisons ", Color::Yellow); - PrintColored("(" + std::to_string(node.comparisons.size()) + "):\n", Color::Gray); - IncreaseIndent(); - - for (size_t i = 0; i < node.comparisons.size(); ++i) - { - const auto& comp = node.comparisons[i]; - PrintIndent(); - PrintColored("[" + std::to_string(i) + "] ", Color::Gray); - PrintOperator(comp.op); - os_ << "\n"; - - if (comp.right) - { - IncreaseIndent(); - PrintExpression(comp.right.get()); - DecreaseIndent(); - } - } - DecreaseIndent(); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitUnaryExpression(UnaryExpression& node) - { - PrintNodeHeader("UnaryExpression", node.location); - IncreaseIndent(); - - PrintIndent(); - PrintColored("operator: ", Color::Yellow); - PrintOperator(node.op); - os_ << "\n"; - - PrintExpression(node.argument.get(), "argument", true); - - DecreaseIndent(); - } - - void DebugPrinter::VisitTernaryExpression(TernaryExpression& node) - { - PrintNodeHeader("TernaryExpression", node.location); - IncreaseIndent(); - - PrintExpression(node.condition.get(), "condition", false); - PrintExpression(node.consequence.get(), "consequence", false); - PrintExpression(node.alternative.get(), "alternative", true); - - DecreaseIndent(); - } - - void DebugPrinter::VisitCallExpression(CallExpression& node) - { - PrintNodeHeader("CallExpression", node.location); - IncreaseIndent(); - - bool has_arguments = !node.arguments.empty(); - PrintExpression(node.callee.get(), "callee", !has_arguments); - - if (has_arguments) - { - PrintIndent(); - PrintColored("arguments ", Color::Yellow); - PrintColored("(" + std::to_string(node.arguments.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - for (size_t i = 0; i < node.arguments.size(); ++i) - { - const auto& arg = node.arguments[i]; - bool is_last = (i == node.arguments.size() - 1); - - if (options_.use_tree_chars) - { - is_last_child_stack_.push_back(is_last); - } - - PrintIndent(is_last); - PrintColored("[" + std::to_string(i) + "]", Color::Gray); - - if (arg.name) - { - os_ << " " << GetColor(Color::Yellow) << *arg.name << GetColor(Color::Reset) << ":"; - } - if (arg.is_spread) - { - os_ << " " << GetColor(Color::Magenta) << "..." << GetColor(Color::Reset); - } - os_ << "\n"; - - if (arg.value) - { - IncreaseIndent(); - arg.value->Accept(*this); - DecreaseIndent(); - } - - if (options_.use_tree_chars) - { - is_last_child_stack_.pop_back(); - } - } - DecreaseIndent(); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitAttributeExpression(AttributeExpression& node) - { - PrintNodeHeader("AttributeExpression", node.location); - IncreaseIndent(); - - PrintExpression(node.object.get(), "object", false); - PrintKeyValue("attribute", node.attribute, Color::BrightGreen); - - DecreaseIndent(); - } - - void DebugPrinter::VisitSubscriptExpression(SubscriptExpression& node) - { - PrintNodeHeader("SubscriptExpression", node.location); - IncreaseIndent(); - - PrintExpression(node.value.get(), "value"); - - if (!node.indices.empty()) - { - PrintIndent(); - PrintColored("indices ", Color::Yellow); - PrintColored("(" + std::to_string(node.indices.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - for (size_t i = 0; i < node.indices.size(); ++i) - { - const auto& idx = node.indices[i]; - PrintIndent(); - PrintColored("[" + std::to_string(i) + "]", Color::Gray); - - if (idx.is_slice) - { - os_ << " " << GetColor(Color::Cyan) << "[slice]" << GetColor(Color::Reset); - } - if (idx.is_empty_slice) - { - os_ << " " << GetColor(Color::Cyan) << "[empty]" << GetColor(Color::Reset); - } - os_ << "\n"; - - IncreaseIndent(); - if (idx.start) - { - PrintExpression(idx.start.get(), "start"); - } - if (idx.end) - { - PrintExpression(idx.end.get(), "end"); - } - if (idx.step) - { - PrintExpression(idx.step.get(), "step"); - } - DecreaseIndent(); - } - DecreaseIndent(); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitArrayExpression(ArrayExpression& node) - { - PrintNodeHeader("ArrayExpression", node.location); - IncreaseIndent(); - - if (!node.elements.empty()) - { - PrintIndent(); - PrintColored("elements ", Color::Yellow); - PrintColored("(" + std::to_string(node.elements.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - for (size_t i = 0; i < node.elements.size(); ++i) - { - const auto& elem = node.elements[i]; - PrintIndent(); - PrintColored("[" + std::to_string(i) + "]", Color::Gray); - - if (elem.is_nested) - { - os_ << " " << GetColor(Color::Cyan) << "[nested]" << GetColor(Color::Reset); - } - os_ << "\n"; - - IncreaseIndent(); - if (elem.key) - { - PrintExpression(elem.key.get(), "key"); - } - if (elem.value) - { - PrintExpression(elem.value.get(), "value"); - } - DecreaseIndent(); - } - DecreaseIndent(); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitAnonymousFunctionExpression(AnonymousFunctionExpression& node) - { - PrintNodeHeader("AnonymousFunction", node.location); - IncreaseIndent(); - - PrintSignature(node.signature); - - if (node.body) - { - PrintStatement(node.body.get(), "body", true); - PrintStatement(node.body.get(), "body", true); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitPrefixIncrementExpression(PrefixIncrementExpression& node) - { - PrintNodeHeader("PrefixIncrement", node.location); - IncreaseIndent(); - PrintExpression(node.argument.get(), "argument", true); - DecreaseIndent(); - } - - void DebugPrinter::VisitPrefixDecrementExpression(PrefixDecrementExpression& node) - { - PrintNodeHeader("PrefixDecrement", node.location); - IncreaseIndent(); - PrintExpression(node.argument.get(), "argument", true); - DecreaseIndent(); - } - - void DebugPrinter::VisitPostfixIncrementExpression(PostfixIncrementExpression& node) - { - PrintNodeHeader("PostfixIncrement", node.location); - IncreaseIndent(); - PrintExpression(node.argument.get(), "argument", true); - DecreaseIndent(); - } - - void DebugPrinter::VisitPostfixDecrementExpression(PostfixDecrementExpression& node) - { - PrintNodeHeader("PostfixDecrement", node.location); - IncreaseIndent(); - PrintExpression(node.argument.get(), "argument", true); - DecreaseIndent(); - } - - void DebugPrinter::VisitFunctionPointerExpression(FunctionPointerExpression& node) - { - PrintNodeHeader("FunctionPointer", node.location); - IncreaseIndent(); - PrintExpression(node.argument.get(), "argument", true); - DecreaseIndent(); - } - - void DebugPrinter::VisitAssignmentExpression(AssignmentExpression& node) - { - PrintNodeHeader("AssignmentExpression", node.location); - IncreaseIndent(); - - PrintIndent(); - PrintColored("operator: ", Color::Yellow); - PrintOperator(node.op); - os_ << "\n"; - - PrintLeftHandSide(node.left, "left", false); - PrintExpression(node.right.get(), "right", true); - - DecreaseIndent(); - } - - void DebugPrinter::VisitExpressionStatement(ExpressionStatement& node) - { - PrintNodeHeader("ExpressionStatement", node.location); - IncreaseIndent(); - PrintExpression(node.expression.get(), "", true); - DecreaseIndent(); - } - - void DebugPrinter::VisitVarStatement(VarStatement& node) - { - PrintNodeHeader("VarStatement", node.location); - IncreaseIndent(); - - if (!node.declarations.empty()) - { - PrintIndent(); - PrintColored("declarations ", Color::Yellow); - PrintColored("(" + std::to_string(node.declarations.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - for (size_t i = 0; i < node.declarations.size(); ++i) - { - bool is_last = (i == node.declarations.size() - 1); - if (node.declarations[i]) - { - if (options_.use_tree_chars) - { - is_last_child_stack_.push_back(is_last); - node.declarations[i]->Accept(*this); - is_last_child_stack_.pop_back(); - } - else - { - node.declarations[i]->Accept(*this); - } - } - } - DecreaseIndent(); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitStaticStatement(StaticStatement& node) - { - PrintNodeHeader("StaticStatement", node.location); - IncreaseIndent(); - - if (!node.declarations.empty()) - { - PrintIndent(); - PrintColored("declarations ", Color::Yellow); - PrintColored("(" + std::to_string(node.declarations.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - for (size_t i = 0; i < node.declarations.size(); ++i) - { - bool is_last = (i == node.declarations.size() - 1); - if (node.declarations[i]) - { - if (options_.use_tree_chars) - { - is_last_child_stack_.push_back(is_last); - node.declarations[i]->Accept(*this); - is_last_child_stack_.pop_back(); - } - else - { - node.declarations[i]->Accept(*this); - } - } - } - DecreaseIndent(); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitGlobalStatement(GlobalStatement& node) - { - PrintNodeHeader("GlobalStatement", node.location); - IncreaseIndent(); - - if (!node.declarations.empty()) - { - PrintIndent(); - PrintColored("declarations ", Color::Yellow); - PrintColored("(" + std::to_string(node.declarations.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - for (size_t i = 0; i < node.declarations.size(); ++i) - { - bool is_last = (i == node.declarations.size() - 1); - if (node.declarations[i]) - { - if (options_.use_tree_chars) - { - is_last_child_stack_.push_back(is_last); - node.declarations[i]->Accept(*this); - is_last_child_stack_.pop_back(); - } - else - { - node.declarations[i]->Accept(*this); - } - } - } - DecreaseIndent(); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitConstStatement(ConstStatement& node) - { - PrintNodeHeader("ConstStatement", node.location); - IncreaseIndent(); - - PrintKeyValue("name", node.name, Color::BrightGreen); - - if (node.type_name) - { - PrintKeyValue("type", *node.type_name, Color::BrightMagenta); - } - - if (node.value) - { - PrintExpression(node.value.get(), "value", true); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitAssignmentStatement(AssignmentStatement& node) - { - PrintNodeHeader("AssignmentStatement", node.location); - IncreaseIndent(); - - PrintIndent(); - PrintColored("operator: ", Color::Yellow); - PrintOperator(node.op); - os_ << "\n"; - - PrintLeftHandSide(node.left, "left", false); - PrintExpression(node.right.get(), "right", true); - - DecreaseIndent(); - } - - void DebugPrinter::VisitBlockStatement(BlockStatement& node) - { - PrintNodeHeader("BlockStatement", node.location); - - if (!node.statements.empty()) - { - IncreaseIndent(); - PrintStatements(node.statements); - DecreaseIndent(); - } - } - - void DebugPrinter::VisitIfStatement(IfStatement& node) - { - PrintNodeHeader("IfStatement", node.location); - IncreaseIndent(); - - if (!node.branches.empty()) - { - PrintIndent(); - PrintColored("branches ", Color::Yellow); - PrintColored("(" + std::to_string(node.branches.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - for (size_t i = 0; i < node.branches.size(); ++i) - { - const auto& branch = node.branches[i]; - PrintIndent(); - PrintColored("[" + std::to_string(i) + "]", Color::Gray); - os_ << "\n"; - - IncreaseIndent(); - if (branch.condition) - { - PrintExpression(branch.condition.get(), "condition"); - } - if (branch.body) - { - PrintStatement(branch.body.get(), "body"); - } - DecreaseIndent(); - } - DecreaseIndent(); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitForInStatement(ForInStatement& node) - { - PrintNodeHeader("ForInStatement", node.location); - IncreaseIndent(); - - if (!node.key.empty()) - { - PrintKeyValue("key", node.key, Color::BrightGreen); - } - if (!node.value.empty()) - { - PrintKeyValue("value", node.value, Color::BrightGreen); - } - - PrintExpression(node.collection.get(), "collection", false); - - if (node.body) - { - PrintStatement(node.body.get(), "body", true); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitForToStatement(ForToStatement& node) - { - PrintNodeHeader("ForToStatement", node.location); - IncreaseIndent(); - - PrintKeyValue("counter", node.counter, Color::BrightGreen); - - if (node.is_downto) - { - PrintKeyValue("direction", "downto", Color::Cyan); - } - - PrintExpression(node.start.get(), "start", false); - PrintExpression(node.end.get(), "end", false); - - if (node.body) - { - PrintStatement(node.body.get(), "body", true); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitWhileStatement(WhileStatement& node) - { - PrintNodeHeader("WhileStatement", node.location); - IncreaseIndent(); - - PrintExpression(node.condition.get(), "condition", false); - - if (node.body) - { - PrintStatement(node.body.get(), "body", true); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitRepeatStatement(RepeatStatement& node) - { - PrintNodeHeader("RepeatStatement", node.location); - IncreaseIndent(); - - if (!node.body.empty()) - { - PrintIndent(); - PrintColored("body ", Color::Yellow); - PrintColored("(" + std::to_string(node.body.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - PrintStatements(node.body); - DecreaseIndent(); - } - - PrintExpression(node.condition.get(), "condition", true); - - DecreaseIndent(); - } - - void DebugPrinter::VisitCaseStatement(CaseStatement& node) - { - PrintNodeHeader("CaseStatement", node.location); - IncreaseIndent(); - - PrintExpression(node.discriminant.get(), "discriminant"); - - if (!node.branches.empty()) - { - PrintIndent(); - PrintColored("branches ", Color::Yellow); - PrintColored("(" + std::to_string(node.branches.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - for (size_t i = 0; i < node.branches.size(); ++i) - { - const auto& branch = node.branches[i]; - PrintIndent(); - PrintColored("[" + std::to_string(i) + "]", Color::Gray); - os_ << "\n"; - - IncreaseIndent(); - if (!branch.values.empty()) - { - PrintIndent(); - PrintColored("values ", Color::Yellow); - PrintColored("(" + std::to_string(branch.values.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - for (const auto& val : branch.values) - { - if (val) - val->Accept(*this); - } - DecreaseIndent(); - } - - if (branch.body) - { - PrintStatement(branch.body.get(), "body"); - } - DecreaseIndent(); - } - DecreaseIndent(); - } - - if (node.default_case) - { - PrintStatement(node.default_case.get(), "default_case"); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitTryStatement(TryStatement& node) - { - PrintNodeHeader("TryStatement", node.location); - IncreaseIndent(); - - if (node.try_body) - { - PrintStatement(node.try_body.get(), "try_body"); - } - - if (node.except_body) - { - PrintStatement(node.except_body.get(), "except_body"); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitBreakStatement(BreakStatement& node) - { - PrintNodeHeader("BreakStatement", node.location); - } - - void DebugPrinter::VisitContinueStatement(ContinueStatement& node) - { - PrintNodeHeader("ContinueStatement", node.location); - } - - void DebugPrinter::VisitReturnStatement(ReturnStatement& node) - { - PrintNodeHeader("ReturnStatement", node.location); - - if (node.value) - { - IncreaseIndent(); - PrintExpression(node.value.get(), "value", true); - DecreaseIndent(); - } - } - - void DebugPrinter::VisitUsesStatement(UsesStatement& node) - { - PrintNodeHeader("UsesStatement", node.location); - IncreaseIndent(); - - if (!node.units.empty()) - { - PrintIndent(); - PrintColored("units: ", Color::Yellow); - os_ << "["; - for (size_t i = 0; i < node.units.size(); ++i) - { - if (i > 0) - os_ << ", "; - PrintColored(node.units[i], Color::BrightGreen); - } - os_ << "]\n"; - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitFunctionDefinition(FunctionDefinition& node) - { - PrintNodeHeader("FunctionDefinition", node.location); - IncreaseIndent(); - - PrintKeyValue("name", node.name, Color::BrightCyan); - - if (node.is_overload) - { - PrintKeyValue("overload", true); - } - - PrintSignature(node.signature); - - if (node.body) - { - PrintStatement(node.body.get(), "body", true); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitFunctionDeclaration(FunctionDeclaration& node) - { - PrintNodeHeader("FunctionDeclaration", node.location); - IncreaseIndent(); - - PrintKeyValue("name", node.name, Color::BrightCyan); - - if (node.is_overload) - { - PrintKeyValue("overload", true); - } - - PrintSignature(node.signature); - - DecreaseIndent(); - } - - void DebugPrinter::VisitVarDeclaration(VarDeclaration& node) - { - PrintNodeHeader("VarDeclaration", node.location); - IncreaseIndent(); - - PrintKeyValue("name", node.name, Color::BrightGreen); - - if (node.type_name) - { - PrintKeyValue("type", *node.type_name, Color::BrightMagenta); - } - - if (node.initial_value) - { - PrintExpression(node.initial_value.get(), "initial_value"); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitStaticDeclaration(StaticDeclaration& node) - { - PrintNodeHeader("StaticDeclaration", node.location); - IncreaseIndent(); - - PrintKeyValue("name", node.name, Color::BrightGreen); - - if (node.reference_modifier != ReferenceModifier::kNone) - { - PrintIndent(); - PrintColored("reference: ", Color::Yellow); - PrintReferenceModifier(node.reference_modifier); - os_ << "\n"; - } - - if (node.type_name) - { - PrintKeyValue("type", *node.type_name, Color::BrightMagenta); - } - - if (node.initial_value) - { - PrintExpression(node.initial_value.get(), "initial_value"); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitGlobalDeclaration(GlobalDeclaration& node) - { - PrintNodeHeader("GlobalDeclaration", node.location); - IncreaseIndent(); - - PrintKeyValue("name", node.name, Color::BrightGreen); - - if (node.type_name) - { - PrintKeyValue("type", *node.type_name, Color::BrightMagenta); - } - - if (node.initial_value) - { - PrintExpression(node.initial_value.get(), "initial_value"); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitFieldDeclaration(FieldDeclaration& node) - { - PrintNodeHeader("FieldDeclaration", node.location); - IncreaseIndent(); - - PrintKeyValue("name", node.name, Color::BrightGreen); - - if (node.reference_modifier != ReferenceModifier::kNone) - { - PrintIndent(); - PrintColored("reference: ", Color::Yellow); - PrintReferenceModifier(node.reference_modifier); - os_ << "\n"; - } - - if (node.type_name) - { - PrintKeyValue("type", *node.type_name, Color::BrightMagenta); - } - - if (node.initial_value) - { - PrintExpression(node.initial_value.get(), "initial_value"); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitUnpackPattern(UnpackPattern& node) - { - PrintNodeHeader("UnpackPattern", node.location); - IncreaseIndent(); - - if (!node.names.empty()) - { - PrintIndent(); - PrintColored("names: ", Color::Yellow); - os_ << "["; - for (size_t i = 0; i < node.names.size(); ++i) - { - if (i > 0) - os_ << ", "; - PrintColored(node.names[i], Color::BrightGreen); - } - os_ << "]\n"; - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitClassDefinition(ClassDefinition& node) - { - PrintNodeHeader("ClassDefinition", node.location); - IncreaseIndent(); - - PrintKeyValue("name", node.name, Color::BrightCyan); - - if (!node.parent_classes.empty()) - { - PrintIndent(); - PrintColored("parents: ", Color::Yellow); - os_ << "["; - for (size_t i = 0; i < node.parent_classes.size(); ++i) - { - if (i > 0) - os_ << ", "; - PrintColored(node.parent_classes[i], Color::BrightCyan); - } - os_ << "]\n"; - } - - if (!node.members.empty()) - { - PrintIndent(); - PrintColored("members ", Color::Yellow); - PrintColored("(" + std::to_string(node.members.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - for (const auto& member : node.members) - { - if (member) - member->Accept(*this); - } - DecreaseIndent(); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitClassMember(ClassMember& node) - { - PrintNodeHeader("ClassMember", node.location); - IncreaseIndent(); - - PrintIndent(); - PrintColored("access: ", Color::Yellow); - PrintAccessModifier(node.access_modifier); - os_ << "\n"; - - std::visit([this](auto&& member) { - if (member) - { - member->Accept(*this); - } - }, - node.member); - - DecreaseIndent(); - } - - void DebugPrinter::VisitMethodDeclaration(MethodDeclaration& node) - { - PrintNodeHeader("MethodDeclaration", node.location); - IncreaseIndent(); - - PrintKeyValue("name", node.name, Color::BrightCyan); - - if (node.method_type == MethodType::kConstructor) - { - PrintKeyValue("type", "constructor", Color::Magenta); - } - else if (node.method_type == MethodType::kDestructor) - { - PrintKeyValue("type", "destructor", Color::Magenta); - } - - if (node.is_class_method) - { - PrintKeyValue("class_method", true); - } - - if (node.is_operator_overload) - { - PrintKeyValue("operator", node.operator_symbol, Color::BrightYellow); - } - - if (node.modifier != MethodModifier::kNone) - { - PrintIndent(); - PrintColored("modifier: ", Color::Yellow); - PrintMethodModifier(node.modifier); - os_ << "\n"; - } - - PrintSignature(node.signature); - - if (node.body) - { - PrintStatement(node.body.get(), "body", true); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitPropertyDeclaration(PropertyDeclaration& node) - { - PrintNodeHeader("PropertyDeclaration", node.location); - IncreaseIndent(); - - PrintKeyValue("name", node.name, Color::BrightCyan); - - if (node.type_name) - { - PrintKeyValue("type", *node.type_name, Color::BrightMagenta); - } - - if (node.index_value) - { - PrintKeyValue("index", *node.index_value); - } - - if (node.read_accessor) - { - PrintKeyValue("read", *node.read_accessor, Color::Green); - } - - if (node.write_accessor) - { - PrintKeyValue("write", *node.write_accessor, Color::Green); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitExternalMethodDefinition(ExternalMethodDefinition& node) - { - PrintNodeHeader("ExternalMethodDefinition", node.location); - IncreaseIndent(); - - PrintKeyValue("class", node.owner_class, Color::BrightCyan); - PrintKeyValue("method", node.name, Color::BrightCyan); - - if (node.method_type == MethodType::kConstructor) - { - PrintKeyValue("type", "constructor", Color::Magenta); - } - else if (node.method_type == MethodType::kDestructor) - { - PrintKeyValue("type", "destructor", Color::Magenta); - } - - if (node.is_class_method) - { - PrintKeyValue("class_method", true); - } - - if (node.is_operator_overload) - { - PrintKeyValue("operator", node.operator_symbol, Color::BrightYellow); - } - - if (node.modifier != MethodModifier::kNone) - { - PrintIndent(); - PrintColored("modifier: ", Color::Yellow); - PrintMethodModifier(node.modifier); - os_ << "\n"; - } - - PrintSignature(node.signature); - - if (node.body) - { - PrintStatement(node.body.get(), "body", true); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitUnitDefinition(UnitDefinition& node) - { - PrintNodeHeader("UnitDefinition", node.location); - IncreaseIndent(); - - PrintKeyValue("name", node.name, Color::BrightCyan); - - if (!node.interface_statements.empty()) - { - PrintIndent(); - PrintColored("interface ", Color::Yellow); - PrintColored("(" + std::to_string(node.interface_statements.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - PrintStatements(node.interface_statements); - DecreaseIndent(); - } - - if (!node.implementation_statements.empty()) - { - PrintIndent(); - PrintColored("implementation ", Color::Yellow); - PrintColored("(" + std::to_string(node.implementation_statements.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - PrintStatements(node.implementation_statements); - DecreaseIndent(); - } - - if (!node.initialization_statements.empty()) - { - PrintIndent(); - PrintColored("initialization ", Color::Yellow); - PrintColored("(" + std::to_string(node.initialization_statements.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - PrintStatements(node.initialization_statements); - DecreaseIndent(); - } - - if (!node.finalization_statements.empty()) - { - PrintIndent(); - PrintColored("finalization ", Color::Yellow); - PrintColored("(" + std::to_string(node.finalization_statements.size()) + "):\n", Color::Gray); - - IncreaseIndent(); - PrintStatements(node.finalization_statements); - DecreaseIndent(); - } - - DecreaseIndent(); - } - - void DebugPrinter::VisitTSSQLExpression(TSSQLExpression& node) - { - PrintNodeHeader("TSSQLExpression", node.location); - IncreaseIndent(); - - const char* type_str = ""; - switch (node.sql_type) - { - case TSSQLExpressionType::kSelect: - type_str = "SELECT"; - break; - case TSSQLExpressionType::kSSelect: - type_str = "SSELECT"; - break; - case TSSQLExpressionType::kVSelect: - type_str = "VSELECT"; - break; - case TSSQLExpressionType::kMSelect: - type_str = "MSELECT"; - break; - case TSSQLExpressionType::kUpdate: - type_str = "UPDATE"; - break; - case TSSQLExpressionType::kDelete: - type_str = "DELETE"; - break; - case TSSQLExpressionType::kInsert: - type_str = "INSERT"; - break; - } - - PrintKeyValue("sql_type", type_str, Color::BrightMagenta); - PrintKeyValue("raw_sql", node.raw_sql, Color::Green); - - DecreaseIndent(); - } - // ===== 便捷函数实现 ===== std::string DebugString(const ASTNode* node, const PrintOptions& opts) { std::ostringstream oss; DebugPrinter printer(oss, opts); - printer.Print(node); + if (node) + { + printer.Print(node); + } return oss.str(); } @@ -1878,7 +28,10 @@ namespace lsp::language::ast void DebugPrint(const ASTNode* node, const PrintOptions& opts) { DebugPrinter printer(std::cout, opts); - printer.Print(node); + if (node) + { + printer.Print(node); + } } void DebugPrint(const ParseResult& result, const PrintOptions& opts) @@ -1891,7 +44,10 @@ namespace lsp::language::ast { DebugPrinter printer(std::cout, opts); printer.SetSourceCode(&source); - printer.Print(node); + if (node) + { + printer.Print(node); + } } void DebugPrint(const ParseResult& result, const std::string& source, const PrintOptions& opts) @@ -1900,4 +56,1646 @@ namespace lsp::language::ast printer.SetSourceCode(&source); printer.PrintParseResult(result); } + + // ===== DebugPrinter 主要方法 ===== + + void DebugPrinter::Print(const ASTNode* node) + { + if (!node) + { + os_ << GetColor(Color::Red) << "nullptr" << GetColor(Color::Reset) << "\n"; + return; + } + + const_cast(node)->Accept(*this); + } + + void DebugPrinter::PrintStatements(const std::vector& statements) + { + if (statements.empty()) + { + PrintColored("(empty)", Color::Gray); + os_ << "\n"; + return; + } + + for (size_t i = 0; i < statements.size(); ++i) + { + bool is_last = (i == statements.size() - 1); + PrintStatement(statements[i].get(), "", is_last); + } + } + + void DebugPrinter::PrintParseResult(const ParseResult& result) + { + PrintColored("=== Parse Result ===", Color::BrightCyan); + os_ << "\n\n"; + + if (result.root) + { + Print(result.root.get()); + } + else + { + PrintColored("No root node", Color::Red); + os_ << "\n"; + } + + if (!result.errors.empty()) + { + os_ << "\n"; + PrintColored("=== Errors ===", Color::BrightRed); + os_ << "\n"; + for (const auto& error : result.errors) + { + PrintError(error); + } + } + } + + // ===== 辅助方法实现 ===== + + void DebugPrinter::PrintIndent(bool is_last) + { + if (!options_.use_tree_chars) + { + os_ << std::string(current_indent_, ' '); + return; + } + + PrintTreePrefix(is_last); + } + + void DebugPrinter::PrintTreePrefix(bool is_last) + { + int depth = current_indent_ / options_.indent_size; + for (int i = 0; i < depth - 1; ++i) + { + if (i < static_cast(is_last_child_stack_.size()) && is_last_child_stack_[i]) + { + os_ << " "; + } + else + { + os_ << "│ "; + } + } + + if (depth > 0) + { + if (is_last) + { + os_ << "└── "; + } + else + { + os_ << "├── "; + } + } + } + + std::string DebugPrinter::GetIndent() const + { + return std::string(current_indent_, ' '); + } + + const char* DebugPrinter::GetColor(const char* color) const + { + return options_.use_colors ? color : ""; + } + + void DebugPrinter::PrintColored(const std::string& text, const char* color) + { + if (color) + { + os_ << GetColor(color); + } + os_ << text; + if (color) + { + os_ << GetColor(Color::Reset); + } + } + + void DebugPrinter::PrintNodeHeader(const std::string& type_name, const Location& loc) + { + PrintColored(type_name, Color::BrightYellow); + + if (options_.show_location) + { + os_ << " "; + PrintLocation(loc); + } + + if (options_.show_source_code && source_code_) + { + os_ << " "; + PrintSourceSnippet(loc); + } + + os_ << "\n"; + } + + void DebugPrinter::PrintLocation(const Location& loc) + { + os_ << GetColor(Color::Gray) << "@" + << loc.start_line << ":" << loc.start_column + << "-" << loc.end_line << ":" << loc.end_column + << GetColor(Color::Reset); + } + + void DebugPrinter::PrintSourceSnippet(const Location& loc) + { + if (!source_code_ || loc.start_byte >= source_code_->length()) + { + return; + } + + std::string snippet = GetSourceText(loc); + snippet = TruncateString(snippet, options_.max_source_length); + snippet = EscapeString(snippet); + + os_ << GetColor(Color::Cyan) << "«" << snippet << "»" << GetColor(Color::Reset); + } + + void DebugPrinter::PrintKeyValue(const std::string& key, const std::string& value, + const Location& location, const char* value_color) + { + PrintIndent(); + PrintColored(key, Color::Green); + os_ << ": "; + PrintColored(value, value_color); + + if (options_.show_location) + { + os_ << " "; + PrintLocation(location); + } + + os_ << "\n"; + } + + void DebugPrinter::PrintKeyValue(const std::string& key, const std::string& value, const char* value_color) + { + PrintIndent(); + PrintColored(key, Color::Green); + os_ << ": "; + PrintColored(value, value_color); + os_ << "\n"; + } + + void DebugPrinter::PrintKeyValue(const std::string& key, int value) + { + PrintIndent(); + PrintColored(key, Color::Green); + os_ << ": "; + PrintColored(std::to_string(value), Color::BrightMagenta); + os_ << "\n"; + } + + void DebugPrinter::PrintKeyValue(const std::string& key, bool value) + { + PrintIndent(); + PrintColored(key, Color::Green); + os_ << ": "; + PrintColored(value ? "true" : "false", Color::BrightMagenta); + os_ << "\n"; + } + + void DebugPrinter::PrintExpression(const Expression* expr, const std::string& label, bool is_last) + { + if (!expr) + { + PrintIndent(is_last); + if (!label.empty()) + { + PrintColored(label, Color::Green); + os_ << ": "; + } + PrintColored("nullptr", Color::Red); + os_ << "\n"; + return; + } + + if (!label.empty()) + { + PrintIndent(is_last); + PrintColored(label, Color::Green); + os_ << ":\n"; + + is_last_child_stack_.push_back(is_last); + IncreaseIndent(); + } + + const_cast(expr)->Accept(*this); + + if (!label.empty()) + { + DecreaseIndent(); + is_last_child_stack_.pop_back(); + } + } + + void DebugPrinter::PrintStatement(const Statement* stmt, const std::string& label, bool is_last) + { + if (!stmt) + { + PrintIndent(is_last); + if (!label.empty()) + { + PrintColored(label, Color::Green); + os_ << ": "; + } + PrintColored("nullptr", Color::Red); + os_ << "\n"; + return; + } + + if (!label.empty()) + { + PrintIndent(is_last); + PrintColored(label, Color::Green); + os_ << ":\n"; + + is_last_child_stack_.push_back(is_last); + IncreaseIndent(); + } + + const_cast(stmt)->Accept(*this); + + if (!label.empty()) + { + DecreaseIndent(); + is_last_child_stack_.pop_back(); + } + } + + void DebugPrinter::PrintSignature(const Signature& sig) + { + PrintIndent(); + PrintColored("signature", Color::Green); + os_ << ":\n"; + + IncreaseIndent(); + + if (!sig.parameters.empty()) + { + PrintIndent(); + PrintColored("parameters", Color::Green); + os_ << ":\n"; + + IncreaseIndent(); + for (size_t i = 0; i < sig.parameters.size(); ++i) + { + bool is_last = (i == sig.parameters.size() - 1); + PrintParameter(sig.parameters[i], is_last); + } + DecreaseIndent(); + } + + if (sig.return_type) + PrintKeyValue("return_type", sig.return_type->name, sig.return_type->location, Color::BrightBlue); + + DecreaseIndent(); + } + + void DebugPrinter::PrintParameter(const Parameter& param, bool is_last) + { + PrintIndent(is_last); + PrintColored("param", Color::Yellow); + os_ << " "; + PrintColored(param.name, Color::BrightCyan); + + if (param.type) + { + os_ << ": "; + PrintColored(param.type->name, Color::BrightBlue); + } + + if (param.is_var) + os_ << " " << GetColor(Color::Magenta) << "[var]" << GetColor(Color::Reset); + + if (param.is_out) + os_ << " " << GetColor(Color::Magenta) << "[out]" << GetColor(Color::Reset); + + if (options_.show_location) + { + os_ << " "; + PrintLocation(param.location); + } + + os_ << "\n"; + + if (param.default_value) + { + is_last_child_stack_.push_back(is_last); + IncreaseIndent(); + PrintExpression(param.default_value.get(), "default", true); + DecreaseIndent(); + is_last_child_stack_.pop_back(); + } + } + + void DebugPrinter::PrintLeftHandSide(const LeftHandSide& lhs, const std::string& label, bool is_last) + { + if (!label.empty()) + { + PrintIndent(is_last); + PrintColored(label, Color::Green); + os_ << ":\n"; + + is_last_child_stack_.push_back(is_last); + IncreaseIndent(); + } + + std::visit([this](auto&& arg) { + if (arg) + { + arg->Accept(*this); + } + else + { + PrintIndent(); + PrintColored("nullptr", Color::Red); + os_ << "\n"; + } + }, lhs); + + if (!label.empty()) + { + DecreaseIndent(); + is_last_child_stack_.pop_back(); + } + } + + void DebugPrinter::PrintOperator(BinaryOperator op) + { + os_ << GetColor(Color::BrightYellow) << GetBinaryOperatorSymbol(op) << GetColor(Color::Reset); + } + + void DebugPrinter::PrintOperator(UnaryOperator op) + { + std::string symbol; + switch (op) + { + case UnaryOperator::kPlus: symbol = "+"; break; + case UnaryOperator::kMinus: symbol = "-"; break; + case UnaryOperator::kNot: symbol = "not"; break; + case UnaryOperator::kBitwiseNot: symbol = "~"; break; + case UnaryOperator::kDotNot: symbol = ".not"; break; + case UnaryOperator::kMatrixTranspose: symbol = "'"; break; + case UnaryOperator::kDerivative: symbol = "∂"; break; + case UnaryOperator::kExprAt: symbol = "@"; break; + case UnaryOperator::kExprRef: symbol = "&"; break; + default: symbol = "unknown"; break; + } + os_ << GetColor(Color::BrightYellow) << symbol << GetColor(Color::Reset); + } + + void DebugPrinter::PrintOperator(AssignmentOperator op) + { + os_ << GetColor(Color::BrightYellow) << GetAssignmentOperatorSymbol(op) << GetColor(Color::Reset); + } + + void DebugPrinter::PrintLiteralKind(LiteralKind kind) + { + std::string kind_str; + const char* color = Color::Cyan; + + switch (kind) + { + case LiteralKind::kNumber: kind_str = "number"; color = Color::BrightMagenta; break; + case LiteralKind::kString: kind_str = "string"; color = Color::BrightGreen; break; + case LiteralKind::kBoolean: kind_str = "boolean"; color = Color::BrightBlue; break; + case LiteralKind::kNil: kind_str = "nil"; color = Color::Gray; break; + case LiteralKind::kInfinity: kind_str = "infinity"; color = Color::BrightMagenta; break; + case LiteralKind::kEllipsis: kind_str = "ellipsis"; color = Color::Gray; break; + default: kind_str = "unknown"; break; + } + + PrintColored(kind_str, color); + } + + void DebugPrinter::PrintAccessModifier(AccessModifier modifier) + { + std::string mod_str; + switch (modifier) + { + case AccessModifier::kPublic: mod_str = "public"; break; + case AccessModifier::kProtected: mod_str = "protected"; break; + case AccessModifier::kPrivate: mod_str = "private"; break; + default: mod_str = "unknown"; break; + } + PrintColored(mod_str, Color::Magenta); + } + + void DebugPrinter::PrintMethodModifier(MethodModifier modifier) + { + std::string mod_str; + switch (modifier) + { + case MethodModifier::kNone: return; + case MethodModifier::kVirtual: mod_str = "virtual"; break; + case MethodModifier::kOverride: mod_str = "override"; break; + case MethodModifier::kOverload: mod_str = "overload"; break; + default: mod_str = "unknown"; break; + } + os_ << " " << GetColor(Color::Magenta) << "[" << mod_str << "]" << GetColor(Color::Reset); + } + + void DebugPrinter::PrintReferenceModifier(ReferenceModifier modifier) + { + std::string mod_str; + switch (modifier) + { + case ReferenceModifier::kNone: return; + case ReferenceModifier::kWeakRef: mod_str = "weakref"; break; + case ReferenceModifier::kAutoRef: mod_str = "autoref"; break; + default: mod_str = "unknown"; break; + } + os_ << " " << GetColor(Color::Magenta) << "[" << mod_str << "]" << GetColor(Color::Reset); + } + + void DebugPrinter::PrintError(const ParseError& error) + { + const char* severity_color = (error.severity == ErrorSeverity::Error) ? Color::BrightRed : Color::BrightYellow; + const char* severity_str = (error.severity == ErrorSeverity::Error) ? "Error" : "Warning"; + + PrintColored(severity_str, severity_color); + os_ << " at "; + PrintLocation(error.location); + os_ << " in " << GetColor(Color::Yellow) << error.node_type << GetColor(Color::Reset); + os_ << ": " << error.message << "\n"; + + if (options_.show_source_code && source_code_) + { + os_ << " "; + PrintSourceSnippet(error.location); + os_ << "\n"; + } + } + + std::string DebugPrinter::EscapeString(const std::string& str) const + { + std::string result; + result.reserve(str.length()); + for (char c : str) + { + switch (c) + { + case '\n': result += "\\n"; break; + case '\r': result += "\\r"; break; + case '\t': result += "\\t"; break; + case '\\': result += "\\\\"; break; + default: result += c; break; + } + } + return result; + } + + std::string DebugPrinter::TruncateString(const std::string& str, size_t max_len) const + { + if (str.length() <= max_len) + { + return str; + } + return str.substr(0, max_len) + "..."; + } + + std::string DebugPrinter::GetSourceText(const Location& loc) const + { + if (!source_code_ || loc.start_byte >= source_code_->length()) + { + return ""; + } + + size_t end = std::min(loc.end_byte, static_cast(source_code_->length())); + return source_code_->substr(loc.start_byte, end - loc.start_byte); + } + + // ===== Visitor 方法实现 ===== + + void DebugPrinter::VisitProgram(Program& node) + { + PrintIndent(); + PrintNodeHeader("Program", node.span); + + IncreaseIndent(); + PrintStatements(node.statements); + DecreaseIndent(); + } + + void DebugPrinter::VisitUnitDefinition(UnitDefinition& node) + { + PrintIndent(); + PrintColored("UnitDefinition", Color::BrightYellow); + os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset); + if (options_.show_location) + { + os_ << " "; + PrintLocation(node.location); + } + os_ << "\n"; + + IncreaseIndent(); + + if (!node.interface_statements.empty()) + { + PrintIndent(); + PrintColored("interface", Color::Green); + os_ << ":\n"; + + IncreaseIndent(); + PrintStatements(node.interface_statements); + DecreaseIndent(); + } + + if (!node.implementation_statements.empty()) + { + PrintIndent(); + PrintColored("implementation", Color::Green); + os_ << ":\n"; + + IncreaseIndent(); + PrintStatements(node.implementation_statements); + DecreaseIndent(); + } + + if (!node.initialization_statements.empty()) + { + PrintIndent(); + PrintColored("initialization", Color::Green); + os_ << ":\n"; + + IncreaseIndent(); + PrintStatements(node.initialization_statements); + DecreaseIndent(); + } + + if (!node.finalization_statements.empty()) + { + PrintIndent(); + PrintColored("finalization", Color::Green); + os_ << ":\n"; + + IncreaseIndent(); + PrintStatements(node.finalization_statements); + DecreaseIndent(); + } + + DecreaseIndent(); + } + + void DebugPrinter::VisitClassDefinition(ClassDefinition& node) + { + PrintIndent(); + PrintColored("ClassDefinition", Color::BrightYellow); + os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset); + if (options_.show_location) + { + os_ << " "; + PrintLocation(node.location); + } + os_ << "\n"; + + IncreaseIndent(); + + if (!node.parent_classes.empty()) + { + PrintIndent(); + PrintColored("inherits", Color::Green); + os_ << ": "; + for (size_t i = 0; i < node.parent_classes.size(); ++i) + { + const auto& parent = node.parent_classes[i]; + if (i > 0) os_ << ", "; + + if (parent.qualifier) + { + PrintColored(*parent.qualifier, Color::BrightBlue); + os_ << "."; + } + PrintColored(parent.name, Color::BrightCyan); + } + os_ << "\n"; + } + + if (!node.members.empty()) + { + PrintIndent(); + PrintColored("members", Color::Green); + os_ << ":\n"; + + IncreaseIndent(); + for (size_t i = 0; i < node.members.size(); ++i) + { + bool is_last = (i == node.members.size() - 1); + is_last_child_stack_.push_back(is_last); + node.members[i]->Accept(*this); + is_last_child_stack_.pop_back(); + } + DecreaseIndent(); + } + + DecreaseIndent(); + } + + void DebugPrinter::VisitClassMember(ClassMember& node) + { + PrintIndent(!is_last_child_stack_.empty() ? is_last_child_stack_.back() : false); + PrintColored("[", Color::Gray); + PrintAccessModifier(node.access_modifier); + PrintColored("]", Color::Gray); + os_ << " "; + + std::visit([this](auto&& arg) { + if (arg) + { + // Don't print indent again since we already did + int saved_indent = current_indent_; + current_indent_ = 0; + arg->Accept(*this); + current_indent_ = saved_indent; + } + }, node.member); + } + + void DebugPrinter::VisitMethodDeclaration(MethodDeclaration& node) + { + PrintIndent(); + PrintColored("MethodDeclaration", Color::BrightYellow); + os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset); + PrintMethodModifier(node.modifier); + + if (node.is_class_method) + { + os_ << " " << GetColor(Color::Magenta) << "[class]" << GetColor(Color::Reset); + } + + if (node.is_operator_overload) + { + os_ << " " << GetColor(Color::Magenta) << "[operator]" << GetColor(Color::Reset); + } + + if (options_.show_location) + { + os_ << " "; + PrintLocation(node.location); + } + os_ << "\n"; + + IncreaseIndent(); + PrintSignature(node.signature); + if (node.body) + { + PrintStatement(node.body.get(), "body", true); + } + DecreaseIndent(); + } + + void DebugPrinter::VisitPropertyDeclaration(PropertyDeclaration& node) + { + PrintIndent(); + PrintColored("PropertyDeclaration", Color::BrightYellow); + os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset); + if (options_.show_location) + { + os_ << " "; + PrintLocation(node.location); + } + os_ << "\n"; + + IncreaseIndent(); + + if (node.type_name) + { + PrintKeyValue("type", *node.type_name, Color::BrightBlue); + } + + if (node.index_value) + { + PrintKeyValue("index", *node.index_value); + } + + if (node.read_accessor) + { + PrintKeyValue("read", *node.read_accessor); + } + + if (node.write_accessor) + { + PrintKeyValue("write", *node.write_accessor); + } + + DecreaseIndent(); + } + + void DebugPrinter::VisitExternalMethodDefinition(ExternalMethodDefinition& node) + { + PrintIndent(); + PrintColored("ExternalMethodDefinition", Color::BrightYellow); + os_ << " " << GetColor(Color::BrightBlue) << node.owner_class.name << GetColor(Color::Reset); + os_ << "." << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset); + PrintMethodModifier(node.modifier); + + if (node.is_class_method) + { + os_ << " " << GetColor(Color::Magenta) << "[class]" << GetColor(Color::Reset); + } + + if (options_.show_location) + { + os_ << " "; + PrintLocation(node.location); + } + os_ << "\n"; + + IncreaseIndent(); + PrintSignature(node.signature); + if (node.body) + { + PrintStatement(node.body.get(), "body", true); + } + DecreaseIndent(); + } + + void DebugPrinter::VisitIdentifier(Identifier& node) + { + PrintIndent(); + PrintColored("Identifier", Color::Yellow); + os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset); + if (options_.show_location) + { + os_ << " "; + PrintLocation(node.location); + } + os_ << "\n"; + } + + void DebugPrinter::VisitLiteral(Literal& node) + { + PrintIndent(); + PrintColored("Literal", Color::Yellow); + os_ << " ["; + PrintLiteralKind(node.literal_kind); + os_ << "] " << GetColor(Color::BrightGreen) << node.name << GetColor(Color::Reset); + if (options_.show_location) + { + os_ << " "; + PrintLocation(node.location); + } + os_ << "\n"; + } + + void DebugPrinter::VisitBinaryExpression(BinaryExpression& node) + { + PrintIndent(); + PrintColored("BinaryExpression", Color::Yellow); + os_ << " "; + PrintOperator(node.op); + os_ << "\n"; + + IncreaseIndent(); + PrintExpression(node.left.get(), "left", false); + PrintExpression(node.right.get(), "right", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitComparisonExpression(ComparisonExpression& node) + { + PrintIndent(); + PrintColored("ComparisonExpression", Color::Yellow); + os_ << "\n"; + + IncreaseIndent(); + PrintExpression(node.left.get(), "left", false); + + for (size_t i = 0; i < node.comparisons.size(); ++i) + { + bool is_last = (i == node.comparisons.size() - 1); + const auto& comp = node.comparisons[i]; + + PrintIndent(is_last); + PrintColored("comparison", Color::Green); + os_ << " "; + PrintOperator(comp.op); + os_ << ":\n"; + + is_last_child_stack_.push_back(is_last); + IncreaseIndent(); + PrintExpression(comp.right.get(), "", true); + DecreaseIndent(); + is_last_child_stack_.pop_back(); + } + + DecreaseIndent(); + } + + void DebugPrinter::VisitUnaryExpression(UnaryExpression& node) + { + PrintIndent(); + PrintColored("UnaryExpression", Color::Yellow); + os_ << " "; + PrintOperator(node.op); + os_ << "\n"; + + IncreaseIndent(); + PrintExpression(node.argument.get(), "argument", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitTernaryExpression(TernaryExpression& node) + { + PrintIndent(); + PrintColored("TernaryExpression", Color::Yellow); + os_ << "\n"; + + IncreaseIndent(); + PrintExpression(node.condition.get(), "condition", false); + PrintExpression(node.consequence.get(), "consequence", false); + PrintExpression(node.alternative.get(), "alternative", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitCallExpression(CallExpression& node) + { + PrintIndent(); + PrintColored("CallExpression", Color::Yellow); + os_ << "\n"; + + IncreaseIndent(); + PrintExpression(node.callee.get(), "callee", false); + + if (!node.arguments.empty()) + { + PrintIndent(true); + PrintColored("arguments", Color::Green); + os_ << ":\n"; + + is_last_child_stack_.push_back(true); + IncreaseIndent(); + + for (size_t i = 0; i < node.arguments.size(); ++i) + { + bool is_last = (i == node.arguments.size() - 1); + const auto& arg = node.arguments[i]; + + PrintIndent(is_last); + if (arg.name) + { + PrintColored(*arg.name, Color::BrightCyan); + os_ << " = "; + } + os_ << "\n"; + + is_last_child_stack_.push_back(is_last); + IncreaseIndent(); + PrintExpression(arg.value.get(), "", true); + DecreaseIndent(); + is_last_child_stack_.pop_back(); + } + + DecreaseIndent(); + is_last_child_stack_.pop_back(); + } + + DecreaseIndent(); + } + + void DebugPrinter::VisitAttributeExpression(AttributeExpression& node) + { + PrintIndent(); + PrintColored("AttributeExpression", Color::Yellow); + os_ << " ." << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset); + if (options_.show_location) + { + os_ << " "; + PrintLocation(node.location); + } + os_ << "\n"; + + IncreaseIndent(); + PrintExpression(node.object.get(), "object", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitSubscriptExpression(SubscriptExpression& node) + { + PrintIndent(); + PrintColored("SubscriptExpression", Color::Yellow); + os_ << "\n"; + + IncreaseIndent(); + PrintExpression(node.value.get(), "value", false); + + if (!node.indices.empty()) + { + PrintIndent(true); + PrintColored("indices", Color::Green); + os_ << ":\n"; + + is_last_child_stack_.push_back(true); + IncreaseIndent(); + + for (size_t i = 0; i < node.indices.size(); ++i) + { + bool is_last = (i == node.indices.size() - 1); + const auto& idx = node.indices[i]; + + PrintIndent(is_last); + if (idx.is_slice) + { + PrintColored("slice", Color::Magenta); + } + else + { + PrintColored("index", Color::Magenta); + } + os_ << ":\n"; + + is_last_child_stack_.push_back(is_last); + IncreaseIndent(); + + if (idx.start) + { + PrintExpression(idx.start.get(), "start", !idx.end && !idx.step); + } + + if (idx.end) + { + PrintExpression(idx.end.get(), "end", !idx.step); + } + + if (idx.step) + { + PrintExpression(idx.step.get(), "step", true); + } + + DecreaseIndent(); + is_last_child_stack_.pop_back(); + } + + DecreaseIndent(); + is_last_child_stack_.pop_back(); + } + + DecreaseIndent(); + } + + void DebugPrinter::VisitArrayExpression(ArrayExpression& node) + { + PrintIndent(); + PrintColored("ArrayExpression", Color::Yellow); + os_ << "\n"; + + if (node.elements.empty()) + { + IncreaseIndent(); + PrintIndent(); + PrintColored("(empty)", Color::Gray); + os_ << "\n"; + DecreaseIndent(); + return; + } + + IncreaseIndent(); + + for (size_t i = 0; i < node.elements.size(); ++i) + { + bool is_last = (i == node.elements.size() - 1); + const auto& elem = node.elements[i]; + + PrintIndent(is_last); + PrintColored("element", Color::Green); + if (elem.is_nested) + { + os_ << " " << GetColor(Color::Magenta) << "[nested]" << GetColor(Color::Reset); + } + os_ << ":\n"; + + is_last_child_stack_.push_back(is_last); + IncreaseIndent(); + + if (elem.key) + { + PrintExpression(elem.key.get(), "key", false); + PrintExpression(elem.value.get(), "value", true); + } + else + { + PrintExpression(elem.value.get(), "", true); + } + + DecreaseIndent(); + is_last_child_stack_.pop_back(); + } + + DecreaseIndent(); + } + + void DebugPrinter::VisitAnonymousFunctionExpression(AnonymousFunctionExpression& node) + { + PrintIndent(); + PrintColored("AnonymousFunctionExpression", Color::Yellow); + os_ << "\n"; + + IncreaseIndent(); + PrintSignature(node.signature); + if (node.body) + { + PrintStatement(node.body.get(), "body", true); + } + DecreaseIndent(); + } + + void DebugPrinter::VisitPrefixIncrementExpression(PrefixIncrementExpression& node) + { + PrintIndent(); + PrintColored("PrefixIncrementExpression", Color::Yellow); + os_ << " ++\n"; + + IncreaseIndent(); + PrintExpression(node.argument.get(), "argument", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitPrefixDecrementExpression(PrefixDecrementExpression& node) + { + PrintIndent(); + PrintColored("PrefixDecrementExpression", Color::Yellow); + os_ << " --\n"; + + IncreaseIndent(); + PrintExpression(node.argument.get(), "argument", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitPostfixIncrementExpression(PostfixIncrementExpression& node) + { + PrintIndent(); + PrintColored("PostfixIncrementExpression", Color::Yellow); + os_ << " ++\n"; + + IncreaseIndent(); + PrintExpression(node.argument.get(), "argument", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitPostfixDecrementExpression(PostfixDecrementExpression& node) + { + PrintIndent(); + PrintColored("PostfixDecrementExpression", Color::Yellow); + os_ << " --\n"; + + IncreaseIndent(); + PrintExpression(node.argument.get(), "argument", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitFunctionPointerExpression(FunctionPointerExpression& node) + { + PrintIndent(); + PrintColored("FunctionPointerExpression", Color::Yellow); + os_ << " @\n"; + + IncreaseIndent(); + PrintExpression(node.argument.get(), "argument", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitAssignmentExpression(AssignmentExpression& node) + { + PrintIndent(); + PrintColored("AssignmentExpression", Color::Yellow); + os_ << " "; + PrintOperator(node.op); + os_ << "\n"; + + IncreaseIndent(); + PrintLeftHandSide(node.left, "left", false); + PrintExpression(node.right.get(), "right", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitExpressionStatement(ExpressionStatement& node) + { + PrintIndent(); + PrintColored("ExpressionStatement", Color::BrightYellow); + os_ << "\n"; + + IncreaseIndent(); + PrintExpression(node.expression.get(), "", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitVarStatement(VarStatement& node) + { + PrintIndent(); + PrintColored("VarStatement", Color::BrightYellow); + os_ << "\n"; + + IncreaseIndent(); + for (size_t i = 0; i < node.declarations.size(); ++i) + { + bool is_last = (i == node.declarations.size() - 1); + is_last_child_stack_.push_back(is_last); + node.declarations[i]->Accept(*this); + is_last_child_stack_.pop_back(); + } + DecreaseIndent(); + } + + void DebugPrinter::VisitStaticStatement(StaticStatement& node) + { + PrintIndent(); + PrintColored("StaticStatement", Color::BrightYellow); + os_ << "\n"; + + IncreaseIndent(); + for (size_t i = 0; i < node.declarations.size(); ++i) + { + bool is_last = (i == node.declarations.size() - 1); + is_last_child_stack_.push_back(is_last); + node.declarations[i]->Accept(*this); + is_last_child_stack_.pop_back(); + } + DecreaseIndent(); + } + + void DebugPrinter::VisitGlobalStatement(GlobalStatement& node) + { + PrintIndent(); + PrintColored("GlobalStatement", Color::BrightYellow); + os_ << "\n"; + + IncreaseIndent(); + for (size_t i = 0; i < node.declarations.size(); ++i) + { + bool is_last = (i == node.declarations.size() - 1); + is_last_child_stack_.push_back(is_last); + node.declarations[i]->Accept(*this); + is_last_child_stack_.pop_back(); + } + DecreaseIndent(); + } + + void DebugPrinter::VisitConstStatement(ConstStatement& node) + { + PrintIndent(); + PrintColored("ConstStatement", Color::BrightYellow); + os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset); + if (node.type_name) + { + os_ << ": " << GetColor(Color::BrightBlue) << *node.type_name << GetColor(Color::Reset); + } + os_ << "\n"; + + IncreaseIndent(); + PrintExpression(node.value.get(), "value", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitAssignmentStatement(AssignmentStatement& node) + { + PrintIndent(); + PrintColored("AssignmentStatement", Color::BrightYellow); + os_ << " "; + PrintOperator(node.op); + os_ << "\n"; + + IncreaseIndent(); + PrintLeftHandSide(node.left, "left", false); + PrintExpression(node.right.get(), "right", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitBlockStatement(BlockStatement& node) + { + PrintIndent(); + PrintColored("BlockStatement", Color::BrightYellow); + os_ << "\n"; + + IncreaseIndent(); + PrintStatements(node.statements); + DecreaseIndent(); + } + + void DebugPrinter::VisitIfStatement(IfStatement& node) + { + PrintIndent(); + PrintColored("IfStatement", Color::BrightYellow); + os_ << "\n"; + + IncreaseIndent(); + + for (size_t i = 0; i < node.branches.size(); ++i) + { + bool is_last = (i == node.branches.size() - 1); + const auto& branch = node.branches[i]; + + PrintIndent(is_last); + PrintColored(i == 0 ? "if" : "elif", Color::Green); + os_ << ":\n"; + + is_last_child_stack_.push_back(is_last); + IncreaseIndent(); + + PrintExpression(branch.condition.get(), "condition", false); + PrintStatement(branch.body.get(), "body", true); + + DecreaseIndent(); + is_last_child_stack_.pop_back(); + } + + DecreaseIndent(); + } + + void DebugPrinter::VisitForInStatement(ForInStatement& node) + { + PrintIndent(); + PrintColored("ForInStatement", Color::BrightYellow); + os_ << "\n"; + + IncreaseIndent(); + + PrintIndent(); + PrintColored("iterator", Color::Green); + os_ << ": "; + if (!node.key.empty()) + { + PrintColored(node.key, Color::BrightCyan); + os_ << ", "; + } + PrintColored(node.value, Color::BrightCyan); + os_ << "\n"; + + PrintExpression(node.collection.get(), "collection", false); + PrintStatement(node.body.get(), "body", true); + + DecreaseIndent(); + } + + void DebugPrinter::VisitForToStatement(ForToStatement& node) + { + PrintIndent(); + PrintColored("ForToStatement", Color::BrightYellow); + os_ << " " << GetColor(Color::BrightCyan) << node.counter << GetColor(Color::Reset); + if (node.is_downto) + { + os_ << " " << GetColor(Color::Magenta) << "[downto]" << GetColor(Color::Reset); + } + os_ << "\n"; + + IncreaseIndent(); + PrintExpression(node.start.get(), "start", false); + PrintExpression(node.end.get(), "end", false); + PrintStatement(node.body.get(), "body", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitWhileStatement(WhileStatement& node) + { + PrintIndent(); + PrintColored("WhileStatement", Color::BrightYellow); + os_ << "\n"; + + IncreaseIndent(); + PrintExpression(node.condition.get(), "condition", false); + PrintStatement(node.body.get(), "body", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitRepeatStatement(RepeatStatement& node) + { + PrintIndent(); + PrintColored("RepeatStatement", Color::BrightYellow); + os_ << "\n"; + + IncreaseIndent(); + + if (!node.body.empty()) + { + PrintIndent(); + PrintColored("body", Color::Green); + os_ << ":\n"; + + IncreaseIndent(); + PrintStatements(node.body); + DecreaseIndent(); + } + + PrintExpression(node.condition.get(), "condition", true); + + DecreaseIndent(); + } + + void DebugPrinter::VisitCaseStatement(CaseStatement& node) + { + PrintIndent(); + PrintColored("CaseStatement", Color::BrightYellow); + os_ << "\n"; + + IncreaseIndent(); + + PrintExpression(node.discriminant.get(), "discriminant", false); + + if (!node.branches.empty()) + { + PrintIndent(!node.default_case); + PrintColored("branches", Color::Green); + os_ << ":\n"; + + is_last_child_stack_.push_back(!node.default_case); + IncreaseIndent(); + + for (size_t i = 0; i < node.branches.size(); ++i) + { + bool is_last = (i == node.branches.size() - 1); + const auto& branch = node.branches[i]; + + PrintIndent(is_last); + PrintColored("case", Color::Magenta); + os_ << ":\n"; + + is_last_child_stack_.push_back(is_last); + IncreaseIndent(); + + if (!branch.values.empty()) + { + PrintIndent(false); + PrintColored("values", Color::Green); + os_ << ":\n"; + + IncreaseIndent(); + for (size_t j = 0; j < branch.values.size(); ++j) + { + bool val_is_last = (j == branch.values.size() - 1); + is_last_child_stack_.push_back(val_is_last); + PrintExpression(branch.values[j].get(), "", val_is_last); + is_last_child_stack_.pop_back(); + } + DecreaseIndent(); + } + + PrintStatement(branch.body.get(), "body", true); + + DecreaseIndent(); + is_last_child_stack_.pop_back(); + } + + DecreaseIndent(); + is_last_child_stack_.pop_back(); + } + + if (node.default_case) + { + PrintStatement(node.default_case.get(), "default", true); + } + + DecreaseIndent(); + } + + void DebugPrinter::VisitTryStatement(TryStatement& node) + { + PrintIndent(); + PrintColored("TryStatement", Color::BrightYellow); + os_ << "\n"; + + IncreaseIndent(); + PrintStatement(node.try_body.get(), "try", false); + PrintStatement(node.except_body.get(), "except", true); + DecreaseIndent(); + } + + void DebugPrinter::VisitBreakStatement(BreakStatement&) + { + PrintIndent(); + PrintColored("BreakStatement", Color::BrightYellow); + os_ << "\n"; + } + + void DebugPrinter::VisitContinueStatement(ContinueStatement&) + { + PrintIndent(); + PrintColored("ContinueStatement", Color::BrightYellow); + os_ << "\n"; + } + + void DebugPrinter::VisitReturnStatement(ReturnStatement& node) + { + PrintIndent(); + PrintColored("ReturnStatement", Color::BrightYellow); + os_ << "\n"; + + if (node.value) + { + IncreaseIndent(); + PrintExpression(node.value.get(), "value", true); + DecreaseIndent(); + } + } + + void DebugPrinter::VisitUsesStatement(UsesStatement& node) + { + PrintIndent(); + PrintColored("UsesStatement", Color::BrightYellow); + os_ << ": "; + for (size_t i = 0; i < node.units.size(); ++i) + { + if (i > 0) os_ << ", "; + PrintColored(node.units[i], Color::BrightCyan); + } + os_ << "\n"; + } + + void DebugPrinter::VisitFunctionDefinition(FunctionDefinition& node) + { + PrintIndent(); + PrintColored("FunctionDefinition", Color::BrightYellow); + os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset); + if (node.is_overload) + { + os_ << " " << GetColor(Color::Magenta) << "[overload]" << GetColor(Color::Reset); + } + if (options_.show_location) + { + os_ << " "; + PrintLocation(node.location); + } + os_ << "\n"; + + IncreaseIndent(); + PrintSignature(node.signature); + if (node.body) + { + PrintStatement(node.body.get(), "body", true); + } + DecreaseIndent(); + } + + void DebugPrinter::VisitFunctionDeclaration(FunctionDeclaration& node) + { + PrintIndent(); + PrintColored("FunctionDeclaration", Color::BrightYellow); + os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset); + if (node.is_overload) + { + os_ << " " << GetColor(Color::Magenta) << "[overload]" << GetColor(Color::Reset); + } + if (options_.show_location) + { + os_ << " "; + PrintLocation(node.location); + } + os_ << "\n"; + + IncreaseIndent(); + PrintSignature(node.signature); + DecreaseIndent(); + } + + void DebugPrinter::VisitVarDeclaration(VarDeclaration& node) + { + PrintIndent(); + PrintColored("VarDeclaration", Color::Yellow); + os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset); + if (node.type) + { + os_ << ": " << GetColor(Color::BrightBlue) << node.type->name << GetColor(Color::Reset); + } + if (options_.show_location) + { + os_ << " "; + PrintLocation(node.location); + } + os_ << "\n"; + + if (node.initial_value) + { + IncreaseIndent(); + PrintExpression(node.initial_value.get(), "initial_value", true); + DecreaseIndent(); + } + } + + void DebugPrinter::VisitStaticDeclaration(StaticDeclaration& node) + { + PrintIndent(); + PrintColored("StaticDeclaration", Color::Yellow); + os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset); + PrintReferenceModifier(node.reference_modifier); + if (node.type) + { + os_ << ": " << GetColor(Color::BrightBlue) << node.type->name << GetColor(Color::Reset); + } + if (options_.show_location) + { + os_ << " "; + PrintLocation(node.location); + } + os_ << "\n"; + + if (node.initial_value) + { + IncreaseIndent(); + PrintExpression(node.initial_value.get(), "initial_value", true); + DecreaseIndent(); + } + } + + void DebugPrinter::VisitGlobalDeclaration(GlobalDeclaration& node) + { + PrintIndent(); + PrintColored("GlobalDeclaration", Color::Yellow); + os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset); + if (node.type) + { + os_ << ": " << GetColor(Color::BrightBlue) << node.type->name << GetColor(Color::Reset); + } + if (options_.show_location) + { + os_ << " "; + PrintLocation(node.location); + } + os_ << "\n"; + + if (node.initial_value) + { + IncreaseIndent(); + PrintExpression(node.initial_value.get(), "initial_value", true); + DecreaseIndent(); + } + } + + void DebugPrinter::VisitFieldDeclaration(FieldDeclaration& node) + { + PrintIndent(); + PrintColored("FieldDeclaration", Color::Yellow); + os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset); + PrintReferenceModifier(node.reference_modifier); + if (node.type) + { + os_ << ": " << GetColor(Color::BrightBlue) << node.type->name << GetColor(Color::Reset); + } + os_ << "\n"; + + if (node.initial_value) + { + IncreaseIndent(); + PrintExpression(node.initial_value.get(), "initial_value", true); + DecreaseIndent(); + } + } + + void DebugPrinter::VisitUnpackPattern(UnpackPattern& node) + { + PrintIndent(); + PrintColored("UnpackPattern", Color::Yellow); + os_ << " ["; + for (size_t i = 0; i < node.names.size(); ++i) + { + if (i > 0) os_ << ", "; + PrintColored(node.names[i], Color::BrightCyan); + } + os_ << "]\n"; + } + + void DebugPrinter::VisitTSSQLExpression(TSSQLExpression& node) + { + PrintIndent(); + PrintColored("TSSQLExpression", Color::Yellow); + + std::string type_str; + switch (node.sql_type) + { + case TSSQLExpressionType::kSelect: type_str = "SELECT"; break; + case TSSQLExpressionType::kSSelect: type_str = "SSELECT"; break; + case TSSQLExpressionType::kVSelect: type_str = "VSELECT"; break; + case TSSQLExpressionType::kMSelect: type_str = "MSELECT"; break; + case TSSQLExpressionType::kUpdate: type_str = "UPDATE"; break; + case TSSQLExpressionType::kDelete: type_str = "DELETE"; break; + case TSSQLExpressionType::kInsert: type_str = "INSERT"; break; + default: type_str = "UNKNOWN"; break; + } + + os_ << " [" << GetColor(Color::BrightBlue) << type_str << GetColor(Color::Reset) << "]\n"; + + IncreaseIndent(); + PrintIndent(); + PrintColored("sql", Color::Green); + os_ << ": " << GetColor(Color::BrightGreen) << EscapeString(node.raw_sql) << GetColor(Color::Reset) << "\n"; + DecreaseIndent(); + } + + void DebugPrinter::VisitMatrixIterationStatement(MatrixIterationStatement& node) + { + PrintIndent(); + PrintColored("MatrixIterationStatement", Color::BrightYellow); + os_ << "\n"; + + IncreaseIndent(); + PrintExpression(node.target.get(), "target", false); + PrintStatement(node.body.get(), "body", true); + DecreaseIndent(); + } } diff --git a/lsp-server/test/test_ast/debug_printer.hpp b/lsp-server/test/test_ast/debug_printer.hpp index e0b0aa5..278c6d7 100644 --- a/lsp-server/test/test_ast/debug_printer.hpp +++ b/lsp-server/test/test_ast/debug_printer.hpp @@ -126,8 +126,8 @@ namespace lsp::language::ast void VisitRepeatStatement(RepeatStatement& node) override; void VisitCaseStatement(CaseStatement& node) override; void VisitTryStatement(TryStatement& node) override; - void VisitBreakStatement(BreakStatement& node) override; - void VisitContinueStatement(ContinueStatement& node) override; + void VisitBreakStatement(BreakStatement&) override; + void VisitContinueStatement(ContinueStatement&) override; void VisitReturnStatement(ReturnStatement& node) override; void VisitUsesStatement(UsesStatement& node) override; void VisitFunctionDefinition(FunctionDefinition& node) override; @@ -138,6 +138,7 @@ namespace lsp::language::ast void VisitFieldDeclaration(FieldDeclaration& node) override; void VisitUnpackPattern(UnpackPattern& node) override; void VisitTSSQLExpression(TSSQLExpression& node) override; + void VisitMatrixIterationStatement(MatrixIterationStatement& node) override; private: std::ostream& os_; @@ -163,6 +164,7 @@ namespace lsp::language::ast void PrintNodeHeader(const std::string& type_name, const Location& loc); void PrintLocation(const Location& loc); void PrintSourceSnippet(const Location& loc); + void PrintKeyValue(const std::string& key, const std::string& value, const Location& location, const char* value_color); void PrintKeyValue(const std::string& key, const std::string& value, const char* value_color = nullptr); void PrintKeyValue(const std::string& key, int value); void PrintKeyValue(const std::string& key, bool value); diff --git a/lsp-server/test/test_ast/test.sh b/lsp-server/test/test_ast/test.sh new file mode 100644 index 0000000..66eaa1b --- /dev/null +++ b/lsp-server/test/test_ast/test.sh @@ -0,0 +1,86 @@ +#!/bin/bash + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# 测试的可执行文件路径 +TEST_AST="./test_ast" + +# 需要测试的目录列表(可以自行添加) +DIRECTORIES=( + "./tests" + "./examples" + "./samples" + # 在这里添加更多目录 + # "./another_directory" +) + +# 检查test_ast是否存在 +if [ ! -f "$TEST_AST" ]; then + echo -e "${RED}错误: 找不到 test_ast 可执行文件${NC}" + echo "请确保 test_ast 在当前目录下,或修改脚本中的 TEST_AST 变量" + exit 1 +fi + +# 统计变量 +total_files=0 +tested_files=0 +failed_files=0 + +echo -e "${BLUE}========================================${NC}" +echo -e "${BLUE}开始测试 TSF 文件${NC}" +echo -e "${BLUE}========================================${NC}" +echo "" + +# 遍历每个目录 +for dir in "${DIRECTORIES[@]}"; do + if [ ! -d "$dir" ]; then + echo -e "${YELLOW}警告: 目录不存在: $dir${NC}" + continue + fi + + echo -e "${BLUE}扫描目录: $dir${NC}" + + # 递归查找所有.tsf文件 + while IFS= read -r -d '' file; do + ((total_files++)) + + echo -e "${YELLOW}[测试]${NC} $file" + + # 运行test_ast,隐藏输出 + if "$TEST_AST" "$file" > /dev/null 2>&1; then + ((tested_files++)) + echo -e "${GREEN} ✓ 通过${NC}" + else + ((failed_files++)) + echo -e "${RED} ✗ 失败${NC}" + echo -e "${RED}========================================${NC}" + echo -e "${RED}测试失败: $file${NC}" + echo -e "${RED}========================================${NC}" + exit 1 + fi + + done < <(find "$dir" -type f -name "*.tsf" -print0 | sort -z) + + echo "" +done + +# 打印总结 +echo -e "${BLUE}========================================${NC}" +echo -e "${GREEN}所有测试完成!${NC}" +echo -e "${BLUE}========================================${NC}" +echo -e "总文件数: $total_files" +echo -e "已测试: $tested_files" +echo -e "失败: $failed_files" + +if [ $failed_files -eq 0 ]; then + echo -e "${GREEN}✓ 全部通过${NC}" + exit 0 +else + echo -e "${RED}✗ 存在失败${NC}" + exit 1 +fi diff --git a/lsp-server/test/test_ast/test.tsf b/lsp-server/test/test_ast/test.tsf index 546e440..4a46b0f 100644 --- a/lsp-server/test/test_ast/test.tsf +++ b/lsp-server/test/test_ast/test.tsf @@ -1,20 +1,10 @@ -var d, e: boolean; -global c, d; -static e, f; -const a: boolean = false; +function f1(a: string; b: boolean = true): integer; +begin +end; -var a, b: boolean := true; -static d := "abc"; -global c := 123456; -// e := f1(); - -// function f1(a: string; b: boolean = true): integer; -// begin -// end; - -// function f2(a, b, c);overload; -// begin -// end; +function f2(a, b, c);overload; +begin +end; // var d := 1; // c := false;