diff --git a/build/.ninja_deps b/build/.ninja_deps index 5664a6a..3e9c5c6 100644 Binary files a/build/.ninja_deps and b/build/.ninja_deps differ diff --git a/build/.ninja_log b/build/.ninja_log index c61abbc..47d2e73 100644 --- a/build/.ninja_log +++ b/build/.ninja_log @@ -15,3 +15,6 @@ 0 22 1781786586571540360 build.ninja 1876a59d627a585 0 22 1781786586571540360 /home/saqut/Masaüstü/saqutcompiler/build/cmake_install.cmake 1876a59d627a585 1 2086 1781786305407208932 CMakeFiles/saqut.dir/src/symbol/symbol_collector.cpp.o 3348f498f369213d +10 1265 1781788264862998611 CMakeFiles/saqut.dir/src/parser/parser.cpp.o 2c65b7be26cead32 +10 2216 1781788264862423222 CMakeFiles/saqut.dir/src/main.cpp.o 110c26cb1d0c3a23 +2216 2383 1781788267068424572 saqut 8525928b86934b0a diff --git a/src/cli/commands/symbols.hpp b/src/cli/commands/symbols.hpp index 90b4b4b..431a7a3 100644 --- a/src/cli/commands/symbols.hpp +++ b/src/cli/commands/symbols.hpp @@ -1,30 +1,93 @@ // ============================================================================ -// saQut CLI — symbols komutu (sembol tablosu — Faz 2) +// saQut CLI — symbols komutu (sembol tablosu — JSON çıktı, Faz 2) // ============================================================================ #ifndef SAQUT_CLI_SYMBOLS #define SAQUT_CLI_SYMBOLS #include +#include #include "cli/args.hpp" #include "tokenizer/tokenizer.hpp" #include "parser/parser.hpp" #include "symbol/symbol_table.hpp" #include "symbol/symbol_collector.hpp" #include "diagnostic/diagnostic_engine.hpp" +#include "tools.hpp" + +// ───────────────────────────────────────────────────────────────────────────── +// symbolsToJson — sembol tablosunu JSON olarak serileştir +// ───────────────────────────────────────────────────────────────────────────── + +inline std::string symbolsToJson(const std::string& filePath, + const SymbolTable& table, + const DiagnosticEngine& diag) { + auto symbols = table.allSymbols(); + std::ostringstream ss; + + ss << "{\n"; + ss << " \"file\": \"" << jsonEscape(filePath) << "\",\n"; + ss << " \"symbols\": ["; + + bool firstSym = true; + for (Symbol* s : symbols) { + if (s->isBuiltin) continue; + + if (!firstSym) ss << ","; + firstSym = false; + + ss << "\n {\n"; + ss << " \"name\": \"" << jsonEscape(s->name) << "\",\n"; + ss << " \"kind\": \"" << symbolKindName(s->kind) << "\",\n"; + ss << " \"type\": \"" << jsonEscape(s->type.toString()) << "\",\n"; + ss << " \"typeDetail\": " << s->type.toJson() << ",\n"; + ss << " \"definition\": " << s->definitionLoc.toJson() << ",\n"; + ss << " \"isBuiltin\": " << (s->isBuiltin ? "true" : "false") << ",\n"; + + // referanslar + ss << " \"references\": ["; + bool firstRef = true; + for (const SourceLocation& ref : s->references) { + if (!firstRef) ss << ", "; + firstRef = false; + ss << ref.toJson(); + } + ss << "]\n"; + + ss << " }"; + } + + if (!firstSym) ss << "\n "; + ss << "],\n"; + + // tanılar (diagnostic engine'den hazır JSON al, iç kısmını sar) + ss << " \"diagnostics\": " << diag.toJson() << "\n"; + ss << "}\n"; + + return ss.str(); +} + +// ───────────────────────────────────────────────────────────────────────────── +// cmdSymbols — giriş noktası +// ───────────────────────────────────────────────────────────────────────────── inline int cmdSymbols(const CliArgs& args) { - std::string source = readSource(args); + std::string filePath = inputFilePath(args); + std::string source = readSource(args); if (source.empty()) return 1; Tokenizer tokenizer; - auto tokens = tokenizer.scan(source, inputFilePath(args)); + auto tokens = tokenizer.scan(source, filePath); Parser parser; ASTNode* ast = parser.parse(tokens); if (!ast) { - std::cerr << "Hata: AST üretilemedi\n"; + // AST null olursa boş ama geçerli bir JSON çıktısı üret + DiagnosticEngine diag; + diag.report("E000", SourceLocation{}, "AST üretilemedi"); + SymbolTable empty; + std::cout << symbolsToJson(filePath, empty, diag); for (auto* t : tokens) delete t; return 1; } @@ -33,32 +96,7 @@ inline int cmdSymbols(const CliArgs& args) { DiagnosticEngine diag; SymbolCollector(table, diag).collect(ast); - auto symbols = table.allSymbols(); - - std::cout << "Sembol Tablosu (" << symbols.size() << " sembol):\n"; - std::cout << "────────────────────────────────────────────\n"; - - if (symbols.empty()) { - std::cout << " (sembol bulunamadı)\n"; - } - - for (Symbol* s : symbols) { - if (s->isBuiltin) continue; // builtinleri çıktıda gösterme - std::cout << " [" << symbolKindName(s->kind) << "] " - << s->type.toString() << " " << s->name - << " @" << s->definitionLoc.shortString() - << " refs(" << s->references.size() << "):"; - for (auto& r : s->references) - std::cout << " " << r.shortString(); - std::cout << "\n"; - } - - std::cout << "────────────────────────────────────────────\n"; - - if (diag.hasErrors()) { - std::cerr << "\n"; - diag.printAll(std::cerr); - } + std::cout << symbolsToJson(filePath, table, diag); delete ast; for (auto* t : tokens) delete t; diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp index 398abde..714ef48 100644 --- a/src/parser/parser.cpp +++ b/src/parser/parser.cpp @@ -63,11 +63,13 @@ ASTNode* Parser::parseProgram() { ProgramNode* program = new ProgramNode(); while (currentToken().type != TokenType::SVR_VOID) { + int prevPos = current; ASTNode* decl = parseDeclaration(); if (decl) program->addChild(decl); - else - break; + // İlerleme olmadıysa token atla — syntax hatasında sonsuz döngüyü önler + if (current == prevPos) + nextToken(); } return program;