#include #include #include #include #include extern "C" { #include } extern "C" const TSLanguage* tree_sitter_tsf(void); #include "../../src/language/ast/deserializer.hpp" #include "../../src/language/symbol/table.hpp" #include "./debug_printer.hpp" using namespace lsp::language; // ==================== 文件读取 ==================== std::string ReadFile(const std::string& filepath) { std::ifstream file(filepath); if (!file.is_open()) { throw std::runtime_error("Cannot open file: " + filepath); } std::ostringstream oss; oss << file.rdbuf(); return oss.str(); } // ==================== Tree-Sitter 解析器 ==================== class TreeSitterParser { public: TreeSitterParser() { parser_ = ts_parser_new(); if (!parser_) { throw std::runtime_error("Failed to create parser"); } if (!ts_parser_set_language(parser_, tree_sitter_tsf())) { ts_parser_delete(parser_); throw std::runtime_error("Failed to set language"); } } ~TreeSitterParser() { if (tree_) { ts_tree_delete(tree_); } if (parser_) { ts_parser_delete(parser_); } } TSTree* Parse(const std::string& source) { if (tree_) { ts_tree_delete(tree_); tree_ = nullptr; } tree_ = ts_parser_parse_string( parser_, nullptr, source.c_str(), source.length()); if (!tree_) { throw std::runtime_error("Failed to parse source"); } return tree_; } TSNode GetRootNode() { if (!tree_) { throw std::runtime_error("No tree available"); } return ts_tree_root_node(tree_); } private: TSParser* parser_ = nullptr; TSTree* tree_ = nullptr; }; // ==================== 命令行选项 ==================== struct Options { std::string input_file; std::string output_file; bool print_all = true; bool print_definitions = false; bool print_scopes = false; bool print_references = false; bool print_inheritance = false; bool print_calls = false; bool compact_mode = false; bool statistics_only = false; std::string search_symbol; bool verbose = false; bool show_ast = false; bool no_color = false; bool print_overview = false; }; void PrintUsage(const char* program_name) { std::cout << "Symbol Table Analyzer - Analyze source code symbols\n\n"; std::cout << "Usage: " << program_name << " [options]\n\n"; std::cout << "Options:\n"; std::cout << " -o, --output Write output to file instead of stdout\n"; std::cout << " -d, --definitions Print only symbol definitions\n"; std::cout << " -s, --scopes Print only scope hierarchy\n"; std::cout << " -r, --references Print only references\n"; std::cout << " -i, --inheritance Print only inheritance graph\n"; std::cout << " -c, --calls Print only call graph\n"; std::cout << " -C, --compact Use compact output format\n"; std::cout << " -S, --stats Print statistics only\n"; std::cout << " -O, --overview Print overview only\n"; std::cout << " -f, --find Search for a specific symbol\n"; std::cout << " -v, --verbose Enable verbose output\n"; std::cout << " -a, --ast Show AST structure\n"; std::cout << " --no-color Disable colored output\n"; std::cout << " -h, --help Show this help message\n\n"; std::cout << "Examples:\n"; std::cout << " " << program_name << " program.tsf\n"; std::cout << " " << program_name << " program.tsf -o symbols.txt\n"; std::cout << " " << program_name << " program.tsf --definitions --scopes\n"; std::cout << " " << program_name << " program.tsf --find MyClass\n"; std::cout << " " << program_name << " program.tsf --compact --stats\n"; std::cout << " " << program_name << " program.tsf --overview\n"; } bool ParseArguments(int argc, char* argv[], Options& options) { if (argc < 2) return false; options.input_file = argv[1]; bool any_specific_print = false; for (int i = 2; i < argc; ++i) { std::string arg = argv[i]; if (arg == "-h" || arg == "--help") { return false; } else if (arg == "-o" || arg == "--output") { if (i + 1 < argc) { options.output_file = argv[++i]; } else { std::cerr << "Error: " << arg << " requires an argument\n"; return false; } } else if (arg == "-d" || arg == "--definitions") { options.print_definitions = true; any_specific_print = true; } else if (arg == "-s" || arg == "--scopes") { options.print_scopes = true; any_specific_print = true; } else if (arg == "-r" || arg == "--references") { options.print_references = true; any_specific_print = true; } else if (arg == "-i" || arg == "--inheritance") { options.print_inheritance = true; any_specific_print = true; } else if (arg == "-c" || arg == "--calls") { options.print_calls = true; any_specific_print = true; } else if (arg == "-C" || arg == "--compact") { options.compact_mode = true; } else if (arg == "-S" || arg == "--stats") { options.statistics_only = true; any_specific_print = true; } else if (arg == "-O" || arg == "--overview") { options.print_overview = true; any_specific_print = true; } else if (arg == "-f" || arg == "--find") { if (i + 1 < argc) { options.search_symbol = argv[++i]; } else { std::cerr << "Error: " << arg << " requires an argument\n"; return false; } } else if (arg == "-v" || arg == "--verbose") { options.verbose = true; } else if (arg == "-a" || arg == "--ast") { options.show_ast = true; } else if (arg == "--no-color") { options.no_color = true; } else { std::cerr << "Error: Unknown option: " << arg << "\n"; return false; } } if (any_specific_print) options.print_all = false; return true; } std::string NodeKindToString(ast::NodeKind kind) { switch (kind) { case ast::NodeKind::kProgram: return "Program"; case ast::NodeKind::kFunctionDefinition: return "FunctionDefinition"; case ast::NodeKind::kClassDefinition: return "ClassDefinition"; case ast::NodeKind::kUnitDefinition: return "UnitDefinition"; case ast::NodeKind::kVarStatement: return "VarStatement"; case ast::NodeKind::kConstStatement: return "ConstStatement"; case ast::NodeKind::kIfStatement: return "IfStatement"; case ast::NodeKind::kForInStatement: return "ForInStatement"; case ast::NodeKind::kWhileStatement: return "WhileStatement"; // ... 添加其他类型 default: return "Unknown"; } } void PrintASTStructure(const ast::ParseResult& parse_result, std::ostream& os) { os << "\n╔════════════════════════════════════════════════════════════╗\n"; os << "║ AST STRUCTURE ║\n"; os << "╚════════════════════════════════════════════════════════════╝\n\n"; os << "Statements: " << parse_result.root->statements.size() << "\n\n"; for (size_t i = 0; i < parse_result.root->statements.size(); ++i) { const auto& stmt = parse_result.root->statements[i]; if (!stmt) continue; // 修复:使用 kind 和 span os << "[" << i << "] " << NodeKindToString(stmt->kind) << " at [" << stmt->span.start_line << ":" << stmt->span.start_column << "]"; // 打印特定类型的详细信息 if (auto* func_def = dynamic_cast(stmt.get())) { os << " - Function: " << func_def->name; } else if (auto* class_def = dynamic_cast(stmt.get())) { os << " - Class: " << class_def->name; } else if (auto* unit_def = dynamic_cast(stmt.get())) { os << " - Unit: " << unit_def->name; } os << "\n"; } os << "\n"; } // ==================== 主分析函数 ==================== void AnalyzeFile(const Options& options) { // 打印头部 if (!options.compact_mode) { std::cout << "\n╔════════════════════════════════════════════════════════════╗\n"; std::cout << "║ SYMBOL TABLE ANALYZER ║\n"; std::cout << "╚════════════════════════════════════════════════════════════╝\n\n"; std::cout << "Input file: " << options.input_file << "\n"; } // 1. 读取源文件 if (options.verbose) std::cout << "Reading file...\n"; std::string source = ReadFile(options.input_file); if (options.verbose) { std::cout << "File size: " << source.length() << " bytes\n"; std::cout << "----------------------------------------\n"; std::cout << source << "\n"; std::cout << "----------------------------------------\n\n"; } // 2. 使用 Tree-Sitter 解析 if (options.verbose) std::cout << "Parsing with Tree-Sitter...\n"; TreeSitterParser ts_parser; [[maybe_unused]] TSTree* tree = ts_parser.Parse(source); TSNode root = ts_parser.GetRootNode(); if (options.verbose) { std::cout << "Root node type: " << ts_node_type(root) << "\n"; std::cout << "Root node child count: " << ts_node_child_count(root) << "\n\n"; } // 3. 反序列化为 AST if (options.verbose) std::cout << "Deserializing to AST...\n"; ast::Deserializer deserializer; ast::ParseResult parse_result = deserializer.Parse(root, source); if (parse_result.HasErrors()) { std::cerr << "\n⚠️ Parse Errors:\n"; for (const auto& error : parse_result.errors) { std::cerr << " [" << error.location.start_line << ":" << error.location.start_column << "] " << error.message << "\n"; } std::cerr << "\n"; } if (options.show_ast) { PrintASTStructure(parse_result, std::cout); } // 4. 构建符号表 if (options.verbose) std::cout << "Building symbol table...\n"; symbol::SymbolTable table; auto start = std::chrono::high_resolution_clock::now(); table.Build(*parse_result.root); auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(end - start); if (options.verbose) std::cout << "Symbol table built in " << duration.count() << " ms\n\n"; // 5. 准备输出流 std::ostream* out = &std::cout; std::ofstream file_out; if (!options.output_file.empty()) { file_out.open(options.output_file); if (!file_out.is_open()) { std::cerr << "Error: Cannot write to file: " << options.output_file << "\n"; return; } out = &file_out; // 写入文件头 *out << "Symbol Table Analysis\n"; *out << "Source: " << options.input_file << "\n"; auto now = std::chrono::system_clock::now(); auto time = std::chrono::system_clock::to_time_t(now); *out << "Generated: " << std::ctime(&time); *out << std::string(80, '=') << "\n\n"; } // 6. ✅ 使用新的 debug_print API // 配置打印选项 symbol::debug::PrintOptions print_opts; if (options.compact_mode) print_opts = symbol::debug::PrintOptions::Compact(); else if (options.verbose) print_opts = symbol::debug::PrintOptions::Verbose(); else print_opts = symbol::debug::PrintOptions::Default(); if (options.no_color || !options.output_file.empty()) print_opts.use_color = false; print_opts.show_references = options.print_references || options.verbose; // 创建打印器 symbol::debug::DebugPrinter printer(table, print_opts); // 7. 执行查询或打印 if (!options.search_symbol.empty()) { // 搜索符号 printer.FindAndPrint(options.search_symbol, *out); } else if (options.statistics_only) { // 只打印统计 printer.PrintStatistics(*out); } else if (options.print_overview) { // 只打印概览 printer.PrintOverview(*out); } else if (options.compact_mode) { // 紧凑模式 symbol::debug::PrintCompact(table, *out); } else if (options.print_all) { // 打印所有内容 printer.PrintAll(*out); } else { // 自定义打印 bool printed_anything = false; if (options.print_definitions) { printer.PrintSymbolList(*out); printed_anything = true; } if (options.print_scopes) { printer.PrintScopeHierarchy(*out); printed_anything = true; } if (options.print_references) { printer.PrintAllReferences(*out); printed_anything = true; } if (options.print_inheritance) { printer.PrintAllInheritance(*out); printed_anything = true; } if (options.print_calls) { printer.PrintAllCalls(*out); printed_anything = true; } // 总是打印统计信息 if (printed_anything) { *out << "\n"; } printer.PrintStatistics(*out); } // 8. 完成 if (file_out.is_open()) { file_out.close(); std::cout << "✓ Symbol table exported to: " << options.output_file << "\n"; } // 9. 打印摘要 if (!options.compact_mode) { std::cout << "\n========================================\n"; std::cout << "Summary:\n"; std::cout << " File: " << options.input_file << "\n"; std::cout << " Size: " << source.length() << " bytes\n"; std::cout << " Lines: " << std::count(source.begin(), source.end(), '\n') + 1 << "\n"; std::cout << " Statements: " << parse_result.root->statements.size() << "\n"; std::cout << " Symbols: " << table.GetAllDefinitions().size() << "\n"; std::cout << " Scopes: " << table.GetScopeManager().GetAllScopes().size() << "\n"; std::cout << " Parse Errors: " << parse_result.errors.size() << "\n"; std::cout << " Build Time: " << duration.count() << " ms\n"; if (parse_result.HasErrors()) { std::cout << " Status: ⚠️ COMPLETED WITH ERRORS\n"; } else { std::cout << " Status: ✓ SUCCESS\n"; } std::cout << "========================================\n\n"; } } // ==================== 主程序 ==================== int main(int argc, char* argv[]) { Options options; if (!ParseArguments(argc, argv, options)) { PrintUsage(argv[0]); return 1; } try { AnalyzeFile(options); return 0; } catch (const std::exception& e) { std::cerr << "❌ Fatal error: " << e.what() << "\n"; return 1; } }