feat(faz1): AST'i Expression/Statement olarak ayır + analiz alanları (#70)
- ast_node.hpp: ExpressionNode (resolvedType + isConstant/foldedValue TODO) ve StatementNode (isReachable) ara taban sınıfları; core/type.hpp dahil. - İfade düğümleri (Literal, Identifier, Binary, Postfix, Call, Member, Index) → ExpressionNode; toJson'a resolvedType (çözülmemişse null). - Deyim düğümleri (Block/If/While/For/DoWhile/Return/Break/Continue/ ExpressionStatement + VariableDecl) → StatementNode; toJson'a isReachable. - IdentifierNode'a Symbol* resolvedSymbol (TODO faz-2, ileri bildirim). - Faz 0 düzeltmesi: diagnostic.hpp kendi jsonEscape'ini kaldırdı, tools.hpp' dekini kullanıyor (ODR çakışması önlendi). Doğrulama: -Wall -Wextra temiz; saqut ast fibonacci.sqt geçerli JSON (48 resolvedType:null, 20 isReachable:true); parser-stress regresyon temiz; Faz 0 birim testleri geçiyor.
This commit is contained in:
parent
b0219411c1
commit
290dcab5ac
|
|
@ -37,6 +37,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include "core/location.hpp"
|
||||
#include "tools.hpp" // jsonEscape — TEK tanım (tools.hpp); çakışmayı önler
|
||||
|
||||
// ============================================================================
|
||||
// DiagLevel — Tanı seviyesi
|
||||
|
|
@ -65,22 +66,7 @@ inline const char* diagLevelNameTr(DiagLevel l) {
|
|||
return "?";
|
||||
}
|
||||
|
||||
// JSON string kaçışı (mesaj/ipucu tırnak veya satır sonu içerebilir)
|
||||
inline std::string jsonEscape(const std::string& s) {
|
||||
std::string out;
|
||||
out.reserve(s.size() + 8);
|
||||
for (char c : s) {
|
||||
switch (c) {
|
||||
case '"': out += "\\\""; break;
|
||||
case '\\': out += "\\\\"; break;
|
||||
case '\n': out += "\\n"; break;
|
||||
case '\r': out += "\\r"; break;
|
||||
case '\t': out += "\\t"; break;
|
||||
default: out += c; break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
// NOT: jsonEscape() tools.hpp'de tanımlıdır (tek tanım — ODR çakışması olmaz).
|
||||
|
||||
// ============================================================================
|
||||
// Diagnostic — Tek bir tanı (hata/uyarı/not/ipucu)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include "core/location.hpp"
|
||||
#include "core/type.hpp"
|
||||
#include "parser/token.hpp"
|
||||
#include "tools.hpp"
|
||||
|
||||
|
|
@ -247,6 +248,47 @@ protected:
|
|||
std::vector<ASTNode*> children;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// ExpressionNode — Değer Üreten Düğümlerin Tabanı (Faz 1, ADR-012)
|
||||
// ============================================================================
|
||||
//
|
||||
// Bir DEĞER üreten her düğüm (Literal, Identifier, BinaryExpression, Call,
|
||||
// Postfix, MemberAccess, IndexExpression) buradan türer. Bir ifadenin bir
|
||||
// TİPİ vardır; analiz/optimizasyon alanları burada toplanır.
|
||||
//
|
||||
class ExpressionNode : public ASTNode {
|
||||
public:
|
||||
// TODO(faz-3): tip denetleyici doldurur. Şimdilik Error = "henüz çözülmedi".
|
||||
Type resolvedType;
|
||||
|
||||
// TODO(faz-4): sabit katlama (constant folding) bayrağı.
|
||||
bool isConstant = false;
|
||||
// TODO(faz-4): foldedValue — katlanmış sabit değer (temsil Faz 4'te netleşir).
|
||||
|
||||
// resolvedType'ın JSON karşılığı (henüz çözülmemişse null gösterilir).
|
||||
std::string resolvedTypeJson() const {
|
||||
return resolvedType.isError() ? std::string("null") : resolvedType.toJson();
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// StatementNode — Eylem/Kontrol Akışı Yürüten Düğümlerin Tabanı (Faz 1)
|
||||
// ============================================================================
|
||||
//
|
||||
// Değer üretmeyen, bir iş/kontrol akışı yürüten her düğüm (Block, If, For,
|
||||
// While, DoWhile, Return, Break, Continue, ExpressionStatement ve şimdilik
|
||||
// VariableDecl) buradan türer. Tipi yoktur; akış-analizi alanları taşır.
|
||||
//
|
||||
// TODO(faz-1 gözden geçirme): VariableDecl/FunctionDecl/StructDecl'in tam
|
||||
// sınıflandırması provizyonel — VariableDecl burada (blok içinde erişilebilirliğe
|
||||
// tabi), Function/StructDecl doğrudan ASTNode altında kaldı.
|
||||
//
|
||||
class StatementNode : public ASTNode {
|
||||
public:
|
||||
// TODO(faz-3/4): erişilebilirlik (dead-code) analizi günceller.
|
||||
bool isReachable = true;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// childrenToJson — Düğümün çocuklarını JSON array olarak yaz
|
||||
// ============================================================================
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ std::string BinaryExpressionNode::toJson(int depth) {
|
|||
obj.add("operator", std::string(OPERATOR_MAP_REV.count(Operator) ? OPERATOR_MAP_REV.at(Operator) : "?"));
|
||||
if (Left) obj.addRaw("left", Left->toJson(depth + 1));
|
||||
if (Right) obj.addRaw("right", Right->toJson(depth + 1));
|
||||
obj.addRaw("resolvedType", resolvedTypeJson());
|
||||
obj.addRaw("location", loc.toJson());
|
||||
return obj.str();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "parser/ast_node.hpp"
|
||||
|
||||
class BinaryExpressionNode : public ASTNode {
|
||||
class BinaryExpressionNode : public ExpressionNode {
|
||||
public:
|
||||
TokenType Operator;
|
||||
ASTNode* Left = nullptr;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ std::string VariableDeclNode::toJson(int depth) {
|
|||
obj.add("kind", "VariableDecl");
|
||||
obj.add("name", name);
|
||||
obj.add("varType", varType);
|
||||
obj.add("isReachable", isReachable);
|
||||
if (initExpr) obj.addRaw("init", initExpr->toJson(depth + 1));
|
||||
obj.addRaw("location", loc.toJson());
|
||||
return obj.str();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ public:
|
|||
std::string toJson(int depth = 0) override;
|
||||
};
|
||||
|
||||
class VariableDeclNode : public ASTNode {
|
||||
class VariableDeclNode : public StatementNode {
|
||||
public:
|
||||
std::string varType;
|
||||
std::string name;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ std::string PostfixNode::toJson(int depth) {
|
|||
obj.add("kind", "Postfix");
|
||||
obj.add("operator", std::string(OPERATOR_MAP_REV.count(Operator) ? OPERATOR_MAP_REV.at(Operator) : "?"));
|
||||
if (operand) obj.addRaw("operand", operand->toJson(depth + 1));
|
||||
obj.addRaw("resolvedType", resolvedTypeJson());
|
||||
obj.addRaw("location", loc.toJson());
|
||||
return obj.str();
|
||||
}
|
||||
|
|
@ -30,6 +31,7 @@ std::string CallExpressionNode::toJson(int depth) {
|
|||
obj.addArray("arguments", [&]() {
|
||||
for (auto* arg : arguments) obj.addItem(arg->toJson(depth + 2));
|
||||
});
|
||||
obj.addRaw("resolvedType", resolvedTypeJson());
|
||||
obj.addRaw("location", loc.toJson());
|
||||
return obj.str();
|
||||
}
|
||||
|
|
@ -46,6 +48,7 @@ std::string MemberAccessNode::toJson(int depth) {
|
|||
obj.add("member", member);
|
||||
obj.add("arrow", arrow);
|
||||
if (object) obj.addRaw("object", object->toJson(depth + 1));
|
||||
obj.addRaw("resolvedType", resolvedTypeJson());
|
||||
obj.addRaw("location", loc.toJson());
|
||||
return obj.str();
|
||||
}
|
||||
|
|
@ -62,6 +65,7 @@ std::string IndexExpressionNode::toJson(int depth) {
|
|||
obj.add("kind", "IndexExpression");
|
||||
if (object) obj.addRaw("object", object->toJson(depth + 1));
|
||||
if (index) obj.addRaw("index", index->toJson(depth + 1));
|
||||
obj.addRaw("resolvedType", resolvedTypeJson());
|
||||
obj.addRaw("location", loc.toJson());
|
||||
return obj.str();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "parser/ast_node.hpp"
|
||||
|
||||
class PostfixNode : public ASTNode {
|
||||
class PostfixNode : public ExpressionNode {
|
||||
public:
|
||||
ASTNode* operand = nullptr;
|
||||
TokenType Operator;
|
||||
|
|
@ -12,7 +12,7 @@ public:
|
|||
std::string toJson(int depth = 0) override;
|
||||
};
|
||||
|
||||
class CallExpressionNode : public ASTNode {
|
||||
class CallExpressionNode : public ExpressionNode {
|
||||
public:
|
||||
ASTNode* callee = nullptr;
|
||||
std::vector<ASTNode*> arguments;
|
||||
|
|
@ -21,7 +21,7 @@ public:
|
|||
std::string toJson(int depth = 0) override;
|
||||
};
|
||||
|
||||
class MemberAccessNode : public ASTNode {
|
||||
class MemberAccessNode : public ExpressionNode {
|
||||
public:
|
||||
ASTNode* object = nullptr;
|
||||
std::string member;
|
||||
|
|
@ -31,7 +31,7 @@ public:
|
|||
std::string toJson(int depth = 0) override;
|
||||
};
|
||||
|
||||
class IndexExpressionNode : public ASTNode {
|
||||
class IndexExpressionNode : public ExpressionNode {
|
||||
public:
|
||||
ASTNode* object = nullptr;
|
||||
ASTNode* index = nullptr;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ std::string IdentifierNode::toJson(int depth) {
|
|||
ss << "{\n"
|
||||
<< in << " \"kind\": \"Identifier\",\n"
|
||||
<< in << " \"name\": \"" << jsonEscape(name) << "\",\n"
|
||||
<< in << " \"resolvedType\": " << resolvedTypeJson() << ",\n"
|
||||
<< in << " \"location\": " << loc.toJson() << "\n"
|
||||
<< in << "}";
|
||||
return ss.str();
|
||||
|
|
|
|||
|
|
@ -3,11 +3,16 @@
|
|||
|
||||
#include "parser/ast_node.hpp"
|
||||
|
||||
class IdentifierNode : public ASTNode {
|
||||
struct Symbol; // TODO(faz-2): sembol tablosu (Symbol) tanımlandığında bağlanacak
|
||||
|
||||
class IdentifierNode : public ExpressionNode {
|
||||
public:
|
||||
Token* lexerToken = nullptr;
|
||||
ParserToken parserToken;
|
||||
|
||||
// TODO(faz-2): isim çözümlemede sembol tablosundaki tanıma bağlanır.
|
||||
Symbol* resolvedSymbol = nullptr;
|
||||
|
||||
IdentifierNode();
|
||||
void log(int indent = 0) override;
|
||||
std::string toJson(int depth = 0) override;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ std::string LiteralNode::toJson(int depth) {
|
|||
if (literalType == LiteralType::FLOAT) {
|
||||
ss << ",\n" << in << " \"isFloat\": true";
|
||||
}
|
||||
ss << ",\n" << in << " \"resolvedType\": " << resolvedTypeJson();
|
||||
ss << ",\n" << in << " \"location\": " << loc.toJson() << "\n"
|
||||
<< in << "}";
|
||||
return ss.str();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "parser/ast_node.hpp"
|
||||
|
||||
class LiteralNode : public ASTNode {
|
||||
class LiteralNode : public ExpressionNode {
|
||||
public:
|
||||
Token* lexerToken = nullptr;
|
||||
ParserToken parserToken;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ std::string BlockNode::toJson(int depth) {
|
|||
obj.addArray("children", [&]() {
|
||||
for (auto* child : children) obj.addItem(child->toJson(depth + 2));
|
||||
});
|
||||
obj.add("isReachable", isReachable);
|
||||
obj.addRaw("location", loc.toJson());
|
||||
return obj.str();
|
||||
}
|
||||
|
|
@ -31,6 +32,7 @@ std::string IfStatementNode::toJson(int depth) {
|
|||
if (condition) obj.addRaw("condition", condition->toJson(depth + 1));
|
||||
if (thenBranch) obj.addRaw("then", thenBranch->toJson(depth + 1));
|
||||
if (elseBranch) obj.addRaw("else", elseBranch->toJson(depth + 1));
|
||||
obj.add("isReachable", isReachable);
|
||||
obj.addRaw("location", loc.toJson());
|
||||
return obj.str();
|
||||
}
|
||||
|
|
@ -47,6 +49,7 @@ std::string WhileStatementNode::toJson(int depth) {
|
|||
obj.add("kind", "WhileStatement");
|
||||
if (condition) obj.addRaw("condition", condition->toJson(depth + 1));
|
||||
if (body) obj.addRaw("body", body->toJson(depth + 1));
|
||||
obj.add("isReachable", isReachable);
|
||||
obj.addRaw("location", loc.toJson());
|
||||
return obj.str();
|
||||
}
|
||||
|
|
@ -67,6 +70,7 @@ std::string ForStatementNode::toJson(int depth) {
|
|||
if (condition) obj.addRaw("condition", condition->toJson(depth + 1));
|
||||
if (update) obj.addRaw("update", update->toJson(depth + 1));
|
||||
if (body) obj.addRaw("body", body->toJson(depth + 1));
|
||||
obj.add("isReachable", isReachable);
|
||||
obj.addRaw("location", loc.toJson());
|
||||
return obj.str();
|
||||
}
|
||||
|
|
@ -83,6 +87,7 @@ std::string DoWhileStatementNode::toJson(int depth) {
|
|||
obj.add("kind", "DoWhileStatement");
|
||||
if (condition) obj.addRaw("condition", condition->toJson(depth + 1));
|
||||
if (body) obj.addRaw("body", body->toJson(depth + 1));
|
||||
obj.add("isReachable", isReachable);
|
||||
obj.addRaw("location", loc.toJson());
|
||||
return obj.str();
|
||||
}
|
||||
|
|
@ -97,6 +102,7 @@ std::string ReturnStatementNode::toJson(int depth) {
|
|||
JsonObject obj(depth);
|
||||
obj.add("kind", "ReturnStatement");
|
||||
if (value) obj.addRaw("value", value->toJson(depth + 1));
|
||||
obj.add("isReachable", isReachable);
|
||||
obj.addRaw("location", loc.toJson());
|
||||
return obj.str();
|
||||
}
|
||||
|
|
@ -109,6 +115,7 @@ void BreakStatementNode::log(int indent) {
|
|||
std::string BreakStatementNode::toJson(int depth) {
|
||||
JsonObject obj(depth);
|
||||
obj.add("kind", "BreakStatement");
|
||||
obj.add("isReachable", isReachable);
|
||||
obj.addRaw("location", loc.toJson());
|
||||
return obj.str();
|
||||
}
|
||||
|
|
@ -121,6 +128,7 @@ void ContinueStatementNode::log(int indent) {
|
|||
std::string ContinueStatementNode::toJson(int depth) {
|
||||
JsonObject obj(depth);
|
||||
obj.add("kind", "ContinueStatement");
|
||||
obj.add("isReachable", isReachable);
|
||||
obj.addRaw("location", loc.toJson());
|
||||
return obj.str();
|
||||
}
|
||||
|
|
@ -135,6 +143,7 @@ std::string ExpressionStatementNode::toJson(int depth) {
|
|||
JsonObject obj(depth);
|
||||
obj.add("kind", "ExpressionStatement");
|
||||
if (expression) obj.addRaw("expression", expression->toJson(depth + 1));
|
||||
obj.add("isReachable", isReachable);
|
||||
obj.addRaw("location", loc.toJson());
|
||||
return obj.str();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@
|
|||
|
||||
#include "parser/ast_node.hpp"
|
||||
|
||||
class BlockNode : public ASTNode {
|
||||
class BlockNode : public StatementNode {
|
||||
public:
|
||||
BlockNode();
|
||||
void log(int indent = 0) override;
|
||||
std::string toJson(int depth = 0) override;
|
||||
};
|
||||
|
||||
class IfStatementNode : public ASTNode {
|
||||
class IfStatementNode : public StatementNode {
|
||||
public:
|
||||
ASTNode* condition = nullptr;
|
||||
ASTNode* thenBranch = nullptr;
|
||||
|
|
@ -20,7 +20,7 @@ public:
|
|||
std::string toJson(int depth = 0) override;
|
||||
};
|
||||
|
||||
class WhileStatementNode : public ASTNode {
|
||||
class WhileStatementNode : public StatementNode {
|
||||
public:
|
||||
ASTNode* condition = nullptr;
|
||||
ASTNode* body = nullptr;
|
||||
|
|
@ -29,7 +29,7 @@ public:
|
|||
std::string toJson(int depth = 0) override;
|
||||
};
|
||||
|
||||
class ForStatementNode : public ASTNode {
|
||||
class ForStatementNode : public StatementNode {
|
||||
public:
|
||||
ASTNode* init = nullptr;
|
||||
ASTNode* condition = nullptr;
|
||||
|
|
@ -40,7 +40,7 @@ public:
|
|||
std::string toJson(int depth = 0) override;
|
||||
};
|
||||
|
||||
class DoWhileStatementNode : public ASTNode {
|
||||
class DoWhileStatementNode : public StatementNode {
|
||||
public:
|
||||
ASTNode* condition = nullptr;
|
||||
ASTNode* body = nullptr;
|
||||
|
|
@ -49,7 +49,7 @@ public:
|
|||
std::string toJson(int depth = 0) override;
|
||||
};
|
||||
|
||||
class ReturnStatementNode : public ASTNode {
|
||||
class ReturnStatementNode : public StatementNode {
|
||||
public:
|
||||
ASTNode* value = nullptr;
|
||||
ReturnStatementNode();
|
||||
|
|
@ -57,21 +57,21 @@ public:
|
|||
std::string toJson(int depth = 0) override;
|
||||
};
|
||||
|
||||
class BreakStatementNode : public ASTNode {
|
||||
class BreakStatementNode : public StatementNode {
|
||||
public:
|
||||
BreakStatementNode();
|
||||
void log(int indent = 0) override;
|
||||
std::string toJson(int depth = 0) override;
|
||||
};
|
||||
|
||||
class ContinueStatementNode : public ASTNode {
|
||||
class ContinueStatementNode : public StatementNode {
|
||||
public:
|
||||
ContinueStatementNode();
|
||||
void log(int indent = 0) override;
|
||||
std::string toJson(int depth = 0) override;
|
||||
};
|
||||
|
||||
class ExpressionStatementNode : public ASTNode {
|
||||
class ExpressionStatementNode : public StatementNode {
|
||||
public:
|
||||
ASTNode* expression = nullptr;
|
||||
ExpressionStatementNode();
|
||||
|
|
|
|||
Loading…
Reference in New Issue