96 lines
2.5 KiB
C++
96 lines
2.5 KiB
C++
#include "semantic/structural_validator.hpp"
|
||
#include "parser/nodes/declarations.hpp"
|
||
#include "parser/nodes/statements.hpp"
|
||
|
||
void StructuralValidator::validate(ASTNode* program) {
|
||
if (!program) return;
|
||
for (ASTNode* child : program->getChildren())
|
||
walkDecl(child);
|
||
}
|
||
|
||
void StructuralValidator::walkDecl(ASTNode* node) {
|
||
if (!node) return;
|
||
if (node->kind == ASTKind::FunctionDecl) {
|
||
auto* fn = (FunctionDeclNode*)node;
|
||
inFunction_ = true;
|
||
auto& ch = fn->getChildren();
|
||
if (!ch.empty()) walkStmt(ch[0]);
|
||
inFunction_ = false;
|
||
}
|
||
// VariableDecl / StructDecl: yapısal kural yok
|
||
}
|
||
|
||
void StructuralValidator::walkStmt(ASTNode* node) {
|
||
if (!node) return;
|
||
|
||
switch (node->kind) {
|
||
|
||
case ASTKind::Block:
|
||
for (ASTNode* child : node->getChildren()) walkStmt(child);
|
||
break;
|
||
|
||
case ASTKind::IfStatement: {
|
||
auto* ifn = (IfStatementNode*)node;
|
||
if (ifn->thenBranch) walkStmt(ifn->thenBranch);
|
||
if (ifn->elseBranch) walkStmt(ifn->elseBranch);
|
||
break;
|
||
}
|
||
|
||
case ASTKind::WhileStatement: {
|
||
auto* ws = (WhileStatementNode*)node;
|
||
loopDepth_++;
|
||
if (ws->body) walkStmt(ws->body);
|
||
loopDepth_--;
|
||
break;
|
||
}
|
||
|
||
case ASTKind::DoWhileStatement: {
|
||
auto* dw = (DoWhileStatementNode*)node;
|
||
loopDepth_++;
|
||
if (dw->body) walkStmt(dw->body);
|
||
loopDepth_--;
|
||
break;
|
||
}
|
||
|
||
case ASTKind::ForStatement: {
|
||
auto* fs = (ForStatementNode*)node;
|
||
loopDepth_++;
|
||
if (fs->init) walkStmt(fs->init);
|
||
if (fs->body) walkStmt(fs->body);
|
||
loopDepth_--;
|
||
break;
|
||
}
|
||
|
||
case ASTKind::BreakStatement:
|
||
if (loopDepth_ == 0)
|
||
diag_.report("E004", node->loc,
|
||
"'break' döngü dışında kullanılamaz");
|
||
break;
|
||
|
||
case ASTKind::ContinueStatement:
|
||
if (loopDepth_ == 0)
|
||
diag_.report("E004", node->loc,
|
||
"'continue' döngü dışında kullanılamaz");
|
||
break;
|
||
|
||
case ASTKind::ReturnStatement:
|
||
if (!inFunction_)
|
||
diag_.report("E005", node->loc,
|
||
"'return' fonksiyon dışında kullanılamaz");
|
||
break;
|
||
|
||
case ASTKind::VariableDecl: {
|
||
// sibling'leri de gez
|
||
for (ASTNode* sib : node->getChildren())
|
||
if (sib->kind == ASTKind::VariableDecl) walkStmt(sib);
|
||
break;
|
||
}
|
||
|
||
case ASTKind::ExpressionStatement:
|
||
break; // ifade içinde return/break olamaz
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|