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