diff --git a/.gitignore b/.gitignore index be6548c..3c8f10c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ lex.yy.o triplets.txt symbols.txt output.asm +cutie +cutie.yy.cc +cutie.yy.o diff --git a/Makefile b/Makefile index f5371b6..4edf20b 100644 --- a/Makefile +++ b/Makefile @@ -4,16 +4,16 @@ LEX=flex YACC=bison LD=gcc -all: leks +all: cutie -leks: def.tab.o lex.yy.o - $(CXX) -std=c++11 lex.yy.o def.tab.o -o leks -ll +cutie: def.tab.o lex.yy.o + $(CXX) -std=c++11 cutie.yy.o def.tab.o -o cutie -ll lex.yy.o: lex.yy.cc - $(CXX) -std=c++11 -c lex.yy.cc + $(CXX) -std=c++11 -c cutie.yy.cc lex.yy.cc: z5.l - $(LEX) -o lex.yy.cc z5.l + $(LEX) -o cutie.yy.cc z5.l def.tab.o: def.tab.cc $(CXX) -std=c++11 -c def.tab.cc @@ -22,4 +22,4 @@ def.tab.cc: def.yy $(YACC) -d def.yy clean: - rm *.o cutie def.tab.cc def.tab.hh lex.yy.* triplets.txt + rm *.o cutie def.tab.cc def.tab.hh cutie.yy.* triplets.txt diff --git a/def.yy b/def.yy index ea95c57..78a4d73 100644 --- a/def.yy +++ b/def.yy @@ -31,9 +31,11 @@ std::map symbolTable; int memoryCounter = 0; std::stack expressionsStack; +std::stack labelStack; FILE *tripletFile; int tempVarCounter = 0; int stringCounter = 0; +int labelCounter = 0; std::vector asmCode; std::map stringLiterals; @@ -57,6 +59,10 @@ void addSymbol(const std::string& name, const std::string& type) { } } +std::string generateLabel() { + return "LBL" + std::to_string(labelCounter++); +} + // ASM std::string generateLoad(const std::string& reg, const std::string& value) { @@ -171,6 +177,42 @@ void writeTriplet(const std::string& result, const std::string& arg1, generateAsm(result, arg1, arg2, op); } +void generateIfJumpStatement(const std::string& op) { + if (expressionsStack.size() < 2) { + yyerror("Blad: niewystarczajaca liczba elementów w warunku"); + return; + } + + StackElement rhs = expressionsStack.top(); + expressionsStack.pop(); + StackElement lhs = expressionsStack.top(); + expressionsStack.pop(); + + std::string label = generateLabel(); + labelStack.push(label); + + asmCode.push_back(generateLoad("$t2", lhs.value)); + asmCode.push_back(generateLoad("$t3", rhs.value)); + + std::string jumpInstr; + if (op == "<") jumpInstr = "bge"; + else if (op == ">") jumpInstr = "ble"; + else if (op == "<=") jumpInstr = "bgt"; + else if (op == ">=") jumpInstr = "blt"; + else if (op == "==") jumpInstr = "bne"; + else if (op == "!=") jumpInstr = "beq"; + + asmCode.push_back(jumpInstr + " $t2, $t3, " + label); +} + +void generateIfEndStatement() { + if (!labelStack.empty()) { + std::string label = labelStack.top(); + labelStack.pop(); + asmCode.push_back(label + ":"); + } +} + %} %union { @@ -181,10 +223,13 @@ void writeTriplet(const std::string& result, const std::string& arg1, %token ID %token STRING_LIT %token INT_LIT +%token IF %token LET PRINT_INT PRINT_FLOAT PRINT_STRING READ_INT READ_FLOAT %token INT_TYPE %token SEMICOLON COLON +%token LE GE EQ NE +%left '<' '>' LE GE EQ NE %left '+' '-' %left '*' '/' @@ -206,6 +251,7 @@ statement | assignment { printf("Instrukcja przypisania\n"); } | print_statement { printf("Instrukcja wypisania\n"); } | read_statement { printf("Instrukcja odczytu\n"); } + | if_expr { printf("Instrukcja warunkowa\n"); } | expression SEMICOLON { printf("instrukcja\n"); if (!expressionsStack.empty()) { @@ -214,6 +260,27 @@ statement } ; + if_expr + : if_begin code_block { generateIfEndStatement(); } + ; + + if_begin + : IF '(' cond_expr ')' { generateIfJumpStatement($3); } + ; + + code_block + : '{' statement_list '}' + ; + + cond_expr + : expression '<' expression { $$ = strdup("<"); } + | expression '>' expression { $$ = strdup(">"); } + | expression LE expression { $$ = strdup("<="); } + | expression GE expression { $$ = strdup(">="); } + | expression EQ expression { $$ = strdup("=="); } + | expression NE expression { $$ = strdup("!="); } + ; + variable_declaration : LET ID COLON INT_TYPE '=' expression SEMICOLON { diff --git a/in5.txt b/in5.txt index f07f38e..77c7dee 100644 --- a/in5.txt +++ b/in5.txt @@ -1,5 +1,5 @@ let x: Int = 42; -print_string("Integer: \n"); +print_string("całkowita: \n"); print_string("\n"); print_integer(x); print_string("\n"); @@ -11,11 +11,13 @@ print_string("Float: \n"); print_float(f); print_string("\n"); -print_string("Podaj integer: \n"); +print_string("Podaj liczbe całkowitą: \n"); let y: Int = 0; read_integer(y); print_string("Wynik: \n"); print_integer(y); print_string("\n"); -print_string("Koniec testu\n"); +if (y == 0) { + print_string("y jest równy zeru"); +} diff --git a/z5.l b/z5.l index 131e37f..83b836d 100644 --- a/z5.l +++ b/z5.l @@ -12,6 +12,7 @@ void yyerror(const char *msg, ...); %option noyywrap %% "let" {fprintf(stdout, "LET\n"); return LET;} +"if" {fprintf(stdout, "IF\n"); return IF;} "Int" {fprintf(stdout, "INT_TYPE\n"); return INT_TYPE;} ":" {fprintf(stdout, ":\n"); return COLON;} ";" {fprintf(stdout, ";\n"); return SEMICOLON;} @@ -20,6 +21,14 @@ void yyerror(const char *msg, ...); "print_string" {fprintf(stdout, "PRINT_STRING\n"); return PRINT_STRING;} "read_integer" {fprintf(stdout, "READ_INT\n"); return READ_INT;} "read_float" {fprintf(stdout, "READ_FLOAT\n"); return READ_FLOAT;} +"{" {fprintf(stdout, "{\n"); return '{';} +"}" {fprintf(stdout, "}\n"); return '}';} +"<" {fprintf(stdout, "<\n"); return '<';} +">" {fprintf(stdout, ">\n"); return '>';} +"<=" {fprintf(stdout, "<=\n"); return LE;} +">=" {fprintf(stdout, ">=\n"); return GE;} +"==" {fprintf(stdout, "==\n"); return EQ;} +"!=" {fprintf(stdout, "!=\n"); return NE;} \+ {fprintf(stdout, "+\n"); return '+';} \* {fprintf(stdout, "*\n"); return '*';} \( {fprintf(stdout, "(\n"); return '(';}