%{ #include #include #include #include #include #include #include #include #define INFILE_ERROR 1 #define OUTFILE_ERROR 2 extern int yylineno; extern FILE *yyin; extern FILE *yyout; int yylex(); void yyerror(const char *msg, ...); struct StackElement { std::string value; enum { INT, VAR } type; }; struct SymbolInfo { std::string type; int memoryLocation; }; std::map symbolTable; int memoryCounter = 0; std::stack expressionsStack; FILE *tripletFile; int tempVarCounter = 0; int stringCounter = 0; std::vector asmCode; std::map stringLiterals; bool isNumber(const std::string& s) { if (s.empty()) return false; size_t start = 0; if (s[0] == '-') start = 1; for (size_t i = start; i < s.length(); i++) { if (!isdigit(s[i])) return false; } return true; } void addSymbol(const std::string& name, const std::string& type) { if (symbolTable.find(name) == symbolTable.end()) { SymbolInfo info; info.type = type; info.memoryLocation = memoryCounter++; symbolTable[name] = info; } } // ASM std::string generateLoad(const std::string& reg, const std::string& value) { if (isNumber(value)) { return "li " + reg + ", " + value; } else { return "lw " + reg + ", " + value; } } void generateAsm(const std::string& result, const std::string& arg1, const std::string& arg2, const std::string& op) { if (op == "=" && arg2.empty()) { asmCode.push_back(generateLoad("$t0", arg1)); asmCode.push_back("sw $t0, " + result); } else { asmCode.push_back(generateLoad("$t0", arg1)); asmCode.push_back(generateLoad("$t1", arg2)); std::string asmOp; if (op == "+") asmOp = "add"; else if (op == "-") asmOp = "sub"; else if (op == "*") asmOp = "mul"; else if (op == "/") asmOp = "div"; asmCode.push_back(asmOp + " $t2, $t0, $t1"); asmCode.push_back("sw $t2, " + result); } } void generatePrintInt(const std::string& var) { asmCode.push_back("# print_integer(" + var + ")"); asmCode.push_back(generateLoad("$a0", var)); asmCode.push_back("li $v0, 1"); asmCode.push_back("syscall"); } void generatePrintFloat(const std::string& var) { asmCode.push_back("# print_float(" + var + ")"); asmCode.push_back("lwc1 $f12, " + var); asmCode.push_back("li $v0, 2"); asmCode.push_back("syscall"); } void generatePrintString(const std::string& strLabel) { asmCode.push_back("# print_string(" + strLabel + ")"); asmCode.push_back("la $a0, " + strLabel); asmCode.push_back("li $v0, 4"); asmCode.push_back("syscall"); } void generateReadInt(const std::string& var) { asmCode.push_back("# read_integer -> " + var); asmCode.push_back("li $v0, 5"); asmCode.push_back("syscall"); asmCode.push_back("sw $v0, " + var); } void generateReadFloat(const std::string& var) { asmCode.push_back("# read_float -> " + var); asmCode.push_back("li $v0, 6"); asmCode.push_back("syscall"); asmCode.push_back("swc1 $f0, " + var); } void writeDataSection(FILE* out) { fprintf(out, ".data\n"); for (auto& pair : symbolTable) { fprintf(out, "%s: .word 0\n", pair.first.c_str()); } for (auto& pair : stringLiterals) { fprintf(out, "%s: .asciiz %s\n", pair.first.c_str(), pair.second.c_str()); } fprintf(out, "\n"); } void writeCodeSection(FILE* out) { fprintf(out, ".text\n"); fprintf(out, ".globl main\n"); fprintf(out, "main:\n"); for (const auto& line : asmCode) { fprintf(out, " %s\n", line.c_str()); } fprintf(out, "\n # Exit program\n"); fprintf(out, " li $v0, 10\n"); fprintf(out, " syscall\n"); } void saveSymbolTable() { FILE* symbolFile = fopen("symbols.txt", "w"); if (symbolFile) { for (auto& pair : symbolTable) { fprintf(symbolFile, "%s: type=%s, location=%d\n", pair.first.c_str(), pair.second.type.c_str(), pair.second.memoryLocation); } fclose(symbolFile); } } // triplets std::string generateTempVar() { std::string result = "result" + std::to_string(tempVarCounter++); addSymbol(result, "Int"); return result; } void writeTriplet(const std::string& result, const std::string& arg1, const std::string& arg2, const std::string& op) { fprintf(tripletFile, "%s= %s %s %s\n", result.c_str(), arg1.c_str(), arg2.c_str(), op.c_str()); generateAsm(result, arg1, arg2, op); } %} %union { char *text; int ival; } %token ID %token STRING_LIT %token INT_LIT %token LET PRINT_INT PRINT_FLOAT PRINT_STRING READ_INT READ_FLOAT %token INT_TYPE %token SEMICOLON COLON %left '+' '-' %left '*' '/' %start program %% program : statement_list { printf("koniec\n"); } ; statement_list : statement | statement_list statement ; statement : variable_declaration { printf("Deklaracja zmiennej\n"); } | assignment { printf("Instrukcja przypisania\n"); } | print_statement { printf("Instrukcja wypisania\n"); } | read_statement { printf("Instrukcja odczytu\n"); } | expression SEMICOLON { printf("instrukcja\n"); if (!expressionsStack.empty()) { expressionsStack.pop(); } } ; variable_declaration : LET ID COLON INT_TYPE '=' expression SEMICOLON { printf("Deklaracja zmiennej: %s\n", $2); addSymbol(std::string($2), "Int"); if (!expressionsStack.empty()) { StackElement expression = expressionsStack.top(); expressionsStack.pop(); writeTriplet(std::string($2), expression.value, "", "="); } } ; assignment : ID '=' expression SEMICOLON { printf("Przypisanie do zmiennej: %s\n", $1); if (!expressionsStack.empty()) { StackElement expression = expressionsStack.top(); expressionsStack.pop(); writeTriplet(std::string($1), expression.value, "", "="); } } ; print_statement : PRINT_INT '(' expression ')' SEMICOLON { printf("print_integer\n"); if (!expressionsStack.empty()) { StackElement expr = expressionsStack.top(); expressionsStack.pop(); generatePrintInt(expr.value); } } | PRINT_FLOAT '(' expression ')' SEMICOLON { printf("print_float\n"); if (!expressionsStack.empty()) { StackElement expr = expressionsStack.top(); expressionsStack.pop(); generatePrintFloat(expr.value); } } | PRINT_STRING '(' STRING_LIT ')' SEMICOLON { printf("print_string: %s\n", $3); std::string label = "str" + std::to_string(stringCounter++); stringLiterals[label] = std::string($3); generatePrintString(label); } ; read_statement : READ_INT '(' ID ')' SEMICOLON { printf("read_integer -> %s\n", $3); generateReadInt(std::string($3)); } | READ_FLOAT '(' ID ')' SEMICOLON { printf("read_float -> %s\n", $3); generateReadFloat(std::string($3)); } ; expression : expression '+' expression { printf("Wyrazenie z +\n"); StackElement rhs = expressionsStack.top(); expressionsStack.pop(); StackElement lhs = expressionsStack.top(); expressionsStack.pop(); std::string temp = generateTempVar(); writeTriplet(temp, lhs.value, rhs.value, "+"); StackElement element; element.value = temp; element.type = StackElement::VAR; expressionsStack.push(element); } | expression '-' expression { printf("Wyrazenie z -\n"); StackElement rhs = expressionsStack.top(); expressionsStack.pop(); StackElement lhs = expressionsStack.top(); expressionsStack.pop(); std::string temp = generateTempVar(); writeTriplet(temp, lhs.value, rhs.value, "-"); StackElement element; element.value = temp; element.type = StackElement::VAR; expressionsStack.push(element); } | expression '*' expression { printf("Wyrazenie z *\n"); StackElement rhs = expressionsStack.top(); expressionsStack.pop(); StackElement lhs = expressionsStack.top(); expressionsStack.pop(); std::string temp = generateTempVar(); writeTriplet(temp, lhs.value, rhs.value, "*"); StackElement element; element.value = temp; element.type = StackElement::VAR; expressionsStack.push(element); } | expression '/' expression { printf("Wyrazenie z /\n"); StackElement rhs = expressionsStack.top(); expressionsStack.pop(); StackElement lhs = expressionsStack.top(); expressionsStack.pop(); std::string temp = generateTempVar(); writeTriplet(temp, lhs.value, rhs.value, "/"); StackElement element; element.value = temp; element.type = StackElement::VAR; expressionsStack.push(element); } | '(' expression ')' { printf("Wyrazenie w nawiasach\n"); } | INT_LIT { printf("Literal calkowity: %d\n", $1); StackElement element; element.value = std::to_string($1); element.type = StackElement::INT; expressionsStack.push(element); } | ID { printf("Identyfikator: %s\n", $1); StackElement element; element.value = std::string($1); element.type = StackElement::VAR; expressionsStack.push(element); } ; %% int main(int argc, char *argv[]) { tripletFile = fopen("triplets.txt", "w"); if (!tripletFile) { fprintf(stderr, "Blad triplets.txt\n"); return OUTFILE_ERROR; } yyout = fopen("output.asm", "w"); if (!yyout) { fprintf(stderr, "Blad output.asm\n"); fclose(tripletFile); return OUTFILE_ERROR; } yyparse(); fclose(tripletFile); writeDataSection(yyout); writeCodeSection(yyout); fclose(yyout); saveSymbolTable(); return 0; }