diff --git a/Final.sqt b/Final.sqt new file mode 100644 index 0000000..f398a28 --- /dev/null +++ b/Final.sqt @@ -0,0 +1,89 @@ +int fibonacci(int n) { + if (n <= 1) + return n; + return fibonacci(n - 1) + fibonacci(n - 2); +} + +void fibonacciIterative(int n) { + int first = 0, second = 1, next; + + for (int i = 0; i < n; i++) { + if (i <= 1) + next = i; + else { + next = first + second; + first = second; + second = next; + } + printf("%d ", next); + } + printf("\n"); +} + +int main() { + int n = 10; + + // Formatlı ifade kullanmadan, string concatenation mantığı ile + printf(""); + printf(n); + printf(" elemanlı Fibonacci dizisi (iterative):\n"); + fibonacciIterative(n); + + printf("\n"); + printf(""); + printf(n); + printf(". Fibonacci sayısı (recursive): "); + printf(fibonacci(n - 1)); + printf("\n"); + + return 0; +} + +struct List { + int arr[100]; + int length; +}; + +struct List createList() { + struct List list; + list.length = 0; + return list; +} + +void push(struct List* list, int value) { + if (list->length < 100) { + list->arr[list->length] = value; + list->length++; + } +} + +int get(struct List* list, int index) { + if (index < list->length) { + return list->arr[index]; + } + return -1; +} + +void printList(struct List* list) { + for (int i = 0; i < list->length; i++) { + // println yerine direkt yaz + int val = list->arr[i]; + // sayıyı göster + } + // yeni satır +} + +int main() { + struct List myList = createList(); + + push(myList, 5); + push(myList, 10); + push(myList, 15); + + // JavaScript benzeri kullanım + // myList[0] gibi düşün + + printList(myList); + + return 0; +} \ No newline at end of file diff --git a/source.sqt b/source.sqt index f96b3bd..bdbbd29 100644 --- a/source.sqt +++ b/source.sqt @@ -1,10 +1 @@ -int main() { - int x = 0; - while (x < 5) { - x = x + 1; - } - do { - x = x - 1; - } while (x > 0); - return x; -} +int main() { int x = 0; while (x < 5) { x = x + 1; } do { x = x - 1; } while (x > 0); return x; } diff --git a/src/json.hpp b/src/json.hpp index 1dfdc08..eb0f81d 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -49,6 +49,10 @@ inline const char* astKindName(ASTKind k) { case ASTKind::BreakStatement: return "BreakStatement"; case ASTKind::ContinueStatement: return "ContinueStatement"; case ASTKind::ExpressionStatement: return "ExpressionStatement"; + case ASTKind::Call: return "Call"; + case ASTKind::MemberAccess: return "MemberAccess"; + case ASTKind::IndexExpression: return "IndexExpression"; + case ASTKind::StructDecl: return "StructDecl"; default: return "Unknown"; } } @@ -158,6 +162,27 @@ inline void analyzeRecursive(ASTNode* node, int currentDepth, AstAnalysis& a) { if (es->expression) analyzeRecursive(es->expression, currentDepth + 1, a); break; } + case ASTKind::Call: { + auto* call = (CallExpressionNode*)node; + if (call->callee) analyzeRecursive(call->callee, currentDepth + 1, a); + for (auto* arg : call->arguments) analyzeRecursive(arg, currentDepth + 1, a); + break; + } + case ASTKind::MemberAccess: { + auto* ma = (MemberAccessNode*)node; + if (ma->object) analyzeRecursive(ma->object, currentDepth + 1, a); + break; + } + case ASTKind::IndexExpression: { + auto* ie = (IndexExpressionNode*)node; + if (ie->object) analyzeRecursive(ie->object, currentDepth + 1, a); + if (ie->index) analyzeRecursive(ie->index, currentDepth + 1, a); + break; + } + case ASTKind::StructDecl: { + for (auto* child : node->getChildren()) analyzeRecursive(child, currentDepth + 1, a); + break; + } default: break; // Literal, Identifier, Break, Continue — yaprak düğüm } } @@ -204,6 +229,9 @@ inline void collectSymbolsRecursive(ASTNode* node, std::vector& sym if (node->kind == ASTKind::FunctionDecl) { auto* fn = (FunctionDeclNode*)node; symbols.push_back({fn->name, "function", fn->returnType}); + } else if (node->kind == ASTKind::StructDecl) { + auto* st = (StructDeclNode*)node; + symbols.push_back({st->name, "struct", ""}); } else if (node->kind == ASTKind::VariableDecl) { auto* vd = (VariableDeclNode*)node; symbols.push_back({vd->name, "variable", vd->varType}); @@ -270,6 +298,27 @@ inline void collectSymbolsRecursive(ASTNode* node, std::vector& sym if (es->expression) collectSymbolsRecursive(es->expression, symbols); break; } + case ASTKind::Call: { + auto* call = (CallExpressionNode*)node; + if (call->callee) collectSymbolsRecursive(call->callee, symbols); + for (auto* arg : call->arguments) collectSymbolsRecursive(arg, symbols); + break; + } + case ASTKind::MemberAccess: { + auto* ma = (MemberAccessNode*)node; + if (ma->object) collectSymbolsRecursive(ma->object, symbols); + break; + } + case ASTKind::IndexExpression: { + auto* ie = (IndexExpressionNode*)node; + if (ie->object) collectSymbolsRecursive(ie->object, symbols); + if (ie->index) collectSymbolsRecursive(ie->index, symbols); + break; + } + case ASTKind::StructDecl: { + for (auto* child : node->getChildren()) collectSymbolsRecursive(child, symbols); + break; + } default: break; } } diff --git a/src/parser/ast.hpp b/src/parser/ast.hpp index e53428f..42db235 100644 --- a/src/parser/ast.hpp +++ b/src/parser/ast.hpp @@ -76,6 +76,10 @@ enum class ASTKind { 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ı }; // ============================================================================ @@ -669,4 +673,149 @@ public: } }; + +// ============================================================================ +// CallExpressionNode — Fonksiyon Çağrısı f(a, b, ...) +// ============================================================================ + +class CallExpressionNode : public ASTNode { +public: + ASTNode* callee = nullptr; + std::vector arguments; + + CallExpressionNode() { kind = ASTKind::Call; } + + void log(int indent = 0) override { + std::cout << padRight("", indent) << "Call\n"; + if (callee) { + std::cout << padRight("", indent + 2) << "Callee:\n"; + callee->log(indent + 4); + } + std::cout << padRight("", indent + 2) << "Args (" << arguments.size() << "):\n"; + for (auto* a : arguments) a->log(indent + 4); + } + + std::string toJson(int depth = 0) override { + std::string in = jsonIndent(depth); + std::ostringstream ss; + ss << in << "{\n" + << in << " \"kind\": \"Call\""; + if (callee) { + ss << ",\n" << in << " \"callee\":\n" + << callee->toJson(depth + 2); + } + ss << ",\n" << in << " \"arguments\": [\n"; + for (size_t i = 0; i < arguments.size(); i++) { + ss << arguments[i]->toJson(depth + 3); + if (i + 1 < arguments.size()) ss << ","; + ss << "\n"; + } + ss << in << " ]\n" << in << "}"; + return ss.str(); + } +}; + +// ============================================================================ +// MemberAccessNode — Üye Erişimi a.b veya a->b +// ============================================================================ + +class MemberAccessNode : public ASTNode { +public: + ASTNode* object = nullptr; + std::string member; + bool arrow = false; + + MemberAccessNode() { kind = ASTKind::MemberAccess; } + + void log(int indent = 0) override { + std::cout << padRight("", indent) << "MemberAccess " + << (arrow ? "->" : ".") << " " << member << "\n"; + if (object) object->log(indent + 2); + } + + std::string toJson(int depth = 0) override { + std::string in = jsonIndent(depth); + std::ostringstream ss; + ss << in << "{\n" + << in << " \"kind\": \"MemberAccess\",\n" + << in << " \"member\": \"" << jsonEscape(member) << "\",\n" + << in << " \"arrow\": " << (arrow ? "true" : "false"); + if (object) { + ss << ",\n" << in << " \"object\":\n" + << object->toJson(depth + 2); + } + ss << "\n" << in << "}"; + return ss.str(); + } +}; + +// ============================================================================ +// IndexExpressionNode — Dizi Erişimi a[i] +// ============================================================================ + +class IndexExpressionNode : public ASTNode { +public: + ASTNode* object = nullptr; + ASTNode* index = nullptr; + + IndexExpressionNode() { kind = ASTKind::IndexExpression; } + + void log(int indent = 0) override { + std::cout << padRight("", indent) << "IndexExpression\n"; + if (object) { + std::cout << padRight("", indent + 2) << "Object:\n"; + object->log(indent + 4); + } + if (index) { + std::cout << padRight("", indent + 2) << "Index:\n"; + index->log(indent + 4); + } + } + + std::string toJson(int depth = 0) override { + std::string in = jsonIndent(depth); + std::ostringstream ss; + ss << in << "{\n" + << in << " \"kind\": \"IndexExpression\""; + if (object) { + ss << ",\n" << in << " \"object\":\n" + << object->toJson(depth + 2); + } + if (index) { + ss << ",\n" << in << " \"index\":\n" + << index->toJson(depth + 2); + } + ss << "\n" << in << "}"; + return ss.str(); + } +}; + +// ============================================================================ +// StructDeclNode — struct Tanımı +// ============================================================================ + +class StructDeclNode : public ASTNode { +public: + std::string name; + + StructDeclNode() { kind = ASTKind::StructDecl; } + + void log(int indent = 0) override { + std::cout << padRight("", indent) << "StructDecl " << name << "\n"; + for (auto* c : getChildren()) c->log(indent + 2); + } + + std::string toJson(int depth = 0) override { + std::string in = jsonIndent(depth); + std::ostringstream ss; + ss << in << "{\n" + << in << " \"kind\": \"StructDecl\",\n" + << in << " \"name\": \"" << jsonEscape(name) << "\",\n" + << in << " \"children\": [\n" + << childrenToJson(this, depth + 3) + << in << " ]\n" + << in << "}"; + return ss.str(); + } +}; #endif // SAQUT_AST diff --git a/src/parser/parser.hpp b/src/parser/parser.hpp index afabedf..73ac58b 100644 --- a/src/parser/parser.hpp +++ b/src/parser/parser.hpp @@ -115,6 +115,7 @@ private: // --- Deklarasyonlar --- ASTNode* parseDeclaration(); ASTNode* parseFunctionDecl(); + ASTNode* parseStructDecl(); ASTNode* parseVariableDecl(); // --- Statement'lar --- @@ -267,7 +268,11 @@ inline ASTNode* Parser::parseDeclaration() { return parseVariableDecl(); } - // Tip keyword'ü değil → statement (veya REPL ifadesi) + // struct + if (ct.type == TokenType::KW_STRUCT) + return parseStructDecl(); + + // Tip keyword'ü değil → statement return parseStatement(); } @@ -308,6 +313,29 @@ inline ASTNode* Parser::parseFunctionDecl() { return fn; } +// -------------------------------------------------------------------------- +// parseStructDecl: struct tanimi. +// -------------------------------------------------------------------------- +inline ASTNode* Parser::parseStructDecl() { + StructDeclNode* st = new StructDeclNode(); + nextToken(); + if (currentToken().type == TokenType::IDENTIFIER) { + st->name = currentToken().token->token; + nextToken(); + } + if (currentToken().type == TokenType::LBRACE) { + nextToken(); + while (currentToken().type != TokenType::RBRACE && currentToken().type != TokenType::SVR_VOID) { + ASTNode* field = parseDeclaration(); + if (field) st->addChild(field); + else break; + } + if (currentToken().type == TokenType::RBRACE) nextToken(); + } + if (currentToken().type == TokenType::SEMICOLON) nextToken(); + return st; +} + // -------------------------------------------------------------------------- // parseVariableDecl: Değişken tanımı. @@ -805,9 +833,8 @@ inline ASTNode* Parser::parseLeftDenotation(ASTNode* left) { auto ct = currentToken(); // --- Postfix: expr++, expr-- --- - // Operatör operand'dan SONRA gelir, sağ operand yok. if (ct.is({TokenType::PLUS_PLUS, TokenType::MINUS_MINUS})) { - nextToken(); // Operatörü tüket + nextToken(); PostfixNode* pf = new PostfixNode(); pf->operand = left; pf->Operator = ct.type; @@ -815,13 +842,60 @@ inline ASTNode* Parser::parseLeftDenotation(ASTNode* left) { return pf; } - // --- Binary infix: expr OP expr --- - // OP'nin önceliğine göre sağ operand'ı ayrıştır. - uint16_t prec = ct.getPowerOperator(); - nextToken(); // Operatörü tüket + // --- Fonksiyon cagrisi: expr(args) --- + if (ct.type == TokenType::LPAREN) { + nextToken(); + CallExpressionNode* call = new CallExpressionNode(); + call->callee = left; + left->parent = call; + + if (currentToken().type != TokenType::RPAREN) { + call->arguments.push_back(parseExpression(0)); + while (currentToken().type == TokenType::COMMA) { + nextToken(); + call->arguments.push_back(parseExpression(0)); + } + } + if (currentToken().type == TokenType::RPAREN) + nextToken(); + return call; + } + + // --- Dizi erisimi: expr[index] --- + if (ct.type == TokenType::LBRACKET) { + nextToken(); + IndexExpressionNode* idx = new IndexExpressionNode(); + idx->object = left; + left->parent = idx; + idx->index = parseExpression(0); + if (currentToken().type == TokenType::RBRACKET) + nextToken(); + return idx; + } + + // --- Uye erisimi: expr.member / expr->member --- + if (ct.type == TokenType::DOT || ct.type == TokenType::ARROW) { + bool arrow = (ct.type == TokenType::ARROW); + nextToken(); + + if (currentToken().type != TokenType::IDENTIFIER) { + std::cerr << "Parser hatasi: uye ismi bekleniyor\n"; + return left; + } + + MemberAccessNode* ma = new MemberAccessNode(); + ma->object = left; + ma->member = currentToken().token->token; + ma->arrow = arrow; + left->parent = ma; + nextToken(); + return ma; + } + + // --- Binary infix: expr OP expr --- + uint16_t prec = ct.getPowerOperator(); + nextToken(); - // Sağ operand. prec parametresi, daha yüksek öncelikli operatörlerin - // sağ operand içinde gruplanmasını sağlar. ASTNode* right = parseExpression(prec); BinaryExpressionNode* bin = new BinaryExpressionNode(); diff --git a/src/parser/token.hpp b/src/parser/token.hpp index 32fea04..d05eee9 100644 --- a/src/parser/token.hpp +++ b/src/parser/token.hpp @@ -129,6 +129,7 @@ enum class TokenType : uint16_t { // --- OOP Keyword'leri --- KW_CLASS, // class + KW_STRUCT, // struct KW_INTERFACE, // interface KW_ENUM, // enum KW_EXTENDS, // extends @@ -302,6 +303,7 @@ inline const std::unordered_map KEYWORD_MAP = { // --- OOP --- {"class", TokenType::KW_CLASS}, + {"struct", TokenType::KW_STRUCT}, {"interface", TokenType::KW_INTERFACE}, {"enum", TokenType::KW_ENUM}, {"extends", TokenType::KW_EXTENDS}, diff --git a/src/tokenizer/token.hpp b/src/tokenizer/token.hpp new file mode 100644 index 0000000..c99af99 --- /dev/null +++ b/src/tokenizer/token.hpp @@ -0,0 +1,69 @@ +// ============================================================================ +// saQut Compiler — Token Sınıfları +// ============================================================================ +// +// DİZİN: src/tokenizer/token.hpp +// KATMAN: Katman 2 — Tokenizer ile Parser arasında veri yapısı +// BAĞIMLI: Yok (sadece ) +// +// AMAÇ: +// Tüm token tiplerinin temel sınıfları. 6 adet polimorfik token tipi: +// Token → NumberToken, StringToken, OperatorToken, DelimiterToken, +// KeywordToken, IdentifierToken +// +// ============================================================================ + +#ifndef SAQUT_TOKENIZER_TOKEN +#define SAQUT_TOKENIZER_TOKEN + +#include + +class Token { +protected: + std::string type; +public: + int start = 0; + int end = 0; + std::string token; + std::string gettype() { return type; } + virtual ~Token() = default; +}; + +class StringToken : public Token { +public: + StringToken() { type = "string"; } + std::string context; + int size = 0; +}; + +class NumberToken : public Token { +public: + NumberToken() { type = "number"; } + bool isFloat = false; + bool hasEpsilon = false; + int base = 10; +}; + +class OperatorToken : public Token { +public: + OperatorToken() { type = "operator"; } +}; + +class DelimiterToken : public Token { +public: + DelimiterToken() { type = "delimiter"; } +}; + +class KeywordToken : public Token { +public: + KeywordToken() { type = "keyword"; } +}; + +class IdentifierToken : public Token { +public: + IdentifierToken() { type = "identifier"; } + std::string context; + int size = 0; +}; + +#endif // SAQUT_TOKENIZER_TOKEN diff --git a/src/tokenizer/tokenizer.hpp b/src/tokenizer/tokenizer.hpp index 7f73091..bd44607 100644 --- a/src/tokenizer/tokenizer.hpp +++ b/src/tokenizer/tokenizer.hpp @@ -73,124 +73,7 @@ #include #include "lexer/lexer.hpp" -// ============================================================================ -// Token Temel Sınıfı -// ============================================================================ -// -// Tüm token tiplerinin ortak atası. Polimorfik kullanım için virtual destructor -// içerir. type alanı, token'ın hangi alt sınıfa ait olduğunu string olarak tutar -// (RTTI'ye alternatif, daha hafif). -// -// ALANLAR: -// type : Token tipi ("number", "string", "operator", "delimiter", "keyword", "identifier") -// token : Token'ın ham metin hali (örn: "42", "+", "if", "myVar") -// start : Kaynak koddaki başlangıç offset'i (Lexer offset'i) -// end : Kaynak koddaki bitiş offset'i -// -class Token { -protected: - std::string type; // Alt sınıf tarafından constructor'da atanır -public: - int start = 0; // Kaynak koddaki başlangıç konumu - int end = 0; // Kaynak koddaki bitiş konumu - std::string token; // Token'ın ham metin gösterimi - - std::string gettype() { return type; } - virtual ~Token() = default; -}; - -// ============================================================================ -// StringToken — String Literal'ları ("...") -// ============================================================================ -// -// Örnek: "merhaba dünya", "satır\niki", "tırnak \" içinde" -// -// context: Escape sequence'ler çözümlenmiş gerçek string içeriği. -// Örn: token="\"a\\nb\"" ise context="a\nb" -// size: context'in uzunluğu (token'dan farklı olabilir) -// token: Tırnak işaretleri ve escape sequence'ler dahil ham hali -// -class StringToken : public Token { -public: - StringToken() { type = "string"; } - std::string context; // İşlenmiş string içeriği (escape'ler açılmış) - int size = 0; // context uzunluğu -}; - -// ============================================================================ -// NumberToken — Sayısal Literal'lar (42, 0xFF, 3.14) -// ============================================================================ -// -// Sayı tabanı, float/整数 ayrımı, bilimsel gösterim bilgisi taşır. -// Lexer'ın INumber yapısından dönüştürülür. -// -// isFloat: true ise float/double literal (nokta veya epsilon içerir) -// hasEpsilon: true ise bilimsel gösterim (örn: 1e10) -// base: Sayı tabanı: 2, 8, 10, 16 -// token: Sayının ham string hali (örn: "0xFF", "3.14e-2") -// -class NumberToken : public Token { -public: - NumberToken() { type = "number"; } - bool isFloat = false; // Ondalıklı sayı mı? - bool hasEpsilon = false; // Bilimsel gösterim (e/E) içeriyor mu? - int base = 10; // Sayı tabanı -}; - -// ============================================================================ -// OperatorToken — Operatörler (+, -, *, /, ==, ++, vb.) -// ============================================================================ -// -// Aritmetik, karşılaştırma, mantıksal, bitsel, atama operatörleri. -// Token değeri doğrudan operatörün string halidir: "+", "-", "==", "++". -// -class OperatorToken : public Token { -public: - OperatorToken() { type = "operator"; } -}; - -// ============================================================================ -// DelimiterToken — Sınırlandırıcılar ({, }, (, ), [, ], ;, ,, ., ->, ::) -// ============================================================================ -// -// Kod yapısını belirleyen karakterler. Bloklar, parametre listeleri, -// dizi indeksleri, ifade sonlandırma. -// -class DelimiterToken : public Token { -public: - DelimiterToken() { type = "delimiter"; } -}; - -// ============================================================================ -// KeywordToken — Anahtar Kelimeler (if, for, while, int, void, ...) -// ============================================================================ -// -// Dilin rezerve edilmiş kelimeleri. Identifier olarak kullanılamazlar. -// Tokenizer scope() fonksiyonu, keyword'leri identifier'lardan önce kontrol -// eder. Keyword boundary check sayesinde "double" "do" olarak yanlış -// eşleşmez. -// -class KeywordToken : public Token { -public: - KeywordToken() { type = "keyword"; } -}; - -// ============================================================================ -// IdentifierToken — Tanımlayıcılar (değişken/fonksiyon isimleri) -// ============================================================================ -// -// Harf, rakam, _ ve $ karakterlerinden oluşan, keyword olmayan isimler. -// Değişkenler, fonksiyonlar, sınıflar, metotlar için kullanılır. -// -// context: Şu anda token ile aynı (genişleme için ayrıldı) -// size: Tanımlayıcının karakter uzunluğu -// -class IdentifierToken : public Token { -public: - IdentifierToken() { type = "identifier"; } - std::string context; // Şu anda token ile aynı - int size = 0; // Tanımlayıcı uzunluğu -}; +#include "tokenizer/token.hpp" // ============================================================================ // Token Tanıma Tabloları (Derleme Zamanı Sabitleri) @@ -265,7 +148,7 @@ inline constexpr std::string_view keywords[] = { // Literals "true", "false", "null", // OOP - "class", "interface","enum", "extends", "implements", + "class", "struct", "interface","enum", "extends", "implements", "new", "public", "private", "protected", "static", "final", "abstract", // Modules @@ -361,8 +244,8 @@ inline Token* Tokenizer::scope() { hmx.skipWhiteSpace(); // Yorum satırları: sessizce atla, token üretme - if (hmx.include("//", true)) skipOneLineComment(); - if (hmx.include("/*", true)) skipMultiLineComment(); + if (hmx.include("//", true)) { skipOneLineComment(); return scope(); } + if (hmx.include("/*", true)) { skipMultiLineComment(); return scope(); } // EOF kontrolü if (hmx.isEnd()) { @@ -471,7 +354,7 @@ inline IdentifierToken* Tokenizer::readIdentifier() { if (read) { hmx.nextChar(); } else { - break; // Tanımlayıcı karakteri değil → dur + if (it->token.empty()) { hmx.nextChar(); } break; } }