parser: function calls, struct, member/index access - Final.sqt parses successfully (289 tokens, 200+ AST nodes)
This commit is contained in:
parent
4d3150e811
commit
6aa0da2378
|
|
@ -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;
|
||||||
|
}
|
||||||
11
source.sqt
11
source.sqt
|
|
@ -1,10 +1 @@
|
||||||
int main() {
|
int main() { int x = 0; while (x < 5) { x = x + 1; } do { x = x - 1; } while (x > 0); return x; }
|
||||||
int x = 0;
|
|
||||||
while (x < 5) {
|
|
||||||
x = x + 1;
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
x = x - 1;
|
|
||||||
} while (x > 0);
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
49
src/json.hpp
49
src/json.hpp
|
|
@ -49,6 +49,10 @@ inline const char* astKindName(ASTKind k) {
|
||||||
case ASTKind::BreakStatement: return "BreakStatement";
|
case ASTKind::BreakStatement: return "BreakStatement";
|
||||||
case ASTKind::ContinueStatement: return "ContinueStatement";
|
case ASTKind::ContinueStatement: return "ContinueStatement";
|
||||||
case ASTKind::ExpressionStatement: return "ExpressionStatement";
|
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";
|
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);
|
if (es->expression) analyzeRecursive(es->expression, currentDepth + 1, a);
|
||||||
break;
|
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
|
default: break; // Literal, Identifier, Break, Continue — yaprak düğüm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -204,6 +229,9 @@ inline void collectSymbolsRecursive(ASTNode* node, std::vector<SymbolEntry>& sym
|
||||||
if (node->kind == ASTKind::FunctionDecl) {
|
if (node->kind == ASTKind::FunctionDecl) {
|
||||||
auto* fn = (FunctionDeclNode*)node;
|
auto* fn = (FunctionDeclNode*)node;
|
||||||
symbols.push_back({fn->name, "function", fn->returnType});
|
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) {
|
} else if (node->kind == ASTKind::VariableDecl) {
|
||||||
auto* vd = (VariableDeclNode*)node;
|
auto* vd = (VariableDeclNode*)node;
|
||||||
symbols.push_back({vd->name, "variable", vd->varType});
|
symbols.push_back({vd->name, "variable", vd->varType});
|
||||||
|
|
@ -270,6 +298,27 @@ inline void collectSymbolsRecursive(ASTNode* node, std::vector<SymbolEntry>& sym
|
||||||
if (es->expression) collectSymbolsRecursive(es->expression, symbols);
|
if (es->expression) collectSymbolsRecursive(es->expression, symbols);
|
||||||
break;
|
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;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,10 @@ enum class ASTKind {
|
||||||
BreakStatement, // break
|
BreakStatement, // break
|
||||||
ContinueStatement, // continue
|
ContinueStatement, // continue
|
||||||
ExpressionStatement, // ifade + ;
|
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<ASTNode*> 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
|
#endif // SAQUT_AST
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,7 @@ private:
|
||||||
// --- Deklarasyonlar ---
|
// --- Deklarasyonlar ---
|
||||||
ASTNode* parseDeclaration();
|
ASTNode* parseDeclaration();
|
||||||
ASTNode* parseFunctionDecl();
|
ASTNode* parseFunctionDecl();
|
||||||
|
ASTNode* parseStructDecl();
|
||||||
ASTNode* parseVariableDecl();
|
ASTNode* parseVariableDecl();
|
||||||
|
|
||||||
// --- Statement'lar ---
|
// --- Statement'lar ---
|
||||||
|
|
@ -267,7 +268,11 @@ inline ASTNode* Parser::parseDeclaration() {
|
||||||
return parseVariableDecl();
|
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();
|
return parseStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -308,6 +313,29 @@ inline ASTNode* Parser::parseFunctionDecl() {
|
||||||
|
|
||||||
return fn;
|
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ı.
|
// parseVariableDecl: Değişken tanımı.
|
||||||
|
|
@ -805,9 +833,8 @@ inline ASTNode* Parser::parseLeftDenotation(ASTNode* left) {
|
||||||
auto ct = currentToken();
|
auto ct = currentToken();
|
||||||
|
|
||||||
// --- Postfix: expr++, expr-- ---
|
// --- Postfix: expr++, expr-- ---
|
||||||
// Operatör operand'dan SONRA gelir, sağ operand yok.
|
|
||||||
if (ct.is({TokenType::PLUS_PLUS, TokenType::MINUS_MINUS})) {
|
if (ct.is({TokenType::PLUS_PLUS, TokenType::MINUS_MINUS})) {
|
||||||
nextToken(); // Operatörü tüket
|
nextToken();
|
||||||
PostfixNode* pf = new PostfixNode();
|
PostfixNode* pf = new PostfixNode();
|
||||||
pf->operand = left;
|
pf->operand = left;
|
||||||
pf->Operator = ct.type;
|
pf->Operator = ct.type;
|
||||||
|
|
@ -815,13 +842,60 @@ inline ASTNode* Parser::parseLeftDenotation(ASTNode* left) {
|
||||||
return pf;
|
return pf;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Binary infix: expr OP expr ---
|
// --- Fonksiyon cagrisi: expr(args) ---
|
||||||
// OP'nin önceliğine göre sağ operand'ı ayrıştır.
|
if (ct.type == TokenType::LPAREN) {
|
||||||
uint16_t prec = ct.getPowerOperator();
|
nextToken();
|
||||||
nextToken(); // Operatörü tüket
|
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);
|
ASTNode* right = parseExpression(prec);
|
||||||
|
|
||||||
BinaryExpressionNode* bin = new BinaryExpressionNode();
|
BinaryExpressionNode* bin = new BinaryExpressionNode();
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,7 @@ enum class TokenType : uint16_t {
|
||||||
|
|
||||||
// --- OOP Keyword'leri ---
|
// --- OOP Keyword'leri ---
|
||||||
KW_CLASS, // class
|
KW_CLASS, // class
|
||||||
|
KW_STRUCT, // struct
|
||||||
KW_INTERFACE, // interface
|
KW_INTERFACE, // interface
|
||||||
KW_ENUM, // enum
|
KW_ENUM, // enum
|
||||||
KW_EXTENDS, // extends
|
KW_EXTENDS, // extends
|
||||||
|
|
@ -302,6 +303,7 @@ inline const std::unordered_map<std::string_view, TokenType> KEYWORD_MAP = {
|
||||||
|
|
||||||
// --- OOP ---
|
// --- OOP ---
|
||||||
{"class", TokenType::KW_CLASS},
|
{"class", TokenType::KW_CLASS},
|
||||||
|
{"struct", TokenType::KW_STRUCT},
|
||||||
{"interface", TokenType::KW_INTERFACE},
|
{"interface", TokenType::KW_INTERFACE},
|
||||||
{"enum", TokenType::KW_ENUM},
|
{"enum", TokenType::KW_ENUM},
|
||||||
{"extends", TokenType::KW_EXTENDS},
|
{"extends", TokenType::KW_EXTENDS},
|
||||||
|
|
|
||||||
|
|
@ -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 <string>)
|
||||||
|
//
|
||||||
|
// 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 <string>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
@ -73,124 +73,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "lexer/lexer.hpp"
|
#include "lexer/lexer.hpp"
|
||||||
|
|
||||||
// ============================================================================
|
#include "tokenizer/token.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
|
|
||||||
};
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Token Tanıma Tabloları (Derleme Zamanı Sabitleri)
|
// Token Tanıma Tabloları (Derleme Zamanı Sabitleri)
|
||||||
|
|
@ -265,7 +148,7 @@ inline constexpr std::string_view keywords[] = {
|
||||||
// Literals
|
// Literals
|
||||||
"true", "false", "null",
|
"true", "false", "null",
|
||||||
// OOP
|
// OOP
|
||||||
"class", "interface","enum", "extends", "implements",
|
"class", "struct", "interface","enum", "extends", "implements",
|
||||||
"new", "public", "private", "protected",
|
"new", "public", "private", "protected",
|
||||||
"static", "final", "abstract",
|
"static", "final", "abstract",
|
||||||
// Modules
|
// Modules
|
||||||
|
|
@ -361,8 +244,8 @@ inline Token* Tokenizer::scope() {
|
||||||
hmx.skipWhiteSpace();
|
hmx.skipWhiteSpace();
|
||||||
|
|
||||||
// Yorum satırları: sessizce atla, token üretme
|
// Yorum satırları: sessizce atla, token üretme
|
||||||
if (hmx.include("//", true)) skipOneLineComment();
|
if (hmx.include("//", true)) { skipOneLineComment(); return scope(); }
|
||||||
if (hmx.include("/*", true)) skipMultiLineComment();
|
if (hmx.include("/*", true)) { skipMultiLineComment(); return scope(); }
|
||||||
|
|
||||||
// EOF kontrolü
|
// EOF kontrolü
|
||||||
if (hmx.isEnd()) {
|
if (hmx.isEnd()) {
|
||||||
|
|
@ -471,7 +354,7 @@ inline IdentifierToken* Tokenizer::readIdentifier() {
|
||||||
if (read) {
|
if (read) {
|
||||||
hmx.nextChar();
|
hmx.nextChar();
|
||||||
} else {
|
} else {
|
||||||
break; // Tanımlayıcı karakteri değil → dur
|
if (it->token.empty()) { hmx.nextChar(); } break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue