Files
zut-n1-kompilatory/def.yy
2026-01-07 23:11:09 +01:00

381 lines
11 KiB
Plaintext

%{
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stack>
#include <string>
#include <map>
#include <vector>
#include <cctype>
#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<std::string, SymbolInfo> symbolTable;
int memoryCounter = 0;
std::stack<StackElement> expressionsStack;
FILE *tripletFile;
int tempVarCounter = 0;
int stringCounter = 0;
std::vector<std::string> asmCode;
std::map<std::string, std::string> 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 <text> ID
%token <text> STRING_LIT
%token <ival> 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;
}