diff options
| -rw-r--r-- | Lexer.l | 11 | ||||
| -rw-r--r-- | Parser.y | 37 | ||||
| -rw-r--r-- | Type.hh | 4 | ||||
| -rw-r--r-- | TypeManager.cc | 25 | ||||
| -rw-r--r-- | node/ExprNode.cc | 4 | ||||
| -rw-r--r-- | node/StatementNode.cc | 104 | ||||
| -rw-r--r-- | node/StatementNode.hh | 35 | ||||
| -rw-r--r-- | t/1.pas | 18 | ||||
| -rw-r--r-- | t/trivial.pas | 66 |
9 files changed, 250 insertions, 54 deletions
@@ -24,7 +24,7 @@ namespace pcc { %option never-interactive %option nounistd %option case-insensitive -%option noyywrap nounput noinput batch +%option noyywrap nounput noinput batch debug decimal ([1-9][0-9]*)|0 octal 0[0-7]* @@ -46,7 +46,7 @@ char_value {trival_char}|{escaped_char}|{hex_char}|{oct_char}|\\' char '{char_value}' string '{char_value}+' -identifier [a-z][0-9a-z]* +identifier [a-z][0-9a-z_]* white [\t\f\r ] @@ -65,6 +65,7 @@ white [\t\f\r ] ":" {return Parser::make_COLON(loc);} ";" {return Parser::make_SEMICOLON(loc);} "." {return Parser::make_DOT(loc);} +"," {return Parser::make_COMMA(loc);} "[" {return Parser::make_LBRACKET(loc);} "]" {return Parser::make_RBRACKET(loc);} "(" {return Parser::make_LPARENTHESIS(loc);} @@ -100,6 +101,8 @@ white [\t\f\r ] "else" {return Parser::make_ELSE(loc);} "while" {return Parser::make_WHILE(loc);} "do" {return Parser::make_DO(loc);} +"repeat" {return Parser::make_REPEAT(loc);} +"until" {return Parser::make_UNTIL(loc);} "integer" {return Parser::make_INTEGER(loc);} "boolean" {return Parser::make_BOOLEAN(loc);} "char" {return Parser::make_CHAR(loc);} @@ -158,9 +161,7 @@ white [\t\f\r ] namespace pcc { int Driver::StartLexer(std::string& filename) { - if(CurrentLogLevel==LogLevel::PCC_DEBUG){ - yy_flex_debug = 1; - } + yy_flex_debug = (CurrentLogLevel==LogLevel::PCC_DEBUG); yyin = std::fopen(filename.c_str(), "r"); if (yyin == NULL) { Log(LogLevel::PCC_ERROR, "Failed to open file %s", filename.c_str()); @@ -43,7 +43,7 @@ YY_DECL; %token FILE_END 0; %token COLON SEMICOLON COMMA DOT ASSIGN LBRACKET RBRACKET LPARENTHESIS RPARENTHESIS %token PROGRAM IDENTIFIER CONST VAR BEGINS ENDS FUNCTION -%token IF THEN ELSE WHILE DO +%token IF THEN ELSE WHILE DO REPEAT UNTIL %token BOOLEAN CHAR INTEGER REAL STRING %token ADD SUB MUL REAL_DIV DIV MOD LT LE GT GE EQ NE %token AND NOT OR XOR @@ -76,6 +76,7 @@ YY_DECL; %type <std::shared_ptr<pcc::BaseNode>> statement open_statement closed_statement normal_statement %type <std::shared_ptr<pcc::EmptyStatementNode>> empty_statement %type <std::shared_ptr<pcc::AssignStatementNode>> assign_statement +%type <std::shared_ptr<pcc::RepeatStatementNode>> repeat_statement %% @@ -95,7 +96,7 @@ global_decls ; global_decl - : VAR var_decls {$$=std::make_shared<pcc::VarDeclNode>(ctx, nullptr, $2);} + : VAR var_decls SEMICOLON {$$=std::make_shared<pcc::VarDeclNode>(ctx, nullptr, $2);} ; functions @@ -106,12 +107,12 @@ functions /* ==================[var part]================== */ var_decls - : var_decls var_decl {$$=$1; auto NewChilds=std::get<0>($2); for(auto& name: NewChilds){$$.push_back({name, std::get<1>($2)});}} - | var_decl {auto NewChilds=std::get<0>($1); for(auto& name: NewChilds){$$.push_back({name, std::get<1>($1)});}} + : var_decls SEMICOLON var_decl {$$=$1; auto NewChilds=std::get<0>($3); for(auto& name: NewChilds){$$.push_back({name, std::get<1>($3)});}} + | var_decl {auto NewChilds=std::get<0>($1); for(auto& name: NewChilds){$$.push_back({name, std::get<1>($1)});}} ; var_decl - : vars COLON type SEMICOLON {$$={$1,$3};} + : vars COLON type {$$={$1,$3};} ; vars @@ -132,6 +133,8 @@ type function : FUNCTION IDENTIFIER LPARENTHESIS var_decls RPARENTHESIS COLON type SEMICOLON local_decls statement_block {$$=std::make_shared<pcc::FunctionNode>(ctx, $2, $4, $9, $7, $10);} + | FUNCTION IDENTIFIER LPARENTHESIS RPARENTHESIS COLON type SEMICOLON + local_decls statement_block {$$=std::make_shared<pcc::FunctionNode>(ctx, $2, std::list<Declaration>(), $8, $6, $9);} ; local_decls @@ -140,7 +143,7 @@ local_decls ; local_decl - : VAR var_decls {$$=std::make_shared<pcc::VarDeclNode>(ctx, nullptr, $2);} + : VAR var_decls SEMICOLON {$$=std::make_shared<pcc::VarDeclNode>(ctx, nullptr, $2);} ; /* ==================[statements part]================== */ @@ -156,21 +159,22 @@ statement ; open_statement - : IF expression THEN statement - | IF expression THEN closed_statement ELSE open_statement - | WHILE expression DO open_statement + : IF expression THEN statement {$$=std::make_shared<pcc::IfStatementNode>(ctx, $2, $4, nullptr);} + | IF expression THEN closed_statement ELSE open_statement {$$=std::make_shared<pcc::IfStatementNode>(ctx, $2, $4, $6);} + | WHILE expression DO open_statement {$$=std::make_shared<pcc::WhileStatementNode>(ctx, $2, $4);} ; closed_statement - : normal_statement {$$=$1;} - | IF expression THEN closed_statement ELSE closed_statement - | WHILE expression DO closed_statement + : normal_statement {$$=$1;} + | IF expression THEN closed_statement ELSE closed_statement {$$=std::make_shared<pcc::IfStatementNode>(ctx, $2, $4, $6);} + | WHILE expression DO closed_statement {$$=std::make_shared<pcc::WhileStatementNode>(ctx, $2, $4);} ; normal_statement : statement_block {$$=$1;} | empty_statement {$$=$1;} | assign_statement {$$=$1;} + | repeat_statement {$$=$1;} | expression {$$=$1;} ; @@ -179,7 +183,11 @@ statement_block ; empty_statement - : {$$=std::make_shared<pcc::EmptyStatementNode>(ctx);} + : {$$=std::make_shared<pcc::EmptyStatementNode>(ctx);} + ; + +repeat_statement + : REPEAT statement UNTIL expression {$$=std::make_shared<pcc::RepeatStatementNode>(ctx, $4, $2);} ; assign_statement @@ -234,6 +242,7 @@ l2_operator l3_operator : MUL {$$=pcc::BinaryOperator::MUL;} | DIV {$$=pcc::BinaryOperator::DIV;} + | REAL_DIV {$$=pcc::BinaryOperator::REAL_DIV;} | MOD {$$=pcc::BinaryOperator::MOD;} | AND {$$=pcc::BinaryOperator::AND;} ; @@ -276,7 +285,7 @@ namespace pcc { { std::stringstream loc; loc<<l; - Log(LogLevel::PCC_ERROR, "error on %s: %s", loc.str().c_str(), m.c_str()); + Log(LogLevel::PCC_ERROR, "error at %s: %s", loc.str().c_str(), m.c_str()); } } @@ -29,7 +29,9 @@ enum class BinaryOperator { OR, XOR, ARRAY_ACCESS, - BINARYOP_NUMBER + BINARYOP_NUMBER, + REAL_DIV // the difference between REAL_DIV and DIV is handled in + // TypeManager, thus we don't need to create instruction for this. }; enum class UnaryOperator { POS, NEG, NOT, UNARYOP_NUMEBR }; diff --git a/TypeManager.cc b/TypeManager.cc index c721df8..d74f3f0 100644 --- a/TypeManager.cc +++ b/TypeManager.cc @@ -89,17 +89,18 @@ std::pair<std::shared_ptr<Type>, Value> std::dynamic_pointer_cast<RealType>(RightType); Value ConvertedLeft, ConvertedRight; std::shared_ptr<Type> CommonType; - if (LeftType != RightType) { + if (op == BinaryOperator::REAL_DIV) { + // we can only set the CommonType to real for REAL_DIV on builtin types, + // for other types, REAL_DIV and DIV are unavaliable. + CommonType = builtins_[ToUnderlying(BuiltinType::REAL)]; + op = BinaryOperator::DIV; + } else if (LeftType != RightType) { // we can cast the boolean, char, integer and real. - if (LeftRealType != nullptr && RightIntegerBaseType != nullptr) { - ConvertedLeft = left; - ConvertedRight = - builder->CreateSIToFP(right, LeftType->GetLLVMType()); + if (op == BinaryOperator::REAL_DIV) { + CommonType = builtins_[ToUnderlying(BuiltinType::REAL)]; + } else if (LeftRealType != nullptr && RightIntegerBaseType != nullptr) { CommonType = LeftType; } else if (RightRealType != nullptr && LeftIntegerBaseType != nullptr) { - ConvertedLeft = - builder->CreateSIToFP(left, RightType->GetLLVMType()); - ConvertedRight = right; CommonType = RightType; } else if (LeftIntegerBaseType != nullptr && RightIntegerBaseType != nullptr) { @@ -107,10 +108,6 @@ std::pair<std::shared_ptr<Type>, Value> RightIntegerBaseType->GetWidth() ? LeftType : RightType); - ConvertedLeft = - builder->CreateSExt(left, CommonType->GetLLVMType()); - ConvertedRight = - builder->CreateSExt(right, CommonType->GetLLVMType()); } else { Log(LogLevel::PCC_ERROR, "can not apply binary operator on two different type %s and %s", @@ -118,10 +115,10 @@ std::pair<std::shared_ptr<Type>, Value> return {nullptr, nullptr}; } } else { - ConvertedLeft = left; - ConvertedRight = right; CommonType = LeftType; } + ConvertedLeft = CreateCast(CommonType, LeftType, left, context); + ConvertedRight = CreateCast(CommonType, RightType, right, context); Value result = CommonType->CreateBinaryOperation(op, ConvertedLeft, ConvertedRight, context); if (result == nullptr) { diff --git a/node/ExprNode.cc b/node/ExprNode.cc index 6127f6f..4183120 100644 --- a/node/ExprNode.cc +++ b/node/ExprNode.cc @@ -90,8 +90,8 @@ Value FunctionCallNode::CodeGen() { name_.c_str()); return nullptr; } - llvm::FunctionCallee fp = - context_->GetModule()->getOrInsertFunction(name_, type->GetLLVMType()); + llvm::FunctionCallee fp = context_->GetModule()->getOrInsertFunction( + name_, llvm::cast<llvm::FunctionType>(type->GetLLVMType())); const std::vector<std::shared_ptr<Type>>& ArgTypes = type->GetArgTypes(); std::vector<Value> ArgValues(args_.size()); auto ArgTypeIt = ArgTypes.begin(); diff --git a/node/StatementNode.cc b/node/StatementNode.cc index fd8ee94..e29398d 100644 --- a/node/StatementNode.cc +++ b/node/StatementNode.cc @@ -29,4 +29,108 @@ Value AssignStatementNode::CodeGen() { context_->GetBuilder()->CreateStore(RightValue, LeftValue); return nullptr; } + +IfStatementNode::IfStatementNode(Context* context, + std::shared_ptr<ExprNode> expr, + std::shared_ptr<BaseNode> ThenPart, + std::shared_ptr<BaseNode> ElsePart) + : BaseNode(context) + , expr_(expr) + , ThenPart_(ThenPart) + , ElsePart_(ElsePart) {} + +Value IfStatementNode::CodeGen() { + llvm::IRBuilder<>* builder = context_->GetBuilder(); + TypeManager* manager = context_->GetTypeManager(); + std::shared_ptr<Type> boolean = + manager->GetBuiltinType(BuiltinType::BOOLEAN); + llvm::Function* body = builder->GetInsertBlock()->getParent(); + llvm::BasicBlock* ThenBlock = + llvm::BasicBlock::Create(GlobalLLVMContext, "then", body); + llvm::BasicBlock* EndBlock = + llvm::BasicBlock::Create(GlobalLLVMContext, "endif"); + Value ExprValue = manager->CreateCast(boolean, expr_->GetType(), + expr_->CodeGen(), context_); + if (ElsePart_ != nullptr) { + llvm::BasicBlock* ElseBlock = + llvm::BasicBlock::Create(GlobalLLVMContext, "else"); + builder->CreateCondBr(ExprValue, ThenBlock, ElseBlock); + builder->SetInsertPoint(ThenBlock); + ThenPart_->CodeGen(); + builder->CreateBr(EndBlock); + body->getBasicBlockList().push_back(ElseBlock); + builder->SetInsertPoint(ElseBlock); + ElsePart_->CodeGen(); + builder->CreateBr(EndBlock); + body->getBasicBlockList().push_back(EndBlock); + builder->SetInsertPoint(EndBlock); + return nullptr; + } + builder->CreateCondBr(ExprValue, ThenBlock, EndBlock); + builder->SetInsertPoint(ThenBlock); + ThenPart_->CodeGen(); + builder->CreateBr(EndBlock); + body->getBasicBlockList().push_back(EndBlock); + builder->SetInsertPoint(EndBlock); + return nullptr; +} + +WhileStatementNode::WhileStatementNode(Context* context, + std::shared_ptr<ExprNode> expr, + std::shared_ptr<BaseNode> WhileBody) + : BaseNode(context) + , expr_(expr) + , WhileBody_(WhileBody) {} + +Value WhileStatementNode::CodeGen() { + llvm::IRBuilder<>* builder = context_->GetBuilder(); + TypeManager* manager = context_->GetTypeManager(); + std::shared_ptr<Type> boolean = + manager->GetBuiltinType(BuiltinType::BOOLEAN); + llvm::Function* body = builder->GetInsertBlock()->getParent(); + llvm::BasicBlock* StartBlock = + llvm::BasicBlock::Create(GlobalLLVMContext, "start", body); + llvm::BasicBlock* LoopBlock = + llvm::BasicBlock::Create(GlobalLLVMContext, "loop"); + llvm::BasicBlock* EndBlock = + llvm::BasicBlock::Create(GlobalLLVMContext, "done"); + builder->SetInsertPoint(StartBlock); + Value ExprValue = manager->CreateCast(boolean, expr_->GetType(), + expr_->CodeGen(), context_); + builder->CreateCondBr(ExprValue, LoopBlock, EndBlock); + body->getBasicBlockList().push_back(LoopBlock); + builder->SetInsertPoint(LoopBlock); + WhileBody_->CodeGen(); + builder->CreateBr(StartBlock); + body->getBasicBlockList().push_back(EndBlock); + builder->SetInsertPoint(EndBlock); + return nullptr; +} + +RepeatStatementNode::RepeatStatementNode(Context* context, + std::shared_ptr<ExprNode> expr, + std::shared_ptr<BaseNode> RepeatBody) + : BaseNode(context) + , expr_(expr) + , RepeatBody_(RepeatBody) {} + +Value RepeatStatementNode::CodeGen() { + llvm::IRBuilder<>* builder = context_->GetBuilder(); + TypeManager* manager = context_->GetTypeManager(); + std::shared_ptr<Type> boolean = + manager->GetBuiltinType(BuiltinType::BOOLEAN); + llvm::Function* body = builder->GetInsertBlock()->getParent(); + llvm::BasicBlock* LoopBlock = + llvm::BasicBlock::Create(GlobalLLVMContext, "loop", body); + llvm::BasicBlock* EndBlock = + llvm::BasicBlock::Create(GlobalLLVMContext, "done"); + builder->SetInsertPoint(LoopBlock); + RepeatBody_->CodeGen(); + Value ExprValue = manager->CreateCast(boolean, expr_->GetType(), + expr_->CodeGen(), context_); + builder->CreateCondBr(ExprValue, EndBlock, LoopBlock); + body->getBasicBlockList().push_back(EndBlock); + builder->SetInsertPoint(EndBlock); + return nullptr; +} } // namespace pcc diff --git a/node/StatementNode.hh b/node/StatementNode.hh index 68c808f..1bd0cb6 100644 --- a/node/StatementNode.hh +++ b/node/StatementNode.hh @@ -25,6 +25,41 @@ class AssignStatementNode : public BaseNode { std::shared_ptr<ExprNode> lhs_; std::shared_ptr<ExprNode> rhs_; }; + +class IfStatementNode : public BaseNode { + public: + IfStatementNode(Context* context, std::shared_ptr<ExprNode> expr, + std::shared_ptr<BaseNode> ThenPart, + std::shared_ptr<BaseNode> ElsePart); + virtual Value CodeGen() override; + + protected: + std::shared_ptr<ExprNode> expr_; + std::shared_ptr<BaseNode> ThenPart_; + std::shared_ptr<BaseNode> ElsePart_; +}; + +class WhileStatementNode : public BaseNode { + public: + WhileStatementNode(Context* context, std::shared_ptr<ExprNode> expr, + std::shared_ptr<BaseNode> WhileBody); + virtual Value CodeGen() override; + + protected: + std::shared_ptr<ExprNode> expr_; + std::shared_ptr<BaseNode> WhileBody_; +}; + +class RepeatStatementNode : public BaseNode { + public: + RepeatStatementNode(Context* context, std::shared_ptr<ExprNode> expr, + std::shared_ptr<BaseNode> RepeatBody); + virtual Value CodeGen() override; + + protected: + std::shared_ptr<ExprNode> expr_; + std::shared_ptr<BaseNode> RepeatBody_; +}; } // namespace pcc #endif diff --git a/t/1.pas b/t/1.pas deleted file mode 100644 index 0b2228f..0000000 --- a/t/1.pas +++ /dev/null @@ -1,18 +0,0 @@ -program a; - -function test(a:integer;b:char;c:real;):integer; -var - d:integer; - e:char; - f:string; -begin - a:=1; - b:='a'; - c:=3.5; - a:=b*(c-b+6)--4; - d:=a*a-b-(5+c); - e:='\x03'; - f:='a normal test \'\\\0\023'; - f[4]; - test:=e+d; -end; diff --git a/t/trivial.pas b/t/trivial.pas new file mode 100644 index 0000000..1a433c5 --- /dev/null +++ b/t/trivial.pas @@ -0,0 +1,66 @@ +program a; + +function arithmetic_test(a:integer;b:char;c:real):integer; +var + d:integer; + e:char; + f:real; +begin + a:=1; d:=-2; + b:='B'; e:='\x46'; + c:=1.5; f:=-3.14; + + a:=a+b-c+d; + b:=b*c-d*e; + c:=c+d*e+f; + + b:=1; e:=2; + a:=1/2+b/e; + d:=1 div 2 + b div e; + arithmetic_test:=a+d +end; + +function string_test():char; +var + s:string; + a,b:char; +begin + s='hello world'; + a:=s[3]; + b:=s[6]; + string_test:=s[b-a] +end; + +function recursion_test(x:integer):integer; +begin + if (x=0) or (x=1) then + recursion_test:=1 + else + recursion_test:=recursion_test(x-1)+recursion_test(x-2) +end; + +function branch_test(a:integer):integer; +var + b,c:integer; +begin + b:=3; + if a<b then + if a>b then + c:=1 + else + c:=0 + else + c:=-1; + while b>0 do + begin + a:=a*b; + b:=b-1 + end; + repeat + begin + a:=a*c; + b:=b+1 + end + until b>5; + branch_test:=a; +end; |
