// ============================================================================ // 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ü // 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 // // BAĞIMLILIKLAR: // - tokenizer/tokenizer.hpp: Token sınıf hiyerarşisi (Token, NumberToken, vs.) // - KULLANAN: parser/ast.hpp, parser/parser.hpp // // 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) // // 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. // // Neden uint16_t tabanlı enum? // -> 65K token tipi fazlasıyla yeterli. 2 byte = bellek tasarrufu. // -> Her AST düğümünde TokenType saklanabilir (opsiyonel). // // 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). // // 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. // // ============================================================================ #ifndef SAQUT_PARSER_TOKEN #define SAQUT_PARSER_TOKEN #include #include #include #include #include #include "tokenizer/tokenizer.hpp" // ============================================================================ // TokenList — Token Vektörü Tip Kısaltması // ============================================================================ // // Tokenizer::scan() tarafından üretilen, Parser::parse() tarafından tüketilen // token listesi. Ham pointer'lar içerir — bellek yönetimi çağırana aittir. // // TODO: std::vector> ile otomatik bellek yönetimi // typedef std::vector TokenList; // ============================================================================ // TokenType — Anlamsal Token Tipleri (Enum) // ============================================================================ // // Tokenizer'ın ürettiği string tipli token'ları ("number", "operator", ...) // Parser'ın anlayacağı anlamsal tiplere dönüştürür. // // KATEGORİLER: // 1. Değerler: IDENTIFIER, NUMBER, STRING, SVR_VOID (geçersiz/EOF) // 2. Keyword'ler: KW_IF ... KW_NOEXCEPT (alfabetik sıralı) // 3. Operatörler: Öncelik sırasına göre gruplanmış // - Seviye 1: DOT, ARROW, LBRACKET, RBRACKET, LPAREN, RPAREN // - Seviye 2: PLUS_PLUS, MINUS_MINUS (postfix) // - Seviye 3: PLUS, MINUS, BANG, TILDE (unary prefix) // - Seviye 4: STAR_STAR, CARET (üs) // - Seviye 5: STAR, SLASH, PERCENT (çarpma/bölme) // - Seviye 6-16: devamı... // 4. Diğer: LBRACE, RBRACE, SEMICOLON, COMMA, COLON_COLON // 5. Özel: END_OF_FILE, UNKNOWN, COMMENT, PREPROCESSOR // // 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/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 (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 (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 (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 (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 (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 (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 (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ış * * 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 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 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 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 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 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 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 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 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: Eşitlik EQUAL_EQUAL, // == (eşittir) — a == b // Değer eşitliği. Öncelik 10. BANG_EQUAL, // != (eşit değildir) — a != b // Seviye 9: Bitsel VE AMPERSAND, // & (bitsel VE) — a & b // Bitwise AND. Öncelik 9. // Seviye 8: Bitsel XOR // ^ (CARET) yukarıda (üs olarak seviye 15'te). // Gelecekte XOR için ayrı token eklenebilir. // Seviye 7: Bitsel VEYA PIPE, // | (bitsel VEYA) — a | b // Bitwise OR. Öncelik 7. // 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 5: Mantıksal VEYA PIPE_PIPE, // || (mantıksal VEYA) — a || b // Kısa devre: a true ise b değerlendirilmez. // Öncelik 5. // 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. // 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 /* ====== 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 Dönüşüm Haritası // ============================================================================ // // 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. // // ANAHTAR: std::string_view — keyword string'i (kopyalanmaz, salt okunur) // DEĞER: TokenType — Parser'ın anlayacağı anlamsal tip // // VERİ YAPISI: std::unordered_map // - 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 KEYWORD_MAP = { // --- Control flow --- {"if", TokenType::KW_IF}, {"else", TokenType::KW_ELSE}, {"for", TokenType::KW_FOR}, {"while", TokenType::KW_WHILE}, {"do", TokenType::KW_DO}, {"switch", TokenType::KW_SWITCH}, {"case", TokenType::KW_CASE}, {"default", TokenType::KW_DEFAULT}, {"break", TokenType::KW_BREAK}, {"continue", TokenType::KW_CONTINUE}, {"return", TokenType::KW_RETURN}, // --- OOP --- {"class", TokenType::KW_CLASS}, {"struct", TokenType::KW_STRUCT}, {"interface", TokenType::KW_INTERFACE}, {"enum", TokenType::KW_ENUM}, {"extends", TokenType::KW_EXTENDS}, {"implements", TokenType::KW_IMPLEMENTS}, {"new", TokenType::KW_NEW}, // --- Access modifiers --- {"public", TokenType::KW_PUBLIC}, {"private", TokenType::KW_PRIVATE}, {"protected", TokenType::KW_PROTECTED}, {"static", TokenType::KW_STATIC}, {"final", TokenType::KW_FINAL}, {"abstract", TokenType::KW_ABSTRACT}, // --- Types --- {"void", TokenType::KW_VOID}, {"bool", TokenType::KW_BOOL}, {"int", TokenType::KW_INT}, {"float", TokenType::KW_FLOAT_TYPE}, {"double", TokenType::KW_DOUBLE}, {"char", TokenType::KW_CHAR}, {"string", TokenType::KW_STRING_TYPE}, // --- Literals --- {"true", TokenType::KW_TRUE}, {"false", TokenType::KW_FALSE}, {"null", TokenType::KW_NULL}, // --- Exception handling --- {"try", TokenType::KW_TRY}, {"catch", TokenType::KW_CATCH}, {"finally", TokenType::KW_FINALLY}, {"throw", TokenType::KW_THROW}, {"throws", TokenType::KW_THROWS}, {"assert", TokenType::KW_ASSERT}, // --- Modules/packages --- {"import", TokenType::KW_IMPORT}, {"package", TokenType::KW_PACKAGE}, // --- C/C++ specific --- {"const", TokenType::KW_CONST}, {"extern", TokenType::KW_EXTERN}, {"typedef", TokenType::KW_TYPEDEF}, {"sizeof", TokenType::KW_SIZEOF}, {"auto", TokenType::KW_AUTO}, {"constexpr", TokenType::KW_CONSTEXPR}, {"noexcept", TokenType::KW_NOEXCEPT}, {"native", TokenType::KW_NATIVE}, {"synchronized",TokenType::KW_SYNCHRONIZED}, {"volatile", TokenType::KW_VOLATILE}, {"transient", TokenType::KW_TRANSIENT}, }; // ============================================================================ // OPERATOR_MAP — Operatör/Delimiter String → TokenType Dönüşüm Haritası // ============================================================================ // // 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. // // ANAHTAR: std::string_view — operatör/delimiter string'i (örn: "+", "->", "{") // DEĞER: TokenType — Parser'ın anlayacağı anlamsal tip // // VERİ YAPISI: std::unordered_map // - 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 OPERATOR_MAP = { // --- 2 karakterli --- {"->", TokenType::ARROW}, {"::", TokenType::COLON_COLON}, {"==", TokenType::EQUAL_EQUAL}, {"!=", TokenType::BANG_EQUAL}, {"<=", TokenType::LESS_EQUAL}, {">=", TokenType::GREATER_EQUAL}, {"&&", TokenType::AMPERSAND_AMPERSAND}, {"||", TokenType::PIPE_PIPE}, {"++", TokenType::PLUS_PLUS}, {"--", TokenType::MINUS_MINUS}, {"<<", TokenType::LSHIFT}, {">>", TokenType::RSHIFT}, {"**", TokenType::STAR_STAR}, // --- Birleşik atama --- {"+=", TokenType::PLUS_EQUAL}, {"-=", TokenType::MINUS_EQUAL}, {"*=", TokenType::STAR_EQUAL}, {"/=", TokenType::SLASH_EQUAL}, {"%=", TokenType::PERCENT_EQUAL}, {"&=", TokenType::AMPERSAND_EQUAL}, {"|=", TokenType::PIPE_EQUAL}, {"^=", TokenType::CARET_EQUAL}, {"<<=", TokenType::LSHIFT_EQUAL}, {">>=", TokenType::RSHIFT_EQUAL}, // --- 1 karakterli operatörler --- {"+", TokenType::PLUS}, {"-", TokenType::MINUS}, {"*", TokenType::STAR}, {"/", TokenType::SLASH}, {"%", TokenType::PERCENT}, {"<", TokenType::LESS}, {">", TokenType::GREATER}, {"^", TokenType::CARET}, {"!", TokenType::BANG}, {"~", TokenType::TILDE}, {"&", TokenType::AMPERSAND}, {"|", TokenType::PIPE}, {"=", TokenType::EQUAL}, // --- Delimiter'lar (operatör gibi işlenir) --- {"[", TokenType::LBRACKET}, {"]", TokenType::RBRACKET}, {"(", TokenType::LPAREN}, {")", TokenType::RPAREN}, {"{", TokenType::LBRACE}, {"}", TokenType::RBRACE}, {";", TokenType::SEMICOLON}, {",", TokenType::COMMA}, {":", TokenType::COLON}, {".", TokenType::DOT}, {"?", TokenType::TERNARY}, }; // ============================================================================ // OPERATOR_MAP_REV — TokenType → Operatör String (Log/Görüntüleme İçin) // ============================================================================ // // 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 OPERATOR_MAP_REV = { {TokenType::ARROW, "->"}, {TokenType::COLON_COLON, "::"}, {TokenType::EQUAL_EQUAL, "=="}, {TokenType::BANG_EQUAL, "!="}, {TokenType::LESS_EQUAL, "<="}, {TokenType::GREATER_EQUAL, ">="}, {TokenType::AMPERSAND_AMPERSAND,"&&"}, {TokenType::PIPE_PIPE, "||"}, {TokenType::PLUS_PLUS, "++"}, {TokenType::MINUS_MINUS, "--"}, {TokenType::LSHIFT, "<<"}, {TokenType::RSHIFT, ">>"}, {TokenType::STAR_STAR, "**"}, {TokenType::PLUS_EQUAL, "+="}, {TokenType::MINUS_EQUAL, "-="}, {TokenType::STAR_EQUAL, "*="}, {TokenType::SLASH_EQUAL, "/="}, {TokenType::PERCENT_EQUAL, "%="}, {TokenType::AMPERSAND_EQUAL, "&="}, {TokenType::PIPE_EQUAL, "|="}, {TokenType::CARET_EQUAL, "^="}, {TokenType::LSHIFT_EQUAL, "<<="}, {TokenType::RSHIFT_EQUAL, ">>="}, {TokenType::PLUS, "+"}, {TokenType::MINUS, "-"}, {TokenType::STAR, "*"}, {TokenType::SLASH, "/"}, {TokenType::PERCENT, "%"}, {TokenType::LESS, "<"}, {TokenType::GREATER, ">"}, {TokenType::CARET, "^"}, {TokenType::BANG, "!"}, {TokenType::TILDE, "~"}, {TokenType::AMPERSAND, "&"}, {TokenType::PIPE, "|"}, {TokenType::EQUAL, "="}, {TokenType::LBRACKET, "["}, {TokenType::RBRACKET, "]"}, {TokenType::LPAREN, "("}, {TokenType::RPAREN, ")"}, {TokenType::LBRACE, "{"}, {TokenType::RBRACE, "}"}, {TokenType::SEMICOLON, ";"}, {TokenType::COMMA, ","}, {TokenType::COLON, ":"}, {TokenType::DOT, "."}, {TokenType::TERNARY, "?"}, }; // ============================================================================ // OPERATOR_MAP_STRREV — TokenType → Enum İsmi (Debug/Log İçin) // ============================================================================ // // 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 OPERATOR_MAP_STRREV = { {TokenType::ARROW, "ARROW"}, {TokenType::COLON_COLON, "COLON_COLON"}, {TokenType::EQUAL_EQUAL, "EQUAL_EQUAL"}, {TokenType::BANG_EQUAL, "BANG_EQUAL"}, {TokenType::LESS_EQUAL, "LESS_EQUAL"}, {TokenType::GREATER_EQUAL, "GREATER_EQUAL"}, {TokenType::AMPERSAND_AMPERSAND,"AMPERSAND_AMPERSAND"}, {TokenType::PIPE_PIPE, "PIPE_PIPE"}, {TokenType::PLUS_PLUS, "PLUS_PLUS"}, {TokenType::MINUS_MINUS, "MINUS_MINUS"}, {TokenType::LSHIFT, "LSHIFT"}, {TokenType::RSHIFT, "RSHIFT"}, {TokenType::STAR_STAR, "STAR_STAR"}, {TokenType::PLUS_EQUAL, "PLUS_EQUAL"}, {TokenType::MINUS_EQUAL, "MINUS_EQUAL"}, {TokenType::STAR_EQUAL, "STAR_EQUAL"}, {TokenType::SLASH_EQUAL, "SLASH_EQUAL"}, {TokenType::PERCENT_EQUAL, "PERCENT_EQUAL"}, {TokenType::AMPERSAND_EQUAL, "AMPERSAND_EQUAL"}, {TokenType::PIPE_EQUAL, "PIPE_EQUAL"}, {TokenType::CARET_EQUAL, "CARET_EQUAL"}, {TokenType::LSHIFT_EQUAL, "LSHIFT_EQUAL"}, {TokenType::RSHIFT_EQUAL, "RSHIFT_EQUAL"}, {TokenType::PLUS, "PLUS"}, {TokenType::MINUS, "MINUS"}, {TokenType::STAR, "STAR"}, {TokenType::SLASH, "SLASH"}, {TokenType::PERCENT, "PERCENT"}, {TokenType::LESS, "LESS"}, {TokenType::GREATER, "GREATER"}, {TokenType::CARET, "CARET"}, {TokenType::BANG, "BANG"}, {TokenType::TILDE, "TILDE"}, {TokenType::AMPERSAND, "AMPERSAND"}, {TokenType::PIPE, "PIPE"}, {TokenType::EQUAL, "EQUAL"}, {TokenType::LBRACKET, "LBRACKET"}, {TokenType::RBRACKET, "RBRACKET"}, {TokenType::LPAREN, "LPAREN"}, {TokenType::RPAREN, "RPAREN"}, {TokenType::LBRACE, "LBRACE"}, {TokenType::RBRACE, "RBRACE"}, {TokenType::SEMICOLON, "SEMICOLON"}, {TokenType::COMMA, "COMMA"}, {TokenType::COLON, "COLON"}, {TokenType::DOT, "DOT"}, {TokenType::TERNARY, "TERNARY"}, }; // ============================================================================ // TokenPrecedence — Operatör Öncelik Tablosu (Pratt Parser'ın Kalbi) // ============================================================================ // // 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 . -> [ ] ( ) — En yüksek // 17: Postfix ++ -- // 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 ^ (ş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. — Sağ birleşmeli // 1: Virgül , // 0: Önceliksiz (değerler, EOF, bilinmeyen) // // 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'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) { // Level 18: Member access / call case TokenType::DOT: case TokenType::ARROW: case TokenType::LBRACKET: case TokenType::LPAREN: return 18; // Level 17: Postfix case TokenType::PLUS_PLUS: case TokenType::MINUS_MINUS: return 17; // Level 16: Unary prefix — sadece her zaman prefix olanlar case TokenType::BANG: // ! case TokenType::TILDE: // ~ return 16; // Level 15: Exponentiation case TokenType::STAR_STAR: // ** case TokenType::CARET: // ^ (Python tarzı üs) return 15; // Level 14: Multiplicative case TokenType::STAR: // * case TokenType::SLASH: // / case TokenType::PERCENT: // % return 14; // Level 13: Additive — PLUS ve MINUS hem unary hem binary case TokenType::PLUS: // + case TokenType::MINUS: // - return 13; // Level 12: Bit shift case TokenType::LSHIFT: // << case TokenType::RSHIFT: // >> return 12; // Level 11: Relational case TokenType::LESS: // < case TokenType::LESS_EQUAL:// <= case TokenType::GREATER: // > case TokenType::GREATER_EQUAL: // >= return 11; // Level 10: Equality case TokenType::EQUAL_EQUAL: // == case TokenType::BANG_EQUAL: // != return 10; // Level 9: Bitwise AND case TokenType::AMPERSAND: // & return 9; // Level 8: Bitwise XOR — şu anda CARET seviye 15'te (üs) // Level 7: Bitwise OR case TokenType::PIPE: // | return 7; // Level 6: Logical AND case TokenType::AMPERSAND_AMPERSAND: // && return 6; // Level 5: Logical OR case TokenType::PIPE_PIPE: // || return 5; // Level 4: Ternary case TokenType::TERNARY: // ? return 4; case TokenType::COLON: // : (ternary için) return 3; // ternary'den düşük, atamadan yüksek // Level 2: Assignment case TokenType::EQUAL: // = case TokenType::PLUS_EQUAL:// += case TokenType::MINUS_EQUAL:// -= case TokenType::STAR_EQUAL:// *= case TokenType::SLASH_EQUAL:// /= case TokenType::PERCENT_EQUAL:// %= case TokenType::AMPERSAND_EQUAL:// &= case TokenType::PIPE_EQUAL:// |= case TokenType::CARET_EQUAL:// ^= case TokenType::LSHIFT_EQUAL:// <<= case TokenType::RSHIFT_EQUAL:// >>= return 2; // Level 1: Comma case TokenType::COMMA: // , return 1; default: return 0; // Önceliksiz: değerler, EOF, bilinmeyen } } // ============================================================================ // RightAssociative — Sağdan Sola Birleşme (Associativity) Kontrolü // ============================================================================ // // 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)): // - 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. // (a + b + c = (a + b) + c, yani önce a+b, sonuç + c) // inline bool RightAssociative(TokenType type) { switch (type) { case TokenType::STAR_STAR: // ** (üs) case TokenType::CARET: // ^ (üs) case TokenType::EQUAL: // = case TokenType::PLUS_EQUAL: // += case TokenType::MINUS_EQUAL:// -= case TokenType::STAR_EQUAL: // *= case TokenType::SLASH_EQUAL:// /= case TokenType::PERCENT_EQUAL:// %= case TokenType::AMPERSAND_EQUAL:// &= case TokenType::PIPE_EQUAL: // |= case TokenType::CARET_EQUAL:// ^= case TokenType::LSHIFT_EQUAL:// <<= case TokenType::RSHIFT_EQUAL:// >>= case TokenType::TERNARY: // ? (ternary) return true; default: return false; } } // ============================================================================ // ParserToken — Parser'ın Kullandığı Token Yapısı (Köprü) // ============================================================================ // // 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'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): 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 { /* ====== Alanlar ====== */ // 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; } // 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 types) const { for (TokenType t : types) if (type == t) return true; return false; } // 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); } // 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