saqut-compiler/src/parser/ast_node.hpp

325 lines
15 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 Düğüm Tabanı (ASTNode, ASTKind, LiteralType)
// ============================================================================
//
// DİZİN: src/parser/ast_node.hpp
// KATMAN: Katman 3 — Parser (Ayrıştırıcı)
// AMAÇ: Tüm AST düğümlerinin taban sınıfını ve temel enum'ları tanımlamak
//
// BAĞIMLILIKLAR:
// - core/location.hpp: Kaynak kod konum bilgisi (SourceLocation)
// - parser/token.hpp: Token tipleri (TokenType, ParserToken)
// - tools.hpp: Yardımcı fonksiyonlar (jsonIndent vb.)
//
// MİMARİ KARARLAR:
// 1. ASTNode, tüm düğümlerin ortak davranışını (log, toJson, children)
// tek bir yerde tanımlar. NVI (Non-Virtual Interface) pattern'i.
// 2. virtual log() ve toJson() — her düğüm kendi çıktısını kendisi üretir.
// 3. parent pointer — AST'de yukarı doğru gezinme (ör: sembol çözümleme).
// 4. children vector — aşağı doğru gezinme (ör: tüm düğümleri ziyaret).
// 5. ASTKind enum — switch/case ile tip kontrolü (dynamic_cast yerine).
// Performans: dynamic_cast < switch/case < virtual method çağrısı
// Ama switch/case ile yeni tip eklemek derleyici uyarısı verir (eksik case).
//
// ============================================================================
#ifndef SAQUT_AST_NODE
#define SAQUT_AST_NODE
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include "core/location.hpp"
#include "core/type.hpp"
#include "parser/token.hpp"
#include "tools.hpp"
// ============================================================================
// ASTKind — Düğüm Tipi Enum
// ============================================================================
//
// Tüm AST düğüm tiplerini tanımlar. Her düğüm sınıfı bu enum'dan bir değer
// alır. enum class olması sayesinde isim çakışması olmaz (ASTKind::Program).
//
// NEDEN enum class, neden inheritance'daki typeid kullanılmıyor?
// - typeid().name() derleyiciye bağlıdır (g++: "4Program", MSVC: "class Program").
// - enum class her derleyicide aynıdır, string dönüşümü kolaydır.
// - static_cast<uint16_t> ile serileştirilebilir.
//
// ============================================================================
enum class ASTKind {
/* ====== En üst seviye ====== */
Program, // Kök düğüm — tüm programı kapsar.
// İçindeki children: FunctionDecl, StructDecl, VariableDecl.
// Tüm .cpp/.sqt dosyası tek bir Program düğümüdür.
/* ====== Tanımlar (Declarations) ====== */
FunctionDecl, // Fonksiyon tanımı.
// children: [returnType?], [name], [params...], [body: Block]
// Örn: int main() { ... }
StructDecl, // struct tanımı.
// children: [name], [members: VariableDecl...]
// Örn: struct Point { int x; int y; };
VariableDecl, // Değişken tanımı.
// children: [type?], [name], [initializer?]
// Örn: int x = 5; veya string name;
/* ====== Kontrol Akışı (Statements) ====== */
Block, // { } bloğu — birleşik ifade.
// children: [statements...]
// Kapsam (scope) oluşturur. Yerel değişkenler burada tanımlanır.
IfStatement, // if (koşul) gövde [else gövde].
// children: [condition], [thenBranch], [elseBranch?]
ForStatement, // for (init; koşul; artım) gövde.
// children: [init?], [condition?], [increment?], [body]
WhileStatement, // while (koşul) gövde.
// children: [condition], [body]
DoWhileStatement, // do gövde while (koşul);
// children: [body], [condition]
ReturnStatement, // return [ifade?];
// children: [value?]
BreakStatement, // break;
// children: yok. Sadece döngü/switch içinde geçerli.
ContinueStatement, // continue;
// children: yok. Sadece döngü içinde geçerli.
ExpressionStatement, // ifade + noktalı virgül (;)
// children: [expression]
// Örn: x = 5; veya foo();
/* ====== İfadeler (Expressions) ====== */
BinaryExpression, // İkili işlem: sol OP sağ.
// children: [left], [right]
// OP bilgisi: exprType alanında saklanır.
UnaryExpression, // Tekli işlem: OP operand.
// children: [operand]
// prefix (++x) veya postfix (x++) olabilir.
Literal, // Sabit değer: 42, 3.14, "hello", true, null.
// children: yok. Değer düğümün kendi alanında.
Identifier, // İsim referansı: x, PI, main.
// children: yok. İsim string olarak saklanır.
Postfix, // Postfix işlem: operand++.
// children: [operand]
Call, // Fonksiyon/metot çağrısı: f(args).
// children: [callee], [args...]
MemberAccess, // Üye erişimi: a.b veya a->b.
// children: [object], [member]
IndexExpression, // Dizi/indeks erişimi: a[i].
// children: [object], [index]
};
// ============================================================================
// LiteralType — Sabit Değer Alt Tipleri
// ============================================================================
//
// Literal düğümünün hangi türde bir sabit değer taşıdığını belirler.
// uint8_t tabanlı — 256 farklı literal tipi yeterli.
//
// KULLANIM:
// Literal düğümü oluşturulurken tip belirtilir:
// Literal lit(LiteralType::INTEGER, "42");
//
// ============================================================================
enum class LiteralType : uint8_t {
INTEGER, // Tamsayı sabiti: 42, 0xFF, 0b1010, 0777
// Decimal, hexadecimal (0x), octal (0), binary (0b) desteklenir.
// Tokenizer NumberToken ile iletilir.
FLOAT, // Ondalıklı sayı: 3.14, 1e-5, 2.0f
// Nokta veya üs (e/E) içeren sayılar.
STRING, // Metin sabiti: "merhaba dünya"
// Çift tırnak içinde. Kaçış dizileri (\n, \t, \") desteklenir.
BOOLEAN, // Mantıksal değer: true / false
// KW_TRUE veya KW_FALSE token'ından gelir.
BOŞ // null sabiti (Türkçe "boş").
// KW_NULL token'ından gelir. Nesne/referans türleri için kullanılır.
};
// ============================================================================
// literalTypeToString — LiteralType'ı string'e çevir (log için)
// ============================================================================
//
// PARAMETRE: t — LiteralType enum değeri
// DÖNÜŞ: const char* — insan tarafından okunabilir string
// KARMAŞIKLIK: O(1) — switch/case (derleyici jump table üretir)
//
inline const char* literalTypeToString(LiteralType t) {
switch (t) {
case LiteralType::INTEGER: return "integer";
case LiteralType::FLOAT: return "float";
case LiteralType::STRING: return "string";
case LiteralType::BOOLEAN: return "boolean";
case LiteralType::BOŞ: return "null";
}
return "?";
}
// ============================================================================
// ASTNode — Soyut Taban Sınıf
// ============================================================================
//
// Tüm AST düğümleri bu sınıftan türetilir. Her düğüm:
// - kind: ASTKind enum — tipini bilir (switch/case için)
// - parent: Ebeveyn düğüme işaretçi (ağaçta yukarı gezinme)
// - loc: Kaynak koddaki satır/sütun konumu (hata mesajları için)
// - children: Alt düğümler (ağaçta aşağı gezinme)
// - log(): Konsola hiyerarşik yazdırma
// - toJson(): JSON formatında serileştirme
//
// KALITIM:
// Program : ASTNode — Kök düğüm
// FunctionDecl : ASTNode — Fonksiyon tanımı
// BinaryExpression : ASTNode — İkili işlem
// ... (her düğüm tipi ayrı sınıf)
//
// BELLEK YÖNETİMİ:
// Düğümler new ile oluşturulur, delete ile yok edilir.
// Sahiplik: Parser oluşturur, çağıran (main/CLI) yok eder.
// TODO(Büyük yeniden düzenleme): std::unique_ptr ile RAII.
//
// ============================================================================
class ASTNode {
public:
/* ====== Her düğümün tipi ====== */
ASTKind kind; // Düğüm tipi (Program, FunctionDecl, ...)
// switch(kind) ile tip kontrolü.
// Set edilir ve bir daha değişmez.
/* ====== Ağaç bağlantıları ====== */
ASTNode* parent = nullptr; // Ebeveyn düğüm pointerı.
// addChild() tarafından otomatik set edilir.
// Kullanım: semantic analizde kapsam bulma.
// Örn: değişkenin tanımlandığı fonksiyonu bulmak
// için parent->parent->... şeklinde yukarı çıkılır.
/* ====== Kaynak konumu ====== */
SourceLocation loc; // Tokenizer'dan gelen satır/sütun bilgisi.
// Hata mesajlarında: "satır 5, sütun 12"
// TODO: Şu anda tüm düğümlerde dolu değil.
/* ====== Sanal Metotlar ====== */
// log() — Düğümü ve alt düğümlerini konsola yazdırır.
// PARAMETRE: indent — girinti seviyesi (her seviyede 2 boşluk artar)
// KULLANIM: ast->log(0); // tüm ağacı yazdır
// KARMAŞIKLIK: O(n) — tüm alt ağacı dolaşır
virtual void log(int indent = 0) {
(void)indent;
std::cout << "<Unknown>\n";
}
// toJson() — Düğümü ve alt düğümlerini JSON formatında döndürür.
// PARAMETRE: indent — JSON girinti seviyesi
// DÖNÜŞ: JSON stringi
// KULLANIM: std::string json = ast->toJson(0);
// KARMAŞIKLIK: O(n) — tüm alt ağacı dolaşır, string birleştirme maliyeti
virtual std::string toJson(int indent = 0) {
(void)indent;
return "{\"kind\":\"Unknown\"}";
}
/* ====== Yardımcı Metotlar ====== */
// addChild() — Alt düğüm ekler ve parent pointer'ını set eder.
// PARAMETRE: child — eklenecek alt düğüm (nullptr olmamalı)
// YAN ETKİ: child->parent = this (otomatik)
// KARMAŞIKLIK: O(1) amortize — vector push_back
void addChild(ASTNode* child) {
children.push_back(child);
child->parent = this;
}
// getChildren() — Alt düğüm vektörüne erişim.
// DÖNÜŞ: std::vector<ASTNode*>& — çocuk düğümler listesi
// KARMAŞIKLIK: O(1) — referans döndürür
std::vector<ASTNode*>& getChildren() { return children; }
// ~ASTNode() — children vektörünü özyinelemeli siler.
// Typed pointer'lar (condition, thenBranch vb.) alt sınıf yıkıcılarına bırakılır;
// children vektörü ile typed pointer'lar örtüşmediği için double-delete olmaz.
virtual ~ASTNode() {
for (auto* ch : children) delete ch;
}
protected:
// children — Alt düğümlerin vektörü.
// protected: doğrudan erişim yerine addChild/getChildren kullanılır.
// Türetilmiş sınıflar erişebilir (ör: log() içinde çocukları gezme).
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
// ============================================================================
//
// Bir düğümün tüm alt düğümlerini dolaşır ve her birinin toJson() çıktısını
// virgülle ayrılmış şekilde birleştirir.
//
// PARAMETRELER:
// node — çocukları yazdırılacak düğüm
// depth — JSON girinti seviyesi
//
// DÖNÜŞ: JSON array içeriği (köşeli parantezler HARİÇ)
//
// KULLANIM:
// std::string json = childrenToJson(this, depth + 1);
//
// KARMAŞIKLIK: O(n) — n = çocuk sayısı
//
inline std::string childrenToJson(ASTNode* node, int depth) {
std::ostringstream ss;
std::string in = jsonIndent(depth);
auto& ch = node->getChildren();
for (size_t i = 0; i < ch.size(); i++) {
ss << ch[i]->toJson(depth);
if (i + 1 < ch.size()) ss << ","; // son elemandan sonra virgül yok
ss << "\n";
}
return ss.str();
}
#endif // SAQUT_AST_NODE