saqut-compiler/src/json.hpp

333 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ============================================================================
// saQut Compiler — AST Analizi ve Sembol Toplayıcı
// ============================================================================
//
// DİZİN: src/json.hpp
// KATMAN: Tüm katmanlardan sonra — AST'yi tüketir
// BAĞIMLI: AST (src/parser/ast.hpp)
// KULLANAN: main.cpp
//
// AMAÇ:
// 1. AST üzerinde analiz yap (düğüm sayısı, derinlik, tip dağılımı)
// 2. Sembolleri topla (fonksiyon isimleri, dönüş tipleri, değişkenler)
//
// NOT: JSON serileştirme ASTNode::toJson() tarafından yapılır.
// Bu dosya sadece analiz ve sembol toplama işlemlerini içerir.
// Yeni bir AST düğümü eklendiğinde buraya dokunmak gerekmez.
//
// ============================================================================
#ifndef SAQUT_JSON
#define SAQUT_JSON
#include <string>
#include <sstream>
#include <map>
#include <vector>
#include "parser/ast.hpp"
// ============================================================================
// astKindName — ASTKind enum'unu string'e çevir (analiz çıktısı için)
// ============================================================================
inline const char* astKindName(ASTKind k) {
switch (k) {
case ASTKind::Program: return "Program";
case ASTKind::FunctionDecl: return "FunctionDecl";
case ASTKind::Block: return "Block";
case ASTKind::VariableDecl: return "VariableDecl";
case ASTKind::BinaryExpression: return "BinaryExpression";
case ASTKind::UnaryExpression: return "UnaryExpression";
case ASTKind::Literal: return "Literal";
case ASTKind::Identifier: return "Identifier";
case ASTKind::Postfix: return "Postfix";
case ASTKind::IfStatement: return "IfStatement";
case ASTKind::ForStatement: return "ForStatement";
case ASTKind::WhileStatement: return "WhileStatement";
case ASTKind::DoWhileStatement: return "DoWhileStatement";
case ASTKind::ReturnStatement: return "ReturnStatement";
case ASTKind::BreakStatement: return "BreakStatement";
case ASTKind::ContinueStatement: return "ContinueStatement";
case ASTKind::ExpressionStatement: return "ExpressionStatement";
case ASTKind::Call: return "Call";
case ASTKind::MemberAccess: return "MemberAccess";
case ASTKind::IndexExpression: return "IndexExpression";
case ASTKind::StructDecl: return "StructDecl";
default: return "Unknown";
}
}
// ============================================================================
// AST → JSON (ince sarmalayıcı — asıl iş ASTNode::toJson()'da)
// ============================================================================
inline std::string astToJson(ASTNode* node, int depth = 0) {
if (!node) return "null";
return node->toJson(depth);
}
// ============================================================================
// AST Analizi
// ============================================================================
struct AstAnalysis {
int totalNodes = 0;
int maxDepth = 0;
int functionCount = 0;
int variableCount = 0;
int ifCount = 0;
int loopCount = 0; // for + while + do-while
std::map<std::string, int> nodeTypeCounts;
};
inline void analyzeRecursive(ASTNode* node, int currentDepth, AstAnalysis& a) {
if (!node) return;
a.totalNodes++;
if (currentDepth > a.maxDepth) a.maxDepth = currentDepth;
const char* name = astKindName(node->kind);
a.nodeTypeCounts[name]++;
switch (node->kind) {
case ASTKind::FunctionDecl: a.functionCount++; break;
case ASTKind::VariableDecl: a.variableCount++; break;
case ASTKind::IfStatement: a.ifCount++; break;
case ASTKind::WhileStatement:
case ASTKind::ForStatement:
case ASTKind::DoWhileStatement:
a.loopCount++; break;
default: break;
}
// Tüm çocukları gez
switch (node->kind) {
case ASTKind::Program:
case ASTKind::FunctionDecl:
case ASTKind::Block: {
for (auto* child : node->getChildren())
analyzeRecursive(child, currentDepth + 1, a);
break;
}
case ASTKind::VariableDecl: {
auto* vd = (VariableDeclNode*)node;
if (vd->initExpr) analyzeRecursive(vd->initExpr, currentDepth + 1, a);
break;
}
case ASTKind::BinaryExpression: {
auto* bin = (BinaryExpressionNode*)node;
if (bin->Left) analyzeRecursive(bin->Left, currentDepth + 1, a);
if (bin->Right) analyzeRecursive(bin->Right, currentDepth + 1, a);
break;
}
case ASTKind::Postfix: {
auto* pf = (PostfixNode*)node;
if (pf->operand) analyzeRecursive(pf->operand, currentDepth + 1, a);
break;
}
case ASTKind::IfStatement: {
auto* ifn = (IfStatementNode*)node;
if (ifn->condition) analyzeRecursive(ifn->condition, currentDepth + 1, a);
if (ifn->thenBranch) analyzeRecursive(ifn->thenBranch, currentDepth + 1, a);
if (ifn->elseBranch) analyzeRecursive(ifn->elseBranch, currentDepth + 1, a);
break;
}
case ASTKind::WhileStatement: {
auto* ws = (WhileStatementNode*)node;
if (ws->condition) analyzeRecursive(ws->condition, currentDepth + 1, a);
if (ws->body) analyzeRecursive(ws->body, currentDepth + 1, a);
break;
}
case ASTKind::ForStatement: {
auto* fs = (ForStatementNode*)node;
if (fs->init) analyzeRecursive(fs->init, currentDepth + 1, a);
if (fs->condition) analyzeRecursive(fs->condition, currentDepth + 1, a);
if (fs->update) analyzeRecursive(fs->update, currentDepth + 1, a);
if (fs->body) analyzeRecursive(fs->body, currentDepth + 1, a);
break;
}
case ASTKind::DoWhileStatement: {
auto* dw = (DoWhileStatementNode*)node;
if (dw->body) analyzeRecursive(dw->body, currentDepth + 1, a);
if (dw->condition) analyzeRecursive(dw->condition, currentDepth + 1, a);
break;
}
case ASTKind::ReturnStatement: {
auto* rs = (ReturnStatementNode*)node;
if (rs->value) analyzeRecursive(rs->value, currentDepth + 1, a);
break;
}
case ASTKind::ExpressionStatement: {
auto* es = (ExpressionStatementNode*)node;
if (es->expression) analyzeRecursive(es->expression, currentDepth + 1, a);
break;
}
case ASTKind::Call: {
auto* call = (CallExpressionNode*)node;
if (call->callee) analyzeRecursive(call->callee, currentDepth + 1, a);
for (auto* arg : call->arguments) analyzeRecursive(arg, currentDepth + 1, a);
break;
}
case ASTKind::MemberAccess: {
auto* ma = (MemberAccessNode*)node;
if (ma->object) analyzeRecursive(ma->object, currentDepth + 1, a);
break;
}
case ASTKind::IndexExpression: {
auto* ie = (IndexExpressionNode*)node;
if (ie->object) analyzeRecursive(ie->object, currentDepth + 1, a);
if (ie->index) analyzeRecursive(ie->index, currentDepth + 1, a);
break;
}
case ASTKind::StructDecl: {
for (auto* child : node->getChildren()) analyzeRecursive(child, currentDepth + 1, a);
break;
}
default: break; // Literal, Identifier, Break, Continue — yaprak düğüm
}
}
inline AstAnalysis analyzeAst(ASTNode* root) {
AstAnalysis a;
analyzeRecursive(root, 0, a);
return a;
}
inline std::string analysisToJson(const AstAnalysis& a) {
std::ostringstream ss;
ss << " \"totalNodes\": " << a.totalNodes << ",\n"
<< " \"maxDepth\": " << a.maxDepth << ",\n"
<< " \"functionCount\": " << a.functionCount << ",\n"
<< " \"variableCount\": " << a.variableCount << ",\n"
<< " \"ifCount\": " << a.ifCount << ",\n"
<< " \"loopCount\": " << a.loopCount << ",\n"
<< " \"nodeTypes\": {\n";
bool first = true;
for (auto& [name, count] : a.nodeTypeCounts) {
if (!first) ss << ",\n";
ss << " \"" << name << "\": " << count;
first = false;
}
ss << "\n }";
return ss.str();
}
// ============================================================================
// Sembol Toplayıcı
// ============================================================================
struct SymbolEntry {
std::string name;
std::string kind; // "function" veya "variable"
std::string type; // Dönüş tipi veya değişken tipi
};
inline void collectSymbolsRecursive(ASTNode* node, std::vector<SymbolEntry>& symbols) {
if (!node) return;
// Sadece FunctionDecl ve VariableDecl toplanır — diğerleri gezilir
if (node->kind == ASTKind::FunctionDecl) {
auto* fn = (FunctionDeclNode*)node;
symbols.push_back({fn->name, "function", fn->returnType});
} else if (node->kind == ASTKind::StructDecl) {
auto* st = (StructDeclNode*)node;
symbols.push_back({st->name, "struct", ""});
} else if (node->kind == ASTKind::VariableDecl) {
auto* vd = (VariableDeclNode*)node;
symbols.push_back({vd->name, "variable", vd->varType});
}
// Çocukları gez
switch (node->kind) {
case ASTKind::Program:
case ASTKind::FunctionDecl:
case ASTKind::Block:
for (auto* child : node->getChildren())
collectSymbolsRecursive(child, symbols);
break;
case ASTKind::VariableDecl: {
auto* vd = (VariableDeclNode*)node;
if (vd->initExpr) collectSymbolsRecursive(vd->initExpr, symbols);
break;
}
case ASTKind::BinaryExpression: {
auto* bin = (BinaryExpressionNode*)node;
if (bin->Left) collectSymbolsRecursive(bin->Left, symbols);
if (bin->Right) collectSymbolsRecursive(bin->Right, symbols);
break;
}
case ASTKind::Postfix: {
auto* pf = (PostfixNode*)node;
if (pf->operand) collectSymbolsRecursive(pf->operand, symbols);
break;
}
case ASTKind::IfStatement: {
auto* ifn = (IfStatementNode*)node;
if (ifn->condition) collectSymbolsRecursive(ifn->condition, symbols);
if (ifn->thenBranch) collectSymbolsRecursive(ifn->thenBranch, symbols);
if (ifn->elseBranch) collectSymbolsRecursive(ifn->elseBranch, symbols);
break;
}
case ASTKind::WhileStatement: {
auto* ws = (WhileStatementNode*)node;
if (ws->condition) collectSymbolsRecursive(ws->condition, symbols);
if (ws->body) collectSymbolsRecursive(ws->body, symbols);
break;
}
case ASTKind::ForStatement: {
auto* fs = (ForStatementNode*)node;
if (fs->init) collectSymbolsRecursive(fs->init, symbols);
if (fs->condition) collectSymbolsRecursive(fs->condition, symbols);
if (fs->update) collectSymbolsRecursive(fs->update, symbols);
if (fs->body) collectSymbolsRecursive(fs->body, symbols);
break;
}
case ASTKind::DoWhileStatement: {
auto* dw = (DoWhileStatementNode*)node;
if (dw->body) collectSymbolsRecursive(dw->body, symbols);
if (dw->condition) collectSymbolsRecursive(dw->condition, symbols);
break;
}
case ASTKind::ReturnStatement: {
auto* rs = (ReturnStatementNode*)node;
if (rs->value) collectSymbolsRecursive(rs->value, symbols);
break;
}
case ASTKind::ExpressionStatement: {
auto* es = (ExpressionStatementNode*)node;
if (es->expression) collectSymbolsRecursive(es->expression, symbols);
break;
}
case ASTKind::Call: {
auto* call = (CallExpressionNode*)node;
if (call->callee) collectSymbolsRecursive(call->callee, symbols);
for (auto* arg : call->arguments) collectSymbolsRecursive(arg, symbols);
break;
}
case ASTKind::MemberAccess: {
auto* ma = (MemberAccessNode*)node;
if (ma->object) collectSymbolsRecursive(ma->object, symbols);
break;
}
case ASTKind::IndexExpression: {
auto* ie = (IndexExpressionNode*)node;
if (ie->object) collectSymbolsRecursive(ie->object, symbols);
if (ie->index) collectSymbolsRecursive(ie->index, symbols);
break;
}
case ASTKind::StructDecl: {
for (auto* child : node->getChildren()) collectSymbolsRecursive(child, symbols);
break;
}
default: break;
}
}
inline std::vector<SymbolEntry> collectSymbols(ASTNode* root) {
std::vector<SymbolEntry> symbols;
collectSymbolsRecursive(root, symbols);
return symbols;
}
#endif // SAQUT_JSON