aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorov-4 <hausemasterstream@gmail.com>2026-01-29 10:20:58 +0000
committerov-4 <hausemasterstream@gmail.com>2026-01-29 10:20:58 +0000
commitc2a3cecc1ab2d3f27dcea40a6f0f353b0306d66a (patch)
tree3adfa6ed51620adcf6b129eade1622b01527c8a9 /lib
parent3f48a1d3af588242cd745e344b6b0b02cfb26131 (diff)
Added INPUT, OUTPUT and DECLARE
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/CodeGen.cc102
-rw-r--r--lib/Lexer/Lexer.cc57
-rw-r--r--lib/Parser/Parser.cc77
3 files changed, 236 insertions, 0 deletions
diff --git a/lib/CodeGen/CodeGen.cc b/lib/CodeGen/CodeGen.cc
new file mode 100644
index 0000000..a2de939
--- /dev/null
+++ b/lib/CodeGen/CodeGen.cc
@@ -0,0 +1,102 @@
+#include "cps/CodeGen.h"
+#include "llvm/IR/Verifier.h"
+
+using namespace llvm;
+using namespace cps;
+
+CodeGen::CodeGen() {
+ TheContext = std::make_unique<LLVMContext>();
+ TheModule = std::make_unique<Module>("cps_module", *TheContext);
+ Builder = std::make_unique<IRBuilder<>>(*TheContext);
+
+ SetupExternalFunctions();
+}
+
+void CodeGen::SetupExternalFunctions() {
+ // printf(i8*, ...)
+ std::vector<Type*> 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());
+}
+
+AllocaInst *CodeGen::CreateEntryBlockAlloca(Function *TheFunction, const std::string &VarName) {
+ IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin());
+ return TmpB.CreateAlloca(Type::getInt32Ty(*TheContext), nullptr, VarName);
+}
+
+void CodeGen::compile(const std::vector<std::unique_ptr<StmtAST>> &Statements) {
+ FunctionType *FT = FunctionType::get(Type::getInt32Ty(*TheContext), false);
+ Function *F = Function::Create(FT, Function::ExternalLinkage, "main", TheModule.get());
+ BasicBlock *BB = BasicBlock::Create(*TheContext, "entry", F);
+ Builder->SetInsertPoint(BB);
+
+ for (const auto &Stmt : Statements) {
+ // DECLARE
+ if (auto *Decl = dynamic_cast<DeclareStmtAST*>(Stmt.get())) {
+ AllocaInst *Alloca = CreateEntryBlockAlloca(F, Decl->getName());
+ NamedValues[Decl->getName()] = Alloca;
+ // 0
+ Builder->CreateStore(ConstantInt::get(*TheContext, APInt(32, 0)), Alloca);
+ }
+ // ASSIGNMENT (x <- expr)
+ else if (auto *Assign = dynamic_cast<AssignStmtAST*>(Stmt.get())) {
+ Value *Val = nullptr;
+ if (auto *Num = dynamic_cast<NumberExprAST*>(Assign->getExpr())) {
+ Val = ConstantInt::get(*TheContext, APInt(32, Num->getVal()));
+ } else if (auto *Var = dynamic_cast<VariableExprAST*>(Assign->getExpr())) {
+ AllocaInst *A = NamedValues[Var->getName()];
+ Val = Builder->CreateLoad(Type::getInt32Ty(*TheContext), A, Var->getName());
+ }
+
+ AllocaInst *Alloca = NamedValues[Assign->getName()];
+ if (Alloca && Val) {
+ Builder->CreateStore(Val, Alloca);
+ }
+ }
+ // INPUT
+ else if (auto *In = dynamic_cast<InputStmtAST*>(Stmt.get())) {
+ AllocaInst *Alloca = NamedValues[In->getName()];
+ if (Alloca) {
+ std::vector<Value*> Args;
+ Args.push_back(ScanfFormatStr);
+ Args.push_back(Alloca);
+ Builder->CreateCall(ScanfFunc, Args);
+ }
+ }
+ // OUTPUT
+ else if (auto *Out = dynamic_cast<OutputStmtAST*>(Stmt.get())) {
+ Value *Val = nullptr;
+ if (auto *Num = dynamic_cast<NumberExprAST*>(Out->getExpr())) {
+ Val = ConstantInt::get(*TheContext, APInt(32, Num->getVal()));
+ } else if (auto *Var = dynamic_cast<VariableExprAST*>(Out->getExpr())) {
+ AllocaInst *A = NamedValues[Var->getName()];
+ Val = Builder->CreateLoad(Type::getInt32Ty(*TheContext), A, Var->getName());
+ }
+
+ if (Val) {
+ // printf("%d\n", val)
+ std::vector<Value*> Args;
+ Args.push_back(PrintfFormatStr);
+ Args.push_back(Val);
+ Builder->CreateCall(PrintfFunc, Args);
+ }
+ }
+ }
+
+ // main return 0
+ Builder->CreateRet(ConstantInt::get(*TheContext, APInt(32, 0)));
+ verifyFunction(*F);
+}
+
+void CodeGen::print() {
+ TheModule->print(errs(), nullptr);
+}
diff --git a/lib/Lexer/Lexer.cc b/lib/Lexer/Lexer.cc
new file mode 100644
index 0000000..b04438b
--- /dev/null
+++ b/lib/Lexer/Lexer.cc
@@ -0,0 +1,57 @@
+#include "cps/Lexer.h"
+#include <cctype>
+#include <cstdio>
+
+using namespace cps;
+
+int Lexer::gettok() {
+ static int LastChar = ' ';
+
+ while (isspace(LastChar))
+ LastChar = getchar();
+
+ if (isalpha(LastChar)) {
+ IdentifierStr = LastChar;
+ while (isalnum((LastChar = getchar())) || LastChar == '_')
+ IdentifierStr += LastChar;
+
+ if (IdentifierStr == "DECLARE") return tok_declare;
+ if (IdentifierStr == "INTEGER") return tok_integer_kw;
+ if (IdentifierStr == "INPUT") return tok_input;
+ if (IdentifierStr == "OUTPUT") return tok_output;
+ return tok_identifier;
+ }
+
+ if (isdigit(LastChar)) {
+ std::string NumStr;
+ do {
+ NumStr += LastChar;
+ LastChar = getchar();
+ } while (isdigit(LastChar));
+ NumVal = strtol(NumStr.c_str(), nullptr, 10);
+ return tok_number;
+ }
+
+ if (LastChar == '<') {
+ LastChar = getchar();
+ if (LastChar == '-') {
+ LastChar = getchar();
+ return tok_assign;
+ }
+ return '<';
+ }
+
+ // for comments
+
+ if (LastChar == ':') {
+ LastChar = getchar();
+ return tok_colon;
+ }
+
+ if (LastChar == EOF)
+ return tok_eof;
+
+ int ThisChar = LastChar;
+ LastChar = getchar();
+ return ThisChar;
+}
diff --git a/lib/Parser/Parser.cc b/lib/Parser/Parser.cc
new file mode 100644
index 0000000..90dc3a0
--- /dev/null
+++ b/lib/Parser/Parser.cc
@@ -0,0 +1,77 @@
+#include "cps/Parser.h"
+
+using namespace cps;
+
+int Parser::getNextToken() {
+ return CurTok = Lex.gettok();
+}
+
+std::unique_ptr<ExprAST> Parser::ParseNumberExpr() {
+ auto Result = std::make_unique<NumberExprAST>(Lex.NumVal);
+ getNextToken();
+ return Result;
+}
+
+std::unique_ptr<ExprAST> Parser::ParseIdentifierExpr() {
+ std::string IdName = Lex.IdentifierStr;
+ getNextToken();
+ return std::make_unique<VariableExprAST>(IdName);
+}
+
+std::unique_ptr<ExprAST> Parser::ParseExpression() {
+ if (CurTok == tok_number)
+ return ParseNumberExpr();
+ if (CurTok == tok_identifier)
+ return ParseIdentifierExpr();
+ return nullptr;
+}
+
+std::vector<std::unique_ptr<StmtAST>> Parser::Parse() {
+ std::vector<std::unique_ptr<StmtAST>> Statements;
+
+ while (CurTok != tok_eof) {
+ if (CurTok == tok_declare) {
+ // DECLARE <id> : INTEGER
+ getNextToken(); // eat DECLARE
+ if (CurTok != tok_identifier) break; // Error
+ std::string Name = Lex.IdentifierStr;
+ getNextToken(); // eat Name
+
+ if (CurTok != tok_colon) break; // Error: expected ':'
+ getNextToken(); // eat ':'
+
+ if (CurTok != tok_integer_kw) break; // Error: expected INTEGER
+ getNextToken(); // eat INTEGER
+
+ Statements.push_back(std::make_unique<DeclareStmtAST>(Name));
+ }
+ else if (CurTok == tok_identifier) {
+ // <id> <- <expr>
+ std::string Name = Lex.IdentifierStr;
+ getNextToken(); // eat Name
+
+ if (CurTok != tok_assign) break; // Error: expected '<-'
+ getNextToken(); // eat '<-'
+
+ auto Expr = ParseExpression();
+ Statements.push_back(std::make_unique<AssignStmtAST>(Name, std::move(Expr)));
+ }
+ else if (CurTok == tok_input) {
+ // INPUT <id>
+ getNextToken(); // eat INPUT
+ if (CurTok != tok_identifier) break;
+ Statements.push_back(std::make_unique<InputStmtAST>(Lex.IdentifierStr));
+ getNextToken();
+ }
+ else if (CurTok == tok_output) {
+ // OUTPUT <expr>
+ getNextToken(); // eat OUTPUT
+ auto Expr = ParseExpression();
+ Statements.push_back(std::make_unique<OutputStmtAST>(std::move(Expr)));
+ }
+ else {
+ getNextToken(); // Skip unknown
+ }
+ }
+ return Statements;
+}