From d5ba54a4cbbeab056caa4ef44622177c88458803 Mon Sep 17 00:00:00 2001 From: Moodle <project_12423_bot_5381ae6b41ffe5aff5e8289e3cc713be@noreply.gitlab.cs.pub.ro> Date: Sun, 23 Mar 2025 09:36:25 +0000 Subject: [PATCH] VMChecker backend --- src/Makefile | 2 +- src/main.c | 10 ++ src/parser.c | 263 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/parser.h | 8 ++ 4 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 src/parser.c create mode 100644 src/parser.h diff --git a/src/Makefile b/src/Makefile index 0622917..22e35f5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,7 +6,7 @@ TARGET = transpiler all: $(TARGET) -$(TARGET): main.o +$(TARGET): main.o parser.o $(CC) $(CFLAGS) -o ../$@ $^ %.o: %.c diff --git a/src/main.c b/src/main.c index 27729cd..373edd8 100644 --- a/src/main.c +++ b/src/main.c @@ -2,9 +2,19 @@ #include <stdlib.h> #include <string.h> +#include "parser.h" + /** * Starting point of the program, write anything here */ int main() { + char buffer[MAX_LINE]; + + while (fgets(buffer, sizeof(buffer), stdin)) { + if (strcmp(buffer, "\n") == 0) break; + buffer[strcspn(buffer, "\n")] = 0; // Remove newline + translate(buffer); + } + return 0; } \ No newline at end of file diff --git a/src/parser.c b/src/parser.c new file mode 100644 index 0000000..eeb1e39 --- /dev/null +++ b/src/parser.c @@ -0,0 +1,263 @@ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> +#include "parser.h" + +int isWhile = 0; +int isFor = 0; +char forVar; + +// Recognize statement types +StatementType identify_statement(const char *line) { + if (strstr(line, "for")) return FOR; + if (strstr(line, "=") && strstr(line, "+")) return ADD; + if (strstr(line, "=") && strstr(line, "-")) return SUB; + if (strstr(line, "*") && strstr(line, "=")) return MUL; + if (strstr(line, "/") && strstr(line, "=")) return DIV; + if (strstr(line, "=") && strstr(line, "<<")) return SHL; + if (strstr(line, "=") && strstr(line, ">>")) return SHR; + if (strstr(line, "^")) return XOR; + if (strstr(line, "&")) return AND; + if (strstr(line, "|")) return OR; + if (strstr(line, "if")) return IF; + if (strstr(line, "else")) return ELSE; + if (strstr(line, "while")) return WHILE; + if (strstr(line, "=")) return ASSIGN; + if (strstr(line, "}")) return ENDOP; + return UNKNOWN; +} + +// Basic translation logic +void translate(const char *line) { + StatementType type = identify_statement(line); + + while (isspace(*line)) { + line++; + } + + switch (type) { + case ASSIGN: { + char var, value[10]; + sscanf(line, "%c = %s", &var, value); + value[strlen(value) - 1] = '\0'; + + if (isdigit(value[0])) { + printf("MOV e%cx, %s\n", var, value); + } else { + printf("MOV e%cx, e%cx\n", var, value[0]); + } + + break; + } + case ADD: { + char var, operand[10]; + sscanf(line, "%c = %c + %s", &var, &var, operand); + operand[strlen(operand) - 1] = '\0'; + + if (isdigit(operand[0])) { + printf("ADD e%cx, %s\n", var, operand); + } else { + printf("ADD e%cx, e%cx\n", var, operand[0]); + } + + break; + } + case SUB: { + char var, operand[10]; + sscanf(line, "%c = %c - %s", &var, &var, operand); + operand[strlen(operand) - 1] = '\0'; + + if (isdigit(operand[0])) { + printf("SUB e%cx, %s\n", var, operand); + } else { + printf("SUB e%cx, e%cx\n", var, operand[0]); + } + + break; + } + case MUL: { + char var, operand[10]; + sscanf(line, "%c = %c * %s", &var, &var, operand); + operand[strlen(operand) - 1] = '\0'; + + if (isdigit(operand[0])) { + if (var == 'a') { + printf("MUL %s\n", operand); + } else { + printf("MOV eax, e%cx\nMUL %s\nMOV e%cx, eax\n", var, operand, var); + } + } else { + if (var == 'a') { + printf("MUL e%cx\n", operand[0]); + } else { + printf("MOV eax, e%cx\nMUL e%cx\nMOV e%cx, eax\n", var, operand[0], var); + } + } + + break; + } + case DIV: { + char var, operand[10]; + sscanf(line, "%c = %c / %s", &var, &var, operand); + operand[strlen(operand) - 1] = '\0'; + + if (isdigit(operand[0])) { + if (operand[0] == '0') { + printf("Error\n"); + return; + } + if (var == 'a') { + printf("DIV %s\n", operand); + } else { + printf("MOV eax, e%cx\nDIV %s\nMOV e%cx, eax\n", var, operand, var); + } + } else { + if (var == 'a') { + printf("DIV e%cx\n", operand[0]); + } else { + printf("MOV eax, e%cx\nDIV e%cx\nMOV e%cx, eax\n", var, operand[0], var); + } + } + + break; + } + case AND: { + char var, operand[3]; + sscanf(line, "%c = %c & %s", &var, &var, operand); + operand[strlen(operand) - 1] = '\0'; + + if (isdigit(operand[0])) { + printf("AND e%cx, %s\n", var, operand); + } else { + printf("AND e%cx, e%cx\n", var, operand[0]); + } + + break; + } + case OR: { + char var, operand[3]; + sscanf(line, "%c = %c | %s", &var, &var, operand); + operand[strlen(operand) - 1] = '\0'; + + if (isdigit(operand[0])) { + printf("OR e%cx, %s\n", var, operand); + } else { + printf("OR e%cx, e%cx\n", var, operand[0]); + } + + break; + } + case XOR: { + char var, operand[3]; + sscanf(line, "%c = %c ^ %s", &var, &var, operand); + operand[strlen(operand) - 1] = '\0'; + + if (isdigit(operand[0])) { + printf("XOR e%cx, %s\n", var, operand); + } else { + printf("XOR e%cx, e%cx\n", var, operand[0]); + } + + break; + } + case SHL: { + char var, operand[3]; + sscanf(line, "%c = %c << %s", &var, &var, operand); + operand[strlen(operand) - 1] = '\0'; + + printf("SHL e%cx, %s\n", var, operand); + break; + } + case SHR: { + char var, operand[3]; + sscanf(line, "%c = %c >> %s", &var, &var, operand); + operand[strlen(operand) - 1] = '\0'; + + printf("SHR e%cx, %s\n", var, operand); + break; + } + case IF: { + char var1, op[3], var2[10]; + sscanf(line, "if ( %c %s %s )", &var1, op, var2); + var2[strlen(var2) - 1] = '\0'; + + printf("CMP e%cx, %s\n", var1, var2); + + if (strstr(op, "==")) { + printf("JNE end_label\n"); + } else if (strstr(op, "!=")) { + printf("JE end_label\n"); + } else if (strstr(op, "<=")) { + printf("JG end_label\n"); + } else if (strstr(op, ">=")) { + printf("JL end_label\n"); + } else if (strstr(op, "<")) { + printf("JGE end_label\n"); + } else if (strstr(op, ">")) { + printf("JLE end_label\n"); + } + + break; + } + case ELSE: { + printf("else_label:\nend_if:\n"); + break; + } + case WHILE: { + char var1, op[3], var2[10]; + sscanf(line, "while ( %c %s %s )", &var1, op, var2); + var2[strlen(var2) - 1] = '\0'; + + printf("start_loop:\nCMP e%cx, %s\n", var1, var2); + + if (strstr(op, "==")) { + printf("JNE end_label\n"); + } else if (strstr(op, "!=")) { + printf("JE end_label\n"); + } else if (strstr(op, "<=")) { + printf("JG end_label\n"); + } else if (strstr(op, ">=")) { + printf("JL end_label\n"); + } else if (strstr(op, "<")) { + printf("JGE end_label\n"); + } else if (strstr(op, ">")) { + printf("JLE end_label\n"); + } + + isWhile = 1; + break; + } + case FOR: { + char var, start[3], end[3]; + sscanf(line, "for ( %c = %[^;]; %c < %[^;]; %c++ )", &var, start, &var, end, &var); + printf("MOV e%cx, %s\nstart_loop:\nCMP e%cx, %s\n", var, start, var, end); + + if (strstr(end, "<=")) { + printf("JG end_label\n"); + } else if (strstr(end, "<")) { + printf("JGE end_label\n"); + } + + isFor = 1; + forVar = var; + break; + } + case ENDOP: { + if (isWhile) { + printf("JMP start_loop\nend_label:\n"); + isWhile = 0; + } else if (isFor) { + printf("ADD e%cx, 1\nJMP start_loop\nend_loop:\n", forVar); + isFor = 0; + } else { + printf("end_label:\n"); + } + break; + } + default: + + printf("; Unrecognized statement: %s\n", line); + break; + } +} diff --git a/src/parser.h b/src/parser.h new file mode 100644 index 0000000..dda432b --- /dev/null +++ b/src/parser.h @@ -0,0 +1,8 @@ +#pragma once + +#define MAX_LINE 256 + +// Simple enum for recognizing statements +typedef enum { ASSIGN, ADD, SUB, MUL, DIV, XOR, OR, AND, SHL, SHR, IF, ELSE, WHILE, FOR, ENDOP, UNKNOWN } StatementType; + +void translate(const char *line); -- GitLab