From 4573880fcc32bd76a72a4ae713190cd997194583 Mon Sep 17 00:00:00 2001 From: ov-4 Date: Thu, 29 Jan 2026 13:02:49 +0000 Subject: Added loop statements, FOR, WHILE and REPEAT --- lib/CodeGen/CodeGen.cc | 150 +++++++++++++++++++++++++++++++------ lib/Lexer/Lexer.cc | 26 +++++-- lib/Parser/Parser.cc | 197 ++++++++++++++++++++++++++++++++++--------------- 3 files changed, 287 insertions(+), 86 deletions(-) (limited to 'lib') diff --git a/lib/CodeGen/CodeGen.cc b/lib/CodeGen/CodeGen.cc index 0a946bf..31d113a 100644 --- a/lib/CodeGen/CodeGen.cc +++ b/lib/CodeGen/CodeGen.cc @@ -14,17 +14,14 @@ CodeGen::CodeGen() { } void CodeGen::SetupExternalFunctions() { - // printf(i8*, ...) std::vector PrintfArgs; PrintfArgs.push_back(PointerType::getUnqual(*TheContext)); FunctionType *PrintfType = FunctionType::get(Type::getInt32Ty(*TheContext), PrintfArgs, true); PrintfFunc = TheModule->getOrInsertFunction("printf", PrintfType); - // scanf(i8*, ...) FunctionType *ScanfType = FunctionType::get(Type::getInt32Ty(*TheContext), PrintfArgs, true); ScanfFunc = TheModule->getOrInsertFunction("scanf", ScanfType); - // format %d\n and %d PrintfFormatStr = Builder->CreateGlobalStringPtr("%d\n", "fmt_nl", 0, TheModule.get()); ScanfFormatStr = Builder->CreateGlobalStringPtr("%d", "fmt_in", 0, TheModule.get()); } @@ -44,7 +41,6 @@ void CodeGen::compile(const std::vector> &Statements) { emitStmt(Stmt.get()); } - // main return 0 if (!Builder->GetInsertBlock()->getTerminator()) Builder->CreateRet(ConstantInt::get(*TheContext, APInt(32, 0))); @@ -92,7 +88,6 @@ Value *CodeGen::emitExpr(ExprAST *Expr) { return nullptr; } } - return nullptr; } @@ -100,12 +95,10 @@ void CodeGen::emitIfStmt(IfStmtAST *Stmt) { Value *CondV = emitExpr(Stmt->getCond()); if (!CondV) return; - if (CondV->getType()->isIntegerTy(32)) { + if (CondV->getType()->isIntegerTy(32)) CondV = Builder->CreateICmpNE(CondV, ConstantInt::get(*TheContext, APInt(32, 0)), "ifcond"); - } Function *TheFunction = Builder->GetInsertBlock()->getParent(); - BasicBlock *ThenBB = BasicBlock::Create(*TheContext, "then", TheFunction); BasicBlock *ElseBB = BasicBlock::Create(*TheContext, "else", TheFunction); BasicBlock *MergeBB = BasicBlock::Create(*TheContext, "ifcont", TheFunction); @@ -113,35 +106,140 @@ void CodeGen::emitIfStmt(IfStmtAST *Stmt) { Builder->CreateCondBr(CondV, ThenBB, ElseBB); Builder->SetInsertPoint(ThenBB); - for (const auto &S : Stmt->getThenStmts()) { - emitStmt(S.get()); - } - if (!Builder->GetInsertBlock()->getTerminator()) - Builder->CreateBr(MergeBB); + for (const auto &S : Stmt->getThenStmts()) emitStmt(S.get()); + if (!Builder->GetInsertBlock()->getTerminator()) Builder->CreateBr(MergeBB); Builder->SetInsertPoint(ElseBB); + for (const auto &S : Stmt->getElseStmts()) emitStmt(S.get()); + if (!Builder->GetInsertBlock()->getTerminator()) Builder->CreateBr(MergeBB); + + Builder->SetInsertPoint(MergeBB); +} + +void CodeGen::emitWhileStmt(WhileStmtAST *Stmt) { + Function *TheFunction = Builder->GetInsertBlock()->getParent(); + + BasicBlock *CondBB = BasicBlock::Create(*TheContext, "whilecond", TheFunction); + BasicBlock *LoopBB = BasicBlock::Create(*TheContext, "whileloop", TheFunction); + BasicBlock *AfterBB = BasicBlock::Create(*TheContext, "whilecont", TheFunction); + + Builder->CreateBr(CondBB); + + Builder->SetInsertPoint(CondBB); + Value *CondV = emitExpr(Stmt->getCond()); + if (!CondV) return; + if (CondV->getType()->isIntegerTy(32)) + CondV = Builder->CreateICmpNE(CondV, ConstantInt::get(*TheContext, APInt(32, 0)), "loopcond"); + + Builder->CreateCondBr(CondV, LoopBB, AfterBB); + + Builder->SetInsertPoint(LoopBB); + for (const auto &S : Stmt->getBody()) emitStmt(S.get()); - for (const auto &S : Stmt->getElseStmts()) { - emitStmt(S.get()); - } if (!Builder->GetInsertBlock()->getTerminator()) - Builder->CreateBr(MergeBB); + Builder->CreateBr(CondBB); - Builder->SetInsertPoint(MergeBB); + Builder->SetInsertPoint(AfterBB); } +void CodeGen::emitRepeatStmt(RepeatStmtAST *Stmt) { + Function *TheFunction = Builder->GetInsertBlock()->getParent(); + + BasicBlock *LoopBB = BasicBlock::Create(*TheContext, "repeatloop", TheFunction); + BasicBlock *CondBB = BasicBlock::Create(*TheContext, "repeatcond", TheFunction); + BasicBlock *AfterBB = BasicBlock::Create(*TheContext, "repeatcont", TheFunction); + + Builder->CreateBr(LoopBB); + + Builder->SetInsertPoint(LoopBB); + for (const auto &S : Stmt->getBody()) emitStmt(S.get()); + if (!Builder->GetInsertBlock()->getTerminator()) + Builder->CreateBr(CondBB); + + Builder->SetInsertPoint(CondBB); + Value *CondV = emitExpr(Stmt->getCond()); + if (!CondV) return; + + if (CondV->getType()->isIntegerTy(32)) + CondV = Builder->CreateICmpNE(CondV, ConstantInt::get(*TheContext, APInt(32, 0)), "untilcond"); + + Builder->CreateCondBr(CondV, AfterBB, LoopBB); + + Builder->SetInsertPoint(AfterBB); +} + +void CodeGen::emitForStmt(ForStmtAST *Stmt) { + Function *TheFunction = Builder->GetInsertBlock()->getParent(); + std::string VarName = Stmt->getVarName(); + + Value *StartVal = emitExpr(Stmt->getStart()); + if (!StartVal) return; + + AllocaInst *Alloca = NamedValues[VarName]; + if (!Alloca) { + fprintf(stderr, "Error: Unknown variable in FOR loop %s\n", VarName.c_str()); + return; + } + Builder->CreateStore(StartVal, Alloca); + + BasicBlock *CondBB = BasicBlock::Create(*TheContext, "forcond", TheFunction); + BasicBlock *LoopBB = BasicBlock::Create(*TheContext, "forloop", TheFunction); + BasicBlock *IncBB = BasicBlock::Create(*TheContext, "forinc", TheFunction); + BasicBlock *AfterBB = BasicBlock::Create(*TheContext, "forcont", TheFunction); + + Builder->CreateBr(CondBB); + Builder->SetInsertPoint(CondBB); + + Value *CurVar = Builder->CreateLoad(Type::getInt32Ty(*TheContext), Alloca, VarName.c_str()); + Value *EndVal = emitExpr(Stmt->getEnd()); + if (!EndVal) return; + + bool isNegativeStep = false; + if (Stmt->getStep()) { + if (auto *Num = dynamic_cast(Stmt->getStep())) { + if (Num->getVal() < 0) isNegativeStep = true; + } + } + + Value *CondV; + if (isNegativeStep) { + CondV = Builder->CreateICmpSGE(CurVar, EndVal, "forcond_ge"); + } else { + CondV = Builder->CreateICmpSLE(CurVar, EndVal, "forcond_le"); + } + + Builder->CreateCondBr(CondV, LoopBB, AfterBB); + + Builder->SetInsertPoint(LoopBB); + for (const auto &S : Stmt->getBody()) emitStmt(S.get()); + if (!Builder->GetInsertBlock()->getTerminator()) + Builder->CreateBr(IncBB); + + Builder->SetInsertPoint(IncBB); + Value *StepVal; + if (Stmt->getStep()) { + StepVal = emitExpr(Stmt->getStep()); + } else { + StepVal = ConstantInt::get(*TheContext, APInt(32, 1)); + } + + Value *CurValForInc = Builder->CreateLoad(Type::getInt32Ty(*TheContext), Alloca, VarName.c_str()); + Value *NextVal = Builder->CreateAdd(CurValForInc, StepVal, "nextval"); + Builder->CreateStore(NextVal, Alloca); + Builder->CreateBr(CondBB); + + Builder->SetInsertPoint(AfterBB); +} void CodeGen::emitStmt(StmtAST *Stmt) { if (!Stmt) return; - // DECLARE if (auto *Decl = dynamic_cast(Stmt)) { Function *TheFunction = Builder->GetInsertBlock()->getParent(); AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Decl->getName()); NamedValues[Decl->getName()] = Alloca; Builder->CreateStore(ConstantInt::get(*TheContext, APInt(32, 0)), Alloca); } - // ASSIGNMENT else if (auto *Assign = dynamic_cast(Stmt)) { Value *Val = emitExpr(Assign->getExpr()); if (Val) { @@ -153,7 +251,6 @@ void CodeGen::emitStmt(StmtAST *Stmt) { Builder->CreateStore(Val, Alloca); } } - // INPUT else if (auto *In = dynamic_cast(Stmt)) { AllocaInst *Alloca = NamedValues[In->getName()]; if (Alloca) { @@ -163,7 +260,6 @@ void CodeGen::emitStmt(StmtAST *Stmt) { Builder->CreateCall(ScanfFunc, Args); } } - // OUTPUT else if (auto *Out = dynamic_cast(Stmt)) { Value *Val = emitExpr(Out->getExpr()); if (Val) { @@ -173,8 +269,16 @@ void CodeGen::emitStmt(StmtAST *Stmt) { Builder->CreateCall(PrintfFunc, Args); } } - // IF else if (auto *IfStmt = dynamic_cast(Stmt)) { emitIfStmt(IfStmt); } + else if (auto *WhileStmt = dynamic_cast(Stmt)) { + emitWhileStmt(WhileStmt); + } + else if (auto *RepeatStmt = dynamic_cast(Stmt)) { + emitRepeatStmt(RepeatStmt); + } + else if (auto *ForStmt = dynamic_cast(Stmt)) { + emitForStmt(ForStmt); + } } diff --git a/lib/Lexer/Lexer.cc b/lib/Lexer/Lexer.cc index c50897b..7f7a167 100644 --- a/lib/Lexer/Lexer.cc +++ b/lib/Lexer/Lexer.cc @@ -1,6 +1,8 @@ #include "cps/Lexer.h" #include #include +#include +#include using namespace cps; @@ -19,10 +21,24 @@ int Lexer::gettok() { if (IdentifierStr == "INTEGER") return tok_integer_kw; if (IdentifierStr == "INPUT") return tok_input; if (IdentifierStr == "OUTPUT") return tok_output; + if (IdentifierStr == "IF") return tok_if; if (IdentifierStr == "THEN") return tok_then; if (IdentifierStr == "ELSE") return tok_else; if (IdentifierStr == "ENDIF") return tok_endif; + + if (IdentifierStr == "WHILE") return tok_while; + if (IdentifierStr == "DO") return tok_do; + if (IdentifierStr == "ENDWHILE") return tok_endwhile; + + if (IdentifierStr == "REPEAT") return tok_repeat; + if (IdentifierStr == "UNTIL") return tok_until; + + if (IdentifierStr == "FOR") return tok_for; + if (IdentifierStr == "TO") return tok_to; + if (IdentifierStr == "STEP") return tok_step; + if (IdentifierStr == "NEXT") return tok_next; + return tok_identifier; } @@ -67,6 +83,11 @@ int Lexer::gettok() { return tok_eq; } + if (LastChar == ':') { + LastChar = getchar(); + return tok_colon; + } + if (LastChar == '/') { int NextChar = getchar(); if (NextChar == '/') { @@ -81,11 +102,6 @@ int Lexer::gettok() { return '/'; } } - - if (LastChar == ':') { - LastChar = getchar(); - return tok_colon; - } if (LastChar == EOF) return tok_eof; diff --git a/lib/Parser/Parser.cc b/lib/Parser/Parser.cc index 998d50b..7a1af89 100644 --- a/lib/Parser/Parser.cc +++ b/lib/Parser/Parser.cc @@ -26,6 +26,22 @@ int Parser::GetTokPrecedence() { return TokPrec; } +int Parser::getNextToken() { + return CurTok = Lex.gettok(); +} + +std::unique_ptr Parser::ParseNumberExpr() { + auto Result = std::make_unique(Lex.NumVal); + getNextToken(); + return Result; +} + +std::unique_ptr Parser::ParseIdentifierExpr() { + std::string IdName = Lex.IdentifierStr; + getNextToken(); + return std::make_unique(IdName); +} + std::unique_ptr Parser::ParseParenExpr() { getNextToken(); auto V = ParseExpression(); @@ -52,9 +68,7 @@ std::unique_ptr Parser::ParsePrimary() { std::unique_ptr Parser::ParseBinOpRHS(int ExprPrec, std::unique_ptr LHS) { while (true) { int TokPrec = GetTokPrecedence(); - - if (TokPrec < ExprPrec) - return LHS; + if (TokPrec < ExprPrec) return LHS; int BinOp = CurTok; getNextToken(); @@ -72,23 +86,6 @@ std::unique_ptr Parser::ParseBinOpRHS(int ExprPrec, std::unique_ptr Parser::ParseNumberExpr() { - auto Result = std::make_unique(Lex.NumVal); - getNextToken(); - return Result; -} - -std::unique_ptr Parser::ParseIdentifierExpr() { - std::string IdName = Lex.IdentifierStr; - getNextToken(); - return std::make_unique(IdName); -} - std::unique_ptr Parser::ParseExpression() { auto LHS = ParsePrimary(); if (!LHS) return nullptr; @@ -97,7 +94,6 @@ std::unique_ptr Parser::ParseExpression() { std::vector> Parser::Parse() { std::vector> Statements; - while (CurTok != tok_eof) { if (auto Stmt = ParseStatement()) { Statements.push_back(std::move(Stmt)); @@ -108,10 +104,8 @@ std::vector> Parser::Parse() { return Statements; } - std::unique_ptr Parser::ParseIfStmt() { getNextToken(); - auto Cond = ParseExpression(); if (!Cond) return nullptr; @@ -121,7 +115,6 @@ std::unique_ptr Parser::ParseIfStmt() { } getNextToken(); - std::vector> ThenStmts; while (CurTok != tok_else && CurTok != tok_endif && CurTok != tok_eof) { auto Stmt = ParseStatement(); @@ -146,69 +139,157 @@ std::unique_ptr Parser::ParseIfStmt() { return std::make_unique(std::move(Cond), std::move(ThenStmts), std::move(ElseStmts)); } +std::unique_ptr Parser::ParseWhileStmt() { + getNextToken(); + auto Cond = ParseExpression(); + if (!Cond) return nullptr; + + if (CurTok != tok_do) { + fprintf(stderr, "Error: expected DO after WHILE condition\n"); + return nullptr; + } + getNextToken(); + + std::vector> Body; + while (CurTok != tok_endwhile && CurTok != tok_eof) { + auto Stmt = ParseStatement(); + if (Stmt) Body.push_back(std::move(Stmt)); + } + + if (CurTok != tok_endwhile) { + fprintf(stderr, "Error: expected ENDWHILE\n"); + return nullptr; + } + getNextToken(); + + return std::make_unique(std::move(Cond), std::move(Body)); +} + +std::unique_ptr Parser::ParseRepeatStmt() { + getNextToken(); + + std::vector> Body; + while (CurTok != tok_until && CurTok != tok_eof) { + auto Stmt = ParseStatement(); + if (Stmt) Body.push_back(std::move(Stmt)); + } + + if (CurTok != tok_until) { + fprintf(stderr, "Error: expected UNTIL\n"); + return nullptr; + } + getNextToken(); + + auto Cond = ParseExpression(); + if (!Cond) return nullptr; + + return std::make_unique(std::move(Body), std::move(Cond)); +} + +std::unique_ptr Parser::ParseForStmt() { + getNextToken(); + if (CurTok != tok_identifier) { + fprintf(stderr, "Error: expected identifier after FOR\n"); + return nullptr; + } + std::string VarName = Lex.IdentifierStr; + getNextToken(); + + if (CurTok != tok_assign) { + fprintf(stderr, "Error: expected '<-' in FOR loop\n"); + return nullptr; + } + getNextToken(); + + auto Start = ParseExpression(); + if (!Start) return nullptr; + + if (CurTok != tok_to) { + fprintf(stderr, "Error: expected TO in FOR loop\n"); + return nullptr; + } + getNextToken(); + + auto End = ParseExpression(); + if (!End) return nullptr; + + std::unique_ptr Step = nullptr; + if (CurTok == tok_step) { + getNextToken(); + Step = ParseExpression(); + } + + std::vector> Body; + while (CurTok != tok_next && CurTok != tok_eof) { + auto Stmt = ParseStatement(); + if (Stmt) Body.push_back(std::move(Stmt)); + } + + if (CurTok != tok_next) { + fprintf(stderr, "Error: expected NEXT\n"); + return nullptr; + } + getNextToken(); + + if (CurTok != tok_identifier) { + fprintf(stderr, "Error: expected identifier after NEXT (e.g., NEXT %s)\n", VarName.c_str()); + return nullptr; + } + + if (Lex.IdentifierStr != VarName) { + fprintf(stderr, "Error: NEXT identifier '%s' does not match FOR variable '%s'\n", + Lex.IdentifierStr.c_str(), VarName.c_str()); + return nullptr; + } + getNextToken(); + + return std::make_unique(VarName, std::move(Start), std::move(End), std::move(Step), std::move(Body)); +} + std::unique_ptr Parser::ParseStatement() { - // DECLARE if (CurTok == tok_declare) { getNextToken(); - if (CurTok != tok_identifier) { - fprintf(stderr, "Error: expected identifier after DECLARE\n"); - return nullptr; - } + if (CurTok != tok_identifier) return nullptr; std::string Name = Lex.IdentifierStr; getNextToken(); - - if (CurTok != tok_colon) { - fprintf(stderr, "Error: expected ':' after identifier\n"); - return nullptr; - } + if (CurTok != tok_colon) return nullptr; getNextToken(); - - if (CurTok != tok_integer_kw) { - fprintf(stderr, "Error: expected INTEGER type\n"); - return nullptr; - } + if (CurTok != tok_integer_kw) return nullptr; getNextToken(); return std::make_unique(Name); } - - // ASSIGNMENT (x <- expr) else if (CurTok == tok_identifier) { std::string Name = Lex.IdentifierStr; - getNextToken(); // eat Name - - if (CurTok != tok_assign) { - fprintf(stderr, "Error: expected '<-' for assignment\n"); - return nullptr; - } getNextToken(); - + if (CurTok != tok_assign) return nullptr; + getNextToken(); auto Expr = ParseExpression(); return std::make_unique(Name, std::move(Expr)); } - - // INPUT else if (CurTok == tok_input) { getNextToken(); - if (CurTok != tok_identifier) { - fprintf(stderr, "Error: expected identifier after INPUT\n"); - return nullptr; - } + if (CurTok != tok_identifier) return nullptr; std::string Name = Lex.IdentifierStr; getNextToken(); return std::make_unique(Name); } - - // OUTPUT else if (CurTok == tok_output) { getNextToken(); auto Expr = ParseExpression(); return std::make_unique(std::move(Expr)); } - - // IF else if (CurTok == tok_if) { return ParseIfStmt(); } + else if (CurTok == tok_while) { + return ParseWhileStmt(); + } + else if (CurTok == tok_repeat) { + return ParseRepeatStmt(); + } + else if (CurTok == tok_for) { + return ParseForStmt(); + } return nullptr; } -- cgit v1.3.1-4-g156e