chore: JsonObject builder, LiteralType enum, token.hpp doc cleanup
This commit is contained in:
parent
9a013c53d4
commit
03970871db
|
|
@ -3,7 +3,8 @@
|
|||
// ============================================================================
|
||||
//
|
||||
// DİZİN: src/parser/ast_json.hpp
|
||||
// KATMAN: AST — Sadece AST düğümlerinin toJson() metotları için
|
||||
// KATMAN: Katman 3 — Parser (AST JSON serileştirme)
|
||||
// AMAÇ: AST düğümlerinin toJson() metotlarında kullanılan builder pattern
|
||||
// BAĞIMLI: Yok (sadece <string>, <sstream>)
|
||||
//
|
||||
// AMAÇ:
|
||||
|
|
@ -17,6 +18,15 @@
|
|||
// obj.add("location", loc.toJson()); // ham JSON gömme
|
||||
// return obj.str();
|
||||
//
|
||||
// TASARIM KARARLARI:
|
||||
// 1. Builder pattern: add() çağrıları zincirlenemez ama okunabilirlik kazanır.
|
||||
// Zincirleme için: return obj.add("a",1).add("b",2).str() — tercih edilmedi.
|
||||
// 2. addRaw(): Önceden formatlanmış JSON (alt düğüm çıktısı) gömmek için.
|
||||
// 3. addArray(): Callback ile dizi oluşturma — C++ lambda'ları sayesinde temiz.
|
||||
// 4. addIfNotEmpty/addIfNot: Koşullu alanlar — null alanları JSON'da göstermemek için.
|
||||
// JSON çıktısını temiz tutar.
|
||||
// 5. JSON_INDENT = 2: Standart JSON girinti (4 değil, 2 okunabilir).
|
||||
//
|
||||
// ============================================================================
|
||||
|
||||
#ifndef SAQUT_AST_JSON
|
||||
|
|
@ -25,7 +35,11 @@
|
|||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
// Girinti sabiti (tools.hpp'deki jsonIndent ile uyumlu)
|
||||
// ============================================================================
|
||||
// JSON_INDENT — JSON girinti miktarı (boşluk sayısı)
|
||||
// ============================================================================
|
||||
// tools.hpp'deki jsonIndent() ile uyumlu olmalıdır.
|
||||
// Her seviyede 2 boşluk içe kaydırılır.
|
||||
#define JSON_INDENT 2
|
||||
|
||||
// jsonEscape ve jsonIndent tools.hpp'de tanımlıdır.
|
||||
|
|
@ -34,6 +48,10 @@
|
|||
// JsonObject — JSON Nesne Builder
|
||||
// ============================================================================
|
||||
//
|
||||
// AST düğümlerini JSON formatına dönüştürmek için kullanılır.
|
||||
// Her çağrıda yeni bir JsonObject oluşturulur, alanlar eklenir ve str() ile
|
||||
// JSON stringi alınır.
|
||||
//
|
||||
// KULLANIM:
|
||||
// JsonObject obj(depth);
|
||||
// obj.add("kind", "FunctionDecl");
|
||||
|
|
@ -46,10 +64,21 @@
|
|||
// });
|
||||
// return obj.str();
|
||||
//
|
||||
// ÖRNEK ÇIKTI (depth=0):
|
||||
// {
|
||||
// "kind": "FunctionDecl",
|
||||
// "name": "main",
|
||||
// "returnType": "int",
|
||||
// "children": [ ... ]
|
||||
// }
|
||||
//
|
||||
// ============================================================================
|
||||
|
||||
class JsonObject {
|
||||
public:
|
||||
// JsonObject — Yapıcı
|
||||
// PARAMETRE: depth — JSON girinti seviyesi (0 = en dış)
|
||||
// YAN ETKİ: m_ss'e açılış süslü parantezi yazar
|
||||
JsonObject(int depth)
|
||||
: m_indent(jsonIndent(depth)),
|
||||
m_indentInner(jsonIndent(depth + 1))
|
||||
|
|
@ -57,44 +86,89 @@ public:
|
|||
m_ss << m_indent << "{\n";
|
||||
}
|
||||
|
||||
// String alan ekle (değer tırnak içinde yazılır)
|
||||
// add() — String alan ekle
|
||||
// PARAMETRELER:
|
||||
// key — JSON anahtarı (tırnak içinde yazılır)
|
||||
// value — string değer (otomatik tırnaklanır ve escape edilir)
|
||||
// YAN ETKİ: m_hasFields true olur
|
||||
// ÖRN: obj.add("name", "main") → "name": "main"
|
||||
void add(const std::string& key, const std::string& value) {
|
||||
addRaw(key, "\"" + jsonEscape(value) + "\"");
|
||||
}
|
||||
|
||||
// Sayısal alan ekle (değer olduğu gibi yazılır)
|
||||
// add() — Sayısal alan ekle
|
||||
// PARAMETRELER:
|
||||
// key — JSON anahtarı
|
||||
// value — tamsayı değer (tırnaklanmaz, olduğu gibi yazılır)
|
||||
// ÖRN: obj.add("line", 42) → "line": 42
|
||||
void add(const std::string& key, int value) {
|
||||
addRaw(key, std::to_string(value));
|
||||
}
|
||||
|
||||
// Boolean alan ekle
|
||||
// add() — Boolean alan ekle
|
||||
// PARAMETRELER:
|
||||
// key — JSON anahtarı
|
||||
// value — true/false
|
||||
// ÖRN: obj.add("isPublic", true) → "isPublic": true
|
||||
void add(const std::string& key, bool value) {
|
||||
addRaw(key, value ? "true" : "false");
|
||||
}
|
||||
|
||||
// Ham JSON değeri ekle (önceden formatlanmış, tırnaklanmamış)
|
||||
// addRaw() — Ham JSON değeri ekle (önceden formatlanmış)
|
||||
// PARAMETRELER:
|
||||
// key — JSON anahtarı
|
||||
// jsonValue — önceden JSON'a çevrilmiş değer (tırnaklanmaz!)
|
||||
// KULLANIM: Alt düğüm toJson() çıktısını gömmek için.
|
||||
// addRaw("location", loc.toJson());
|
||||
void addRaw(const std::string& key, const std::string& jsonValue) {
|
||||
if (m_hasFields) m_ss << ",\n";
|
||||
m_ss << m_indentInner << "\"" << jsonEscape(key) << "\": " << jsonValue;
|
||||
m_hasFields = true;
|
||||
}
|
||||
|
||||
// Alt nesne ekle (bir alt seviyede JSON nesnesi)
|
||||
// addNested() — Alt nesne ekle (addRaw alias)
|
||||
// PARAMETRELER: addRaw ile aynı
|
||||
// KULLANIM: addRaw ile aynı. Sadece okunabilirlik için.
|
||||
void addNested(const std::string& key, const std::string& nestedJson) {
|
||||
addRaw(key, nestedJson);
|
||||
}
|
||||
|
||||
// Koşullu string alan (value boş değilse ekle)
|
||||
// addIfNotEmpty() — Koşullu string alan
|
||||
// PARAMETRELER:
|
||||
// key — JSON anahtarı
|
||||
// value — string değer (sadece boş DEĞİLSE eklenir)
|
||||
// KULLANIM: Opsiyonel alanlar için. JSON çıktısını temiz tutar.
|
||||
// obj.addIfNotEmpty("defaultValue", defaultVal);
|
||||
void addIfNotEmpty(const std::string& key, const std::string& value) {
|
||||
if (!value.empty()) add(key, value);
|
||||
}
|
||||
|
||||
// Koşullu sayı alan (value varsayılandan farklıysa ekle)
|
||||
// addIfNot() — Koşullu sayı alan
|
||||
// PARAMETRELER:
|
||||
// key — JSON anahtarı
|
||||
// value — mevcut değer
|
||||
// defaultValue — varsayılan değer
|
||||
// EKLEME KOŞULU: value != defaultValue
|
||||
// KULLANIM: Varsayılan değerler JSON'da tekrarlanmaz.
|
||||
// obj.addIfNot("precedence", 0, 14);
|
||||
void addIfNot(const std::string& key, int value, int defaultValue) {
|
||||
if (value != defaultValue) add(key, value);
|
||||
}
|
||||
|
||||
// Dizi alanı (callback içinde addItem çağrılır)
|
||||
// addArray() — Dizi alanı (callback ile)
|
||||
// PARAMETRELER:
|
||||
// key — JSON anahtarı
|
||||
// callback — dizi elemanlarını addItem ile ekleyen lambda/fonksiyon
|
||||
// KULLANIM:
|
||||
// obj.addArray("children", [&] {
|
||||
// for (auto* child : children)
|
||||
// obj.addItem(child->toJson(depth + 2));
|
||||
// });
|
||||
// ÖRNEK ÇIKTI:
|
||||
// "children": [
|
||||
// { "kind": "Literal", ... },
|
||||
// { "kind": "Identifier", ... }
|
||||
// ]
|
||||
template<typename Fn>
|
||||
void addArray(const std::string& key, Fn callback) {
|
||||
if (m_hasFields) m_ss << ",\n";
|
||||
|
|
@ -106,7 +180,10 @@ public:
|
|||
m_hasFields = true;
|
||||
}
|
||||
|
||||
// Diziye eleman ekle (addArray callback'i içinde kullanılır)
|
||||
// addItem() — Diziye eleman ekle
|
||||
// PARAMETRE: itemJson — JSON formatında dizi elemanı
|
||||
// KULLANIM: Sadece addArray callback'i içinde kullanılır.
|
||||
// YAN ETKİ: m_hasArrayItem true olur (virgül kontrolü için)
|
||||
void addItem(const std::string& itemJson) {
|
||||
if (m_hasArrayItem) m_ss << ",";
|
||||
// Öğeler m_indentInner'in bir seviye altında (depth + 2)
|
||||
|
|
@ -116,19 +193,36 @@ public:
|
|||
m_hasArrayItem = true;
|
||||
}
|
||||
|
||||
// Nesneyi kapat ve string olarak döndür
|
||||
// str() — JSON nesnesini kapat ve string olarak döndür
|
||||
// DÖNÜŞ: Tam JSON stringi ({"key": "value", ...})
|
||||
// YAN ETKİ: Kapanış süslü parantezini ekler.
|
||||
// KULLANIM:
|
||||
// JsonObject obj(depth);
|
||||
// obj.add("kind", "FunctionDecl");
|
||||
// return obj.str();
|
||||
std::string str() {
|
||||
m_ss << "\n" << m_indent << "}";
|
||||
return m_ss.str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostringstream m_ss;
|
||||
std::string m_indent; // Bu nesnenin girintisi
|
||||
std::string m_indentInner; // Bir alt seviye girinti
|
||||
bool m_hasFields = false;
|
||||
int m_arrayDepth = 0; // İç içe dizi seviyesi
|
||||
bool m_hasArrayItem = false;
|
||||
/* ====== Builder State ====== */
|
||||
std::ostringstream m_ss; // JSON çıktısının biriktirildiği string stream
|
||||
|
||||
std::string m_indent; // Bu nesnenin girinti seviyesi (depth * 2 boşluk)
|
||||
// Örn: depth=0 → "", depth=1 → " "
|
||||
|
||||
std::string m_indentInner; // Bir alt seviye girinti ((depth+1) * 2 boşluk)
|
||||
// Örn: depth=0 → " ", depth=1 → " "
|
||||
|
||||
bool m_hasFields = false; // Alan eklendi mi? (virgül kontrolü için)
|
||||
// true ise bir sonraki alandan önce virgül + newline
|
||||
|
||||
int m_arrayDepth = 0; // İç içe dizi seviyesi (şu anda kullanılmıyor,
|
||||
// ileride çok boyutlu diziler için)
|
||||
|
||||
bool m_hasArrayItem = false; // Diziye eleman eklendi mi? (virgül kontrolü)
|
||||
// true ise bir sonraki elemandan önce virgül
|
||||
};
|
||||
|
||||
#endif // SAQUT_AST_JSON
|
||||
|
|
|
|||
|
|
@ -3,12 +3,23 @@
|
|||
// ============================================================================
|
||||
//
|
||||
// DİZİN: src/parser/ast_node.hpp
|
||||
// KATMAN: Katman 3 — Parser
|
||||
// BAĞIMLI: core/location.hpp, parser/token.hpp, tools.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
|
||||
//
|
||||
// Bu dosya: ASTNode taban sınıfını, ASTKind enum'unu, LiteralType enum'unu
|
||||
// ve çocuk düğümleri JSON olarak yazdırmak için childrenToJson yardımcısını
|
||||
// içerir. Diğer tüm düğüm sınıfları bu dosyayı include eder.
|
||||
// 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).
|
||||
//
|
||||
// ============================================================================
|
||||
|
||||
|
|
@ -26,43 +37,112 @@
|
|||
// ============================================================================
|
||||
// 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 {
|
||||
Program, // Kök düğüm
|
||||
FunctionDecl, // Fonksiyon tanımı
|
||||
Block, // { } bloğu
|
||||
VariableDecl, // Değişken tanımı
|
||||
BinaryExpression, // İkili işlem (a + b)
|
||||
UnaryExpression, // Tekli işlem (-a, !a)
|
||||
Literal, // Sabit değer
|
||||
Identifier, // İsim referansı
|
||||
Postfix, // Son ek (a++)
|
||||
IfStatement, // if/else
|
||||
ForStatement, // for
|
||||
WhileStatement, // while
|
||||
DoWhileStatement, // do-while
|
||||
ReturnStatement, // return
|
||||
BreakStatement, // break
|
||||
ContinueStatement, // continue
|
||||
ExpressionStatement, // ifade + ;
|
||||
Call, // Fonksiyon çağrısı f(args)
|
||||
MemberAccess, // Üye erişimi a.b, a->b
|
||||
IndexExpression, // Dizi erişimi a[i]
|
||||
StructDecl, // struct tanımı
|
||||
/* ====== 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ı (decimal, hex, octal, binary)
|
||||
FLOAT, // Ondalıklı sayı (3.14, 1e-5)
|
||||
STRING, // Metin ("hello")
|
||||
BOOLEAN, // true / false
|
||||
BOŞ // null
|
||||
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";
|
||||
|
|
@ -79,53 +159,119 @@ inline const char* literalTypeToString(LiteralType t) {
|
|||
// ============================================================================
|
||||
//
|
||||
// Tüm AST düğümleri bu sınıftan türetilir. Her düğüm:
|
||||
// - kind: Tipini bilir (ASTKind enum)
|
||||
// - parent: Ebeveynine işaret eder
|
||||
// - loc: Kaynak koddaki konumunu bilir
|
||||
// - log(): Konsola yazdırılabilir
|
||||
// - toJson: JSON olarak serileştirilebilir
|
||||
// - 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:
|
||||
ASTKind kind;
|
||||
ASTNode* parent = nullptr;
|
||||
SourceLocation loc;
|
||||
/* ====== 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() — Sanal yıkıcı (polimorfik silme için)
|
||||
// delete ASTNode* yapıldığında doğru alt sınıf yıkıcısı çağrılır.
|
||||
// Bu olmazsa türetilmiş sınıfların kaynakları sızdırılır.
|
||||
virtual ~ASTNode() = default;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// 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 << ",";
|
||||
if (i + 1 < ch.size()) ss << ","; // son elemandan sonra virgül yok
|
||||
ss << "\n";
|
||||
}
|
||||
return ss.str();
|
||||
|
|
|
|||
|
|
@ -1,65 +1,43 @@
|
|||
// ============================================================================
|
||||
// saQut Compiler — Parser Token Tipleri ve Operatör Öncelik Tablosu
|
||||
// saQut Compiler — Parser Token Tipleri, Operatör Öncelik Tablosu ve ParserToken
|
||||
// ============================================================================
|
||||
//
|
||||
// DİZİN: src/parser/token.hpp
|
||||
// KATMAN: Katman 3 — Tokenizer ile Parser arasında köprü
|
||||
// BAĞIMLI: Tokenizer (src/tokenizer/tokenizer.hpp)
|
||||
// KULLANAN: AST (src/parser/ast.hpp), Parser (src/parser/parser.hpp)
|
||||
// KATMAN: Katman 3 — Tokenizer ile Parser Arasında Köprü
|
||||
// AMAÇ: Tokenizer'ın ham token'larını anlamsal tiplere dönüştürmek,
|
||||
// operatör öncelik ve birleşme kurallarını merkezi olarak tanımlamak
|
||||
//
|
||||
// AMAÇ:
|
||||
// Tokenizer'ın ürettiği ham Token'ları (string tipli) Parser'ın anlayacağı
|
||||
// anlamsal tiplere (TokenType enum) dönüştürür. Ayrıca operatör önceliğini
|
||||
// (precedence) ve birleşme yönünü (associativity) merkezi olarak tanımlar.
|
||||
// BAĞIMLILIKLAR:
|
||||
// - tokenizer/tokenizer.hpp: Token sınıf hiyerarşisi (Token, NumberToken, vs.)
|
||||
// - KULLANAN: parser/ast.hpp, parser/parser.hpp
|
||||
//
|
||||
// Bu dosya, Pratt parser'ın "kalbi"dir — tüm operatör önceliği ve birleşme
|
||||
// kuralları burada tek bir yerde tanımlanır.
|
||||
// BU DOSYANIN İÇERDİKLERİ:
|
||||
// 1. TokenType enum (uint16_t): 100+ token tipi (keyword'ler, operatörler, delimiter'lar)
|
||||
// 2. KEYWORD_MAP: string → TokenType (keyword çözümleme)
|
||||
// 3. OPERATOR_MAP: string → TokenType (operatör çözümleme)
|
||||
// 4. OPERATOR_MAP_REV: TokenType → string (log çıktısı için ters harita)
|
||||
// 5. OPERATOR_MAP_STRREV: TokenType → string (enum ismi, debug için)
|
||||
// 6. TokenPrecedence(): Öncelik tablosu (18 seviye, Pratt parser'ın kalbi)
|
||||
// 7. RightAssociative(): Sağ birleşme kontrolü (atama, üs, ternary)
|
||||
// 8. ParserToken: Parser'ın kullandığı token yapısı (Token* + TokenType)
|
||||
//
|
||||
// ADR-002: Neden Merkezi Operatör Öncelik Tablosu?
|
||||
// Recursive descent parser'larda operatör önceliği, her seviye için ayrı
|
||||
// bir fonksiyon yazılarak (parseAddExpr, parseMulExpr, ...) kod tekrarına
|
||||
// neden olur. Yeni bir operatör eklemek için yeni fonksiyon + mevcut
|
||||
// fonksiyonları değiştirmek gerekir.
|
||||
// TASARIM KARARLARI (ADR-002):
|
||||
// Neden TokenType enum'ı burada tanımlı, Tokenizer'da değil?
|
||||
// -> Tokenizer sadece ham token'lar üretir. Anlamsal tipler Parser'ın işidir.
|
||||
// -> Tokenizer'ın Tokenizer'ın ham yapısını değiştirmeden yeni diller eklenebilir.
|
||||
//
|
||||
// Pratt parser'da tüm öncelik bilgisi TEK BİR TABLODA (TokenPrecedence)
|
||||
// toplanır. Yeni operatör eklemek = tabloya bir satır eklemek.
|
||||
// Neden uint16_t tabanlı enum?
|
||||
// -> 65K token tipi fazlasıyla yeterli. 2 byte = bellek tasarrufu.
|
||||
// -> Her AST düğümünde TokenType saklanabilir (opsiyonel).
|
||||
//
|
||||
// TASARIM KARARLARI:
|
||||
// 1. TokenType enum: uint16_t tabanlı. Neden? 65K'dan fazla token tipi
|
||||
// olmayacak, 2 byte yeterli. Bellek tasarrufu AST'de fark eder.
|
||||
// Neden dört ayrı map?
|
||||
// -> unordered_map tek yönlüdür. Her yön için ayrı map gerekir.
|
||||
// -> OPERATOR_MAP_REV: log çıktısında "+" göstermek için.
|
||||
// -> OPERATOR_MAP_STRREV: enum ismini string olarak (debug, AST dump).
|
||||
//
|
||||
// 2. Üç harita (KEYWORD_MAP, OPERATOR_MAP, OPERATOR_MAP_REV, OPERATOR_MAP_STRREV):
|
||||
// - KEYWORD_MAP: "if" → KW_IF, string'den TokenType'a
|
||||
// - OPERATOR_MAP: "+" → PLUS, operatör string'inden TokenType'a
|
||||
// - OPERATOR_MAP_REV: PLUS → "+", log çıktısı için ters harita
|
||||
// - OPERATOR_MAP_STRREV: PLUS → "PLUS", enum ismini string olarak verir
|
||||
// Neden dört harita? Çünkü std::unordered_map tek yönlüdür.
|
||||
// bidirectional_map kütüphanesi kullanılabilirdi ama bağımlılık istemedik.
|
||||
//
|
||||
// 3. TokenPrecedence(): 18 seviyeli öncelik sistemi.
|
||||
// C/C++/Java standartlarına uygun. Yüksek sayı = yüksek öncelik.
|
||||
// Seviye 18 (en yüksek): üye erişimi (., ->, [], (), ::)
|
||||
// Seviye 1 (en düşük): virgül (,)
|
||||
// Seviye 0: önceliksiz (değerler, EOF, vb.)
|
||||
//
|
||||
// 4. RightAssociative(): Hangi operatörler sağdan sola birleşir?
|
||||
// - Atama (=, +=, vb.)
|
||||
// - Üs alma (**, ^) — matematiksel sağ birleşme: a^b^c = a^(b^c)
|
||||
// - Ternary (?:)
|
||||
// Diğer tüm operatörler soldan sağa birleşir.
|
||||
//
|
||||
// 5. ParserToken yapısı:
|
||||
// Token* token: Tokenizer'ın ürettiği Token'a pointer. Değer kopyası
|
||||
// DEĞİL. Neden pointer? Çünkü Token polimorfik (NumberToken, StringToken,
|
||||
// vb.) ve değer kopyası object slicing'e neden olur.
|
||||
// BUG FIX (commit 40579ca): Eskiden Token token (değer) vardı.
|
||||
// TokenType type: Token'ın anlamsal tipi.
|
||||
// is() / getPowerOperator() / isRightAssociative(): kolaylık metotları.
|
||||
//
|
||||
// BİLİNEN SINIRLAMALAR (TODO):
|
||||
// TODO: Özel operatörler: ?., ??, |>, >>=, vb. (ileride eklenebilir)
|
||||
// TODO: Kullanıcı tanımlı operatör önceliği (DSL'ler için)
|
||||
// TODO: Token konum bilgisi (satır/sütun) ParserToken'a eklenmeli
|
||||
// Neden bu kadar çok keyword?
|
||||
// -> saQut hem C/C++ hem Java hem de kendi sözdizimini destekler.
|
||||
// -> Tüm keyword'ler tek enum'da toplanmıştır.
|
||||
//
|
||||
// ============================================================================
|
||||
|
||||
|
|
@ -107,185 +85,334 @@ typedef std::vector<Token*> TokenList;
|
|||
// NEDEN uint16_t? Bellek optimizasyonu. Her AST düğümü bir TokenType taşır.
|
||||
// Binlerce düğümde 2 byte vs 4 byte fark eder.
|
||||
//
|
||||
/* ================================================================
|
||||
* TokenType — Anlamsal Token Tipleri
|
||||
* ================================================================
|
||||
*
|
||||
* Tokenizer'ın ürettiği ham token'ları (string tipli) Parser'ın
|
||||
* anlayacağı anlamsal tiplere dönüştürür.
|
||||
*
|
||||
* uint16_t tabanlı — 65K token tipi yeterli.
|
||||
* Bellek: AST düğümlerinde taşınabilir (2 byte).
|
||||
*
|
||||
* KATEGORİLER (öncelik sırasına göre):
|
||||
* 1. Değerler: IDENTIFIER, NUMBER, STRING, SVR_VOID
|
||||
* 2. Keyword'ler: KW_IF ... KW_NOEXCEPT (C/C++/Java ortak)
|
||||
* 3. Operatörler: DOT(18) ... COMMA(1) (Pratt öncelik seviyesi)
|
||||
* 4. Delimiter'lar: LBRACE, RBRACE, SEMICOLON, vb.
|
||||
* 5. Özel: END_OF_FILE, UNKNOWN, COMMENT, PREPROCESSOR
|
||||
*
|
||||
* ================================================================ */
|
||||
enum class TokenType : uint16_t {
|
||||
// --- Değerler ve Tanımlayıcılar ---
|
||||
IDENTIFIER, // değişken/fonksiyon ismi
|
||||
NUMBER, // 42, 0xFF, 0b1010, 3.14
|
||||
STRING, // "merhaba"
|
||||
SVR_VOID, // Geçersiz/EOF sinyali (Parser içinde kullanılır)
|
||||
/* ====== Değerler ve Tanımlayıcılar ====== */
|
||||
IDENTIFIER, // Değişken/fonksiyon/sınıf ismi.
|
||||
// Tokenizer'da IdentifierToken olarak üretilir.
|
||||
// Örn: x, main, Point, calculateAverage
|
||||
NUMBER, // Sayısal sabit: 42, 0xFF, 0b1010, 3.14, 1e-5
|
||||
// Tokenizer'da NumberToken olarak üretilir.
|
||||
// .isFloat alanı ile tamsayı/ondalık ayrımı yapılır.
|
||||
STRING, // Metin sabiti: "merhaba", "selam"
|
||||
// Tokenizer'da StringToken olarak üretilir.
|
||||
// Kaçış dizileri (\n, \t, \") tokenizer'da çözülür.
|
||||
SVR_VOID, // Geçersiz/EOF sinyali.
|
||||
// Parser içinde kullanılır. Tokenizer ÜRETMEZ.
|
||||
// currentToken() geçersiz indeks gösterdiğinde döner.
|
||||
|
||||
// --- Kontrol Akışı Keyword'leri ---
|
||||
KW_IF, // if
|
||||
KW_ELSE, // else
|
||||
KW_FOR, // for
|
||||
KW_WHILE, // while
|
||||
KW_DO, // do
|
||||
KW_SWITCH, // switch
|
||||
KW_CASE, // case
|
||||
KW_DEFAULT, // default
|
||||
KW_BREAK, // break
|
||||
KW_CONTINUE, // continue
|
||||
KW_RETURN, // return
|
||||
/* ====== Kontrol Akışı Keyword'leri ====== */
|
||||
KW_IF, // if (koşullu dal)
|
||||
// Sözdizimi: if (koşul) gövde [else gövde]
|
||||
KW_ELSE, // else (if'in alternatif dalı)
|
||||
// Sözdizimi: if (...) ... else ...
|
||||
// Parser'da if'ten sonra else opsiyoneldir.
|
||||
KW_FOR, // for (tekrarlı döngü)
|
||||
// Sözdizimi: for (init; koşul; artım) gövde
|
||||
KW_WHILE, // while (koşullu döngü)
|
||||
// Sözdizimi: while (koşul) gövde
|
||||
KW_DO, // do (en az bir kez çalışan döngü)
|
||||
// Sözdizimi: do gövde while (koşul);
|
||||
KW_SWITCH, // switch (çoklu dal — henüz implemente edilmedi)
|
||||
KW_CASE, // case (switch dalı — henüz implemente edilmedi)
|
||||
KW_DEFAULT, // default (switch varsayılan — henüz implemente edilmedi)
|
||||
KW_BREAK, // break (döngü/switch'ten çık)
|
||||
// Sadece döngü veya switch içinde geçerlidir.
|
||||
KW_CONTINUE, // continue (döngünün bir sonraki iterasyonuna geç)
|
||||
// Sadece döngü içinde geçerlidir.
|
||||
KW_RETURN, // return (fonksiyondan dön)
|
||||
// İsteğe bağlı dönüş değeri: return expr;
|
||||
|
||||
// --- OOP Keyword'leri ---
|
||||
KW_CLASS, // class
|
||||
KW_STRUCT, // struct
|
||||
KW_INTERFACE, // interface
|
||||
KW_ENUM, // enum
|
||||
KW_EXTENDS, // extends
|
||||
KW_IMPLEMENTS, // implements
|
||||
KW_NEW, // new
|
||||
KW_PUBLIC, // public
|
||||
KW_PRIVATE, // private
|
||||
KW_PROTECTED, // protected
|
||||
KW_STATIC, // static
|
||||
KW_FINAL, // final
|
||||
KW_ABSTRACT, // abstract
|
||||
/* ====== OOP Keyword'leri ====== */
|
||||
KW_CLASS, // class (sınıf tanımı — Java/C++ tarzı)
|
||||
KW_STRUCT, // struct (yapı tanımı — C tarzı)
|
||||
// saQut'ta class ve struct ikisi de desteklenir.
|
||||
KW_INTERFACE, // interface (soyut tip — Java tarzı)
|
||||
KW_ENUM, // enum (sabit listesi — C/C++/Java tarzı)
|
||||
KW_EXTENDS, // extends (kalıtım — Java tarzı)
|
||||
KW_IMPLEMENTS, // implements (interface gerçekleme — Java tarzı)
|
||||
KW_NEW, // new (nesne oluşturma — Java/C++ tarzı)
|
||||
KW_PUBLIC, // public (erişim belirteci)
|
||||
KW_PRIVATE, // private (erişim belirteci)
|
||||
KW_PROTECTED, // protected (erişim belirteci — alt sınıflara açık)
|
||||
KW_STATIC, // static (sınıf üyesi / dosya içi bağlantı)
|
||||
KW_FINAL, // final (değiştirilemez — Java tarzı)
|
||||
KW_ABSTRACT, // abstract (soyut sınıf/metot — Java tarzı)
|
||||
|
||||
// --- Tip Keyword'leri ---
|
||||
KW_VOID, // void
|
||||
KW_BOOL, // bool
|
||||
KW_INT, // int
|
||||
KW_FLOAT_TYPE, // float (FLOAT math.h'de tanımlı olabilir, TYPE eki var)
|
||||
KW_DOUBLE, // double
|
||||
KW_CHAR, // char
|
||||
KW_STRING_TYPE, // string
|
||||
/* ====== Tip Keyword'leri ====== */
|
||||
KW_VOID, // void (değer döndürmeyen fonksiyon / tip yok)
|
||||
// C/C++/Java uyumluluğu için.
|
||||
KW_BOOL, // bool (mantıksal tip: true/false)
|
||||
// C++ bool ile aynı.
|
||||
KW_INT, // int (tamsayı tipi: 32-bit işaretli)
|
||||
// Varsayılan tamsayı tipi.
|
||||
KW_FLOAT_TYPE, // float (32-bit ondalıklı sayı)
|
||||
// FLOAT_MATH hatasından kaçınmak için _TYPE eki.
|
||||
// math.h'deki float tanımıyla çakışmaz.
|
||||
KW_DOUBLE, // double (64-bit ondalıklı sayı)
|
||||
KW_CHAR, // char (8-bit karakter)
|
||||
// Tek tırnak içindeki karakterler için: 'A'
|
||||
KW_STRING_TYPE, // string (metin tipi)
|
||||
// string.h'daki string işlevleriyle çakışmaz.
|
||||
|
||||
// --- Literal Keyword'ler ---
|
||||
KW_TRUE, // true
|
||||
KW_FALSE, // false
|
||||
KW_NULL, // null
|
||||
/* ====== Literal Keyword'ler ====== */
|
||||
KW_TRUE, // true (mantıksal doğru sabiti)
|
||||
// Boolean literal: if (true) { ... }
|
||||
KW_FALSE, // false (mantıksal yanlış sabiti)
|
||||
// Boolean literal: while (false) { ... }
|
||||
KW_NULL, // null (boş referans sabiti)
|
||||
// Pointer/referans tipleri için: Object obj = null;
|
||||
|
||||
// --- İstisna Yönetimi ---
|
||||
KW_TRY, // try
|
||||
KW_CATCH, // catch
|
||||
KW_FINALLY, // finally
|
||||
KW_THROW, // throw
|
||||
KW_THROWS, // throws
|
||||
KW_ASSERT, // assert
|
||||
/* ====== İstisna Yönetimi ====== */
|
||||
KW_TRY, // try (istisna deneme bloğu — Java/C++ tarzı)
|
||||
// Sözdizimi: try { ... } catch (Ex e) { ... }
|
||||
KW_CATCH, // catch (istisna yakalama bloğu)
|
||||
KW_FINALLY, // finally (her durumda çalışan blok — Java tarzı)
|
||||
KW_THROW, // throw (istisna fırlatma — C++/Java tarzı)
|
||||
// Sözdizimi: throw new Exception("hata");
|
||||
KW_THROWS, // throws (metot imzasında istisna bildirimi — Java)
|
||||
KW_ASSERT, // assert (debug assertions — C/Java tarzı)
|
||||
|
||||
// --- Modül/Paket ---
|
||||
KW_IMPORT, // import
|
||||
KW_PACKAGE, // package
|
||||
/* ====== Modül/Paket ====== */
|
||||
KW_IMPORT, // import (modül içe aktarma — Java/Python tarzı)
|
||||
// Sözdizimi: import java.util.List;
|
||||
KW_PACKAGE, // package (modül bildirimi — Java tarzı)
|
||||
// Sözdizimi: package com.saqut.compiler;
|
||||
|
||||
// --- C/C++ Ekleri ---
|
||||
KW_NATIVE, // native (JNI)
|
||||
KW_SYNCHRONIZED, // synchronized (Java)
|
||||
KW_VOLATILE, // volatile
|
||||
KW_TRANSIENT, // transient
|
||||
KW_CONST, // const
|
||||
KW_EXTERN, // extern
|
||||
KW_TYPEDEF, // typedef
|
||||
KW_SIZEOF, // sizeof
|
||||
KW_ALIGNOF, // alignof
|
||||
KW_DECLTYPE, // decltype
|
||||
KW_AUTO, // auto
|
||||
KW_CONSTEXPR, // constexpr
|
||||
KW_NOEXCEPT, // noexcept
|
||||
/* ====== C/C++ Ekleri ====== */
|
||||
KW_NATIVE, // native (yerel kod bildirimi — JNI)
|
||||
// Java native metotları için.
|
||||
KW_SYNCHRONIZED, // synchronized (iş parçacığı senkronizasyonu — Java)
|
||||
KW_VOLATILE, // volatile (derleyici optimizasyonunu engelle — C/C++/Java)
|
||||
KW_TRANSIENT, // transient (serileştirmeyi atla — Java)
|
||||
KW_CONST, // const (değişmez değer — C/C++ tarzı)
|
||||
// Örn: const int MAX = 100;
|
||||
KW_EXTERN, // extern (harici bağlantı — C/C++ tarzı)
|
||||
KW_TYPEDEF, // typedef (tip takma adı — C/C++ tarzı)
|
||||
KW_SIZEOF, // sizeof (tip/boyut sorgulama — C/C++ tarzı)
|
||||
// Sözdizimi: sizeof(int) veya sizeof x
|
||||
KW_ALIGNOF, // alignof (hizalama sorgulama — C++11)
|
||||
KW_DECLTYPE, // decltype (ifade tipi çıkarımı — C++11)
|
||||
KW_AUTO, // auto (otomatik tip çıkarımı — C++11)
|
||||
KW_CONSTEXPR, // constexpr (derleme zamanı sabiti — C++11)
|
||||
KW_NOEXCEPT, // noexcept (istisna fırlatmayan bildirimi — C++11)
|
||||
|
||||
// ================================================================
|
||||
// Operatörler — Öncelik sırasına göre gruplanmış
|
||||
// ================================================================
|
||||
/* ================================================================
|
||||
* Operatörler — Öncelik sırasına göre gruplanmış
|
||||
*
|
||||
* Her operatörün yanında Pratt parser öncelik seviyesi yazılıdır.
|
||||
* Yüksek sayı = daha sıkı bağlanma (önce işlenir).
|
||||
*
|
||||
* Seviye 18 (en yüksek): Üye erişimi ve çağrı
|
||||
* Seviye 17: Postfix ++ --
|
||||
* Seviye 16: Unary prefix + - ! ~
|
||||
* Seviye 15: Üs alma ** ^
|
||||
* Seviye 14: Çarpma/Bölme * / %
|
||||
* Seviye 13: Toplama/Çıkarma + -
|
||||
* Seviye 12: Bitsel kaydırma << >>
|
||||
* Seviye 11: İlişkisel < <= > >=
|
||||
* Seviye 10: Eşitlik == !=
|
||||
* Seviye 9: Bitsel VE &
|
||||
* Seviye 8: Bitsel XOR ^ (CARET üs olarak 15'te)
|
||||
* Seviye 7: Bitsel VEYA |
|
||||
* Seviye 6: Mantıksal VE &&
|
||||
* Seviye 5: Mantıksal VEYA ||
|
||||
* Seviye 4: Ternary ?
|
||||
* Seviye 3: Ternary else :
|
||||
* Seviye 2: Atama = += -= vb.
|
||||
* Seviye 1 (en düşük): Virgül ,
|
||||
* ================================================================ */
|
||||
|
||||
// Seviye 1 (18): Üye erişimi ve çağrı — En yüksek öncelik
|
||||
DOT, // .
|
||||
ARROW, // ->
|
||||
LBRACKET, // [
|
||||
RBRACKET, // ]
|
||||
LPAREN, // (
|
||||
RPAREN, // )
|
||||
// Seviye 18: Üye erişimi ve çağrı — En yüksek öncelik
|
||||
DOT, // . (üye erişimi) — obj.field
|
||||
// Öncelik 18. En sıkı bağlanan operatör.
|
||||
ARROW, // -> (pointer üye erişimi) — ptr->field
|
||||
// C++ tarzı. Öncelik 18.
|
||||
LBRACKET, // [ (dizi/indeks erişimi başlangıcı) — a[i]
|
||||
// Açılış köşeli parantez. Öncelik 18.
|
||||
RBRACKET, // ] (dizi/indeks erişimi bitişi) — a[i]
|
||||
// Kapanış köşeli parantez. Tek başına kullanılmaz.
|
||||
LPAREN, // ( (fonksiyon çağrısı/grouping başlangıcı)
|
||||
// İki anlamı: f(args) çağrı, (expr) gruplama.
|
||||
// Öncelik 18.
|
||||
RPAREN, // ) (fonksiyon çağrısı/grouping bitişi)
|
||||
// Kapanış parantez. Tek başına kullanılmaz.
|
||||
|
||||
// Seviye 2 (17): Postfix
|
||||
PLUS_PLUS, // ++ (postfix)
|
||||
MINUS_MINUS, // -- (postfix)
|
||||
// Seviye 17: Postfix — Soldaki ifadeye sonradan uygulanan operatörler
|
||||
PLUS_PLUS, // ++ (postfix artım) — x++
|
||||
// Önce x'in değerini döndür, sonra artır.
|
||||
// Öncelik 17. Sağ birleşmeli DEĞİL.
|
||||
MINUS_MINUS, // -- (postfix azaltım) — x--
|
||||
// Önce x'in değerini döndür, sonra azalt.
|
||||
// Öncelik 17.
|
||||
|
||||
// Seviye 3 (16): Unary Prefix
|
||||
PLUS, // + (unary)
|
||||
MINUS, // - (unary)
|
||||
BANG, // ! (mantıksal değil)
|
||||
TILDE, // ~ (bitsel değil)
|
||||
// Seviye 16: Unary Prefix — Sağındaki ifadeye uygulanan tekli operatörler
|
||||
PLUS, // + (unary plus / binary toplama)
|
||||
// Unary: +x (pozitif işareti, genelde etkisiz).
|
||||
// Binary: a + b (toplama, öncelik 13).
|
||||
// Hangi anlamda kullanıldığı parse bağlamında belirlenir.
|
||||
MINUS, // - (unary minus / binary çıkarma)
|
||||
// Unary: -x (negatif yap).
|
||||
// Binary: a - b (çıkarma, öncelik 13).
|
||||
BANG, // ! (mantıksal değil) — !x
|
||||
// Örn: if (!flag) { ... }
|
||||
// Sadece prefix. Öncelik 16.
|
||||
TILDE, // ~ (bitsel değil) — ~x
|
||||
// Bitwise NOT. Sadece prefix. Öncelik 16.
|
||||
|
||||
// Seviye 4 (15): Üs alma
|
||||
STAR_STAR, // ** (Python tarzı üs)
|
||||
CARET, // ^ (bazı dillerde üs)
|
||||
// Seviye 15: Üs alma — Sağ birleşmeli
|
||||
STAR_STAR, // ** (üs alma) — a ** b = a^b
|
||||
// Python tarzı. Öncelik 15. Sağ birleşmeli.
|
||||
// 2 ** 3 ** 2 = 2 ** (3 ** 2) = 512
|
||||
CARET, // ^ (üs alma veya bitsel XOR)
|
||||
// saQut'ta varsayılan: üs alma (öncelik 15).
|
||||
// C/C++'da XOR (öncelik 8) — bağlama göre değişebilir.
|
||||
|
||||
// Seviye 5 (14): Çarpma/Bölme
|
||||
STAR, // *
|
||||
SLASH, // /
|
||||
PERCENT, // %
|
||||
// Seviye 14: Çarpma/Bölme — Sol birleşmeli
|
||||
STAR, // * (çarpma) — a * b
|
||||
// Öncelik 14.
|
||||
SLASH, // / (bölme) — a / b
|
||||
// Tamsayı bölmesi: int / int = int.
|
||||
// Ondalık bölme: float / float = float.
|
||||
PERCENT, // % (mod alma) — a % b
|
||||
// Sadece tamsayılar için.
|
||||
|
||||
// Seviye 6 (13): Toplama/Çıkarma — PLUS ve MINUS yukarıda (unary + binary)
|
||||
// Seviye 7 (12): Bitsel kaydırma
|
||||
LSHIFT, // <<
|
||||
RSHIFT, // >>
|
||||
// Seviye 13: Toplama/Çıkarma
|
||||
// PLUS ve MINUS yukarıda tanımlandı (hem unary 16 hem binary 13).
|
||||
// Pratt parser bağlama göre doğru önceliği kullanır.
|
||||
|
||||
// Seviye 8 (11): İlişkisel karşılaştırma
|
||||
LESS, // <
|
||||
LESS_EQUAL, // <=
|
||||
GREATER, // >
|
||||
GREATER_EQUAL, // >=
|
||||
// Seviye 12: Bitsel kaydırma
|
||||
LSHIFT, // << (sola kaydırma) — a << b
|
||||
// a * 2^b. Öncelik 12.
|
||||
RSHIFT, // >> (sağa kaydırma) — a >> b
|
||||
// a / 2^b (işaretli: arithmetic, işaretsiz: logical).
|
||||
|
||||
// Seviye 9 (10): Eşitlik
|
||||
EQUAL_EQUAL, // ==
|
||||
BANG_EQUAL, // !=
|
||||
// Seviye 11: İlişkisel karşılaştırma
|
||||
LESS, // < (küçüktür) — a < b
|
||||
// true/false döndürür.
|
||||
LESS_EQUAL, // <= (küçük eşittir) — a <= b
|
||||
GREATER, // > (büyüktür) — a > b
|
||||
GREATER_EQUAL, // >= (büyük eşittir) — a >= b
|
||||
|
||||
// Seviye 10 (9): Bitsel VE
|
||||
AMPERSAND, // &
|
||||
// Seviye 10: Eşitlik
|
||||
EQUAL_EQUAL, // == (eşittir) — a == b
|
||||
// Değer eşitliği. Öncelik 10.
|
||||
BANG_EQUAL, // != (eşit değildir) — a != b
|
||||
|
||||
// Seviye 11 (8): Bitsel XOR — CARET yukarıda (üs veya XOR)
|
||||
// Seviye 9: Bitsel VE
|
||||
AMPERSAND, // & (bitsel VE) — a & b
|
||||
// Bitwise AND. Öncelik 9.
|
||||
|
||||
// Seviye 12 (7): Bitsel VEYA
|
||||
PIPE, // |
|
||||
// Seviye 8: Bitsel XOR
|
||||
// ^ (CARET) yukarıda (üs olarak seviye 15'te).
|
||||
// Gelecekte XOR için ayrı token eklenebilir.
|
||||
|
||||
// Seviye 13 (6): Mantıksal VE
|
||||
AMPERSAND_AMPERSAND, // &&
|
||||
// Seviye 7: Bitsel VEYA
|
||||
PIPE, // | (bitsel VEYA) — a | b
|
||||
// Bitwise OR. Öncelik 7.
|
||||
|
||||
// Seviye 14 (5): Mantıksal VEYA
|
||||
PIPE_PIPE, // ||
|
||||
// Seviye 6: Mantıksal VE
|
||||
AMPERSAND_AMPERSAND, // && (mantıksal VE) — a && b
|
||||
// Kısa devre (short-circuit): a false ise b değerlendirilmez.
|
||||
// Öncelik 6.
|
||||
|
||||
// Seviye 15 (4): Üçlü koşul (ternary)
|
||||
TERNARY, // ?
|
||||
COLON, // : (ternary ve etiket için)
|
||||
// Seviye 5: Mantıksal VEYA
|
||||
PIPE_PIPE, // || (mantıksal VEYA) — a || b
|
||||
// Kısa devre: a true ise b değerlendirilmez.
|
||||
// Öncelik 5.
|
||||
|
||||
// Seviye 16 (3): Atama
|
||||
EQUAL, // =
|
||||
PLUS_EQUAL, // +=
|
||||
MINUS_EQUAL, // -=
|
||||
STAR_EQUAL, // *=
|
||||
SLASH_EQUAL, // /=
|
||||
PERCENT_EQUAL, // %=
|
||||
AMPERSAND_EQUAL, // &=
|
||||
PIPE_EQUAL, // |=
|
||||
CARET_EQUAL, // ^=
|
||||
LSHIFT_EQUAL, // <<=
|
||||
RSHIFT_EQUAL, // >>=
|
||||
// Seviye 4: Üçlü koşul (ternary) — Sağ birleşmeli
|
||||
TERNARY, // ? (ternary if) — a ? b : c
|
||||
// Öncelik 4. Sağ birleşmeli.
|
||||
// a ? b : c ? d : e = a ? b : (c ? d : e)
|
||||
COLON, // : (ternary else / etiket) — ternary'in ikinci kısmı
|
||||
// Ternary'de öncelik 3 (0 değil!).
|
||||
// Ayrıca switch/case etiketleri için de kullanılır.
|
||||
|
||||
// --- Diğer Semboller ---
|
||||
LBRACE, // {
|
||||
RBRACE, // }
|
||||
SEMICOLON, // ;
|
||||
COMMA, // ,
|
||||
COLON_COLON, // ::
|
||||
// Seviye 2: Atama — Sağ birleşmeli
|
||||
EQUAL, // = (basit atama) — a = b
|
||||
// Öncelik 2. Sağ birleşmeli.
|
||||
// a = b = 5 = a = (b = 5)
|
||||
PLUS_EQUAL, // += (topla ve ata) — a += b → a = a + b
|
||||
MINUS_EQUAL, // -= (çıkar ve ata) — a -= b → a = a - b
|
||||
STAR_EQUAL, // *= (çarp ve ata) — a *= b → a = a * b
|
||||
SLASH_EQUAL, // /= (böl ve ata) — a /= b → a = a / b
|
||||
PERCENT_EQUAL, // %= (mod al ve ata) — a %= b → a = a % b
|
||||
AMPERSAND_EQUAL, // &= (bitsel VE ve ata) — a &= b → a = a & b
|
||||
PIPE_EQUAL, // |= (bitsel VEYA ve ata) — a |= b → a = a | b
|
||||
CARET_EQUAL, // ^= (XOR ve ata) — a ^= b → a = a ^ b
|
||||
LSHIFT_EQUAL, // <<= (sola kaydır ve ata) — a <<= b → a = a << b
|
||||
RSHIFT_EQUAL, // >>= (sağa kaydır ve ata) — a >>= b → a = a >> b
|
||||
|
||||
// --- Özel ---
|
||||
END_OF_FILE, // Dosya sonu
|
||||
UNKNOWN, // Bilinmeyen karakter
|
||||
COMMENT, // Yorum (// veya /* */) — şu anda token üretilmez
|
||||
PREPROCESSOR, // Önişlemci (#) — şu anda kullanılmıyor
|
||||
/* ====== Diğer Semboller ====== */
|
||||
LBRACE, // { (açılış süslü parantez) — blok başlangıcı
|
||||
// Sözdizimi: { statement1; statement2; }
|
||||
RBRACE, // } (kapanış süslü parantez) — blok bitişi
|
||||
SEMICOLON, // ; (noktalı virgül) — ifade sonu belirteci
|
||||
// C/C++/Java tarzında her ifade ; ile biter.
|
||||
COMMA, // , (virgül) — ifade ayırıcı
|
||||
// Örn: int a, b, c; veya f(1, 2, 3)
|
||||
// Öncelik 1 (en düşük).
|
||||
COLON_COLON, // :: (kapsam çözümleme) — Class::method
|
||||
// C++ tarzı. Şu anda sadece token tanımlı, parse yok.
|
||||
|
||||
/* ====== Özel Token'lar ====== */
|
||||
END_OF_FILE, // Dosya sonu belirteci.
|
||||
// Tokenizer dosya sonuna gelindiğinde üretir.
|
||||
// Parser'ın durma koşuludur.
|
||||
UNKNOWN, // Bilinmeyen/tanınamayan karakter.
|
||||
// Tokenizer'ın çözemediği her şey.
|
||||
// Hata raporlamada kullanılır.
|
||||
COMMENT, // Yorum token'ı (// veya /* */).
|
||||
// ŞU ANDA TOKEN ÜRETİLMEZ — tokenizer yorumları atlar.
|
||||
// Gelecekte belge yorumları (///, /** */) için kullanılabilir.
|
||||
PREPROCESSOR, // Önişlemci direktifi (#).
|
||||
// ŞU ANDA KULLANILMIYOR — C önişlemcisi yok.
|
||||
// Gelecekte #include, #define için.
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// KEYWORD_MAP — Keyword String → TokenType
|
||||
// KEYWORD_MAP — Keyword String → TokenType Dönüşüm Haritası
|
||||
// ============================================================================
|
||||
//
|
||||
// Tokenizer'ın ürettiği KeywordToken'ların token değerini (örn: "if")
|
||||
// Parser'ın anlayacağı TokenType'a (KW_IF) dönüştürür.
|
||||
// AMAÇ: Tokenizer'ın ürettiği KeywordToken'ların token değerini (örn: "if")
|
||||
// Parser'ın anlayacağı TokenType'a (KW_IF) dönüştürür.
|
||||
//
|
||||
// std::unordered_map: O(1) ortalama arama. const: derleme zamanı sabiti.
|
||||
// std::string_view: string kopyalamadan kaçınır.
|
||||
// ANAHTAR: std::string_view — keyword string'i (kopyalanmaz, salt okunur)
|
||||
// DEĞER: TokenType — Parser'ın anlayacağı anlamsal tip
|
||||
//
|
||||
// NOT: Bu harita, Tokenizer'daki keywords[] dizisi ile eşleşmelidir.
|
||||
// Birinde ekleme yapılırsa diğerine de eklenmelidir.
|
||||
// VERİ YAPISI: std::unordered_map<string_view, TokenType>
|
||||
// - O(1) ortalama arama süresi
|
||||
// - constexpr: derleme zamanı sabiti (derleyici tabloya gömer)
|
||||
// - std::string_view: string kopyalamadan kaçınır (performans)
|
||||
//
|
||||
// BOYUT: ~60 girdi (tüm keyword'ler)
|
||||
// NEDEN unordered_map, neden map değil?
|
||||
// - Arama sıklığı: her token için bir kez
|
||||
// - unordered_map O(1) vs map O(log n) — fark küçük ama var
|
||||
// - Sıralı erişim gerekmez
|
||||
//
|
||||
// SENKRONİZASYON UYARISI:
|
||||
// Bu harita, Tokenizer'daki keywords[] dizisi İLE EŞLEŞMELİDİR.
|
||||
// Birinde ekleme yapılırsa diğerine de eklenmelidir.
|
||||
// TODO: İki listeyi ortak bir kaynaktan üretecek bir makro/kod üreteci.
|
||||
//
|
||||
inline const std::unordered_map<std::string_view, TokenType> KEYWORD_MAP = {
|
||||
// --- Control flow ---
|
||||
|
|
@ -359,16 +486,30 @@ inline const std::unordered_map<std::string_view, TokenType> KEYWORD_MAP = {
|
|||
};
|
||||
|
||||
// ============================================================================
|
||||
// OPERATOR_MAP — Operatör/Delimiter String → TokenType
|
||||
// OPERATOR_MAP — Operatör/Delimiter String → TokenType Dönüşüm Haritası
|
||||
// ============================================================================
|
||||
//
|
||||
// Tokenizer'ın ürettiği OperatorToken ve DelimiterToken'ları TokenType'a
|
||||
// dönüştürür. Her iki token tipi de aynı haritayı kullanır çünkü parser
|
||||
// seviyesinde delimiter'lar da operatör gibi işlenir.
|
||||
// AMAÇ: Tokenizer'ın ürettiği OperatorToken ve DelimiterToken'ları TokenType'a
|
||||
// dönüştürür. Her iki token tipi de aynı haritayı kullanır çünkü
|
||||
// Parser seviyesinde delimiter'lar da operatör gibi işlenir.
|
||||
//
|
||||
// SIRALAMA ÖNEMLİ DEĞİL (unordered_map).
|
||||
// Ama Tokenizer'daki operators[] ve delimiters[] dizilerindeki sıralama
|
||||
// önemlidir — çok karakterliler önce gelmelidir.
|
||||
// ANAHTAR: std::string_view — operatör/delimiter string'i (örn: "+", "->", "{")
|
||||
// DEĞER: TokenType — Parser'ın anlayacağı anlamsal tip
|
||||
//
|
||||
// VERİ YAPISI: std::unordered_map<string_view, TokenType>
|
||||
// - O(1) ortalama arama
|
||||
// - const: derleme zamanı sabiti
|
||||
// - Boyut: ~40 girdi
|
||||
//
|
||||
// NEDEN İKİ AYRI HARİTA DEĞİL (operator + delimiter)?
|
||||
// - Parser seviyesinde fark yok: {, }, ; hepsi operatör gibi işlenir.
|
||||
// - Tek harita = tek arama = daha basit kod.
|
||||
//
|
||||
// SIRALAMA UYARISI:
|
||||
// Bu haritada sıralama önemli DEĞİL (unordered_map).
|
||||
// ANCAK Tokenizer'daki operators[] ve delimiters[] dizilerindeki
|
||||
// sıralama ÖNEMLİDİR — çok karakterliler önce gelmelidir!
|
||||
// Örn: "->" önce, "-" sonra kontrol edilmelidir.
|
||||
//
|
||||
inline const std::unordered_map<std::string_view, TokenType> OPERATOR_MAP = {
|
||||
// --- 2 karakterli ---
|
||||
|
|
@ -428,12 +569,21 @@ inline const std::unordered_map<std::string_view, TokenType> OPERATOR_MAP = {
|
|||
};
|
||||
|
||||
// ============================================================================
|
||||
// OPERATOR_MAP_REV — TokenType → Operatör String (Log için)
|
||||
// OPERATOR_MAP_REV — TokenType → Operatör String (Log/Görüntüleme İçin)
|
||||
// ============================================================================
|
||||
//
|
||||
// AST ağacını konsola yazdırırken (log) TokenType enum değerini insan
|
||||
// tarafından okunabilir operatör sembolüne dönüştürür.
|
||||
// Örn: TokenType::PLUS → "+"
|
||||
// AMAÇ: TokenType enum değerini insan tarafından okunabilir operatör
|
||||
// sembolüne dönüştürür. Log çıktısı ve hata mesajları için kullanılır.
|
||||
//
|
||||
// ANAHTAR: TokenType — enum değeri (örn: TokenType::PLUS)
|
||||
// DEĞER: std::string_view — operatör sembolü (örn: "+")
|
||||
//
|
||||
// KULLANIM:
|
||||
// auto it = OPERATOR_MAP_REV.find(type);
|
||||
// if (it != OPERATOR_MAP_REV.end()) std::cout << it->second;
|
||||
//
|
||||
// NOT: TokenType::IDENTIFIER, NUMBER, STRING, KW_* ve özel token'lar
|
||||
// bu haritada YOKTUR (operatör değiller). Onlar için ayrı dönüşüm gerekir.
|
||||
//
|
||||
inline const std::unordered_map<TokenType, std::string_view> OPERATOR_MAP_REV = {
|
||||
{TokenType::ARROW, "->"},
|
||||
|
|
@ -486,11 +636,24 @@ inline const std::unordered_map<TokenType, std::string_view> OPERATOR_MAP_REV =
|
|||
};
|
||||
|
||||
// ============================================================================
|
||||
// OPERATOR_MAP_STRREV — TokenType → Enum İsmi (Log için)
|
||||
// OPERATOR_MAP_STRREV — TokenType → Enum İsmi (Debug/Log İçin)
|
||||
// ============================================================================
|
||||
//
|
||||
// AST log çıktısında operatörün enum ismini gösterir.
|
||||
// Örn: TokenType::PLUS → "PLUS"
|
||||
// AMAÇ: AST log çıktısında operatörün enum ismini (string olarak) gösterir.
|
||||
// OPERATOR_MAP_REV'den farkı: sembol yerine enum adı döndürür.
|
||||
//
|
||||
// KULLANIM:
|
||||
// AST dump/debug çıktısı: TokenPrecedence(PLUS) yerine "PLUS(13)" gösterimi.
|
||||
//
|
||||
// ANAHTAR: TokenType — enum değeri (örn: TokenType::PLUS)
|
||||
// DEĞER: std::string_view — enum ismi (örn: "PLUS")
|
||||
//
|
||||
// ÖRN: TokenType::PLUS → "PLUS"
|
||||
// TokenType::PLUS_EQUAL → "PLUS_EQUAL"
|
||||
//
|
||||
// NOT: İki harita da (REV ve STRREV) aynı anahtarları içerir ama farklı değerler.
|
||||
// REV: "+" (operatör sembolü)
|
||||
// STRREV: "PLUS" (enum ismi)
|
||||
//
|
||||
inline const std::unordered_map<TokenType, std::string_view> OPERATOR_MAP_STRREV = {
|
||||
{TokenType::ARROW, "ARROW"},
|
||||
|
|
@ -543,40 +706,50 @@ inline const std::unordered_map<TokenType, std::string_view> OPERATOR_MAP_STRREV
|
|||
};
|
||||
|
||||
// ============================================================================
|
||||
// TokenPrecedence — Operatör Öncelik Tablosu
|
||||
// TokenPrecedence — Operatör Öncelik Tablosu (Pratt Parser'ın Kalbi)
|
||||
// ============================================================================
|
||||
//
|
||||
// Pratt parser'ın kalbi. Her TokenType için bir öncelik seviyesi döndürür.
|
||||
// Yüksek sayı = daha sıkı bağlanma (daha yüksek öncelik).
|
||||
// AMAÇ: Her TokenType için bir öncelik seviyesi döndürür.
|
||||
// Yüksek sayı = daha sıkı bağlanma (önce işlenir).
|
||||
//
|
||||
// PARAMETRE: type — sorgulanan token tipi
|
||||
// DÖNÜŞ: uint16_t — öncelik seviyesi (0-18)
|
||||
// KARMAŞIKLIK: O(1) — switch/case (derleyici jump table üretir)
|
||||
//
|
||||
// KULLANIM:
|
||||
// uint16_t prec = TokenPrecedence(current.type);
|
||||
// if (prec >= minPrec) { parseLeftDenotation(left); }
|
||||
//
|
||||
// ÖNCELİK SEVİYELERİ (yüksekten düşüğe):
|
||||
// 18: Üye erişimi . -> [ ] ( )
|
||||
// 18: Üye erişimi . -> [ ] ( ) — En yüksek
|
||||
// 17: Postfix ++ --
|
||||
// 16: Unary prefix ! ~
|
||||
// 15: Üs alma ** ^
|
||||
// 16: Unary prefix ! ~ + -
|
||||
// 15: Üs alma ** ^ — Sağ birleşmeli
|
||||
// 14: Çarpma/Bölme * / %
|
||||
// 13: Toplama/Çıkarma + -
|
||||
// 12: Bitsel kaydırma << >>
|
||||
// 11: İlişkisel < <= > >=
|
||||
// 10: Eşitlik == !=
|
||||
// 9: Bitsel VE &
|
||||
// 8: Bitsel XOR ^ (üs olarak 15'te de var — bağlama göre)
|
||||
// 8: Bitsel XOR ^ (şu anda üs olarak 15'te)
|
||||
// 7: Bitsel VEYA |
|
||||
// 6: Mantıksal VE &&
|
||||
// 5: Mantıksal VEYA ||
|
||||
// 4: Ternary ?
|
||||
// 3: Ternary else :
|
||||
// 2: Atama = += -= vb.
|
||||
// 2: Atama = += -= vb. — Sağ birleşmeli
|
||||
// 1: Virgül ,
|
||||
// 0: Önceliksiz (değerler, EOF, bilinmeyen)
|
||||
//
|
||||
// NOT: C/C++'da ^ operatörü bitsel XOR'tur (seviye 8), ama Python'da üs (seviye 15).
|
||||
// saQut'ta ^ hem üs hem XOR olarak kullanılabilir (AST'de bağlam belirler).
|
||||
// Şimdilik ^ seviye 15 (üs) olarak ayarlı.
|
||||
// KARAR: Neden ^ (CARET) seviye 15 (üs) olarak ayarlı?
|
||||
// - C/C++'da ^ bitsel XOR'tur (seviye 8).
|
||||
// - Python'da ** üs, ^ XOR'tur.
|
||||
// - saQut'ta ^ varsayılan olarak üs alma olarak kullanılır.
|
||||
// - Gelecekte XOR için ayrı token (CARET_CARET ^^) eklenebilir.
|
||||
//
|
||||
// BUG FIX (commit 438bc0e): Seviye 8'deki ölü kod (CARET için case olmadan
|
||||
// return 8) temizlendi. CARET zaten seviye 15'te STAR_STAR ile birlikte
|
||||
// işleniyor.
|
||||
// BUG FIX (commit 438bc0e):
|
||||
// Seviye 8'de CARET için ölü kod (case olmadan return 8) vardı.
|
||||
// Temizlendi. CARET zaten seviye 15'te STAR_STAR ile birlikte işleniyor.
|
||||
//
|
||||
inline uint16_t TokenPrecedence(TokenType type) {
|
||||
switch (type) {
|
||||
|
|
@ -677,18 +850,29 @@ inline uint16_t TokenPrecedence(TokenType type) {
|
|||
}
|
||||
|
||||
// ============================================================================
|
||||
// RightAssociative — Sağdan Sola Birleşme Kontrolü
|
||||
// RightAssociative — Sağdan Sola Birleşme (Associativity) Kontrolü
|
||||
// ============================================================================
|
||||
//
|
||||
// Hangi operatörler sağdan sola birleşir?
|
||||
// AMAÇ: Bir operatörün sağdan sola mı, yoksa soldan sağa mı birleştiğini
|
||||
// belirler. Pratt parser'da doğru ağaç yapısını oluşturmak için kritik.
|
||||
//
|
||||
// PARAMETRE: type — sorgulanan operatör tipi
|
||||
// DÖNÜŞ: bool — true: sağ birleşmeli, false: sol birleşmeli
|
||||
// KARMAŞIKLIK: O(1) — switch/case
|
||||
//
|
||||
// Sağ birleşmeli operatörler (a OP b OP c = a OP (b OP c)):
|
||||
// - Üs alma: **, ^ (matematiksel: 2^3^2 = 2^(3^2) = 2^9 = 512)
|
||||
// - Atama: =, +=, -=, vb. (a = b = 5 → a = (b = 5))
|
||||
// - Ternary: ?: (a ? b : c ? d : e → a ? b : (c ? d : e))
|
||||
// - STAR_STAR (üs alma): 2 ** 3 ** 2 = 2 ** (3 ** 2) = 2^9 = 512
|
||||
// (matematiksel kural: üs sağdan sola birleşir)
|
||||
// - CARET (üs alma): 2 ^ 3 ^ 2 = 2 ^ (3 ^ 2) = 512
|
||||
// - EQUAL (atama): a = b = 5 → a = (b = 5)
|
||||
// (önce b = 5 çalışır, sonra a = b)
|
||||
// - +=, -=, *=, vb. (birleşik atama): a += b += 5 → a += (b += 5)
|
||||
// - TERNARY (üçlü koşul): a ? b : c ? d : e → a ? b : (c ? d : e)
|
||||
// (iç içe ternary'lerde sağdan sola)
|
||||
//
|
||||
// Sol birleşmeli operatörler (a OP b OP c = (a OP b) OP c):
|
||||
// - Tüm diğerleri: +, -, *, /, ==, &&, vb.
|
||||
// - Tüm diğerleri: +, -, *, /, ==, &&, ||, vb.
|
||||
// (a + b + c = (a + b) + c, yani önce a+b, sonuç + c)
|
||||
//
|
||||
inline bool RightAssociative(TokenType type) {
|
||||
switch (type) {
|
||||
|
|
@ -713,52 +897,103 @@ inline bool RightAssociative(TokenType type) {
|
|||
}
|
||||
|
||||
// ============================================================================
|
||||
// ParserToken — Parser'ın Kullandığı Token Yapısı
|
||||
// ParserToken — Parser'ın Kullandığı Token Yapısı (Köprü)
|
||||
// ============================================================================
|
||||
//
|
||||
// Tokenizer'ın ürettiği ham Token ile Parser'ın ihtiyaç duyduğu anlamsal
|
||||
// tipi (TokenType) bir arada tutar.
|
||||
// AMAÇ: Tokenizer'ın ürettiği ham Token ile Parser'ın ihtiyaç duyduğu
|
||||
// anlamsal tipi (TokenType) bir arada tutar. İki katman arasında
|
||||
// köprü görevi görür.
|
||||
//
|
||||
// ALANLAR:
|
||||
// token (Token*): Tokenizer'dan gelen orijinal token. Neden pointer?
|
||||
// Çünkü Token polimorfik bir sınıf hiyerarşisidir. Değer kopyası (Token)
|
||||
// object slicing'e neden olur — alt sınıf verileri (NumberToken.isFloat,
|
||||
// StringToken.context) kaybolur.
|
||||
// BUG FIX (commit 40579ca): Eskiden Token token (değer) tutuyordu.
|
||||
//
|
||||
// type (TokenType): Token'ın anlamsal tipi. Örn: NUMBER, PLUS, KW_IF.
|
||||
// token (Token*):
|
||||
// Tokenizer'dan gelen orijinal token'a pointer.
|
||||
// Neden pointer, neden değer (Token token) değil?
|
||||
//
|
||||
// Çünkü Token polimorfik bir sınıf hiyerarşisidir:
|
||||
// Token (base)
|
||||
// +-- NumberToken (isFloat, numberValue alanları)
|
||||
// +-- StringToken (context alanı)
|
||||
// +-- IdentifierToken
|
||||
// +-- OperatorToken
|
||||
// +-- DelimiterToken
|
||||
// +-- KeywordToken
|
||||
//
|
||||
// Değer kopyası (Token token) OBJECT SLICING'e neden olur:
|
||||
// NumberToken → Token'a kopyalanırken isFloat, numberValue KAYBOLUR.
|
||||
//
|
||||
// BUG FIX (commit 40579ca):
|
||||
// Eskiden "Token token" (değer) olarak tanımlanmıştı.
|
||||
// NumberToken.isFloat her zaman false dönüyordu çünkü slicing oluyordu.
|
||||
// "Token* token" (pointer) olarak değiştirildi.
|
||||
//
|
||||
// type (TokenType):
|
||||
// Token'ın anlamsal tipi. Örn: NUMBER, PLUS, KW_IF.
|
||||
// Tokeni parselerken parseToken() tarafından atanır.
|
||||
//
|
||||
// METOTLAR:
|
||||
// is(TokenType): Bu token belirtilen tipte mi?
|
||||
// is({...}): Bu token listedeki tiplerden biri mi?
|
||||
// getPowerOperator(): Bu token bir operatör ise önceliğini döndür.
|
||||
// isRightAssociative(): Bu operatör sağ birleşmeli mi?
|
||||
// is(TokenType): Tek tip kontrolü (O(1))
|
||||
// is(initializer_list): Çoklu tip kontrolü (O(k), k = liste boyutu)
|
||||
// getPowerOperator(): Öncelik sorgulama (O(1), TokenPrecedence'a yönlendirir)
|
||||
// isRightAssociative(): Birleşme yönü sorgulama (O(1))
|
||||
//
|
||||
struct ParserToken {
|
||||
Token* token = nullptr; // Tokenizer'dan gelen orijinal token
|
||||
TokenType type = TokenType::SVR_VOID; // Anlamsal tip
|
||||
/* ====== Alanlar ====== */
|
||||
|
||||
// Tek tip kontrolü
|
||||
// Tokenizer'dan gelen orijinal token pointer'ı.
|
||||
// nullptr olabilir mi? Hayır — geçerli bir token her zaman vardır.
|
||||
// SVR_VOID durumunda token nullptr olabilir (EOF sinyali).
|
||||
Token* token = nullptr;
|
||||
|
||||
// Token'ın anlamsal tipi.
|
||||
// Varsayılan: SVR_VOID (geçersiz/başlangıç değeri).
|
||||
// parseToken() tarafından atanır.
|
||||
TokenType type = TokenType::SVR_VOID;
|
||||
|
||||
/* ====== Kolaylık Metotları ====== */
|
||||
|
||||
// is() — Tek tip kontrolü
|
||||
// PARAMETRE: t — sorgulanan token tipi
|
||||
// DÖNÜŞ: true — bu token t tipinde
|
||||
// KARMAŞIKLIK: O(1)
|
||||
// KULLANIM: if (current.is(TokenType::SEMICOLON)) { ... }
|
||||
bool is(TokenType t) const {
|
||||
return type == t;
|
||||
}
|
||||
|
||||
// Çoklu tip kontrolü — örn: is({KW_INT, KW_FLOAT, KW_VOID})
|
||||
// is() — Çoklu tip kontrolü
|
||||
// PARAMETRE: types — kontrol edilecek tipler listesi
|
||||
// DÖNÜŞ: true — bu token listedeki tiplerden birine aitse
|
||||
// KARMAŞIKLIK: O(k) — k = liste boyutu
|
||||
// KULLANIM:
|
||||
// if (current.is({KW_INT, KW_FLOAT, KW_VOID})) { ... }
|
||||
// if (current.is({TokenType::SEMICOLON, TokenType::RPAREN})) { ... }
|
||||
bool is(std::initializer_list<TokenType> types) const {
|
||||
for (TokenType t : types)
|
||||
if (type == t) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Operatör önceliği (Pratt parser için)
|
||||
// getPowerOperator() — Operatör önceliği sorgulama (Pratt parser için)
|
||||
// DÖNÜŞ: uint16_t — öncelik seviyesi (0-18)
|
||||
// KARMAŞIKLIK: O(1) — TokenPrecedence'a yönlendirir
|
||||
// KULLANIM:
|
||||
// uint16_t prec = current.getPowerOperator();
|
||||
// while (prec >= minPrec) { ... parseLeftDenotation(left); }
|
||||
uint16_t getPowerOperator() const {
|
||||
return TokenPrecedence(type);
|
||||
}
|
||||
|
||||
// Sağ birleşmeli mi?
|
||||
// isRightAssociative() — Birleşme yönü sorgulama
|
||||
// DÖNÜŞ: true — sağ birleşmeli (atama, üs, ternary)
|
||||
// false — sol birleşmeli (toplama, çarpma, vb.)
|
||||
// KARMAŞIKLIK: O(1) — RightAssociative'a yönlendirir
|
||||
// KULLANIM:
|
||||
// bool rightAssoc = current.isRightAssociative();
|
||||
// uint16_t nextPrec = rightAssoc ? prec : prec + 1;
|
||||
bool isRightAssociative() const {
|
||||
return RightAssociative(type);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SAQUT_PARSER_TOKEN
|
||||
#endif // SAQUT_PARSER_TOKEN
|
||||
Loading…
Reference in New Issue