From e4e06fe1ac1b855f4abdba0748a4f058486c08e8 Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Mon, 12 Feb 2024 13:29:07 +0100 Subject: [PATCH 01/22] Start new version for parser - Rework parser - Edit AST structure - Restart bin exporter, builder and debugger - Add error system following technical standard --- CMakeLists.txt | 2 + src/2at2.c | 28 ++- src/ast.h | 154 +++----------- src/binExporter.c | 283 ------------------------- src/binExporter.h | 67 ------ src/builder.c | 478 +++++++++++++++++++++--------------------- src/builder.h | 66 +++--- src/debug.c | 266 +----------------------- src/debug.h | 71 +------ src/error.c | 93 +++++++++ src/error.h | 49 +++++ src/parser.c | 515 +++++++--------------------------------------- src/parser.h | 38 +--- 13 files changed, 543 insertions(+), 1567 deletions(-) create mode 100644 src/error.c create mode 100644 src/error.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d735f1..920d7a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ add_executable(tests src/parser.c src/builder.c src/debug.c + src/error.c src/binExporter.c test/test.cc googletest/googletest/src/gtest-all.cc @@ -60,6 +61,7 @@ add_executable(2at2 src/parser.c src/builder.c src/debug.c + src/error.c src/binExporter.c src/2at2.c ) diff --git a/src/2at2.c b/src/2at2.c index 6ecaea8..a677748 100644 --- a/src/2at2.c +++ b/src/2at2.c @@ -4,12 +4,15 @@ */ #include #include +#include + #include "parser.h" #include "builder.h" #include "2at2.h" #include "debug.h" +#include "error.h" -#define VERSION "0.0.3" +#define VERSION "0.0.5" int main(int argc, char *argv[]) { // Parse program arguments and get flags @@ -42,24 +45,17 @@ int main(int argc, char *argv[]) { instList_t *instList = malloc(sizeof(instList_t)); instList->head = NULL; - // run parser - parseFile(instList, argv[1]); - - if(flags.debug) { - printInstList(instList, "../others/parsing.log"); - printVarList(varList, "../others/parsing.log"); - printLabelList(labelList, "../others/parsing.log"); - } + // Init error data history + error_t *errData = malloc(sizeof(error_t)); + errData->errors = 0; + errData->inputFile = malloc(sizeof(argv[1])+1); + strcpy(errData->inputFile, argv[1]); + // run parser + parseFile(instList, argv[1], errData); // run builder - build(instList, labelList, varList); - - if(flags.debug) { - printInstList(instList, "../others/building.log"); - printVarList(varList, "../others/building.log"); - printLabelList(labelList, "../others/building.log"); - } + // TODO: Do Builder // run exporter // TODO: make the function export to binary diff --git a/src/ast.h b/src/ast.h index 47b5556..993e980 100644 --- a/src/ast.h +++ b/src/ast.h @@ -4,80 +4,44 @@ #pragma once -// Variables types -enum varKind{ - VAR_INT, - VAR_FLOAT, - VAR_CHAR, - VAR_STRING, - VAR_REG, - VAR_TARGET, - VAR_CMP, - VAR_NONE -}; - -// Instruction types -enum instKind{ - INST_OP, - INST_ACT, - INST_LABEL, - INST_VAR -}; +#include // Operation types enum opKind{ + OP_MOV, + OP_GOTO, + OP_CALL, + OP_INT, + OP_PUSH, + OP_B_XOR, + OP_POP, + OP_DIV, OP_ADD, OP_SUB, OP_MUL, - OP_DIV, - OP_MOD, OP_R_SHIFT, OP_L_SHIFT, OP_B_AND, OP_B_OR, - OP_B_XOR, OP_B_NOT, - OP_B_NEG, - OP_INC, - OP_DEC -}; - -// Action types -enum actKind{ - ACT_MOV, - ACT_GOTO, - ACT_CALL, - ACT_RET, - ACT_CLOK, - ACT_DRAW, - ACT_CMP, - ACT_EXIT, - ACT_PUSH, - ACT_POP, - ACT_PUSH_A, - ACT_POP_A, - ACT_OB1 -}; - -// comparison statements -enum cmpStatem{ - CMP_IF, - CMP_ELSE, - CMP_END }; -// Comparison types -enum cmpKind{ - CMP_OR, - CMP_AND, - CMP_NOT, - CMP_XOR, - CMP_LT, // less than - CMP_GT, // greater than - CMP_LTE, // less than or equal - CMP_GTE, // greater than or equal - CMP_EQ, - CMP_NEQ // not equal +// interrupt types +enum interruptKind{ + INT_EXIT, + INT_DRAW, + INT_OB1, + INT_OR, + INT_AND, + INT_XOR, + INT_LT, + INT_LTE, + INT_GT, + INT_GTE, + INT_EQ, + INT_NEQ, + INT_PUSHA, + INT_POPA, }; // Register names @@ -92,55 +56,17 @@ enum regKind{ RG_7 }; -// Structs for operations nodes -typedef struct opNode{ - enum opKind op; -} opNode_t; - -// Structs for comparison nodes -typedef struct cmpNode{ - enum cmpStatem statem; - enum cmpKind cmp; - long elseId; - long endId; -} cmpNode_t; - -// Structs for action nodes -typedef struct actNode{ - enum actKind act; - cmpNode_t *cmp; -} actNode_t; // Structs for instruction nodes typedef struct instNode{ long id; long lineNb; - enum instKind inst; - union{ - opNode_t *op; - actNode_t *act; - char *label; - } nodeType; + enum opKind op; + bool isInter; + enum interruptKind inter; + char * arg; + enum regKind inputReg; struct instNode *next; - enum varKind arg0Type; - union{ - int i_value; - float f_value; - char c_value; - char * s_value; - enum regKind reg; - char * target; // to target variable or label - }arg0; - enum varKind arg1Type; - union{ - int i_value; - float f_value; - char c_value; - char * s_value; - enum regKind reg; - char * target; - }arg1; - enum regKind targetReg; } instNode_t; // Structs for instruction list @@ -148,28 +74,10 @@ typedef struct instList{ instNode_t *head; } instList_t; -// Struct for register -typedef struct reg{ - enum regKind name; - enum varKind type; - union{ - int i_value; - float f_value; - char c_value; - char * s_value; - }value; -} reg_t; - // Structs for variable storage typedef struct var{ char *name; - enum varKind type; - union{ - int i_value; - float f_value; - char c_value; - char * s_value; - }value; + char * value; } var_t; // Structs for variable list diff --git a/src/binExporter.c b/src/binExporter.c index f214351..3fdfdcd 100644 --- a/src/binExporter.c +++ b/src/binExporter.c @@ -8,286 +8,3 @@ #include "binExporter.h" -void exportAST(instList_t *ast, varList_t *varList, labelList_t *labelList, char *filename){ - FILE *file = fopen(filename, "wb"); - if(file == NULL){ - fprintf(stderr, "Error opening file\n"); - exit(EXIT_FAILURE); - } - fprintf(file, "[\n"); - - // write varList - writeVarList(varList, file); - - - // write labelList - writeLabelList(labelList, file); - - - // write ast - writeAST(ast, file); - - fprintf(file, "\n]"); - - fclose(file); -} - -void writeVarList(varList_t *varList, FILE *file) { - if (!varList || !file) { - fprintf(stderr, "Invalid arguments\n"); - return; - } - - fprintf(file, "{\"size\": %zu, \"vars\": [", varList->size); - - for (size_t i = 0; i < varList->size; i++) { - fprintf(file, "\n{\"name\": \"%s\", \"type\": \"%s\", \"value\": ", - varList->list[i].name, - varList->list[i].type == VAR_INT ? "int" : - varList->list[i].type == VAR_FLOAT ? "float" : - varList->list[i].type == VAR_CHAR ? "char" : - varList->list[i].type == VAR_STRING ? "string" : "unknown"); - - switch (varList->list[i].type) { - case VAR_INT: - fprintf(file, "%d", varList->list[i].value.i_value); - break; - case VAR_FLOAT: - fprintf(file, "%f", varList->list[i].value.f_value); - break; - case VAR_CHAR: - fprintf(file, "'%c'", varList->list[i].value.c_value); - break; - case VAR_STRING: - fprintf(file, "\"%s\"", varList->list[i].value.s_value); - break; - default: - fprintf(file, "null"); - } - - fprintf(file, "}"); - - if (i < varList->size - 1) { - fprintf(file, ","); - } - } - - fprintf(file, "\n]},\n"); -} - -void writeLabelList(labelList_t *labelList, FILE *file){ - if (!labelList || !file) { - fprintf(stderr, "Invalid arguments\n"); - return; - } - - fprintf(file, "{\"size\": %zu, \"labels\": [", labelList->size); - - for (size_t i = 0; i < labelList->size; i++) { - fprintf(file, "\n{\"name\": \"%s\", \"nodeId\": %ld, \"id\": %ld}", - labelList->list[i].name, - labelList->list[i].nodeId, - labelList->list[i].id); - - if (i < labelList->size - 1) { - fprintf(file, ","); - } - } - - fprintf(file, "\n]},\n"); -} - -void writeAST(instList_t *ast, FILE *file){ - if (!ast || !file) { - fprintf(stderr, "Invalid arguments\n"); - return; - } - - fprintf(file, "{ \"nodes\": ["); - - instNode_t *node = ast->head; - while (node) { - fprintf(file, "\n{\"nodeId\": %ld, ",node->id); - - // set instKind - switch (node->inst) - { - case INST_OP: - fprintf(file, "\"instKind\": \"ope\", \"inst\": \"%s\"", getOpkindStr(node->nodeType.op->op)); - break; - case INST_ACT: - fprintf(file, "\"instKind\": \"act\", \"inst\": \"%s\"", getActkindStr(node->nodeType.act->act)); - break; - case INST_LABEL: - fprintf(file, "\"instKind\": \"label\", \"label\": \"lab\""); - break; - case INST_VAR: - fprintf(file, "\"instKind\": \"var\", \"var\": \"var\""); - break; - default: - break; - } - - //Add args - fprintf(file, ", \"args\": ["); - if(node->inst == INST_ACT && node->nodeType.act->act == ACT_CMP && node->nodeType.act->cmp->statem == CMP_IF){ - fprintf(file, "{\"type\": \"cmp\", \"val\": %s},", getCmpKindStr(node->nodeType.act->cmp->cmp)); - } - - switch (node->arg0Type){ - case VAR_INT: - fprintf(file, "{\"type\": \"int\", \"val\": %d},", node->arg0.i_value); - break; - case VAR_FLOAT: - fprintf(file, "{\"type\": \"float\", \"val\": %f},", node->arg0.f_value); - break; - case VAR_CHAR: - fprintf(file, "{\"type\": \"char\", \"val\": \"%c\"},", node->arg0.c_value); - break; - case VAR_STRING: - fprintf(file, "{\"type\": \"string\", \"val\": \"%s\"},", node->arg0.s_value); - break; - case VAR_REG: - fprintf(file, "{\"type\": \"reg\", \"val\": \"%s\"},", node->arg0.reg == RG_0 ? "r0" : node->arg0.reg == RG_1 ? "r1" : node->arg0.reg == RG_2 ? "r2" : node->arg0.reg == RG_3 ? "r3" : node->arg0.reg == RG_4 ? "r4" : node->arg0.reg == RG_5 ? "r5" : node->arg0.reg == RG_6 ? "r6" : node->arg0.reg == RG_7 ? "r7" : "unknown"); - break; - case VAR_TARGET: - fprintf(file, "{\"type\": \"target\", \"val\": \"%s\"},", node->arg0.target); - break; - - default: - break; - } - - switch (node->arg1Type){ - case VAR_INT: - fprintf(file, "{\"type\": \"int\", \"val\": %d}", node->arg1.i_value); - break; - case VAR_FLOAT: - fprintf(file, "{\"type\": \"float\", \"val\": %f}", node->arg1.f_value); - break; - case VAR_CHAR: - fprintf(file, "{\"type\": \"char\", \"val\": \"%c\"}", node->arg1.c_value); - break; - case VAR_STRING: - fprintf(file, "{\"type\": \"string\", \"val\": \"%s\"}", node->arg1.s_value); - break; - case VAR_REG: - fprintf(file, "{\"type\": \"reg\", \"val\": \"%s\"}", node->arg1.reg == RG_0 ? "r0" : node->arg0.reg == RG_1 ? "r1" : node->arg0.reg == RG_2 ? "r2" : node->arg0.reg == RG_3 ? "r3" : node->arg0.reg == RG_4 ? "r4" : node->arg0.reg == RG_5 ? "r5" : node->arg0.reg == RG_6 ? "r6" : node->arg0.reg == RG_7 ? "r7" : "unknown"); - break; - case VAR_TARGET: - fprintf(file, "{\"type\": \"target\", \"val\": \"%s\"}", node->arg1.target); - break; - - default: - break; - } - fprintf(file, "]"); - - fprintf(file, "}"); - if (node->next) { - fprintf(file, ","); - } - node = node->next; - } - - - fprintf(file, "\n]}"); -} - -char *getOpkindStr(enum opKind kind){ - switch (kind) - { - case OP_ADD: - return "add"; - case OP_SUB: - return "sub"; - case OP_MUL: - return "mul"; - case OP_DIV: - return "div"; - case OP_MOD: - return "mod"; - case OP_INC: - return "inc"; - case OP_DEC: - return "dec"; - case OP_B_AND: - return "and"; - case OP_B_OR: - return "or"; - case OP_B_XOR: - return "xor"; - case OP_B_NOT: - return "not"; - case OP_L_SHIFT: - return "shl"; - case OP_R_SHIFT: - return "shr"; - case OP_B_NEG: - return "neg"; - default: - return "unknown"; - } -} - -char *getActkindStr(enum actKind kind){ - switch (kind) - { - case ACT_MOV: - return "mov"; - case ACT_GOTO: - return "goto"; - case ACT_CALL: - return "call"; - case ACT_RET: - return "ret"; - case ACT_CLOK: - return "clok"; - case ACT_DRAW: - return "draw"; - case ACT_CMP: - return "cmp"; - case ACT_EXIT: - return "exit"; - case ACT_PUSH: - return "push"; - case ACT_POP: - return "pop"; - case ACT_PUSH_A: - return "pusha"; - case ACT_POP_A: - return "popa"; - case ACT_OB1: - return "ob1"; - default: - return "unknown"; - } -} - -char *getCmpKindStr(enum cmpKind kind){ - switch (kind) - { - case CMP_OR: - return "or"; - case CMP_AND: - return "and"; - case CMP_NOT: - return "not"; - case CMP_XOR: - return "xor"; - case CMP_LT: - return "lt"; - case CMP_GT: - return "gt"; - case CMP_LTE: - return "lte"; - case CMP_GTE: - return "gte"; - case CMP_EQ: - return "eq"; - case CMP_NEQ: - return "neq"; - default: - return "unknown"; - } -} \ No newline at end of file diff --git a/src/binExporter.h b/src/binExporter.h index 620d0f1..9dcf124 100644 --- a/src/binExporter.h +++ b/src/binExporter.h @@ -5,73 +5,6 @@ extern "C" { #endif -/* - Export the AST to a binary file - params: - astNb *node: the root of the AST - varList_t *varList: the list of variables - labelList_t *labelList: the list of labels - char *filename: the name of the file to export - -*/ -void exportAST(instList_t *ast, varList_t *varList, labelList_t *labelList, char *filename); - -/* - Write variable list to file in json format - format exemple: - {"size": 2,"list": [{"name": "var1","type": "int","value": 5},{"name": "var2","type": "float","value": 3.14}]} - params: - varList_t *varList: the list of variables - FILE *file: the file to write to -*/ -void writeVarList(varList_t *varList, FILE *file); - -/* - Write label list to file in json format - format exemple: - {"size": 2,"list": [{"name": "label1","nodeId": 5,"id": 1},{"name": "label2","nodeId": 10,"id": 2}]} - params: - labelList_t *labelList: the list of labels - FILE *file: the file to write to -*/ -void writeLabelList(labelList_t *labelList, FILE *file); - -/* - Write AST to file in json format - format exemple: - [{"instKind": "ope", "nodeId": 4, "inst": "++", "args": [{"type": "float", "val": 3.14}, ..]}, {"instKind": "if", "inst": ">", "nodeId": 5, "args": [{"type": "int", "val": 5}, ..], "true": {"instKind": "ope", "inst": "++", "nodeId": 6, "args": [{"type": "float", "val": 3.14}, ..] - params: - instList_t *ast: the AST - FILE *file: the file to write to -*/ -void writeAST(instList_t *ast, FILE *file); - -/* - Get the string representation of an operation kind - params: - enum opKind kind: the kind of operation - return: - char *: the string representation -*/ -char *getOpkindStr(enum opKind kind); - -/* - Get the string representation of an action kind - params: - enum actKind kind: the kind of action - return: - char *: the string representation -*/ -char *getActkindStr(enum actKind kind); - -/* - Get the string representation of a comparison kind - params: - enum cmpKind kind: the kind of comparison - return: - char *: the string representation -*/ -char *getCmpKindStr(enum cmpKind kind); #ifdef __cplusplus } diff --git a/src/builder.c b/src/builder.c index 76311fb..653f954 100644 --- a/src/builder.c +++ b/src/builder.c @@ -10,266 +10,266 @@ #include "builder.h" -void build(instList_t *nodeList, labelList_t *labelList, varList_t *varList){ - // init lifo for if/else statements - lifoCmpNode_t *lifoCmpNode = (lifoCmpNode_t *)malloc(sizeof(lifoCmpNode_t)); - if(lifoCmpNode == NULL){ - fprintf(stderr, "Error allocating memory\n"); - exit(EXIT_FAILURE); - } - lifoCmpNode->list = NULL; - lifoCmpNode->size = 0; +// void build(instList_t *nodeList, labelList_t *labelList, varList_t *varList){ +// // init lifo for if/else statements +// lifoCmpNode_t *lifoCmpNode = (lifoCmpNode_t *)malloc(sizeof(lifoCmpNode_t)); +// if(lifoCmpNode == NULL){ +// fprintf(stderr, "Error allocating memory\n"); +// exit(EXIT_FAILURE); +// } +// lifoCmpNode->list = NULL; +// lifoCmpNode->size = 0; - // read the list of instructions - instNode_t *currNode = nodeList->head; - instNode_t *prevNode = NULL; - while (currNode != NULL) - { - // Check if node is an action - if(currNode->inst == INST_ACT){ - buildActNode(currNode, lifoCmpNode); - } +// // read the list of instructions +// instNode_t *currNode = nodeList->head; +// instNode_t *prevNode = NULL; +// while (currNode != NULL) +// { +// // Check if node is an action +// if(currNode->inst == INST_ACT){ +// buildActNode(currNode, lifoCmpNode); +// } - // Check if node is a label - if(currNode->inst == INST_LABEL){ - buildLabelNode(currNode, labelList); - } +// // Check if node is a label +// if(currNode->inst == INST_LABEL){ +// buildLabelNode(currNode, labelList); +// } - // Check if node is a variable declaration - if(currNode->inst == INST_VAR){ - addVar(varList, currNode); - // remove var declaration from list - if(prevNode == NULL){ - nodeList->head = currNode->next; - } - else{ - prevNode->next = currNode->next; - } - } +// // Check if node is a variable declaration +// if(currNode->inst == INST_VAR){ +// addVar(varList, currNode); +// // remove var declaration from list +// if(prevNode == NULL){ +// nodeList->head = currNode->next; +// } +// else{ +// prevNode->next = currNode->next; +// } +// } - prevNode = currNode; - currNode = currNode->next; - } +// prevNode = currNode; +// currNode = currNode->next; +// } - // Check if lifo is empty - if(lifoCmpNode->size != 0){ - fprintf(stderr, "Error: Comparison Lifo is not empty\n"); - exit(EXIT_FAILURE); - } +// // Check if lifo is empty +// if(lifoCmpNode->size != 0){ +// fprintf(stderr, "Error: Comparison Lifo is not empty\n"); +// exit(EXIT_FAILURE); +// } -} +// } -void buildActNode(instNode_t *node, lifoCmpNode_t *lifo){ - // Check if it's a comparison - if(node->nodeType.act->act == ACT_CMP){ - buildCmpNode(node, lifo); - } +// void buildActNode(instNode_t *node, lifoCmpNode_t *lifo){ +// // Check if it's a comparison +// if(node->nodeType.act->act == ACT_CMP){ +// buildCmpNode(node, lifo); +// } -} +// } -void buildCmpNode(instNode_t *node, lifoCmpNode_t *lifo){ - // Check kind of statement - switch (node->nodeType.act->cmp->statem) - { - case CMP_IF: - // add to lifo - pushCmpLifo(lifo, node->nodeType.act->cmp); - break; - case CMP_ELSE: - // set else goto - lifo->list[0]->elseId = node->id; - break; - case CMP_END: - // set end goto - lifo->list[0]->endId = node->id; - // remove from lifo - popCmpLifo(lifo); - break; - default: - fprintf(stderr, "Error: Unknown comparison statement\n"); - exit(EXIT_FAILURE); - break; - } -} +// void buildCmpNode(instNode_t *node, lifoCmpNode_t *lifo){ +// // Check kind of statement +// switch (node->nodeType.act->cmp->statem) +// { +// case CMP_IF: +// // add to lifo +// pushCmpLifo(lifo, node->nodeType.act->cmp); +// break; +// case CMP_ELSE: +// // set else goto +// lifo->list[0]->elseId = node->id; +// break; +// case CMP_END: +// // set end goto +// lifo->list[0]->endId = node->id; +// // remove from lifo +// popCmpLifo(lifo); +// break; +// default: +// fprintf(stderr, "Error: Unknown comparison statement\n"); +// exit(EXIT_FAILURE); +// break; +// } +// } -void buildLabelNode(instNode_t *node, labelList_t *labelList){ - // Check if label is already in the list - for(size_t i = 0; i < labelList->size; i++){ - if(labelList->list[i].name == NULL){ - continue; - } - else if(strcmp(labelList->list[i].name, node->arg0.target) == 0){ - fprintf(stderr, "Label %s already declared\n", node->arg0.target); - exit(EXIT_FAILURE); - } - } - // Add label to the list - addLabel(labelList, node->arg0.target, node->id); -} +// void buildLabelNode(instNode_t *node, labelList_t *labelList){ +// // Check if label is already in the list +// for(size_t i = 0; i < labelList->size; i++){ +// if(labelList->list[i].name == NULL){ +// continue; +// } +// else if(strcmp(labelList->list[i].name, node->arg0.target) == 0){ +// fprintf(stderr, "Label %s already declared\n", node->arg0.target); +// exit(EXIT_FAILURE); +// } +// } +// // Add label to the list +// addLabel(labelList, node->arg0.target, node->id); +// } -void addLabel(labelList_t *list, char *name, long nodeId){ - // Check if list is full - bool full = true; - for(size_t i = 0; i < list->size; i++){ - if(list->list[i].name == NULL){ - full = false; - break; - } - } - if(full){ - // Increase list size - incLabelList(list); - } +// void addLabel(labelList_t *list, char *name, long nodeId){ +// // Check if list is full +// bool full = true; +// for(size_t i = 0; i < list->size; i++){ +// if(list->list[i].name == NULL){ +// full = false; +// break; +// } +// } +// if(full){ +// // Increase list size +// incLabelList(list); +// } - // Add label to the list - for(size_t i = 0; i < list->size; i++){ - if(list->list[i].name == NULL){ - list->list[i].name = name; - list->list[i].nodeId = nodeId; - list->list[i].id = (long)i; - break; - } - } -} +// // Add label to the list +// for(size_t i = 0; i < list->size; i++){ +// if(list->list[i].name == NULL){ +// list->list[i].name = name; +// list->list[i].nodeId = nodeId; +// list->list[i].id = (long)i; +// break; +// } +// } +// } -void incLabelList(labelList_t *list){ - // Increase list size - list->size *= 2; - list->list = (label_t *)realloc(list->list, sizeof(label_t) * list->size); - if(list->list == NULL){ - fprintf(stderr, "Error reallocating memory\n"); - exit(EXIT_FAILURE); - } +// void incLabelList(labelList_t *list){ +// // Increase list size +// list->size *= 2; +// list->list = (label_t *)realloc(list->list, sizeof(label_t) * list->size); +// if(list->list == NULL){ +// fprintf(stderr, "Error reallocating memory\n"); +// exit(EXIT_FAILURE); +// } - // Init new memory - for(size_t i = list->size / 2; i < list->size; i++){ - list->list[i].name = NULL; - } -} +// // Init new memory +// for(size_t i = list->size / 2; i < list->size; i++){ +// list->list[i].name = NULL; +// } +// } -labelList_t* initLabelList(){ - labelList_t *labelList = malloc(sizeof(labelList_t)); - labelList->size = 10; - labelList->list = malloc(sizeof(label_t) * labelList->size); - for(size_t i = 0; i < labelList->size; i++){ - labelList->list[i].name = NULL; - labelList->list[i].nodeId = -1; - labelList->list[i].id = -1; - } - return labelList; -} +// labelList_t* initLabelList(){ +// labelList_t *labelList = malloc(sizeof(labelList_t)); +// labelList->size = 10; +// labelList->list = malloc(sizeof(label_t) * labelList->size); +// for(size_t i = 0; i < labelList->size; i++){ +// labelList->list[i].name = NULL; +// labelList->list[i].nodeId = -1; +// labelList->list[i].id = -1; +// } +// return labelList; +// } -void pushCmpLifo(lifoCmpNode_t *lifo, cmpNode_t *node){ - // resize lifo to add new node - lifo->size++; - // realloc lifo with node as new head - cmpNode_t **newLifo = (cmpNode_t **)malloc(sizeof(cmpNode_t *) * lifo->size); - if(newLifo == NULL){ - fprintf(stderr, "Error allocating memory\n"); - exit(EXIT_FAILURE); - } - newLifo[0] = node; - for(size_t i = 1; i < lifo->size; i++){ - newLifo[i] = lifo->list[i - 1]; - } - free(lifo->list); - lifo->list = newLifo; -} +// void pushCmpLifo(lifoCmpNode_t *lifo, cmpNode_t *node){ +// // resize lifo to add new node +// lifo->size++; +// // realloc lifo with node as new head +// cmpNode_t **newLifo = (cmpNode_t **)malloc(sizeof(cmpNode_t *) * lifo->size); +// if(newLifo == NULL){ +// fprintf(stderr, "Error allocating memory\n"); +// exit(EXIT_FAILURE); +// } +// newLifo[0] = node; +// for(size_t i = 1; i < lifo->size; i++){ +// newLifo[i] = lifo->list[i - 1]; +// } +// free(lifo->list); +// lifo->list = newLifo; +// } -cmpNode_t *popCmpLifo(lifoCmpNode_t *lifo){ - // Check if lifo is empty - if(lifo->size == 0){ - fprintf(stderr, "Error: Lifo is empty\n"); - exit(EXIT_FAILURE); - } +// cmpNode_t *popCmpLifo(lifoCmpNode_t *lifo){ +// // Check if lifo is empty +// if(lifo->size == 0){ +// fprintf(stderr, "Error: Lifo is empty\n"); +// exit(EXIT_FAILURE); +// } - // resize lifo to remove node - lifo->size--; - // realloc lifo without node as new head - cmpNode_t **newLifo = (cmpNode_t **)malloc(sizeof(cmpNode_t *) * lifo->size); - if(newLifo == NULL){ - fprintf(stderr, "Error allocating memory\n"); - exit(EXIT_FAILURE); - } - cmpNode_t *node = lifo->list[0]; - for(size_t i = 0; i < lifo->size; i++){ - newLifo[i] = lifo->list[i + 1]; - } - free(lifo->list); - lifo->list = newLifo; +// // resize lifo to remove node +// lifo->size--; +// // realloc lifo without node as new head +// cmpNode_t **newLifo = (cmpNode_t **)malloc(sizeof(cmpNode_t *) * lifo->size); +// if(newLifo == NULL){ +// fprintf(stderr, "Error allocating memory\n"); +// exit(EXIT_FAILURE); +// } +// cmpNode_t *node = lifo->list[0]; +// for(size_t i = 0; i < lifo->size; i++){ +// newLifo[i] = lifo->list[i + 1]; +// } +// free(lifo->list); +// lifo->list = newLifo; - return node; -} +// return node; +// } -void addVar(varList_t *list, instNode_t *node){ - // Check if list is full - bool full = true; - for(size_t i = 0; i < list->size; i++){ - if(list->list[i].name == NULL){ - full = false; - break; - } - } - if(full){ - // Increase list size - incVarList(list); - } +// void addVar(varList_t *list, instNode_t *node){ +// // Check if list is full +// bool full = true; +// for(size_t i = 0; i < list->size; i++){ +// if(list->list[i].name == NULL){ +// full = false; +// break; +// } +// } +// if(full){ +// // Increase list size +// incVarList(list); +// } - // Add var to the list - for(size_t i = 0; i < list->size; i++){ - if(list->list[i].name == NULL){ - list->list[i].name = node->arg0.target; - list->list[i].type = node->arg1Type; - switch (node->arg1Type) - { - case VAR_INT: - list->list[i].value.i_value = node->arg1.i_value; - break; - case VAR_FLOAT: - list->list[i].value.f_value = node->arg1.f_value; - break; - case VAR_CHAR: - list->list[i].value.c_value = node->arg1.c_value; - break; - case VAR_STRING: - list->list[i].value.s_value = node->arg1.s_value; - break; - default: - fprintf(stderr, "Error: Unknown variable type\n"); - exit(EXIT_FAILURE); - break; - } - break; - } - else if(strcmp(list->list[i].name, node->arg0.target) == 0){ - fprintf(stderr, "Variable %s already declared\n", node->arg0.target); - exit(EXIT_FAILURE); - } - } -} +// // Add var to the list +// for(size_t i = 0; i < list->size; i++){ +// if(list->list[i].name == NULL){ +// list->list[i].name = node->arg0.target; +// list->list[i].type = node->arg1Type; +// switch (node->arg1Type) +// { +// case VAR_INT: +// list->list[i].value.i_value = node->arg1.i_value; +// break; +// case VAR_FLOAT: +// list->list[i].value.f_value = node->arg1.f_value; +// break; +// case VAR_CHAR: +// list->list[i].value.c_value = node->arg1.c_value; +// break; +// case VAR_STRING: +// list->list[i].value.s_value = node->arg1.s_value; +// break; +// default: +// fprintf(stderr, "Error: Unknown variable type\n"); +// exit(EXIT_FAILURE); +// break; +// } +// break; +// } +// else if(strcmp(list->list[i].name, node->arg0.target) == 0){ +// fprintf(stderr, "Variable %s already declared\n", node->arg0.target); +// exit(EXIT_FAILURE); +// } +// } +// } -void incVarList(varList_t *list){ - // Increase list size - list->size *= 2; - list->list = (var_t *)realloc(list->list, sizeof(var_t) * list->size); - if(list->list == NULL){ - fprintf(stderr, "Error reallocating memory\n"); - exit(EXIT_FAILURE); - } +// void incVarList(varList_t *list){ +// // Increase list size +// list->size *= 2; +// list->list = (var_t *)realloc(list->list, sizeof(var_t) * list->size); +// if(list->list == NULL){ +// fprintf(stderr, "Error reallocating memory\n"); +// exit(EXIT_FAILURE); +// } - // Init new memory - for(size_t i = list->size / 2; i < list->size; i++){ - list->list[i].name = NULL; - } -} +// // Init new memory +// for(size_t i = list->size / 2; i < list->size; i++){ +// list->list[i].name = NULL; +// } +// } -varList_t *initVarList(){ - varList_t* varList = malloc(sizeof(varList_t)); - varList->size = 10; - varList->list = malloc(sizeof(var_t) * varList->size); - // Init variables list - for(size_t i = 0; i < varList->size; i++){ - varList->list[i].name = NULL; - } - return varList; -} \ No newline at end of file +// varList_t *initVarList(){ +// varList_t* varList = malloc(sizeof(varList_t)); +// varList->size = 10; +// varList->list = malloc(sizeof(var_t) * varList->size); +// // Init variables list +// for(size_t i = 0; i < varList->size; i++){ +// varList->list[i].name = NULL; +// } +// return varList; +// } \ No newline at end of file diff --git a/src/builder.h b/src/builder.h index f37b3d6..7676680 100644 --- a/src/builder.h +++ b/src/builder.h @@ -4,11 +4,11 @@ extern "C" { #endif -// Lifo to build if/ else statements -typedef struct lifoCmpNode{ - cmpNode_t **list; - size_t size; -} lifoCmpNode_t; +// // Lifo to build if/ else statements +// typedef struct lifoCmpNode{ +// cmpNode_t **list; +// size_t size; +// } lifoCmpNode_t; /* @@ -27,19 +27,19 @@ void build(instList_t *nodeList, labelList_t *labelList, varList_t *varList); */ // void buildOpNode(instNode_t *node); -/* - Build an action node - params: - node: pointer to the instruction node -*/ -void buildActNode(instNode_t *node, lifoCmpNode_t *lifo); +// /* +// Build an action node +// params: +// node: pointer to the instruction node +// */ +// void buildActNode(instNode_t *node, lifoCmpNode_t *lifo); -/* - Build a comparison node - params: - node: pointer to the instruction node -*/ -void buildCmpNode(instNode_t *node, lifoCmpNode_t *lifo); +// /* +// Build a comparison node +// params: +// node: pointer to the instruction node +// */ +// void buildCmpNode(instNode_t *node, lifoCmpNode_t *lifo); @@ -74,22 +74,22 @@ void incLabelList(labelList_t *list); */ labelList_t* initLabelList(); -/* - Add cmp node to the lifo (as new head) - params: - lifo: pointer to the lifo - node: pointer to the node -*/ -void pushCmpLifo(lifoCmpNode_t *lifo, cmpNode_t *node); - -/* - Remove cmp node from the lifo (as head) - params: - lifo: pointer to the lifo - return: - cmpNode_t: pointer to the node -*/ -cmpNode_t *popCmpLifo(lifoCmpNode_t *lifo); +// /* +// Add cmp node to the lifo (as new head) +// params: +// lifo: pointer to the lifo +// node: pointer to the node +// */ +// void pushCmpLifo(lifoCmpNode_t *lifo, cmpNode_t *node); + +// /* +// Remove cmp node from the lifo (as head) +// params: +// lifo: pointer to the lifo +// return: +// cmpNode_t: pointer to the node +// */ +// cmpNode_t *popCmpLifo(lifoCmpNode_t *lifo); /* Add variable to the variable list diff --git a/src/debug.c b/src/debug.c index 9f3a572..4c3c006 100644 --- a/src/debug.c +++ b/src/debug.c @@ -7,268 +7,4 @@ #include #include -#include "debug.h" - -void printInstList(instList_t *list, char *dest){ - FILE *file = fopen(dest, "w"); - if(file == NULL){ - fprintf(stderr, "Error opening file\n"); - exit(EXIT_FAILURE); - } - instNode_t *node = list->head; - while(node != NULL){ - switch(node->inst){ - case INST_OP: - fprintf(file, "%ld(OP): %s %s\n", node->id, printOPKind(node->nodeType.op->op), printArgs(node)); - break; - case INST_ACT: - if(node->nodeType.act->act != ACT_CMP){ - fprintf(file, "%ld(ACT): %s %s\n", node->id, printACTKind(node->nodeType.act->act), printArgs(node)); - break; - } - else{ - if(node->nodeType.act->cmp->statem == CMP_IF){ - fprintf(file, "%ld(ACT): %s %s\n\t\t(ELSE)%ld\n\t\t(END)%ld\n", node->id, printCMP(node), printArgs(node), node->nodeType.act->cmp->elseId, node->nodeType.act->cmp->endId); - break; - } - else{ - fprintf(file, "%ld(ACT): %s\n", node->id, printCMP(node)); - break; - } - - } - case INST_LABEL: - fprintf(file, "%ld(LAB): %s\n", node->id, node->arg0.target); - break; - case INST_VAR: - fprintf(file, "%ld(VAR): %s\n", node->id, printArgs(node)); - break; - default: - fprintf(stderr, "Invalid instruction\n"); - exit(EXIT_FAILURE); - } - node = node->next; - } - fclose(file); -} - -char *printArgs(instNode_t *node){ - char *arg0 = malloc(sizeof(char) * 128); - // get type of arguments - if(node->arg0Type == VAR_INT){ - sprintf(arg0, "%d(int)", node->arg0.i_value); - } - else if(node->arg0Type == VAR_FLOAT){ - sprintf(arg0, "%f(float)", node->arg0.f_value); - } - else if(node->arg0Type == VAR_CHAR){ - sprintf(arg0, "%c(char)", node->arg0.c_value); - } - else if(node->arg0Type == VAR_STRING){ - sprintf(arg0, "%s(string)", node->arg0.s_value); - } - else if(node->arg0Type == VAR_REG){ - sprintf(arg0, "%d(reg)", node->arg0.reg); - } - else if(node->arg0Type == VAR_TARGET){ - sprintf(arg0, "%s(target)", node->arg0.target); - } - else{ - sprintf(arg0, "(none)"); - } - - char *arg1 = malloc(sizeof(char) * 128); - if(node->arg1Type == VAR_INT){ - sprintf(arg1, "%d(int)", node->arg1.i_value); - } - else if(node->arg1Type == VAR_FLOAT){ - sprintf(arg1, "%f(float)", node->arg1.f_value); - } - else if(node->arg1Type == VAR_CHAR){ - sprintf(arg1, "%c(char)", node->arg1.c_value); - } - else if(node->arg1Type == VAR_STRING){ - sprintf(arg1, "%s(string)", node->arg1.s_value); - } - else if(node->arg1Type == VAR_REG){ - sprintf(arg1, "%d(reg)", node->arg1.reg); - } - else if(node->arg1Type == VAR_TARGET){ - sprintf(arg1, "%s(target)", node->arg1.target); - } - else{ - sprintf(arg1, "(none)"); - } - - char *args = malloc(sizeof(char) * 256); - sprintf(args, "%s, %s", arg0, arg1); - - return args; -} - -char *printOPKind(enum opKind op){ - switch(op){ - case OP_ADD: - return "ADD"; - case OP_SUB: - return "SUB"; - case OP_MUL: - return "MUL"; - case OP_DIV: - return "DIV"; - case OP_MOD: - return "MOD"; - case OP_R_SHIFT: - return "R_SHIFT"; - case OP_L_SHIFT: - return "L_SHIFT"; - case OP_B_AND: - return "B_AND"; - case OP_B_OR: - return "B_OR"; - case OP_B_XOR: - return "B_XOR"; - case OP_B_NOT: - return "B_NOT"; - case OP_B_NEG: - return "B_NEG"; - case OP_INC: - return "INC"; - case OP_DEC: - return "DEC"; - default: - fprintf(stderr, "Invalid operation\n"); - exit(EXIT_FAILURE); - } -} - -char *printACTKind(enum actKind act){ - switch(act){ - case ACT_MOV: - return "MOV"; - case ACT_GOTO: - return "GOTO"; - case ACT_CALL: - return "CALL"; - case ACT_RET: - return "RET"; - case ACT_CLOK: - return "CLOK"; - case ACT_DRAW: - return "DRAW"; - case ACT_CMP: - return "DRAW"; - case ACT_EXIT: - return "EXIT"; - case ACT_PUSH: - return "PUSH"; - case ACT_POP: - return "POP"; - case ACT_PUSH_A: - return "PUSH_A"; - case ACT_POP_A: - return "POP_A"; - case ACT_OB1: - return "OB1"; - default: - fprintf(stderr, "Invalid action\n"); - exit(EXIT_FAILURE); - } -} - -char* printCMP(instNode_t *node){ - char *cmp = malloc(sizeof(char) * 128); - if(node->nodeType.act->cmp->statem == CMP_IF){ - sprintf(cmp, "IF"); - sprintf(cmp, "%s %s", cmp, printCMPKind(node->nodeType.act->cmp->cmp)); - } - else if(node->nodeType.act->cmp->statem == CMP_ELSE){ - sprintf(cmp, "ELSE"); - } - else if(node->nodeType.act->cmp->statem == CMP_END){ - sprintf(cmp, "END"); - } - else{ - fprintf(stderr, "Invalid comparison\n"); - exit(EXIT_FAILURE); - } - return cmp; -} - -char *printCMPKind(enum cmpKind cmp){ - switch(cmp){ - case CMP_OR: - return "OR"; - case CMP_AND: - return "AND"; - case CMP_NOT: - return "NOT"; - case CMP_XOR: - return "XOR"; - case CMP_LT: - return "LT"; - case CMP_GT: - return "GT"; - case CMP_LTE: - return "LTE"; - case CMP_GTE: - return "GTE"; - case CMP_EQ: - return "EQ"; - case CMP_NEQ: - return "NEQ"; - default: - fprintf(stderr, "Invalid comparison\n"); - exit(EXIT_FAILURE); - } - -} - -void printVarList(varList_t *list, char *dest){ - FILE *file = fopen(dest, "a"); - if(file == NULL){ - fprintf(stderr, "Error opening file\n"); - exit(EXIT_FAILURE); - } - fprintf(file, "\n\nVARS:\n"); - for(size_t i = 0; i < list->size; i++){ - if(list->list[i].name == NULL){ - continue; - } - switch(list->list[i].type){ - case VAR_INT: - fprintf(file, "%s: %d(INT)\n", list->list[i].name, list->list[i].value.i_value); - break; - case VAR_FLOAT: - fprintf(file, "%s: %f(FLOAT)\n", list->list[i].name, list->list[i].value.f_value); - break; - case VAR_CHAR: - fprintf(file, "%s: %c(CHAR)\n", list->list[i].name, list->list[i].value.c_value); - break; - case VAR_STRING: - fprintf(file, "%s: %s(STRING)\n", list->list[i].name, list->list[i].value.s_value); - break; - default: - fprintf(stderr, "Invalid variable type\n"); - exit(EXIT_FAILURE); - } - } - - fclose(file); -} - -void printLabelList(labelList_t *list, char *dest){ - FILE *file = fopen(dest, "a"); - if(file == NULL){ - fprintf(stderr, "Error opening file\n"); - exit(EXIT_FAILURE); - } - fprintf(file, "\n\nLABELS:\n"); - for(size_t i = 0; i < list->size; i++){ - if(list->list[i].name == NULL){ - continue; - } - fprintf(file, "(NAME): %s, (ID)%ld, (NODE ID): %ld\n", list->list[i].name, list->list[i].id, list->list[i].nodeId); - } - fclose(file); -} \ No newline at end of file +#include "debug.h" \ No newline at end of file diff --git a/src/debug.h b/src/debug.h index 52540bb..c397a0a 100644 --- a/src/debug.h +++ b/src/debug.h @@ -1,72 +1,3 @@ #pragma once -#include "ast.h" - -/* - Print the instruction list to a file - params: - list: pointer to the instruction list - dest: destination file -*/ -void printInstList(instList_t *list, char *dest); - -/* - Print arguments of an instruction node - params: - node: pointer to the instruction node - returns: - char*: string with the arguments -*/ -char *printArgs(instNode_t *node); - -/* - Print the kind of an operation - params: - op: operation kind - returns: - char*: string with the operation kind -*/ -char *printOPKind(enum opKind op); - -/* - Print the kind of an action - params: - act: action kind - returns: - char*: string with the action kind -*/ -char *printACTKind(enum actKind act); - -/* - Print details of comparison node - params: - node: pointer to the instruction node - returns: - char*: string with the comparison details -*/ -char* printCMP(instNode_t *node); - -/* - Print the kind of a comparison - params: - cmp: comparison kind - returns: - char*: string with the comparison kind -*/ -char *printCMPKind(enum cmpKind cmp); - -/* - Print variable list to a file - params: - list: pointer to the variable list - dest: destination file -*/ -void printVarList(varList_t *list, char *dest); - -/* - Print label list to a file - params: - list: pointer to the label list - dest: destination file -*/ -void printLabelList(labelList_t *list, char *dest); \ No newline at end of file +#include "ast.h" \ No newline at end of file diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..77ad050 --- /dev/null +++ b/src/error.c @@ -0,0 +1,93 @@ +/* + This file contains functions for throwing errors assembling errors +*/ + +#include +#include +#include +#include +#include + +#include "error.h" + +void errorInstruction(char* inst, instNode_t *node, const char* out, error_t *errData){ + ++ errData->errors; + fprintf(stderr, "Error: syntax error\n"); + fprintf(stderr, "Details: %s instruction is not recognized\n", inst); + fprintf(stderr, "In: file %s, line %ld\n\n", errData->inputFile, node->lineNb); + if(out != NULL){ + FILE *file = fopen(out, "ab"); + if(file == NULL){ + fprintf(stderr, "Error opening file: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + // Get current time + time_t rawtime; + struct tm *timeinfo; + time(&rawtime); + timeinfo = localtime(&rawtime); + + // Format date + char date_str[20]; // Sufficiently large buffer to hold formatted date + strftime(date_str, sizeof(date_str), "%d-%m-%y", timeinfo); + fprintf(file, "%s |\tError: syntax error\n", date_str); + fprintf(file, "%s |\tDetails: %s instruction is not recognized\n", date_str, inst); + fprintf(file, "%s |\tIn: file %s, line %ld\n\n", date_str, errData->inputFile, node->lineNb); + fclose(file); + } +} + +void errorLineSize(long lineNb, const char* out, error_t *errData){ + ++ errData->errors; + fprintf(stderr, "Error: syntax error\n"); + fprintf(stderr, "Details: line must to be under 64 characters\n"); + fprintf(stderr, "In: file %s, line %ld\n\n", errData->inputFile, lineNb); + if(out != NULL){ + FILE *file = fopen(out, "ab"); + if(file == NULL){ + fprintf(stderr, "Error opening file: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + // Get current time + time_t rawtime; + struct tm *timeinfo; + time(&rawtime); + timeinfo = localtime(&rawtime); + + // Format date + char date_str[20]; // Sufficiently large buffer to hold formatted date + strftime(date_str, sizeof(date_str), "%d-%m-%y", timeinfo); + fprintf(file, "%s |\tError: syntax error\n", date_str); + fprintf(file, "%s |\tDetails: line must to be under 64 characters\n", date_str); + fprintf(file, "%s |\tIn: file %s, line %ld\n\n", date_str, errData->inputFile, lineNb); + fclose(file); + } + +} + +void errorfnf(char* filename, const char* out, error_t *errData){ + ++ errData->errors; + fprintf(stderr, "Error: file not found\n"); + fprintf(stderr, "Details: file %s not found\n", filename); + if(out != NULL){ + FILE *file = fopen(out, "ab"); + if(file == NULL){ + fprintf(stderr, "Error opening file: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + // Get current time + time_t rawtime; + struct tm *timeinfo; + time(&rawtime); + timeinfo = localtime(&rawtime); + + // Format date + char date_str[20]; // Sufficiently large buffer to hold formatted date + strftime(date_str, sizeof(date_str), "%d-%m-%y", timeinfo); + fprintf(file, "%s |\tError: file not found\n", date_str); + fprintf(file, "%s |\tDetails: file %s not found\n", date_str, filename); + fclose(file); + } + + exit(EXIT_FAILURE); +} diff --git a/src/error.h b/src/error.h new file mode 100644 index 0000000..d25bc2f --- /dev/null +++ b/src/error.h @@ -0,0 +1,49 @@ +#pragma once + +#include "ast.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct errorData{ + long errors; + char *inputFile; +} error_t; + +// ---------- Parsing/ Assembling errors ---------- + +/* + Throw an error whrn the given instruction doesn't exist + params: + inst: Instruction + node: Instruction node to get additionnal information + out: Target file (can be NULL) + errData: Error history +*/ +void errorInstruction(char* inst, instNode_t *node, const char* out, error_t *errData); + +/* + Throw an error when the line size is too big + params: + lineNb: Line number + out: Target file (can be NULL) + errData: Error history +*/ +void errorLineSize(long lineNb, const char* out, error_t *errData); + +// ---------- Fatal errors ---------- + + +/* + Throw an error when the file is not found + params: + filename: File name + out: Target file (can be NULL) + errData: Error history +*/ +void errorfnf(char* filename, const char* out, error_t *errData); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/parser.c b/src/parser.c index 72133e0..5bd526a 100644 --- a/src/parser.c +++ b/src/parser.c @@ -12,6 +12,8 @@ #define LINE_MAX_SIZE 64 +const char* errorFile= "errors.log"; + flags_t parseArgs(int argc, char *argv[]){ if(argc > 3){ fprintf(stderr, "Too many arguments\n Try 'iat2 --help' for more information\n"); @@ -63,12 +65,11 @@ void flagsSet(char *flag, flags_t *flags){ } } -void parseFile(instList_t *nodeList, char *filename){ +void parseFile(instList_t *nodeList, char *filename, error_t *errData){ // check if the file exists FILE *file = fopen(filename, "r"); if(file == NULL){ - fprintf(stderr, "Error opening file: %s\n", strerror(errno)); - exit(EXIT_FAILURE); + errorfnf(filename, errorFile, errData); } // Check the file extension @@ -83,12 +84,11 @@ void parseFile(instList_t *nodeList, char *filename){ while(fgets(line, LINE_MAX_SIZE, file)){ // Check if one of the file's line doesn't exceed 64 characters if (!checkLineSize(line, file)){ - fprintf(stderr,"Lines shouldn't be above 64 in a file. Please enter a valid file.\n"); - exit(EXIT_FAILURE); //Exit the program when the condition isn't met. + errorLineSize(lineNb, errorFile, errData); } // parse the line - instNode_t *node = parseLine(line, nodeId, lineNb); + instNode_t *node = parseLine(line, nodeId, lineNb, errData); // continue if the line is empty if(node == NULL){ @@ -111,341 +111,101 @@ void parseFile(instList_t *nodeList, char *filename){ fclose(file); } -instNode_t *parseLine(char *line, long nodeId, long lineNb){ +instNode_t *parseLine(char *line, long nodeId, long lineNb, error_t *errData){ // check if the line is empty or a comment if(line[0] == '\n' || strncmp(line, "//", 2) == 0){ return NULL; } - // copy the line to tokenize it - char* lineCopy = malloc((strlen(line) + 1) * sizeof(char)); - if (!lineCopy) { - fprintf(stderr, "Memory allocation error\n"); - exit(EXIT_FAILURE); - } - strcpy(lineCopy, line); - - // Get the instruction - char *inst = getInst(lineCopy); - inst = cleanString(inst); - - // Get the arguments - char **args = getInstArgs(lineCopy); - - free(lineCopy); - instNode_t *newNode = malloc(sizeof(instNode_t)); newNode->id = nodeId; newNode->lineNb = lineNb; + newNode->isInter = false; newNode->next = NULL; - // Set arguments - setArgs(newNode, args); + // Get the instruction + char *inst = getInst(line); - bool isThatKind = false; - // Check if the instruction is an operation - isThatKind = isOp(inst, newNode); - if(isThatKind){ - return newNode; - } + // Get the arguments + char **args = getInstArgs(line); - // Check if the instruction is an action - isThatKind = isAct(inst, newNode); - if(isThatKind){ - return newNode; - } + // Set arguments + setArgs(newNode, args); - // Check if the instruction is a comparison - isThatKind = isCmp(inst, newNode, line); + newNode->isInter = false; + + bool isThatKind = false; + // Set the instruction + isThatKind = isOp(inst, newNode, errData); if(isThatKind){ return newNode; } - // Check if the instruction is a declaration - isThatKind = isDecla(inst, newNode); - if(isThatKind){ - return newNode; - } + // TODO: Check if the instruction is a declaration // Trow error if the line is not an instruction - fprintf(stderr, "\"%s\" Is not a valid instruction. line %ld\n", line, lineNb); - exit(EXIT_FAILURE); + errorInstruction(inst, newNode, errorFile, errData); + return newNode; } -bool isOp(char *inst, instNode_t *newNode){ - // Check if the instruction is an operation - if(strcmp(inst, "add") == 0 || strcmp(inst, "+") == 0){ - newNode->inst = INST_OP; - newNode->nodeType.op = malloc(sizeof(opNode_t)); - // Set type of operation - newNode->nodeType.op->op = OP_ADD; - return true; +bool isOp(char *inst, instNode_t *newNode, error_t *errData){ + if(strcmp(inst, "mov") == 0){ + newNode->op = OP_MOV; } - else if(strcmp(inst, "sub") == 0 || strcmp(inst, "-") == 0){ - newNode->inst = INST_OP; - newNode->nodeType.op = malloc(sizeof(opNode_t)); - // Set type of operation - newNode->nodeType.op->op = OP_SUB; - return true; - } - else if(strcmp(inst, "mul") == 0 || strcmp(inst, "*") == 0){ - newNode->inst = INST_OP; - newNode->nodeType.op = malloc(sizeof(opNode_t)); - // Set type of operation - newNode->nodeType.op->op = OP_MUL; - return true; + else if(strcmp(inst, "goto") == 0){ + newNode->op = OP_GOTO; } - else if(strcmp(inst, "div") == 0 || strcmp(inst, "/") == 0){ - newNode->inst = INST_OP; - newNode->nodeType.op = malloc(sizeof(opNode_t)); - // Set type of operation - newNode->nodeType.op->op = OP_DIV; - return true; - } - else if(strcmp(inst,"mod") == 0 || strcmp(inst,"%") == 0){ - newNode->inst = INST_OP; - newNode->nodeType.op = malloc(sizeof(opNode_t)); - // Set type of operation - newNode->nodeType.op->op = OP_MOD; - return true; + else if(strcmp(inst, "call") == 0){ + newNode->op = OP_CALL; } - else if(strcmp(inst, "shl") == 0 || strcmp(inst, "<<") == 0){ - newNode->inst = INST_OP; - newNode->nodeType.op = malloc(sizeof(opNode_t)); - // Set type of operation - newNode->nodeType.op->op = OP_L_SHIFT; - return true; + else if(strcmp(inst, "int") == 0){ + newNode->op = OP_INT; + newNode->isInter = true; } - else if(strcmp(inst, "and") == 0 || strcmp(inst, "&") == 0){ - newNode->inst = INST_OP; - newNode->nodeType.op = malloc(sizeof(opNode_t)); - // Set type of operation - newNode->nodeType.op->op = OP_B_AND; - return true; + else if(strcmp(inst, "push") == 0){ + newNode->op = OP_PUSH; } - else if(strcmp(inst, "or") == 0 || strcmp(inst, "|") == 0){ - newNode->inst = INST_OP; - newNode->nodeType.op = malloc(sizeof(opNode_t)); - // Set type of operation - newNode->nodeType.op->op = OP_B_OR; - return true; - } else if(strcmp(inst, "xor") == 0 || strcmp(inst, "^") == 0){ - newNode->inst = INST_OP; - newNode->nodeType.op = malloc(sizeof(opNode_t)); - // Set type of operation - newNode->nodeType.op->op = OP_B_XOR; - return true; - } - else if(strcmp(inst, "not") == 0 || strcmp(inst, "!") == 0){ - newNode->inst = INST_OP; - newNode->nodeType.op = malloc(sizeof(opNode_t)); - // Set type of operation - newNode->nodeType.op->op = OP_B_NOT; - return true; - } - else if(strcmp(inst, "neg") == 0){ - newNode->inst = INST_OP; - newNode->nodeType.op = malloc(sizeof(opNode_t)); - // Set type of operation - newNode->nodeType.op->op = OP_B_NEG; - return true; - } - else if(strcmp(inst, "inc") == 0 || strcmp(inst, "++") == 0){ - newNode->inst = INST_OP; - newNode->nodeType.op = malloc(sizeof(opNode_t)); - // Set type of operation - newNode->nodeType.op->op = OP_INC; - return true; - } - else if(strcmp(inst, "dec") == 0 || strcmp(inst, "--") == 0){ - newNode->inst = INST_OP; - newNode->nodeType.op = malloc(sizeof(opNode_t)); - // Set type of operation - newNode->nodeType.op->op = OP_DEC; - return true; - } - - return false; -} - -bool isAct(char *inst, instNode_t *newNode){ - if(strcmp(inst, "goto") == 0){ - // Set type of instruction - newNode->inst = INST_ACT; - newNode->nodeType.act = malloc(sizeof(actNode_t)); - // Set type of action - newNode->nodeType.act->act = ACT_GOTO; - return true; - } - else if(strcmp(inst, "mov") == 0){ - newNode->inst = INST_ACT; - newNode->nodeType.act = malloc(sizeof(actNode_t)); - // Set type of action - newNode->nodeType.act->act = ACT_MOV; - return true; - } - else if(strcmp(inst, "call") == 0){ - newNode->inst = INST_ACT; - newNode->nodeType.act = malloc(sizeof(actNode_t)); - // Set type of action - newNode->nodeType.act->act = ACT_CALL; - return true; - } - else if(strcmp(inst, "ret") == 0){ - newNode->inst = INST_ACT; - newNode->nodeType.act = malloc(sizeof(actNode_t)); - // Set type of action - newNode->nodeType.act->act = ACT_RET; - return true; - } - else if(strcmp(inst, "clok") == 0){ - newNode->inst = INST_ACT; - newNode->nodeType.act = malloc(sizeof(actNode_t)); - // Set type of action - newNode->nodeType.act->act = ACT_CLOK; - return true; - } - else if(strcmp(inst, "draw") == 0){ - newNode->inst = INST_ACT; - newNode->nodeType.act = malloc(sizeof(actNode_t)); - // Set type of action - newNode->nodeType.act->act = ACT_DRAW; - return true; - } - else if(strcmp(inst, "ngr") == 0){ - newNode->inst = INST_ACT; - newNode->nodeType.act = malloc(sizeof(actNode_t)); - // Set type of action - newNode->nodeType.act->act = ACT_EXIT; - return true; - } - else if(strcmp(inst, "push") == 0){ - newNode->inst = INST_ACT; - newNode->nodeType.act = malloc(sizeof(actNode_t)); - // Set type of action - newNode->nodeType.act->act = ACT_PUSH; - return true; + newNode->op = OP_B_XOR; } else if(strcmp(inst, "pop") == 0){ - newNode->inst = INST_ACT; - newNode->nodeType.act = malloc(sizeof(actNode_t)); - // Set type of action - newNode->nodeType.act->act = ACT_POP; - return true; - } - else if(strcmp(inst, "pusha") == 0){ - newNode->inst = INST_ACT; - newNode->nodeType.act = malloc(sizeof(actNode_t)); - // Set type of action - newNode->nodeType.act->act = ACT_PUSH_A; - return true; - } - else if(strcmp(inst, "popa") == 0){ - newNode->inst = INST_ACT; - newNode->nodeType.act = malloc(sizeof(actNode_t)); - // Set type of action - newNode->nodeType.act->act = ACT_POP_A; - return true; - } - else if(strcmp(inst, "ob1") == 0){ - newNode->inst = INST_ACT; - newNode->nodeType.act = malloc(sizeof(actNode_t)); - // Set type of action - newNode->nodeType.act->act = ACT_OB1; - return true; - } - - return false; -} - -bool isCmp(char *inst, instNode_t *newNode, char* line){ - if(strcmp(inst, "if") == 0){ - newNode->inst = INST_ACT; - newNode->nodeType.act = malloc(sizeof(actNode_t)); - // Set type of action - newNode->nodeType.act->act = ACT_CMP; - newNode->nodeType.act->cmp = malloc(sizeof(cmpNode_t)); - // Set type of comparison - newNode->nodeType.act->cmp->statem = CMP_IF; - char **args = getIfArgs(line); - setCmpKind(newNode, args[0]); - setArgs(newNode, args + 1); - return true; - } - else if(strcmp(inst, "else") == 0){ - newNode->inst = INST_ACT; - newNode->nodeType.act = malloc(sizeof(actNode_t)); - // Set type of action - newNode->nodeType.act->act = ACT_CMP; - newNode->nodeType.act->cmp = malloc(sizeof(cmpNode_t)); - // Set type of comparison - newNode->nodeType.act->cmp->statem = CMP_ELSE; - return true; - } - - else if(strcmp(inst, "end") == 0){ - newNode->inst = INST_ACT; - newNode->nodeType.act = malloc(sizeof(actNode_t)); - // Set type of action - newNode->nodeType.act->act = ACT_CMP; - newNode->nodeType.act->cmp = malloc(sizeof(cmpNode_t)); - // Set type of comparison - newNode->nodeType.act->cmp->statem = CMP_END; - return true; - } - - return false; -} - -void setCmpKind(instNode_t *newNode, char *cmp){ - if(strcmp(cmp, "eq") == 0 || strcmp(cmp, "==") == 0){ - newNode->nodeType.act->cmp->cmp = CMP_EQ; + newNode->op = OP_POP; } - else if(strcmp(cmp, "neq") == 0 || strcmp(cmp, "!=") == 0){ - newNode->nodeType.act->cmp->cmp = CMP_NEQ; + else if(strcmp(inst, "div") == 0 || strcmp(inst, "/") == 0){ + newNode->op = OP_DIV; } - else if(strcmp(cmp, "lt") == 0 || strcmp(cmp, "<") == 0){ - newNode->nodeType.act->cmp->cmp = CMP_LT; + else if(strcmp(inst, "add") == 0 || strcmp(inst, "+") == 0){ + newNode->op = OP_ADD; } - else if(strcmp(cmp, "lte") == 0 || strcmp(cmp, "<=") == 0){ - newNode->nodeType.act->cmp->cmp = CMP_LTE; + else if(strcmp(inst, "sub") == 0 || strcmp(inst, "-") == 0){ + newNode->op = OP_SUB; } - else if(strcmp(cmp, "gt") == 0 || strcmp(cmp, ">") == 0){ - newNode->nodeType.act->cmp->cmp = CMP_GT; + else if(strcmp(inst, "mul") == 0 || strcmp(inst, "*") == 0){ + newNode->op = OP_MUL; } - else if(strcmp(cmp, "gte") == 0 || strcmp(cmp, ">=") == 0){ - newNode->nodeType.act->cmp->cmp = CMP_GTE; + else if(strcmp(inst, "shr") == 0 || strcmp(inst, ">>") == 0){ + newNode->op = OP_R_SHIFT; } - else if(strcmp(cmp, "and") == 0 || strcmp(cmp, "&&") == 0){ - newNode->nodeType.act->cmp->cmp = CMP_AND; + else if(strcmp(inst, "shl") == 0 || strcmp(inst, "<<") == 0){ + newNode->op = OP_L_SHIFT; } - else if(strcmp(cmp, "or") == 0 || strcmp(cmp, "||") == 0){ - newNode->nodeType.act->cmp->cmp = CMP_OR; + else if(strcmp(inst, "and") == 0 || strcmp(inst, "&") == 0){ + newNode->op = OP_B_AND; } - else if(strcmp(cmp, "xor") == 0 || strcmp(cmp, "^^") == 0){ - newNode->nodeType.act->cmp->cmp = CMP_XOR; + else if(strcmp(inst, "or") == 0 || strcmp(inst, "|") == 0){ + newNode->op = OP_B_OR; + } + else if(strcmp(inst, "not") == 0 || strcmp(inst, "!") == 0){ + newNode->op = OP_B_NOT; } - \ else{ - fprintf(stderr, "Invalid comparison\n"); - exit(EXIT_FAILURE); + errorInstruction(inst, newNode, errorFile, errData); + return false; } + return true; } -bool isDecla(char *inst, instNode_t *newNode){ - if(strcmp(inst, "lab") == 0){ - newNode->inst = INST_LABEL; - return true; - } - else if(strcmp(inst, "var") == 0){ - newNode->inst = INST_VAR; - return true; - } - - return false; -} char *getInst(char *line) { char *buffer = malloc((strlen(line) + 1) * sizeof(char)); @@ -464,20 +224,21 @@ char *getInst(char *line) { exit(EXIT_FAILURE); } - return inst; + return cleanString(inst); } char **getInstArgs(char *line) { - char **args = (char **)malloc(2 * sizeof(char *)); + char **args = malloc(2 * sizeof(char *)); if (!args) { fprintf(stderr, "Memory allocation error\n"); exit(EXIT_FAILURE); } // Remove the instruction name - char *token = strtok((char *)line, " "); + char *token = strtok(line, " "); if (!token) { fprintf(stderr, "Invalid input format\n"); + free(args); // Free allocated memory before exit exit(EXIT_FAILURE); } @@ -488,157 +249,35 @@ char **getInstArgs(char *line) { args[i] = NULL; } else { // Allocate memory for the argument and copy it - args[i] = (char *)malloc((strlen(token) + 1) * sizeof(char)); + args[i] = malloc(strlen(token) + 1); if (!args[i]) { fprintf(stderr, "Memory allocation error\n"); + for (int j = 0; j < i; j++) { + free(args[j]); // Free previously allocated memory + } + free(args); // Free args array exit(EXIT_FAILURE); } - // Remove spaces - strcpy(args[i], token); + strcpy(args[i], cleanString(token)); } } return args; } -char** getIfArgs(char* line){ - char **args = (char **)malloc(2 * sizeof(char *)); - if (!args) { - fprintf(stderr, "Memory allocation error\n"); - exit(EXIT_FAILURE); - } - - // Remove the instruction name - char *token = strtok((char *)line, " "); - if (!token) { - fprintf(stderr, "Invalid input format\n"); - exit(EXIT_FAILURE); - } - - // Get the arguments - for (int i = 0; i < 3; i++) { - token = strtok(NULL, ","); - if (!token) { - args[i] = NULL; - } else { - // Allocate memory for the argument and copy it - args[i] = (char *)malloc((strlen(token) + 1) * sizeof(char)); - if (!args[i]) { - fprintf(stderr, "Memory allocation error\n"); - exit(EXIT_FAILURE); - } - // Remove spaces - strcpy(args[i], token); - args[i] = cleanString(args[i]); - } - } - return args; - -} - -void setArgs(instNode_t *node, char **args) { - // Clean the arguments - for (int i = 0; i < 2; i++) { - if (args[i] != NULL) { - args[i] = cleanString(args[i]); - } - } - - // Check type of the arguments - if (args[0] == NULL) { - node->arg0.i_value = 0; - } - else{ - if (isInt(args[0])) { - node->arg0.i_value = atoi(args[0]); - node->arg0Type = VAR_INT; - } - else if(isBinary(args[0])){ - node->arg0.i_value = strToBin(args[0]); - node->arg0Type = VAR_INT; - } - else if(isOctal(args[0])){ - node->arg0.i_value = strToOct(args[0]); - node->arg0Type = VAR_INT; - } - else if(isHex(args[0])){ - node->arg0.i_value = strToHex(args[0]); - node->arg0Type = VAR_INT; - } - else if(isFloat(args[0])){ - node->arg0.f_value = strtof(args[0], NULL); - node->arg0Type = VAR_FLOAT; - } - else if(isChar(args[0])){ - node->arg0.c_value = strToChar(args[0]); - node->arg0Type = VAR_CHAR; - } - else if(isString(args[0])){ - node->arg0.s_value = strToString(args[0]); - node->arg0Type = VAR_STRING; - } - else if(isReg(args[0])){ - node->arg0.reg = strToReg(args[0]); - node->arg0Type = VAR_REG; - } - else if(isTarget(args[0])){ - node->arg0.target = args[0]; - node->arg0Type = VAR_TARGET; - } - else{ - node->arg0.s_value = NULL; - node->arg0Type = VAR_NONE; +void setArgs(instNode_t *node, char **args){ + if(isReg(args[0])){ + node->inputReg = strToReg(args[0]); + if(args[1] != NULL){ + node->arg = malloc(sizeof(args[1])+1); + strcpy(node->arg, args[1]); return; } } - - if (args[1] == NULL) { - node->arg1.i_value = 0; - } - else{ - if (isInt(args[1])) { - node->arg1.i_value = atoi(args[1]); - node->arg1Type = VAR_INT; - } - else if(isBinary(args[1])){ - node->arg1.i_value = strToBin(args[1]); - node->arg1Type = VAR_INT; - } - else if(isOctal(args[1])){ - node->arg1.i_value = strToOct(args[1]); - node->arg1Type = VAR_INT; - } - else if(isHex(args[1])){ - node->arg1.i_value = strToHex(args[1]); - node->arg1Type = VAR_INT; - } - else if(isFloat(args[1])){ - node->arg1.f_value = strtof(args[1], NULL); - node->arg1Type = VAR_FLOAT; - } - else if(isChar(args[1])){ - node->arg1.c_value = strToChar(args[1]); - node->arg1Type = VAR_CHAR; - } - else if(isString(args[1])){ - node->arg1.s_value = strToString(args[1]); - node->arg1Type = VAR_STRING; - } - else if(isReg(args[1])){ - node->arg1.reg = strToReg(args[1]); - node->arg1Type = VAR_REG; - } - else if(isTarget(args[1])){ - node->arg1.target = args[1]; - node->arg1Type = VAR_TARGET; - } - else{ - node->arg1.s_value = NULL; - node->arg1Type = VAR_NONE; - return; - } + else if(args[0] != NULL){ + node->arg = malloc(sizeof(args[0])+1); + strcpy(node->arg, args[0]); } - } bool isInt(char *arg) { diff --git a/src/parser.h b/src/parser.h index 71a2b8b..8674701 100644 --- a/src/parser.h +++ b/src/parser.h @@ -1,6 +1,8 @@ #include #include + #include "ast.h" +#include "error.h" #ifdef __cplusplus extern "C" { @@ -38,7 +40,7 @@ void flagsSet(char *flag, flags_t *flags); nodeList: pointer to the instruction list filename: name of the file to be parsed */ -void parseFile(instList_t *nodeList, char *filename); +void parseFile(instList_t *nodeList, char *filename, error_t *errData); /* Parse a line and return an instruction node @@ -47,7 +49,7 @@ void parseFile(instList_t *nodeList, char *filename); returns: instNode_t: instruction node */ -instNode_t *parseLine(char *line, long nodeId, long lineNb); +instNode_t *parseLine(char *line, long nodeId, long lineNb, error_t *errData); /* Read the line and check if it is an operation @@ -57,38 +59,8 @@ instNode_t *parseLine(char *line, long nodeId, long lineNb); returns: bool: true if it is an operation */ -bool isOp(char *inst, instNode_t *newNode); +bool isOp(char *inst, instNode_t *newNode, error_t *errData); -/* - Read the line and check if it is an action - params: - char*: instruction to be checked - instNode_t*: pointer to the instruction node - returns: - bool: true if it is an action -*/ -bool isAct(char *inst, instNode_t *newNode); - - -/* - Read the line and check if it is a comparison - params: - char*: instruction to be checked - instNode_t*: pointer to the instruction node - char*: line to be parsed - returns: - bool: true if it is a comparison - -*/ -bool isCmp(char *inst, instNode_t *newNode, char *line); - -/* - Set the comparison kind - params: - instNode_t*: pointer to the instruction node - char*: comparison string -*/ -void setCmpKind(instNode_t *newNode, char *cmp); /* Read the line and check if it is a declaration for a label or a variable From 71fb2c15861be0c52353034410df9855ade14aec Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Mon, 12 Feb 2024 20:31:24 +0100 Subject: [PATCH 02/22] Update parsing system - Update parsed instructions - Update AST struct to manage with new implementation - Update error system - Recreate debug mod --- src/2at2.c | 5 +++ src/ast.h | 8 +++++ src/debug.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/debug.h | 33 ++++++++++++++++++- src/error.c | 33 +++++++++++++++++-- src/error.h | 9 ++++++ src/parser.c | 26 ++++++++++----- src/parser.h | 3 +- 8 files changed, 193 insertions(+), 13 deletions(-) diff --git a/src/2at2.c b/src/2at2.c index a677748..a914075 100644 --- a/src/2at2.c +++ b/src/2at2.c @@ -53,6 +53,11 @@ int main(int argc, char *argv[]) { // run parser parseFile(instList, argv[1], errData); + + if(flags.debug){ + printAst(instList); + } + // run builder // TODO: Do Builder diff --git a/src/ast.h b/src/ast.h index 993e980..ba62f4f 100644 --- a/src/ast.h +++ b/src/ast.h @@ -24,6 +24,12 @@ enum opKind{ OP_B_AND, OP_B_OR, OP_B_NOT, + OP_INC, + OP_DEC, + OP_LAB, + OP_VAR, + OP_MOD, + OP_RET, }; // interrupt types @@ -82,6 +88,8 @@ typedef struct var{ // Structs for variable list typedef struct varList{ + char* name; + long id; size_t size; var_t *list; } varList_t; diff --git a/src/debug.c b/src/debug.c index 4c3c006..56613c3 100644 --- a/src/debug.c +++ b/src/debug.c @@ -6,5 +6,92 @@ #include #include #include +#include -#include "debug.h" \ No newline at end of file +#include "debug.h" + +const char *logFile = "2at2.log"; + +void printAst(instList_t *nodeList){ + instNode_t *node = nodeList->head; + while(node != NULL){ + printNodeData(node); + node = node->next; + } +} + +void printNodeData(instNode_t *node){ + FILE *file = fopen(logFile, "ab"); + if(file == NULL){ + fprintf(stderr, "Error opening file: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + // Get current time + time_t rawtime; + struct tm *timeinfo; + time(&rawtime); + timeinfo = localtime(&rawtime); + // Format date + char date_str[20]; + strftime(date_str, sizeof(date_str), "%d-%m-%y %H:%M:%S", timeinfo); + + fprintf(file, "%s | Node ID: %ld\n", date_str, node->id); + fprintf(file, "%s | Line number: %ld\n", date_str, node->lineNb); + fprintf(file, "%s | Instruction: %s\n", date_str, getOpName(node->op)); + fprintf(file, "%s | Target reg: %d\n", date_str, node->inputReg); + fprintf(file, "%s | Arguments: %s\n", date_str, node->arg); + fprintf(file, "\n"); + fclose(file); +} + +char *getOpName(enum opKind kind){ + switch(kind){ + case OP_MOV: + return "MOV"; + case OP_GOTO: + return "GOTO"; + case OP_CALL: + return "CALL"; + case OP_INT: + return "INT"; + case OP_PUSH: + return "PUSH"; + case OP_B_XOR: + return "XOR"; + case OP_POP: + return "POP"; + case OP_DIV: + return "DIV"; + case OP_ADD: + return "ADD"; + case OP_SUB: + return "SUB"; + case OP_MUL: + return "MUL"; + case OP_R_SHIFT: + return "R_SHIFT"; + case OP_L_SHIFT: + return "L_SHIFT"; + case OP_B_AND: + return "AND"; + case OP_B_OR: + return "OR"; + case OP_B_NOT: + return "NOT"; + case OP_INC: + return "INC"; + case OP_DEC: + return "DEC"; + case OP_LAB: + return "LAB"; + case OP_VAR: + return "VAR"; + case OP_MOD: + return "MOD"; + case OP_RET: + return "RET"; + default: + return "UNKNOWN"; + } +} \ No newline at end of file diff --git a/src/debug.h b/src/debug.h index c397a0a..2f10e07 100644 --- a/src/debug.h +++ b/src/debug.h @@ -1,3 +1,34 @@ #pragma once -#include "ast.h" \ No newline at end of file +#include "ast.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + Print ast nodes data + params: + nodeList: pointer to the instruction list +*/ +void printAst(instList_t *nodeList); + +/* + Print the node data + params: + node: pointer to the instruction node +*/ +void printNodeData(instNode_t *node); + +/* + Return text corresponding to instruction kind + params: + kind: instruction kind + returns: + char*: text corresponding to instruction kind +*/ +char *getOpName(enum opKind kind); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/error.c b/src/error.c index 77ad050..e79b332 100644 --- a/src/error.c +++ b/src/error.c @@ -29,7 +29,7 @@ void errorInstruction(char* inst, instNode_t *node, const char* out, error_t *er // Format date char date_str[20]; // Sufficiently large buffer to hold formatted date - strftime(date_str, sizeof(date_str), "%d-%m-%y", timeinfo); + strftime(date_str, sizeof(date_str), "%d-%m-%y %H:%M:%S", timeinfo); fprintf(file, "%s |\tError: syntax error\n", date_str); fprintf(file, "%s |\tDetails: %s instruction is not recognized\n", date_str, inst); fprintf(file, "%s |\tIn: file %s, line %ld\n\n", date_str, errData->inputFile, node->lineNb); @@ -56,7 +56,7 @@ void errorLineSize(long lineNb, const char* out, error_t *errData){ // Format date char date_str[20]; // Sufficiently large buffer to hold formatted date - strftime(date_str, sizeof(date_str), "%d-%m-%y", timeinfo); + strftime(date_str, sizeof(date_str), "%d-%m-%y %H:%M:%S", timeinfo); fprintf(file, "%s |\tError: syntax error\n", date_str); fprintf(file, "%s |\tDetails: line must to be under 64 characters\n", date_str); fprintf(file, "%s |\tIn: file %s, line %ld\n\n", date_str, errData->inputFile, lineNb); @@ -83,7 +83,7 @@ void errorfnf(char* filename, const char* out, error_t *errData){ // Format date char date_str[20]; // Sufficiently large buffer to hold formatted date - strftime(date_str, sizeof(date_str), "%d-%m-%y", timeinfo); + strftime(date_str, sizeof(date_str), "%d-%m-%y %H:%M:%S", timeinfo); fprintf(file, "%s |\tError: file not found\n", date_str); fprintf(file, "%s |\tDetails: file %s not found\n", date_str, filename); fclose(file); @@ -91,3 +91,30 @@ void errorfnf(char* filename, const char* out, error_t *errData){ exit(EXIT_FAILURE); } + +void errorInvalidExt(char* filename, const char* out, error_t *errData){ + ++ errData->errors; + fprintf(stderr, "Error: invalid file extension\n"); + fprintf(stderr, "Details: file %s has an invalid extension\n", filename); + if(out != NULL){ + FILE *file = fopen(out, "ab"); + if(file == NULL){ + fprintf(stderr, "Error opening file: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + // Get current time + time_t rawtime; + struct tm *timeinfo; + time(&rawtime); + timeinfo = localtime(&rawtime); + + // Format date + char date_str[20]; // Sufficiently large buffer to hold formatted date + strftime(date_str, sizeof(date_str), "%d-%m-%y %H:%M:%S", timeinfo); + fprintf(file, "%s |\tError: invalid file extension\n", date_str); + fprintf(file, "%s |\tDetails: file %s has an invalid extension\n", date_str, filename); + fclose(file); + } + + exit(EXIT_FAILURE); +} diff --git a/src/error.h b/src/error.h index d25bc2f..ebf7f23 100644 --- a/src/error.h +++ b/src/error.h @@ -44,6 +44,15 @@ void errorLineSize(long lineNb, const char* out, error_t *errData); */ void errorfnf(char* filename, const char* out, error_t *errData); +/* + Throw an error when the file extension is invalid + params: + filename: File name + out: Target file (can be NULL) + errData: Error history +*/ +void errorInvalidExt(char* filename, const char* out, error_t *errData); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/src/parser.c b/src/parser.c index 5bd526a..f0f1551 100644 --- a/src/parser.c +++ b/src/parser.c @@ -73,7 +73,7 @@ void parseFile(instList_t *nodeList, char *filename, error_t *errData){ } // Check the file extension - checkAOPFile(filename); + checkAOPFile(filename, errData); char line[LINE_MAX_SIZE]; instNode_t *lastNode = NULL; @@ -142,8 +142,6 @@ instNode_t *parseLine(char *line, long nodeId, long lineNb, error_t *errData){ return newNode; } - // TODO: Check if the instruction is a declaration - // Trow error if the line is not an instruction errorInstruction(inst, newNode, errorFile, errData); return newNode; @@ -199,6 +197,21 @@ bool isOp(char *inst, instNode_t *newNode, error_t *errData){ else if(strcmp(inst, "not") == 0 || strcmp(inst, "!") == 0){ newNode->op = OP_B_NOT; } + else if(strcmp(inst, "inc") == 0 || strcmp(inst, "++") == 0){ + newNode->op = OP_INC; + } + else if(strcmp(inst, "dec") == 0 || strcmp(inst, "--") == 0){ + newNode->op = OP_DEC; + } + else if(strcmp(inst, "lab") == 0){ + newNode->op = OP_LAB; + } + else if(strcmp(inst, "var") == 0){ + newNode->op = OP_VAR; + } + else if(strcmp(inst, "mod") == 0 || strcmp(inst, "%") == 0){ + newNode->op = OP_MOD; + } else{ errorInstruction(inst, newNode, errorFile, errData); return false; @@ -422,13 +435,12 @@ enum regKind strToReg(char *arg) { } } -void checkAOPFile(char* fileName) { +void checkAOPFile(char* fileName, error_t *errData) { size_t size = strlen(fileName); //Check if the filename ends by ".aop" and contains at least 5 characters if (size < 5 || fileName[size - 4] != '.' || fileName[size - 3] != 'a' || fileName[size - 2] != 'o' || fileName[size - 1] != 'p') { - // trow error - fprintf(stderr, "The filename is invalid. Please enter a valid .aop filename.\n"); - exit(EXIT_FAILURE); + // throw error + errorInvalidExt(fileName, errorFile, errData); } } diff --git a/src/parser.h b/src/parser.h index 8674701..14ed0b1 100644 --- a/src/parser.h +++ b/src/parser.h @@ -201,8 +201,9 @@ enum regKind strToReg(char *arg); Checks if the filename ends by .aop or trows an error params: filename: name of the file to check + errData: error history */ -void checkAOPFile(char* fileName); +void checkAOPFile(char* fileName, error_t *errData); /* Checks if a line has more than 64 characters or not From 3c394d7e048a1b015b6d05b602402a3995d21b9d Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Mon, 12 Feb 2024 21:01:56 +0100 Subject: [PATCH 03/22] Update running interfaces --- src/2at2.c | 37 +++++++++++++++++++++++++++++++------ src/error.c | 25 +++++++++++++++++++++++-- src/error.h | 18 ++++++++++++++++++ 3 files changed, 72 insertions(+), 8 deletions(-) diff --git a/src/2at2.c b/src/2at2.c index a914075..b5db2c1 100644 --- a/src/2at2.c +++ b/src/2at2.c @@ -15,6 +15,8 @@ #define VERSION "0.0.5" int main(int argc, char *argv[]) { + // ---------- Parse arguments ---------- + // Parse program arguments and get flags flags_t flags = parseArgs(argc, argv); @@ -25,6 +27,10 @@ int main(int argc, char *argv[]) { printVersion(); } + fprintf(stderr, "[\t5%%\t] Parsing arguments successfully\n"); + + // ---------- Init data ---------- + // Init variables list struct varList_t *varList = malloc(sizeof(varList_t)); varList->size = 10; @@ -46,10 +52,11 @@ int main(int argc, char *argv[]) { instList->head = NULL; // Init error data history - error_t *errData = malloc(sizeof(error_t)); - errData->errors = 0; - errData->inputFile = malloc(sizeof(argv[1])+1); - strcpy(errData->inputFile, argv[1]); + error_t *errData = initErrorFile("error.log", argv[1]); + + fprintf(stderr, "[\t10%%\t] Data initialized successfully\n"); + + // ---------- Parse ---------- // run parser parseFile(instList, argv[1], errData); @@ -57,19 +64,37 @@ int main(int argc, char *argv[]) { if(flags.debug){ printAst(instList); } - + + fprintf(stderr, "[\t45%%\t] File parsed successfully\n"); + + // ---------- Build ---------- // run builder // TODO: Do Builder + fprintf(stderr, "[\t70%%\t] File built successfully\n"); + + // ---------- Assemble ---------- + // run exporter // TODO: make the function export to binary + fprintf(stderr, "[\t95%%\t] File assembled successfully\n"); + + // ---------- Print error summary ---------- + // Free memory free(varList); free(labelList); free(instList); - + + fprintf(stderr, "[\t100%%\t] Work success\n"); + + printErrorSummary(errData); + + // Free error data + free(errData); + exit(EXIT_SUCCESS); } diff --git a/src/error.c b/src/error.c index e79b332..508cac4 100644 --- a/src/error.c +++ b/src/error.c @@ -10,6 +10,22 @@ #include "error.h" +error_t *initErrorFile(const char* out, char *inputFile){ + error_t *errData = malloc(sizeof(error_t)); + errData->errors = 0; + errData->inputFile = inputFile; + if(out != NULL){ + FILE *file = fopen(out, "wb"); + if(file == NULL){ + fprintf(stderr, "Error opening file: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + fclose(file); + } + errData->errors = 0; + return errData; +} + void errorInstruction(char* inst, instNode_t *node, const char* out, error_t *errData){ ++ errData->errors; fprintf(stderr, "Error: syntax error\n"); @@ -65,6 +81,11 @@ void errorLineSize(long lineNb, const char* out, error_t *errData){ } +void printErrorSummary(error_t *errData){ + fprintf(stderr, "Error summary:\n"); + fprintf(stderr, "Total errors: %ld\n", errData->errors); +} + void errorfnf(char* filename, const char* out, error_t *errData){ ++ errData->errors; fprintf(stderr, "Error: file not found\n"); @@ -88,7 +109,7 @@ void errorfnf(char* filename, const char* out, error_t *errData){ fprintf(file, "%s |\tDetails: file %s not found\n", date_str, filename); fclose(file); } - + printErrorSummary(errData); exit(EXIT_FAILURE); } @@ -115,6 +136,6 @@ void errorInvalidExt(char* filename, const char* out, error_t *errData){ fprintf(file, "%s |\tDetails: file %s has an invalid extension\n", date_str, filename); fclose(file); } - + printErrorSummary(errData); exit(EXIT_FAILURE); } diff --git a/src/error.h b/src/error.h index ebf7f23..5f41745 100644 --- a/src/error.h +++ b/src/error.h @@ -11,6 +11,16 @@ typedef struct errorData{ char *inputFile; } error_t; +/* + Init error file + params: + out: Target file + inputFile: Input file + returns: + error_t: Error history +*/ +error_t *initErrorFile(const char* out, char *inputFile); + // ---------- Parsing/ Assembling errors ---------- /* @@ -32,6 +42,14 @@ void errorInstruction(char* inst, instNode_t *node, const char* out, error_t *er */ void errorLineSize(long lineNb, const char* out, error_t *errData); +/* + Print error summary + params: + errData: Error history + out: Target file (can be NULL) +*/ +void printErrorSummary(error_t *errData); + // ---------- Fatal errors ---------- From d2583590fc518d8bcc8977b7e07e5e05596700ca Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Tue, 13 Feb 2024 15:32:55 +0100 Subject: [PATCH 04/22] Update 2at2.c - Change init error file --- src/2at2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/2at2.c b/src/2at2.c index b5db2c1..93338e7 100644 --- a/src/2at2.c +++ b/src/2at2.c @@ -15,6 +15,9 @@ #define VERSION "0.0.5" int main(int argc, char *argv[]) { + // Init error data history + error_t *errData = initErrorFile("errors.log", argv[1]); + // ---------- Parse arguments ---------- // Parse program arguments and get flags @@ -51,9 +54,6 @@ int main(int argc, char *argv[]) { instList_t *instList = malloc(sizeof(instList_t)); instList->head = NULL; - // Init error data history - error_t *errData = initErrorFile("error.log", argv[1]); - fprintf(stderr, "[\t10%%\t] Data initialized successfully\n"); // ---------- Parse ---------- From d0048b12863e25e99201d8bd235bc350ffdc6759 Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Tue, 13 Feb 2024 15:52:47 +0100 Subject: [PATCH 05/22] Update parser.c - Add instructions handling --- src/parser.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/src/parser.c b/src/parser.c index f0f1551..300c554 100644 --- a/src/parser.c +++ b/src/parser.c @@ -198,10 +198,12 @@ bool isOp(char *inst, instNode_t *newNode, error_t *errData){ newNode->op = OP_B_NOT; } else if(strcmp(inst, "inc") == 0 || strcmp(inst, "++") == 0){ - newNode->op = OP_INC; + newNode->op = OP_ADD; + newNode->arg = "1"; } else if(strcmp(inst, "dec") == 0 || strcmp(inst, "--") == 0){ - newNode->op = OP_DEC; + newNode->op = OP_SUB; + newNode->arg = "1"; } else if(strcmp(inst, "lab") == 0){ newNode->op = OP_LAB; @@ -212,6 +214,79 @@ bool isOp(char *inst, instNode_t *newNode, error_t *errData){ else if(strcmp(inst, "mod") == 0 || strcmp(inst, "%") == 0){ newNode->op = OP_MOD; } + else if(strcmp(inst, "ret") == 0){ + newNode->op = OP_RET; + } + else if(strcmp(inst, "ngr") == 0){ + newNode->op = OP_INT; + newNode->isInter = true; + newNode->arg = "0"; + } + else if(strcmp(inst, "draw") == 0){ + newNode->op = OP_INT; + newNode->isInter = true; + newNode->arg = "1"; + } + else if(strcmp(inst, "ob1") == 0){ + newNode->op = OP_INT; + newNode->isInter = true; + newNode->arg = "2"; + } + else if(strcmp(inst, "or") == 0){ + newNode->op = OP_INT; + newNode->isInter = true; + newNode->arg = "3"; + } + else if(strcmp(inst, "if_and") == 0){ + newNode->op = OP_INT; + newNode->isInter = true; + newNode->arg = "4"; + } + else if(strcmp(inst, "if_xor") == 0){ + newNode->op = OP_INT; + newNode->isInter = true; + newNode->arg = "5"; + } + else if(strcmp(inst, "if_lt") == 0){ + newNode->op = OP_INT; + newNode->isInter = true; + newNode->arg = "6"; + } + else if(strcmp(inst, "if_lte") == 0){ + newNode->op = OP_INT; + newNode->isInter = true; + newNode->arg = "7"; + } + else if(strcmp(inst, "if_gt") == 0){ + newNode->op = OP_INT; + newNode->isInter = true; + newNode->arg = "8"; + } + else if(strcmp(inst, "if_gte") == 0){ + newNode->op = OP_INT; + newNode->isInter = true; + newNode->arg = "9"; + } + else if(strcmp(inst, "if_eq") == 0){ + newNode->op = OP_INT; + newNode->isInter = true; + newNode->arg = "10"; + } + else if(strcmp(inst, "if_neq") == 0){ + newNode->op = OP_INT; + newNode->isInter = true; + newNode->arg = "11"; + } + else if(strcmp(inst, "pusha") == 0){ + newNode->op = OP_INT; + newNode->isInter = true; + newNode->arg = "12"; + } + else if(strcmp(inst, "popa") == 0){ + newNode->op = OP_INT; + newNode->isInter = true; + newNode->arg = "13"; + } else{ errorInstruction(inst, newNode, errorFile, errData); return false; From c73e0737035e8b4448ced4b24125a71e87920c87 Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Tue, 13 Feb 2024 16:50:23 +0100 Subject: [PATCH 06/22] remove unsused functions Remove unused functions from: - parser.c/h - builder.c/h --- src/builder.c | 266 +------------------------------------------------- src/builder.h | 107 -------------------- src/parser.c | 108 -------------------- src/parser.h | 82 ---------------- 4 files changed, 2 insertions(+), 561 deletions(-) diff --git a/src/builder.c b/src/builder.c index 653f954..a1b0b2a 100644 --- a/src/builder.c +++ b/src/builder.c @@ -1,6 +1,7 @@ /* This file is the builder of the project - It will read the instruction list and build the program + It will read the instruction list and optimize or change them + to make the program able to be translated to binary code */ #include @@ -10,266 +11,3 @@ #include "builder.h" -// void build(instList_t *nodeList, labelList_t *labelList, varList_t *varList){ -// // init lifo for if/else statements -// lifoCmpNode_t *lifoCmpNode = (lifoCmpNode_t *)malloc(sizeof(lifoCmpNode_t)); -// if(lifoCmpNode == NULL){ -// fprintf(stderr, "Error allocating memory\n"); -// exit(EXIT_FAILURE); -// } -// lifoCmpNode->list = NULL; -// lifoCmpNode->size = 0; - -// // read the list of instructions -// instNode_t *currNode = nodeList->head; -// instNode_t *prevNode = NULL; -// while (currNode != NULL) -// { -// // Check if node is an action -// if(currNode->inst == INST_ACT){ -// buildActNode(currNode, lifoCmpNode); -// } - -// // Check if node is a label -// if(currNode->inst == INST_LABEL){ -// buildLabelNode(currNode, labelList); -// } - -// // Check if node is a variable declaration -// if(currNode->inst == INST_VAR){ -// addVar(varList, currNode); -// // remove var declaration from list -// if(prevNode == NULL){ -// nodeList->head = currNode->next; -// } -// else{ -// prevNode->next = currNode->next; -// } -// } - -// prevNode = currNode; -// currNode = currNode->next; -// } - -// // Check if lifo is empty -// if(lifoCmpNode->size != 0){ -// fprintf(stderr, "Error: Comparison Lifo is not empty\n"); -// exit(EXIT_FAILURE); -// } - -// } - -// void buildActNode(instNode_t *node, lifoCmpNode_t *lifo){ -// // Check if it's a comparison -// if(node->nodeType.act->act == ACT_CMP){ -// buildCmpNode(node, lifo); -// } - -// } - -// void buildCmpNode(instNode_t *node, lifoCmpNode_t *lifo){ -// // Check kind of statement -// switch (node->nodeType.act->cmp->statem) -// { -// case CMP_IF: -// // add to lifo -// pushCmpLifo(lifo, node->nodeType.act->cmp); -// break; -// case CMP_ELSE: -// // set else goto -// lifo->list[0]->elseId = node->id; -// break; -// case CMP_END: -// // set end goto -// lifo->list[0]->endId = node->id; -// // remove from lifo -// popCmpLifo(lifo); -// break; -// default: -// fprintf(stderr, "Error: Unknown comparison statement\n"); -// exit(EXIT_FAILURE); -// break; -// } -// } - -// void buildLabelNode(instNode_t *node, labelList_t *labelList){ -// // Check if label is already in the list -// for(size_t i = 0; i < labelList->size; i++){ -// if(labelList->list[i].name == NULL){ -// continue; -// } -// else if(strcmp(labelList->list[i].name, node->arg0.target) == 0){ -// fprintf(stderr, "Label %s already declared\n", node->arg0.target); -// exit(EXIT_FAILURE); -// } -// } -// // Add label to the list -// addLabel(labelList, node->arg0.target, node->id); -// } - -// void addLabel(labelList_t *list, char *name, long nodeId){ -// // Check if list is full -// bool full = true; -// for(size_t i = 0; i < list->size; i++){ -// if(list->list[i].name == NULL){ -// full = false; -// break; -// } -// } -// if(full){ -// // Increase list size -// incLabelList(list); -// } - -// // Add label to the list -// for(size_t i = 0; i < list->size; i++){ -// if(list->list[i].name == NULL){ -// list->list[i].name = name; -// list->list[i].nodeId = nodeId; -// list->list[i].id = (long)i; -// break; -// } -// } -// } - -// void incLabelList(labelList_t *list){ -// // Increase list size -// list->size *= 2; -// list->list = (label_t *)realloc(list->list, sizeof(label_t) * list->size); -// if(list->list == NULL){ -// fprintf(stderr, "Error reallocating memory\n"); -// exit(EXIT_FAILURE); -// } - -// // Init new memory -// for(size_t i = list->size / 2; i < list->size; i++){ -// list->list[i].name = NULL; -// } -// } - -// labelList_t* initLabelList(){ -// labelList_t *labelList = malloc(sizeof(labelList_t)); -// labelList->size = 10; -// labelList->list = malloc(sizeof(label_t) * labelList->size); -// for(size_t i = 0; i < labelList->size; i++){ -// labelList->list[i].name = NULL; -// labelList->list[i].nodeId = -1; -// labelList->list[i].id = -1; -// } -// return labelList; -// } - -// void pushCmpLifo(lifoCmpNode_t *lifo, cmpNode_t *node){ -// // resize lifo to add new node -// lifo->size++; -// // realloc lifo with node as new head -// cmpNode_t **newLifo = (cmpNode_t **)malloc(sizeof(cmpNode_t *) * lifo->size); -// if(newLifo == NULL){ -// fprintf(stderr, "Error allocating memory\n"); -// exit(EXIT_FAILURE); -// } -// newLifo[0] = node; -// for(size_t i = 1; i < lifo->size; i++){ -// newLifo[i] = lifo->list[i - 1]; -// } -// free(lifo->list); -// lifo->list = newLifo; -// } - -// cmpNode_t *popCmpLifo(lifoCmpNode_t *lifo){ -// // Check if lifo is empty -// if(lifo->size == 0){ -// fprintf(stderr, "Error: Lifo is empty\n"); -// exit(EXIT_FAILURE); -// } - -// // resize lifo to remove node -// lifo->size--; -// // realloc lifo without node as new head -// cmpNode_t **newLifo = (cmpNode_t **)malloc(sizeof(cmpNode_t *) * lifo->size); -// if(newLifo == NULL){ -// fprintf(stderr, "Error allocating memory\n"); -// exit(EXIT_FAILURE); -// } -// cmpNode_t *node = lifo->list[0]; -// for(size_t i = 0; i < lifo->size; i++){ -// newLifo[i] = lifo->list[i + 1]; -// } -// free(lifo->list); -// lifo->list = newLifo; - -// return node; -// } - -// void addVar(varList_t *list, instNode_t *node){ -// // Check if list is full -// bool full = true; -// for(size_t i = 0; i < list->size; i++){ -// if(list->list[i].name == NULL){ -// full = false; -// break; -// } -// } -// if(full){ -// // Increase list size -// incVarList(list); -// } - -// // Add var to the list -// for(size_t i = 0; i < list->size; i++){ -// if(list->list[i].name == NULL){ -// list->list[i].name = node->arg0.target; -// list->list[i].type = node->arg1Type; -// switch (node->arg1Type) -// { -// case VAR_INT: -// list->list[i].value.i_value = node->arg1.i_value; -// break; -// case VAR_FLOAT: -// list->list[i].value.f_value = node->arg1.f_value; -// break; -// case VAR_CHAR: -// list->list[i].value.c_value = node->arg1.c_value; -// break; -// case VAR_STRING: -// list->list[i].value.s_value = node->arg1.s_value; -// break; -// default: -// fprintf(stderr, "Error: Unknown variable type\n"); -// exit(EXIT_FAILURE); -// break; -// } -// break; -// } -// else if(strcmp(list->list[i].name, node->arg0.target) == 0){ -// fprintf(stderr, "Variable %s already declared\n", node->arg0.target); -// exit(EXIT_FAILURE); -// } -// } -// } - -// void incVarList(varList_t *list){ -// // Increase list size -// list->size *= 2; -// list->list = (var_t *)realloc(list->list, sizeof(var_t) * list->size); -// if(list->list == NULL){ -// fprintf(stderr, "Error reallocating memory\n"); -// exit(EXIT_FAILURE); -// } - -// // Init new memory -// for(size_t i = list->size / 2; i < list->size; i++){ -// list->list[i].name = NULL; -// } -// } - -// varList_t *initVarList(){ -// varList_t* varList = malloc(sizeof(varList_t)); -// varList->size = 10; -// varList->list = malloc(sizeof(var_t) * varList->size); -// // Init variables list -// for(size_t i = 0; i < varList->size; i++){ -// varList->list[i].name = NULL; -// } -// return varList; -// } \ No newline at end of file diff --git a/src/builder.h b/src/builder.h index 7676680..8ea4775 100644 --- a/src/builder.h +++ b/src/builder.h @@ -4,115 +4,8 @@ extern "C" { #endif -// // Lifo to build if/ else statements -// typedef struct lifoCmpNode{ -// cmpNode_t **list; -// size_t size; -// } lifoCmpNode_t; -/* - Read nodes from the instruction list and build the program - params: - nodeList: pointer to the instruction list - labelList: pointer to the label list - varList: pointer to the variable list -*/ -void build(instList_t *nodeList, labelList_t *labelList, varList_t *varList); - -/* - Build an operation node - params: - node: pointer to the instruction node -*/ -// void buildOpNode(instNode_t *node); - -// /* -// Build an action node -// params: -// node: pointer to the instruction node -// */ -// void buildActNode(instNode_t *node, lifoCmpNode_t *lifo); - -// /* -// Build a comparison node -// params: -// node: pointer to the instruction node -// */ -// void buildCmpNode(instNode_t *node, lifoCmpNode_t *lifo); - - - -/* - Build a label node - params: - node: pointer to the instruction node - labelList: pointer to the label list -*/ -void buildLabelNode(instNode_t *node, labelList_t *labelList); - -/* - Add a label to the label list - params: - list: pointer to the label list - name: label name - nodeId: node id -*/ -void addLabel(labelList_t *list, char *name, long nodeId); - -/* - Upgrades the size of the variable list - params: - list: pointer to the variable list -*/ -void incLabelList(labelList_t *list); - -/* - Init the label list - return: - labelList_t: pointer to the label list -*/ -labelList_t* initLabelList(); - -// /* -// Add cmp node to the lifo (as new head) -// params: -// lifo: pointer to the lifo -// node: pointer to the node -// */ -// void pushCmpLifo(lifoCmpNode_t *lifo, cmpNode_t *node); - -// /* -// Remove cmp node from the lifo (as head) -// params: -// lifo: pointer to the lifo -// return: -// cmpNode_t: pointer to the node -// */ -// cmpNode_t *popCmpLifo(lifoCmpNode_t *lifo); - -/* - Add variable to the variable list - params: - list: pointer to the variable list - nide: instNode_t pointer -*/ -void addVar(varList_t *list, instNode_t *node); - -/* - Upgrades the size of the variable list - params: - list: pointer to the variable list -*/ -void incVarList(varList_t *list); - -/* - Init the variable list - return: - varList_t: pointer to the variable list -*/ -varList_t* initVarList(); - #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/src/parser.c b/src/parser.c index 300c554..6b9a44e 100644 --- a/src/parser.c +++ b/src/parser.c @@ -368,103 +368,6 @@ void setArgs(instNode_t *node, char **args){ } } -bool isInt(char *arg) { - // Check if the argument is a number - size_t size = strlen(arg); - for (size_t i = 0; i < size; i++) { - if (arg[i] < '0' || arg[i] > '9') { - return false; - } - } - - return true; -} - -bool isBinary(char *arg) { - // Check if the argument is a binary number - size_t size = strlen(arg); - if (size < 3 || arg[0] != '0' || arg[1] != 'b') { - return false; - } - - for (size_t i = 2; i < size; i++) { - if (arg[i] != '0' && arg[i] != '1') { - return false; - } - } - - return true; -} - -bool isOctal(char *arg) { - // Check if the argument is a octal number - size_t size = strlen(arg); - if (size < 3 || arg[0] != '0' || arg[1] != 'o') { - return false; - } - - for (size_t i = 2; i < size; i++) { - if (arg[i] < '0' || arg[i] > '7') { - return false; - } - } - - return true; -} - -bool isHex(char *arg) { - // Check if the argument is a hexadecimal number - size_t size = strlen(arg); - if (size < 3 || arg[0] != '0' || arg[1] != 'x') { - return false; - } - - for (size_t i = 2; i < size; i++) { - if ((arg[i] < '0' || arg[i] > '9') && (arg[i] < 'a' || arg[i] > 'f') && (arg[i] < 'A' || arg[i] > 'F')) { - return false; - } - } - - return true; -} - -bool isFloat(char *arg) { - // Check if the argument is a float - size_t size = strlen(arg); - bool dot = false; - for (size_t i = 0; i < size; i++) { - if (arg[i] < '0' || arg[i] > '9') { - if (arg[i] == '.' && !dot) { - dot = true; - } else { - return false; - } - } - } - - return true; -} - -bool isChar(char *arg) { - // Check if the argument is a char - size_t size = strlen(arg); - if (size != 3 || arg[0] != '\'' || arg[2] != '\'') { - return false; - } - - return true; -} - -bool isString(char *arg) { - // Check if the argument is a string - size_t size = strlen(arg); - if (size < 3 || arg[0] != '"' || arg[size - 1] != '"') { - return false; - } - - return true; -} - bool isReg(char *arg) { // Check if the argument is a register if (strlen(arg) != 3 || arg[0] != 'r' || arg[1] != 'g' || arg[2] < '0' || arg[2] > '7') { @@ -474,17 +377,6 @@ bool isReg(char *arg) { return true; } -bool isTarget(char *arg) { - // Check if the argument contain other characters than letters, numbers and underscores - for (size_t i = 0; i < strlen(arg); i++) { - if ((arg[i] < 'a' || arg[i] > 'z') && (arg[i] < 'A' || arg[i] > 'Z') && (arg[i] < '0' || arg[i] > '9') && arg[i] != '_') { - return false; - } - } - - return true; -} - enum regKind strToReg(char *arg) { // Convert a string to a register switch (arg[2]) { diff --git a/src/parser.h b/src/parser.h index 14ed0b1..62b02fc 100644 --- a/src/parser.h +++ b/src/parser.h @@ -62,16 +62,6 @@ instNode_t *parseLine(char *line, long nodeId, long lineNb, error_t *errData); bool isOp(char *inst, instNode_t *newNode, error_t *errData); -/* - Read the line and check if it is a declaration for a label or a variable - params: - char*: instruction to be checked - instNode_t*: pointer to the instruction node - returns: - bool: true if it is a label -*/ -bool isDecla(char *inst, instNode_t *newNode); - /* Get instruction from line params: @@ -90,15 +80,6 @@ char* getInst(char *line); */ char** getInstArgs(char *line); -/* - Get arguments from a if instruction line - params: - line: line to be parsed - returns: - char**: array of strings (no more than 2) -*/ -char **getIfArgs(char *line); - /* Set the arguments of an instruction node params: @@ -107,69 +88,6 @@ char **getIfArgs(char *line); */ void setArgs(instNode_t *node, char **args); -/* - Check if the argument is a number - params: - arg: argument to be checked - returns: - bool: true if it is a number -*/ -bool isInt(char *arg); - -/* - Check if the argument is a binary number - params: - arg: argument to be checked - returns: - bool: true if it is a binary number -*/ -bool isBinary(char *arg); - -/* - Check if the argument is a octal number - params: - arg: argument to be checked - returns: - bool: true if it is a octal number -*/ -bool isOctal(char *arg); - -/* - Check if the argument is a hexadecimal number - params: - arg: argument to be checked - returns: - bool: true if it is a hexadecimal number -*/ -bool isHex(char *arg); - -/* - Check if the argument is a float - params: - arg: argument to be checked - returns: - bool: true if it is a float -*/ -bool isFloat(char *arg); - -/* - Check if the argument is a char - params: - arg: argument to be checked - returns: - bool: true if it is a char -*/ -bool isChar(char *arg); - -/* - Check if the argument is a string - params: - arg: argument to be checked - returns: - bool: true if it is a string -*/ -bool isString(char *arg); - /* Check if the argument is a register params: From fd038f55f9c8e3bf8c4032d5a85c00b3d6a83cda Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Wed, 14 Feb 2024 12:29:00 +0100 Subject: [PATCH 07/22] start builder and edit parser - add second string arg to ast - add capacity to manage instructions with 2 args but without register to the parser - start simple building function in builder - adapt debug output to print the new arg --- src/ast.h | 3 ++- src/builder.c | 18 ++++++++++++++++++ src/builder.h | 16 ++++++++++++++++ src/debug.c | 3 ++- src/parser.c | 46 +++++++++++++++++++++++++--------------------- src/parser.h | 9 --------- 6 files changed, 63 insertions(+), 32 deletions(-) diff --git a/src/ast.h b/src/ast.h index ba62f4f..02996fe 100644 --- a/src/ast.h +++ b/src/ast.h @@ -70,7 +70,8 @@ typedef struct instNode{ enum opKind op; bool isInter; enum interruptKind inter; - char * arg; + char * arg0; + char * arg1; enum regKind inputReg; struct instNode *next; } instNode_t; diff --git a/src/builder.c b/src/builder.c index a1b0b2a..fb9632c 100644 --- a/src/builder.c +++ b/src/builder.c @@ -11,3 +11,21 @@ #include "builder.h" +void buildProgram(instList_t *nodeList, error_t *errData) { + instNode_t *node = nodeList->head; + while(node != NULL){ + buildNode(node, errData); + node = node->next; + } +} + +void buildNode(instNode_t *node, error_t *errData) { + switch(node->op){ + case OP_MOV: + break; + default: + // TODO: transform to build error + errorInstruction("unknown", node, NULL, errData); + break; + } +} \ No newline at end of file diff --git a/src/builder.h b/src/builder.h index 8ea4775..7d9213b 100644 --- a/src/builder.h +++ b/src/builder.h @@ -1,9 +1,25 @@ #include "ast.h" +#include "error.h" #ifdef __cplusplus extern "C" { #endif +/* + Build the program + params: + nodeList: pointer to the instruction list + errData: pointer to the error struct +*/ +void buildProgram(instList_t *nodeList, error_t *errData); + +/* + Build a node + params: + node: pointer to the instruction node + errData: pointer to the error struct +*/ +void buildNode(instNode_t *node, error_t *errData); #ifdef __cplusplus diff --git a/src/debug.c b/src/debug.c index 56613c3..3b0c036 100644 --- a/src/debug.c +++ b/src/debug.c @@ -40,7 +40,8 @@ void printNodeData(instNode_t *node){ fprintf(file, "%s | Line number: %ld\n", date_str, node->lineNb); fprintf(file, "%s | Instruction: %s\n", date_str, getOpName(node->op)); fprintf(file, "%s | Target reg: %d\n", date_str, node->inputReg); - fprintf(file, "%s | Arguments: %s\n", date_str, node->arg); + fprintf(file, "%s | Argument 0: %s\n", date_str, node->arg0); + fprintf(file, "%s | Argument 1: %s\n", date_str, node->arg1); fprintf(file, "\n"); fclose(file); } diff --git a/src/parser.c b/src/parser.c index 6b9a44e..92690e0 100644 --- a/src/parser.c +++ b/src/parser.c @@ -199,11 +199,11 @@ bool isOp(char *inst, instNode_t *newNode, error_t *errData){ } else if(strcmp(inst, "inc") == 0 || strcmp(inst, "++") == 0){ newNode->op = OP_ADD; - newNode->arg = "1"; + newNode->arg0 = "1"; } else if(strcmp(inst, "dec") == 0 || strcmp(inst, "--") == 0){ newNode->op = OP_SUB; - newNode->arg = "1"; + newNode->arg0 = "1"; } else if(strcmp(inst, "lab") == 0){ newNode->op = OP_LAB; @@ -220,72 +220,72 @@ bool isOp(char *inst, instNode_t *newNode, error_t *errData){ else if(strcmp(inst, "ngr") == 0){ newNode->op = OP_INT; newNode->isInter = true; - newNode->arg = "0"; + newNode->arg0 = "0"; } else if(strcmp(inst, "draw") == 0){ newNode->op = OP_INT; newNode->isInter = true; - newNode->arg = "1"; + newNode->arg0 = "1"; } else if(strcmp(inst, "ob1") == 0){ newNode->op = OP_INT; newNode->isInter = true; - newNode->arg = "2"; + newNode->arg0 = "2"; } else if(strcmp(inst, "or") == 0){ newNode->op = OP_INT; newNode->isInter = true; - newNode->arg = "3"; + newNode->arg0 = "3"; } else if(strcmp(inst, "if_and") == 0){ newNode->op = OP_INT; newNode->isInter = true; - newNode->arg = "4"; + newNode->arg0 = "4"; } else if(strcmp(inst, "if_xor") == 0){ newNode->op = OP_INT; newNode->isInter = true; - newNode->arg = "5"; + newNode->arg0 = "5"; } else if(strcmp(inst, "if_lt") == 0){ newNode->op = OP_INT; newNode->isInter = true; - newNode->arg = "6"; + newNode->arg0 = "6"; } else if(strcmp(inst, "if_lte") == 0){ newNode->op = OP_INT; newNode->isInter = true; - newNode->arg = "7"; + newNode->arg0 = "7"; } else if(strcmp(inst, "if_gt") == 0){ newNode->op = OP_INT; newNode->isInter = true; - newNode->arg = "8"; + newNode->arg0 = "8"; } else if(strcmp(inst, "if_gte") == 0){ newNode->op = OP_INT; newNode->isInter = true; - newNode->arg = "9"; + newNode->arg0 = "9"; } else if(strcmp(inst, "if_eq") == 0){ newNode->op = OP_INT; newNode->isInter = true; - newNode->arg = "10"; + newNode->arg0 = "10"; } else if(strcmp(inst, "if_neq") == 0){ newNode->op = OP_INT; newNode->isInter = true; - newNode->arg = "11"; + newNode->arg0 = "11"; } else if(strcmp(inst, "pusha") == 0){ newNode->op = OP_INT; newNode->isInter = true; - newNode->arg = "12"; + newNode->arg0 = "12"; } else if(strcmp(inst, "popa") == 0){ newNode->op = OP_INT; newNode->isInter = true; - newNode->arg = "13"; + newNode->arg0 = "13"; } else{ errorInstruction(inst, newNode, errorFile, errData); @@ -357,15 +357,19 @@ void setArgs(instNode_t *node, char **args){ if(isReg(args[0])){ node->inputReg = strToReg(args[0]); if(args[1] != NULL){ - node->arg = malloc(sizeof(args[1])+1); - strcpy(node->arg, args[1]); - return; + node->arg1 = malloc(sizeof(args[1])+1); + strcpy(node->arg1, args[1]); } } else if(args[0] != NULL){ - node->arg = malloc(sizeof(args[0])+1); - strcpy(node->arg, args[0]); + node->arg0 = malloc(sizeof(args[0])+1); + strcpy(node->arg0, args[0]); + if(args[1] != NULL){ + node->arg1 = malloc(sizeof(args[1])+1); + strcpy(node->arg1, args[1]); + } } + return; } bool isReg(char *arg) { diff --git a/src/parser.h b/src/parser.h index 62b02fc..20f203a 100644 --- a/src/parser.h +++ b/src/parser.h @@ -97,15 +97,6 @@ void setArgs(instNode_t *node, char **args); */ bool isReg(char *arg); -/* - Check if the argument is a variable or a label - params: - arg: argument to be checked - returns: - bool: true if it is a variable -*/ -bool isTarget(char *arg); - /* Convert a string to a register params: From 2fa3769330eb44faec2f0326fc3a92c8f73ce74b Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Wed, 14 Feb 2024 18:05:14 +0100 Subject: [PATCH 08/22] Improve builder base - add new interrupt to debug - add ast.c file for ast related functions - add "isbuilt" option to ast and init it in parser - start mov build --- CMakeLists.txt | 2 + src/2at2.c | 6 ++- src/ast.c | 53 ++++++++++++++++++++++++++ src/ast.h | 21 ++++++++-- src/builder.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++- src/builder.h | 39 +++++++++++++++++++ src/debug.c | 12 ++++-- src/parser.c | 1 + 8 files changed, 226 insertions(+), 9 deletions(-) create mode 100644 src/ast.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 920d7a2..3d5f72b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ add_executable(tests src/debug.c src/error.c src/binExporter.c + src/ast.c test/test.cc googletest/googletest/src/gtest-all.cc ) @@ -64,6 +65,7 @@ add_executable(2at2 src/error.c src/binExporter.c src/2at2.c + src/ast.c ) target_include_directories(2at2 diff --git a/src/2at2.c b/src/2at2.c index 93338e7..e87a810 100644 --- a/src/2at2.c +++ b/src/2at2.c @@ -70,10 +70,14 @@ int main(int argc, char *argv[]) { // ---------- Build ---------- // run builder - // TODO: Do Builder + buildProgram(instList, errData); fprintf(stderr, "[\t70%%\t] File built successfully\n"); + if(flags.debug){ + printAst(instList); + } + // ---------- Assemble ---------- // run exporter diff --git a/src/ast.c b/src/ast.c new file mode 100644 index 0000000..7f58f01 --- /dev/null +++ b/src/ast.c @@ -0,0 +1,53 @@ +/* + this file is used to define the functions of the ast.h +*/ + +#include +#include +#include +#include +#include + +#include "ast.h" + +char *getIntCode(enum interruptKind kind){ + switch(kind){ + case INT_EXIT: + return "0"; + case INT_DRAW: + return "1"; + case INT_OB1: + return "2"; + case INT_OR: + return "3"; + case INT_AND: + return "4"; + case INT_XOR: + return "5"; + case INT_LT: + return "6"; + case INT_LTE: + return "7"; + case INT_GT: + return "8"; + case INT_GTE: + return "9"; + case INT_EQ: + return "10"; + case INT_NEQ: + return "11"; + case INT_PUSHA: + return "12"; + case INT_POPA: + return "13"; + case INT_MOV_F_REG: + return "14"; + case INT_ELSE: + return "15"; + case INT_END: + return "16"; + default: + // TODO: transform to error + exit(EXIT_FAILURE); + } +} \ No newline at end of file diff --git a/src/ast.h b/src/ast.h index 02996fe..fd80790 100644 --- a/src/ast.h +++ b/src/ast.h @@ -24,12 +24,16 @@ enum opKind{ OP_B_AND, OP_B_OR, OP_B_NOT, - OP_INC, - OP_DEC, + OP_USE_REG, + OP_USE_VAR, OP_LAB, OP_VAR, OP_MOD, OP_RET, + OP_MOV_F_VAR, + OP_MOV_T_VAR, + OP_VAR_SIZE, + OP_VAR_DATA, }; // interrupt types @@ -48,6 +52,9 @@ enum interruptKind{ INT_NEQ, INT_PUSHA, INT_POPA, + INT_MOV_F_REG, + INT_ELSE, + INT_END, }; // Register names @@ -73,6 +80,7 @@ typedef struct instNode{ char * arg0; char * arg1; enum regKind inputReg; + bool isBuilt; struct instNode *next; } instNode_t; @@ -106,4 +114,11 @@ typedef struct label{ typedef struct labelList{ size_t size; label_t *list; -} labelList_t; \ No newline at end of file +} labelList_t; + +/* + given a string, return the code of the interrupt + params: + kind: interrupt type +*/ +char *getIntCode(enum interruptKind kind); \ No newline at end of file diff --git a/src/builder.c b/src/builder.c index fb9632c..b9a4e20 100644 --- a/src/builder.c +++ b/src/builder.c @@ -16,16 +16,115 @@ void buildProgram(instList_t *nodeList, error_t *errData) { while(node != NULL){ buildNode(node, errData); node = node->next; + while(node != NULL && node->isBuilt){ + node = node->next; + } } } void buildNode(instNode_t *node, error_t *errData) { switch(node->op){ case OP_MOV: + buildMov(node, errData); break; default: // TODO: transform to build error - errorInstruction("unknown", node, NULL, errData); + // errorInstruction("unknown", node, NULL, errData); + node->isBuilt = true; break; } +} + +void buildMov(instNode_t *node, error_t *errData){ + // check if it's mov to reg + if(node->arg0 == NULL){ + // check if it's val -> reg + if(isUnsignedInt(node->arg1)){ + return; + } + // check if it's reg -> reg + if (isFromReg(node->arg1)){ + // Create a new node + instNode_t *newNode = copyInstNode(node); + + return; + } + // check if it's var -> reg + } + // check if it's reg -> var + // check if it's value -> var + // check if it's var -> var + return; +} + +instNode_t *copyInstNode(instNode_t *node){ + instNode_t *newNode = (instNode_t *)malloc(sizeof(instNode_t)); + if(newNode == NULL){ + // TODO: thorw memory alloc error + exit(EXIT_FAILURE); + } + newNode->id = node->id; + newNode->lineNb = node->lineNb; + newNode->op = node->op; + newNode->isInter = node->isInter; + newNode->inter = node->inter; + newNode->arg0 = node->arg0; + newNode->arg1 = node->arg1; + newNode->inputReg = node->inputReg; + newNode->next = node->next; + return newNode; +} + +bool isUnsignedInt(char *str){ + for(size_t i = 0; i < strlen(str); i++){ + if(str[i] < '0' || str[i] > '9'){ + return false; + } + } + return true; +} + +bool isFromReg(char *str){ + if(strlen(str) != 3){ + return false; + } + if(str[0] != 'R' && str[0] != 'r'){ + return false; + } + if(str[1] < 'G' || str[1] > 'g'){ + return false; + } + if(str[2] < '0' || str[2] > '7'){ + return false; + } + return true; +} + +enum regKind getRegKind(char *str) { + if (str == NULL || str[0] != 'r' || str[1] != 'g' || str[2] < '0' || str[2] > '7' || str[3] != '\0') { + fprintf(stderr, "Error: invalid register format\n"); + exit(EXIT_FAILURE); + } + + switch (str[2]) { + case '0': + return RG_0; + case '1': + return RG_1; + case '2': + return RG_2; + case '3': + return RG_3; + case '4': + return RG_4; + case '5': + return RG_5; + case '6': + return RG_6; + case '7': + return RG_7; + default: + fprintf(stderr, "Error: unknown register\n"); + exit(EXIT_FAILURE); + } } \ No newline at end of file diff --git a/src/builder.h b/src/builder.h index 7d9213b..e69a561 100644 --- a/src/builder.h +++ b/src/builder.h @@ -21,6 +21,45 @@ void buildProgram(instList_t *nodeList, error_t *errData); */ void buildNode(instNode_t *node, error_t *errData); +/* + Build a mov instruction + params: + node: pointer to the instruction node + errData: pointer to the error struct +*/ +void buildMov(instNode_t *node, error_t *errData); + +/* + Copy an instruction node + params: + node: pointer to the instruction node + returns: + instNode_t: copy of the instruction node +*/ +instNode_t *copyInstNode(instNode_t *node); + +/* + Check if the string is an unsigned int + params: + str: string to be checked +*/ +bool isUnsignedInt(char *str); + +/* + Check if the string is a register + params: + str: string to be checked +*/ +bool isFromReg(char *str); + +/* + Get the register kind + params: + str: string to be checked + returns: + regKind: kind of the register +*/ +enum regKind getRegKind(char *str); #ifdef __cplusplus } diff --git a/src/debug.c b/src/debug.c index 3b0c036..ec92a56 100644 --- a/src/debug.c +++ b/src/debug.c @@ -80,10 +80,6 @@ char *getOpName(enum opKind kind){ return "OR"; case OP_B_NOT: return "NOT"; - case OP_INC: - return "INC"; - case OP_DEC: - return "DEC"; case OP_LAB: return "LAB"; case OP_VAR: @@ -92,6 +88,14 @@ char *getOpName(enum opKind kind){ return "MOD"; case OP_RET: return "RET"; + case OP_MOV_F_VAR: + return "MOV_F_VAR"; + case OP_MOV_T_VAR: + return "MOV_T_VAR"; + case OP_VAR_SIZE: + return "VAR_SIZE"; + case OP_VAR_DATA: + return "VAR_DATA"; default: return "UNKNOWN"; } diff --git a/src/parser.c b/src/parser.c index 92690e0..7949786 100644 --- a/src/parser.c +++ b/src/parser.c @@ -121,6 +121,7 @@ instNode_t *parseLine(char *line, long nodeId, long lineNb, error_t *errData){ newNode->id = nodeId; newNode->lineNb = lineNb; newNode->isInter = false; + newNode->isBuilt = false; newNode->next = NULL; From 1bfc91ff5864a77507911224b390b2e879e61c99 Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Wed, 14 Feb 2024 19:30:45 +0100 Subject: [PATCH 09/22] Build for var adding Create vars and generate id during the build --- src/2at2.c | 2 +- src/ast.h | 36 +++++++++++++++++-- src/builder.c | 96 ++++++++++++++++++++++++++++++++++++--------------- src/builder.h | 21 ++++++----- src/debug.c | 48 ++++++++++++++++++++++++-- src/debug.h | 9 +++++ 6 files changed, 171 insertions(+), 41 deletions(-) diff --git a/src/2at2.c b/src/2at2.c index e87a810..5a6019e 100644 --- a/src/2at2.c +++ b/src/2at2.c @@ -70,7 +70,7 @@ int main(int argc, char *argv[]) { // ---------- Build ---------- // run builder - buildProgram(instList, errData); + buildProgram(instList, varList, labelList, errData); fprintf(stderr, "[\t70%%\t] File built successfully\n"); diff --git a/src/ast.h b/src/ast.h index fd80790..2cfd1ee 100644 --- a/src/ast.h +++ b/src/ast.h @@ -91,14 +91,14 @@ typedef struct instList{ // Structs for variable storage typedef struct var{ + int id; + int size; char *name; char * value; } var_t; // Structs for variable list typedef struct varList{ - char* name; - long id; size_t size; var_t *list; } varList_t; @@ -121,4 +121,34 @@ typedef struct labelList{ params: kind: interrupt type */ -char *getIntCode(enum interruptKind kind); \ No newline at end of file +char *getIntCode(enum interruptKind kind); + +/* + Add a variable to the list + params: + varList: pointer to the variable list + name: name of the variable + value: value of the variable + returns: + bool: true if the variable was added +*/ +bool addVar(varList_t *varList, char *name, char *value); + +/* + Check if a variable exists in the list + params: + varList: pointer to the variable list + name: name of the variable + returns: + int: id of the variable or -1 if it does not exist +*/ +int isVarExist(varList_t *varList, char *name); + +/* + Copy an instruction node + params: + node: pointer to the instruction node + returns: + instNode_t: copy of the instruction node +*/ +instNode_t *copyInstNode(instNode_t *node); \ No newline at end of file diff --git a/src/builder.c b/src/builder.c index b9a4e20..efc4bb7 100644 --- a/src/builder.c +++ b/src/builder.c @@ -11,10 +11,10 @@ #include "builder.h" -void buildProgram(instList_t *nodeList, error_t *errData) { +void buildProgram(instList_t *nodeList, varList_t *varList, labelList_t *labeList, error_t *errData) { instNode_t *node = nodeList->head; while(node != NULL){ - buildNode(node, errData); + buildNode(node, varList, labeList, errData); node = node->next; while(node != NULL && node->isBuilt){ node = node->next; @@ -22,10 +22,13 @@ void buildProgram(instList_t *nodeList, error_t *errData) { } } -void buildNode(instNode_t *node, error_t *errData) { +void buildNode(instNode_t *node, varList_t *varList, labelList_t *labeList, error_t *errData) { switch(node->op){ case OP_MOV: - buildMov(node, errData); + buildMov(node, varList, errData); + break; + case OP_VAR: + buildVar(node, varList, errData); break; default: // TODO: transform to build error @@ -35,7 +38,13 @@ void buildNode(instNode_t *node, error_t *errData) { } } -void buildMov(instNode_t *node, error_t *errData){ +void buildVar(instNode_t *node, varList_t *varList, error_t *errData){ + // try to add the variable to the list + addVar(varList, node->arg0, node->arg1); + node->isBuilt = true; +} + +void buildMov(instNode_t *node, varList_t *varList, error_t *errData){ // check if it's mov to reg if(node->arg0 == NULL){ // check if it's val -> reg @@ -47,32 +56,65 @@ void buildMov(instNode_t *node, error_t *errData){ // Create a new node instNode_t *newNode = copyInstNode(node); + // set the node + node->op = OP_INT; + node->isInter = true; + node->inter = INT_MOV_F_REG; + node->inputReg = getRegKind(node->arg1); + node->arg0 = NULL; + node->arg1 = NULL; + node->isBuilt = true; + node->next = newNode; + + // set the new node + newNode->arg0 = NULL; + newNode->arg1 = NULL; + newNode->isBuilt = true; + return; } - // check if it's var -> reg - } - // check if it's reg -> var - // check if it's value -> var - // check if it's var -> var - return; -} + // if it's var -> reg + else{ + // check if the variable is in the list + int varId = isVarExist(varList, node->arg1); + if(varId == -1){ + // TODO: throw error + } -instNode_t *copyInstNode(instNode_t *node){ - instNode_t *newNode = (instNode_t *)malloc(sizeof(instNode_t)); - if(newNode == NULL){ - // TODO: thorw memory alloc error - exit(EXIT_FAILURE); + // Create a new node + instNode_t *newNode = copyInstNode(node); + + // set the node + node->op = OP_MOV_F_VAR; + node->isInter = false; + node->inputReg = RG_0; + char buffer[5]; + sprintf(buffer, "%d", varId); + node->arg0 = (char *)malloc(sizeof(char) * 5); + // check if the memory is allocated + if(node->arg0 == NULL){ + // TODO: throw memory alloc error + exit(EXIT_FAILURE); + } + strcpy(node->arg0, buffer); + node->arg1 = NULL; + node->isBuilt = true; + node->next = newNode; + + // set the new node + newNode->arg0 = NULL; + newNode->arg1 = NULL; + newNode->isBuilt = true; + + return; + } } - newNode->id = node->id; - newNode->lineNb = node->lineNb; - newNode->op = node->op; - newNode->isInter = node->isInter; - newNode->inter = node->inter; - newNode->arg0 = node->arg0; - newNode->arg1 = node->arg1; - newNode->inputReg = node->inputReg; - newNode->next = node->next; - return newNode; + else{ + // check if it's reg -> var + // check if it's value -> var + // check if it's var -> var + } + return; } bool isUnsignedInt(char *str){ diff --git a/src/builder.h b/src/builder.h index e69a561..975984f 100644 --- a/src/builder.h +++ b/src/builder.h @@ -9,34 +9,39 @@ extern "C" { Build the program params: nodeList: pointer to the instruction list + varList: pointer to the variable list + labeList: pointer to the label list errData: pointer to the error struct */ -void buildProgram(instList_t *nodeList, error_t *errData); +void buildProgram(instList_t *nodeList, varList_t *varList, labelList_t *labeList, error_t *errData); /* Build a node params: node: pointer to the instruction node + varList: pointer to the variable list + labeList: pointer to the label list errData: pointer to the error struct */ -void buildNode(instNode_t *node, error_t *errData); +void buildNode(instNode_t *node, varList_t *varList, labelList_t *labeList, error_t *errData); /* - Build a mov instruction + Build a variable params: node: pointer to the instruction node + varList: pointer to the variable list errData: pointer to the error struct */ -void buildMov(instNode_t *node, error_t *errData); +void buildVar(instNode_t *node, varList_t *varList, error_t *errData); /* - Copy an instruction node + Build a mov instruction params: node: pointer to the instruction node - returns: - instNode_t: copy of the instruction node + varList: pointer to the variable list + errData: pointer to the error struct */ -instNode_t *copyInstNode(instNode_t *node); +void buildMov(instNode_t *node, varList_t *varList, error_t *errData); /* Check if the string is an unsigned int diff --git a/src/debug.c b/src/debug.c index ec92a56..c1bd4ac 100644 --- a/src/debug.c +++ b/src/debug.c @@ -26,7 +26,6 @@ void printNodeData(instNode_t *node){ fprintf(stderr, "Error opening file: %s\n", strerror(errno)); exit(EXIT_FAILURE); } - // Get current time time_t rawtime; struct tm *timeinfo; @@ -35,13 +34,17 @@ void printNodeData(instNode_t *node){ // Format date char date_str[20]; strftime(date_str, sizeof(date_str), "%d-%m-%y %H:%M:%S", timeinfo); - fprintf(file, "%s | Node ID: %ld\n", date_str, node->id); fprintf(file, "%s | Line number: %ld\n", date_str, node->lineNb); fprintf(file, "%s | Instruction: %s\n", date_str, getOpName(node->op)); + fprintf(file, "%s | Is interrupt: %s\n", date_str, node->isInter ? "true" : "false"); + if(node->isInter){ + fprintf(file, "%s | Interrupt: %s\n", date_str, getInterName(node->inter)); + } fprintf(file, "%s | Target reg: %d\n", date_str, node->inputReg); fprintf(file, "%s | Argument 0: %s\n", date_str, node->arg0); fprintf(file, "%s | Argument 1: %s\n", date_str, node->arg1); + fprintf(file, "%s | Is built: %s\n", date_str, node->isBuilt ? "true" : "false"); fprintf(file, "\n"); fclose(file); } @@ -99,4 +102,45 @@ char *getOpName(enum opKind kind){ default: return "UNKNOWN"; } +} + +char *getInterName(enum interruptKind kind){ + switch(kind){ + case INT_EXIT: + return "EXIT"; + case INT_DRAW: + return "DRAW"; + case INT_OB1: + return "OB1"; + case INT_OR: + return "OR"; + case INT_AND: + return "AND"; + case INT_XOR: + return "XOR"; + case INT_LT: + return "LT"; + case INT_LTE: + return "LTE"; + case INT_GT: + return "GT"; + case INT_GTE: + return "GTE"; + case INT_EQ: + return "EQ"; + case INT_NEQ: + return "NEQ"; + case INT_PUSHA: + return "PUSHA"; + case INT_POPA: + return "POPA"; + case INT_MOV_F_REG: + return "MOV_F_REG"; + case INT_ELSE: + return "ELSE"; + case INT_END: + return "END"; + default: + return "UNKNOWN"; + } } \ No newline at end of file diff --git a/src/debug.h b/src/debug.h index 2f10e07..8cf8ec5 100644 --- a/src/debug.h +++ b/src/debug.h @@ -29,6 +29,15 @@ void printNodeData(instNode_t *node); */ char *getOpName(enum opKind kind); +/* + Return text corresponding to interrupt kind + params: + kind: interrupt kind + returns: + char*: text corresponding to interrupt kind +*/ +char *getInterName(enum interruptKind kind); + #ifdef __cplusplus } #endif \ No newline at end of file From 0bf9d5a3b65e41f33d5ffc6d317de6c6e026ecdc Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Wed, 14 Feb 2024 19:31:17 +0100 Subject: [PATCH 10/22] Update ast.c - Add functions for var adding --- src/ast.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/ast.c b/src/ast.c index 7f58f01..9dc3f01 100644 --- a/src/ast.c +++ b/src/ast.c @@ -50,4 +50,75 @@ char *getIntCode(enum interruptKind kind){ // TODO: transform to error exit(EXIT_FAILURE); } +} + +bool addVar(varList_t *varList, char *name, char *value){ + // check if the variable already exists + for(size_t i = 0; i < varList->size; i++){ + if (varList->list[i].name == NULL){ + continue; + } + if(strcmp(varList->list[i].name, name) == 0){ + // TODO: add error variable already exists + return false; + } + } + // check if the list is full + bool isFull = true; + for(size_t i = 0; i < varList->size; i++){ + if(varList->list[i].name == NULL){ + isFull = false; + break; + } + } + if(isFull){ + // double the size of the list + varList->size *= 2; + varList->list = realloc(varList->list, sizeof(var_t) * varList->size); + for(size_t i = varList->size / 2; i < varList->size; i++){ + varList->list[i].name = NULL; + } + } + // add the variable + for(size_t i = 0; i < varList->size; i++){ + if(varList->list[i].name == NULL){ + // create id + varList->list[i].id = i; + varList->list[i].name = name; + varList->list[i].value = value; + return true; + } + } + // TODO: throw error + exit(EXIT_FAILURE); +} + +int isVarExist(varList_t *varList, char *name){ + for(size_t i = 0; i < varList->size; i++){ + if(varList->list[i].name == NULL){ + continue; + } + if(strcmp(varList->list[i].name, name) == 0){ + return i; + } + } + return -1; +} + +instNode_t *copyInstNode(instNode_t *node){ + instNode_t *newNode = (instNode_t *)malloc(sizeof(instNode_t)); + if(newNode == NULL){ + // TODO: thorw memory alloc error + exit(EXIT_FAILURE); + } + newNode->id = node->id; + newNode->lineNb = node->lineNb; + newNode->op = node->op; + newNode->isInter = node->isInter; + newNode->inter = node->inter; + newNode->arg0 = node->arg0; + newNode->arg1 = node->arg1; + newNode->inputReg = node->inputReg; + newNode->next = node->next; + return newNode; } \ No newline at end of file From 88a189d65e37b600a735089a368f4ab6a61901b3 Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Wed, 14 Feb 2024 20:38:57 +0100 Subject: [PATCH 11/22] Update builder.c - add building for mov instruction --- src/builder.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 114 insertions(+), 7 deletions(-) diff --git a/src/builder.c b/src/builder.c index efc4bb7..0b3e2e9 100644 --- a/src/builder.c +++ b/src/builder.c @@ -49,6 +49,8 @@ void buildMov(instNode_t *node, varList_t *varList, error_t *errData){ if(node->arg0 == NULL){ // check if it's val -> reg if(isUnsignedInt(node->arg1)){ + node->arg0 = node->arg1; + node->arg1 = NULL; return; } // check if it's reg -> reg @@ -88,14 +90,9 @@ void buildMov(instNode_t *node, varList_t *varList, error_t *errData){ node->op = OP_MOV_F_VAR; node->isInter = false; node->inputReg = RG_0; - char buffer[5]; + char buffer[8]; sprintf(buffer, "%d", varId); - node->arg0 = (char *)malloc(sizeof(char) * 5); - // check if the memory is allocated - if(node->arg0 == NULL){ - // TODO: throw memory alloc error - exit(EXIT_FAILURE); - } + node->arg0 = (char *)malloc(sizeof(char) * 8); strcpy(node->arg0, buffer); node->arg1 = NULL; node->isBuilt = true; @@ -111,9 +108,119 @@ void buildMov(instNode_t *node, varList_t *varList, error_t *errData){ } else{ // check if it's reg -> var + if(node->arg1 != NULL && isFromReg(node->arg1)){ + // check if the variable is in the list + int varId = isVarExist(varList, node->arg0); + if(varId == -1){ + // TODO: throw error + } + // Create a new node + instNode_t *newNode = copyInstNode(node); + + // set the node + node->op = OP_INT; + node->isInter = true; + node->inter = INT_MOV_F_REG; + node->inputReg = getRegKind(node->arg1); + node->arg0 = NULL; + node->arg1 = NULL; + node->isBuilt = true; + node->next = newNode; + + // set the new node + newNode->op = OP_MOV_T_VAR; + newNode->isInter = false; + newNode->inputReg = RG_0; + + char buffer[8]; + sprintf(buffer, "%d", varId); + newNode->arg0 = (char *)malloc(sizeof(char) * 8); + strcpy(newNode->arg0, buffer); + + newNode->arg1 = NULL; + newNode->isBuilt = true; + + return; + } // check if it's value -> var + else if(isUnsignedInt(node->arg1)){ + // check if the variable is in the list + int varId = isVarExist(varList, node->arg0); + if(varId == -1){ + // TODO: throw error + } + + // Create a new node + instNode_t *newNode = copyInstNode(node); + + // set the node + node->op = OP_MOV_T_VAR; + node->isInter = false; + node->inputReg = RG_0; + + char buffer[8]; + sprintf(buffer, "%d", varId); + node->arg0 = (char *)malloc(sizeof(char) * 8); + strcpy(node->arg0, buffer); + + node->arg1 = NULL; + node->isBuilt = true; + node->next = newNode; + + // set the new node + newNode->op = OP_MOV; + newNode->inputReg = RG_0; + newNode->arg0 = newNode->arg1; + newNode->arg1 = NULL; + newNode->isBuilt = true; + return; + } // check if it's var -> var + else{ + // Create a new node + instNode_t *newNode = copyInstNode(node); + + // set the new node + // check if the variable is in the list + int varId = isVarExist(varList, node->arg0); + if(varId == -1){ + // TODO: throw error + } + newNode->op = OP_MOV_T_VAR; + newNode->isInter = false; + newNode->inputReg = RG_0; + + char buffer[8]; + sprintf(buffer, "%d", varId); + newNode->arg0 = (char *)malloc(sizeof(char) * 8); + strcpy(newNode->arg0, buffer); + + newNode->arg1 = NULL; + newNode->isBuilt = true; + + // set the node + // check if the variable is in the list + varId = isVarExist(varList, node->arg1); + if(varId == -1){ + // TODO: throw error + } + + node->op = OP_MOV_F_VAR; + node->isInter = false; + node->inputReg = RG_0; + + sprintf(buffer, "%d", varId); + node->arg0 = (char *)malloc(sizeof(char) * 8); + strcpy(node->arg0, buffer); + + node->arg1 = NULL; + node->isBuilt = true; + node->next = newNode; + return; + } } + // TODO: throw error + return; } From f59307d8d74d4e44037959b803f2447939d98b04 Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Wed, 14 Feb 2024 22:40:55 +0100 Subject: [PATCH 12/22] Add label building - Add functions to handle label creation in building - Correct parser -> Now if a comment is preceded by tab or space it's still recognised as a comment --- src/ast.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/ast.h | 23 ++++++++++++++++++++- src/builder.c | 20 +++++++++++++++++++ src/builder.h | 9 +++++++++ src/parser.c | 2 +- 5 files changed, 107 insertions(+), 2 deletions(-) diff --git a/src/ast.c b/src/ast.c index 9dc3f01..5810154 100644 --- a/src/ast.c +++ b/src/ast.c @@ -121,4 +121,59 @@ instNode_t *copyInstNode(instNode_t *node){ newNode->inputReg = node->inputReg; newNode->next = node->next; return newNode; +} + +int addLabel(labelList_t *labelList, char *name, long nodeId){ + // check if the label already exists + for(size_t i = 0; i < labelList->size; i++){ + if (labelList->list[i].name == NULL){ + continue; + } + if(strcmp(labelList->list[i].name, name) == 0){ + // TODO: add error label already exists + return -1; + } + } + + // check if the list is full + bool isFull = true; + for(size_t i = 0; i < labelList->size; i++){ + if(labelList->list[i].name == NULL){ + isFull = false; + break; + } + } + if(isFull){ + // double the size of the list + labelList->size *= 2; + labelList->list = realloc(labelList->list, sizeof(label_t) * labelList->size); + for(size_t i = labelList->size / 2; i < labelList->size; i++){ + labelList->list[i].name = NULL; + } + } + + // add the label + for(size_t i = 0; i < labelList->size; i++){ + if(labelList->list[i].name == NULL){ + labelList->list[i].name = name; + labelList->list[i].nodeId = nodeId; + labelList->list[i].id = i; + return i; + } + } + + // TODO: throw error + return -1; +} + +int isLabelExist(labelList_t *labelList, char *name){ + for(size_t i = 0; i < labelList->size; i++){ + if(labelList->list[i].name == NULL){ + continue; + } + if(strcmp(labelList->list[i].name, name) == 0){ + return labelList->list[i].id; + } + } + return -1; } \ No newline at end of file diff --git a/src/ast.h b/src/ast.h index 2cfd1ee..63e73dc 100644 --- a/src/ast.h +++ b/src/ast.h @@ -151,4 +151,25 @@ int isVarExist(varList_t *varList, char *name); returns: instNode_t: copy of the instruction node */ -instNode_t *copyInstNode(instNode_t *node); \ No newline at end of file +instNode_t *copyInstNode(instNode_t *node); + +/* + Add a label to the list + params: + labelList: pointer to the label list + name: name of the label + nodeId: id of the node + returns: + int: id of the label or -1 if it does not exist +*/ +int addLabel(labelList_t *labelList, char *name, long nodeId); + +/* + Check if a label exists in the list + params: + labelList: pointer to the label list + name: name of the label + returns: + int: id of the label or -1 if it does not exist +*/ +int isLabelExist(labelList_t *labelList, char *name); \ No newline at end of file diff --git a/src/builder.c b/src/builder.c index 0b3e2e9..504acda 100644 --- a/src/builder.c +++ b/src/builder.c @@ -30,6 +30,9 @@ void buildNode(instNode_t *node, varList_t *varList, labelList_t *labeList, erro case OP_VAR: buildVar(node, varList, errData); break; + case OP_LAB: + buildLabel(node, labeList, errData); + break; default: // TODO: transform to build error // errorInstruction("unknown", node, NULL, errData); @@ -44,6 +47,23 @@ void buildVar(instNode_t *node, varList_t *varList, error_t *errData){ node->isBuilt = true; } +void buildLabel(instNode_t *node, labelList_t *labelList, error_t *errData){ + // try to add the label to the list + int labId = addLabel(labelList, node->arg0, node->id); + if(labId == -1){ + // TODO: throw error + } + + // set arg0 as id + char buffer[8]; + sprintf(buffer, "%d", labId); + node->arg0 = (char *)malloc(sizeof(char) * 8); + strcpy(node->arg0, buffer); + + node->isBuilt = true; +} + + void buildMov(instNode_t *node, varList_t *varList, error_t *errData){ // check if it's mov to reg if(node->arg0 == NULL){ diff --git a/src/builder.h b/src/builder.h index 975984f..11e5357 100644 --- a/src/builder.h +++ b/src/builder.h @@ -34,6 +34,15 @@ void buildNode(instNode_t *node, varList_t *varList, labelList_t *labeList, erro */ void buildVar(instNode_t *node, varList_t *varList, error_t *errData); +/* + Build a label + params: + node: pointer to the instruction node + labelList: pointer to the label list + errData: pointer to the error struct +*/ +void buildLabel(instNode_t *node, labelList_t *labelList, error_t *errData); + /* Build a mov instruction params: diff --git a/src/parser.c b/src/parser.c index 7949786..a0f5270 100644 --- a/src/parser.c +++ b/src/parser.c @@ -113,7 +113,7 @@ void parseFile(instList_t *nodeList, char *filename, error_t *errData){ instNode_t *parseLine(char *line, long nodeId, long lineNb, error_t *errData){ // check if the line is empty or a comment - if(line[0] == '\n' || strncmp(line, "//", 2) == 0){ + if(line[0] == '\n' || strncmp(cleanString(line), "//", 2) == 0){ return NULL; } From 54ec1cb9b8c3dc863ed53f5ea3698fbe2f62ff16 Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Wed, 14 Feb 2024 22:59:56 +0100 Subject: [PATCH 13/22] Add goto building - Add functions to build a goto with check if the label exist --- src/builder.c | 21 ++++++++++++++++++++- src/builder.h | 9 +++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/builder.c b/src/builder.c index 504acda..be2f6d2 100644 --- a/src/builder.c +++ b/src/builder.c @@ -27,6 +27,8 @@ void buildNode(instNode_t *node, varList_t *varList, labelList_t *labeList, erro case OP_MOV: buildMov(node, varList, errData); break; + case OP_GOTO: + case OP_VAR: buildVar(node, varList, errData); break; @@ -63,7 +65,6 @@ void buildLabel(instNode_t *node, labelList_t *labelList, error_t *errData){ node->isBuilt = true; } - void buildMov(instNode_t *node, varList_t *varList, error_t *errData){ // check if it's mov to reg if(node->arg0 == NULL){ @@ -244,6 +245,24 @@ void buildMov(instNode_t *node, varList_t *varList, error_t *errData){ return; } +void buildGoto(instNode_t *node, labelList_t *labelList, error_t *errData){ + // check if the label is in the list + int labId = isLabelExist(labelList, node->arg0); + if(labId == -1){ + // TODO: throw error + return; + } + + // change arg0 to id + char buffer[8]; + sprintf(buffer, "%d", labId); + node->arg0 = (char *)malloc(sizeof(char) * 8); + strcpy(node->arg0, buffer); + node->arg1 = NULL; + node->isBuilt = true; + return; +} + bool isUnsignedInt(char *str){ for(size_t i = 0; i < strlen(str); i++){ if(str[i] < '0' || str[i] > '9'){ diff --git a/src/builder.h b/src/builder.h index 11e5357..38cc654 100644 --- a/src/builder.h +++ b/src/builder.h @@ -52,6 +52,15 @@ void buildLabel(instNode_t *node, labelList_t *labelList, error_t *errData); */ void buildMov(instNode_t *node, varList_t *varList, error_t *errData); +/* + Build a goto instruction + params: + node: pointer to the instruction node + labelList: pointer to the label list + errData: pointer to the error struct +*/ +void buildGoto(instNode_t *node, labelList_t *labelList, error_t *errData); + /* Check if the string is an unsigned int params: From 969fd9cda334610e2b26338fcff187c0b51c85cb Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Wed, 14 Feb 2024 23:27:18 +0100 Subject: [PATCH 14/22] Add call and ret build - Handle call and ret instructions to build them - Correct parsing error caused by not checking if the first argument of the command is null --- src/builder.c | 22 +++++++++++++++++++++- src/builder.h | 9 +++++++++ src/parser.c | 5 +++-- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/builder.c b/src/builder.c index be2f6d2..aaccf89 100644 --- a/src/builder.c +++ b/src/builder.c @@ -28,7 +28,8 @@ void buildNode(instNode_t *node, varList_t *varList, labelList_t *labeList, erro buildMov(node, varList, errData); break; case OP_GOTO: - + buildGoto(node, labeList, errData); + break; case OP_VAR: buildVar(node, varList, errData); break; @@ -263,6 +264,25 @@ void buildGoto(instNode_t *node, labelList_t *labelList, error_t *errData){ return; } +void buildCall(instNode_t *node, labelList_t *labelList, error_t *errData){ + // check if the label is in the list + int labId = isLabelExist(labelList, node->arg0); + if(labId == -1){ + // TODO: throw error + return; + } + + // change arg0 to id + char buffer[8]; + sprintf(buffer, "%d", labId); + node->arg0 = (char *)malloc(sizeof(char) * 8); + strcpy(node->arg0, buffer); + node->arg1 = NULL; + node->isBuilt = true; + + return; +} + bool isUnsignedInt(char *str){ for(size_t i = 0; i < strlen(str); i++){ if(str[i] < '0' || str[i] > '9'){ diff --git a/src/builder.h b/src/builder.h index 38cc654..e9c81ab 100644 --- a/src/builder.h +++ b/src/builder.h @@ -61,6 +61,15 @@ void buildMov(instNode_t *node, varList_t *varList, error_t *errData); */ void buildGoto(instNode_t *node, labelList_t *labelList, error_t *errData); +/* + Build a call instruction + params: + node: pointer to the instruction node + labelList: pointer to the label list + errData: pointer to the error struct +*/ +void buildCall(instNode_t *node, labelList_t *labelList, error_t *errData); + /* Check if the string is an unsigned int params: diff --git a/src/parser.c b/src/parser.c index a0f5270..fdd7b6f 100644 --- a/src/parser.c +++ b/src/parser.c @@ -89,7 +89,6 @@ void parseFile(instList_t *nodeList, char *filename, error_t *errData){ // parse the line instNode_t *node = parseLine(line, nodeId, lineNb, errData); - // continue if the line is empty if(node == NULL){ ++ lineNb; @@ -217,6 +216,8 @@ bool isOp(char *inst, instNode_t *newNode, error_t *errData){ } else if(strcmp(inst, "ret") == 0){ newNode->op = OP_RET; + newNode->arg0 = "0"; + newNode->arg1 = "0"; } else if(strcmp(inst, "ngr") == 0){ newNode->op = OP_INT; @@ -355,7 +356,7 @@ char **getInstArgs(char *line) { } void setArgs(instNode_t *node, char **args){ - if(isReg(args[0])){ + if(args[0] != NULL && isReg(args[0])){ node->inputReg = strToReg(args[0]); if(args[1] != NULL){ node->arg1 = malloc(sizeof(args[1])+1); From d9e36ce2d177c68f14ba4e85f74876b78f1f7f80 Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Thu, 15 Feb 2024 00:38:19 +0100 Subject: [PATCH 15/22] build arithmetic and boolean operations - Add building for all kinds of operation - Update parser by adding checking for operation syntax --- src/ast.h | 4 +-- src/builder.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/builder.h | 9 +++++++ src/parser.c | 57 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 139 insertions(+), 5 deletions(-) diff --git a/src/ast.h b/src/ast.h index 63e73dc..b4b8fe6 100644 --- a/src/ast.h +++ b/src/ast.h @@ -13,8 +13,8 @@ enum opKind{ OP_CALL, OP_INT, OP_PUSH, - OP_B_XOR, OP_POP, + OP_B_XOR, OP_DIV, OP_ADD, OP_SUB, @@ -24,11 +24,11 @@ enum opKind{ OP_B_AND, OP_B_OR, OP_B_NOT, + OP_MOD, OP_USE_REG, OP_USE_VAR, OP_LAB, OP_VAR, - OP_MOD, OP_RET, OP_MOV_F_VAR, OP_MOV_T_VAR, diff --git a/src/builder.c b/src/builder.c index aaccf89..5b77b5f 100644 --- a/src/builder.c +++ b/src/builder.c @@ -30,12 +30,18 @@ void buildNode(instNode_t *node, varList_t *varList, labelList_t *labeList, erro case OP_GOTO: buildGoto(node, labeList, errData); break; + case OP_CALL: + buildCall(node, labeList, errData); + break; case OP_VAR: buildVar(node, varList, errData); break; case OP_LAB: buildLabel(node, labeList, errData); break; + case OP_B_XOR...OP_MOD: + buildOperation(node, varList, errData); + break; default: // TODO: transform to build error // errorInstruction("unknown", node, NULL, errData); @@ -279,7 +285,73 @@ void buildCall(instNode_t *node, labelList_t *labelList, error_t *errData){ strcpy(node->arg0, buffer); node->arg1 = NULL; node->isBuilt = true; - + + return; +} + +void buildOperation(instNode_t *node, varList_t *varList, error_t *errData){ + // check if the second argument is an unsigned int + if(node->arg1 != NULL && isUnsignedInt(node->arg1)){ + // pass argument 1 to arg0 + node->arg0 = node->arg1; + node->arg1 = NULL; + return; + } + // check if the second argument is a register + else if(node->arg1 != NULL && isFromReg(node->arg1)){ + // Create a new node + instNode_t *newNode = copyInstNode(node); + + // set the node + node->op = OP_INT; + node->isInter = true; + node->inter = INT_MOV_F_REG; + node->inputReg = getRegKind(node->arg1); + node->arg0 = NULL; + node->arg1 = NULL; + node->isBuilt = true; + node->next = newNode; + + // set the new node + newNode->arg0 = NULL; + newNode->arg1 = NULL; + newNode->isBuilt = true; + + return; + + } + // check if the second argument is a variable + else if(node->arg1 != NULL){ + // check if the variable is in the list + int varId = isVarExist(varList, node->arg1); + if(varId == -1){ + // TODO: throw error + } + + // Create a new node + instNode_t *newNode = copyInstNode(node); + + // set the node + node->op = OP_MOV_F_VAR; + node->isInter = false; + node->inputReg = RG_0; + char buffer[8]; + sprintf(buffer, "%d", varId); + node->arg0 = (char *)malloc(sizeof(char) * 8); + strcpy(node->arg0, buffer); + node->arg1 = NULL; + node->isBuilt = true; + node->next = newNode; + + // set the new node + newNode->arg0 = NULL; + newNode->arg1 = NULL; + newNode->isBuilt = true; + + return; + } + + // TODO: throw error return; } diff --git a/src/builder.h b/src/builder.h index e9c81ab..213b5c9 100644 --- a/src/builder.h +++ b/src/builder.h @@ -70,6 +70,15 @@ void buildGoto(instNode_t *node, labelList_t *labelList, error_t *errData); */ void buildCall(instNode_t *node, labelList_t *labelList, error_t *errData); +/* + Build an operation (add, xor, etc.) + params: + node: pointer to the instruction node + varList: pointer to the variable list + errData: pointer to the error struct +*/ +void buildOperation(instNode_t *node, varList_t *varList, error_t *errData); + /* Check if the string is an unsigned int params: diff --git a/src/parser.c b/src/parser.c index fdd7b6f..ce05d85 100644 --- a/src/parser.c +++ b/src/parser.c @@ -166,44 +166,93 @@ bool isOp(char *inst, instNode_t *newNode, error_t *errData){ } else if(strcmp(inst, "xor") == 0 || strcmp(inst, "^") == 0){ newNode->op = OP_B_XOR; + // check if first argument is null + if(newNode->arg0 == NULL){ + // TODO: throw error + } + } else if(strcmp(inst, "pop") == 0){ newNode->op = OP_POP; } else if(strcmp(inst, "div") == 0 || strcmp(inst, "/") == 0){ newNode->op = OP_DIV; + // check if first argument is null + if(newNode->arg0 == NULL){ + // TODO: throw error + } } else if(strcmp(inst, "add") == 0 || strcmp(inst, "+") == 0){ newNode->op = OP_ADD; + // check if first argument is null + if(newNode->arg0 == NULL){ + // TODO: throw error + } } else if(strcmp(inst, "sub") == 0 || strcmp(inst, "-") == 0){ newNode->op = OP_SUB; + // check if first argument is null + if(newNode->arg0 == NULL){ + // TODO: throw error + } } else if(strcmp(inst, "mul") == 0 || strcmp(inst, "*") == 0){ newNode->op = OP_MUL; + // check if first argument is null + if(newNode->arg0 == NULL){ + // TODO: throw error + } } else if(strcmp(inst, "shr") == 0 || strcmp(inst, ">>") == 0){ newNode->op = OP_R_SHIFT; + // check if first argument is null + if(newNode->arg0 == NULL){ + // TODO: throw error + } } else if(strcmp(inst, "shl") == 0 || strcmp(inst, "<<") == 0){ newNode->op = OP_L_SHIFT; + // check if first argument is null + if(newNode->arg0 == NULL){ + // TODO: throw error + } } else if(strcmp(inst, "and") == 0 || strcmp(inst, "&") == 0){ newNode->op = OP_B_AND; + // check if first argument is null + if(newNode->arg0 == NULL){ + // TODO: throw error + } } else if(strcmp(inst, "or") == 0 || strcmp(inst, "|") == 0){ newNode->op = OP_B_OR; + // check if first argument is null + if(newNode->arg0 == NULL){ + // TODO: throw error + } } else if(strcmp(inst, "not") == 0 || strcmp(inst, "!") == 0){ newNode->op = OP_B_NOT; + // check if first argument is null + if(newNode->arg0 == NULL){ + // TODO: throw error + } } else if(strcmp(inst, "inc") == 0 || strcmp(inst, "++") == 0){ newNode->op = OP_ADD; - newNode->arg0 = "1"; + // check if first argument is null + if(newNode->arg0 == NULL){ + // TODO: throw error + } + newNode->arg1 = "1"; } else if(strcmp(inst, "dec") == 0 || strcmp(inst, "--") == 0){ newNode->op = OP_SUB; - newNode->arg0 = "1"; + // check if first argument is null + if(newNode->arg0 == NULL){ + // TODO: throw error + } + newNode->arg1 = "1"; } else if(strcmp(inst, "lab") == 0){ newNode->op = OP_LAB; @@ -213,6 +262,10 @@ bool isOp(char *inst, instNode_t *newNode, error_t *errData){ } else if(strcmp(inst, "mod") == 0 || strcmp(inst, "%") == 0){ newNode->op = OP_MOD; + // check if first argument is null + if(newNode->arg0 == NULL){ + // TODO: throw error + } } else if(strcmp(inst, "ret") == 0){ newNode->op = OP_RET; From 54f794338d92c0840e0e6ddb3904d697cefc165e Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Thu, 15 Feb 2024 02:48:41 +0100 Subject: [PATCH 16/22] Update var instruction build Now the var's build do that: Initial instruction: var name, "test" Built instruction: var 0, var_id varsize 0, 5 vardata 0, 't' . . vardata 0, '\0' --- src/ast.c | 17 +++++ src/ast.h | 7 ++ src/builder.c | 180 +++++++++++++++++++++++++++++++---------------- src/builder.h | 19 ++--- src/stringPlus.c | 31 +++++++- src/stringPlus.h | 18 ++++- 6 files changed, 196 insertions(+), 76 deletions(-) diff --git a/src/ast.c b/src/ast.c index 5810154..df79211 100644 --- a/src/ast.c +++ b/src/ast.c @@ -123,6 +123,23 @@ instNode_t *copyInstNode(instNode_t *node){ return newNode; } +instNode_t *createEmptyInstNode(){ + instNode_t *newNode = (instNode_t *)malloc(sizeof(instNode_t)); + if(newNode == NULL){ + // TODO: thorw memory alloc error + exit(EXIT_FAILURE); + } + newNode->id = -1; + newNode->lineNb = -1; + newNode->isInter = false; + newNode->arg0 = NULL; + newNode->arg1 = NULL; + newNode->isBuilt = false; + newNode->next = NULL; + + return newNode; +} + int addLabel(labelList_t *labelList, char *name, long nodeId){ // check if the label already exists for(size_t i = 0; i < labelList->size; i++){ diff --git a/src/ast.h b/src/ast.h index b4b8fe6..8129878 100644 --- a/src/ast.h +++ b/src/ast.h @@ -153,6 +153,13 @@ int isVarExist(varList_t *varList, char *name); */ instNode_t *copyInstNode(instNode_t *node); +/* + Create an empty instruction node + returns: + instNode_t: pointer to the instruction node +*/ +instNode_t *createEmptyInstNode(); + /* Add a label to the list params: diff --git a/src/builder.c b/src/builder.c index 5b77b5f..4841f83 100644 --- a/src/builder.c +++ b/src/builder.c @@ -10,6 +10,9 @@ #include #include "builder.h" +#include "stringPlus.h" + +#define IMMEDIATE_VAL_SIZE 8 void buildProgram(instList_t *nodeList, varList_t *varList, labelList_t *labeList, error_t *errData) { instNode_t *node = nodeList->head; @@ -51,9 +54,94 @@ void buildNode(instNode_t *node, varList_t *varList, labelList_t *labeList, erro } void buildVar(instNode_t *node, varList_t *varList, error_t *errData){ + // copy variable value + char *varData = (char *)malloc(sizeof(char) * (strlen(node->arg1) + 1)); + strcpy(varData, node->arg1); + // try to add the variable to the list addVar(varList, node->arg0, node->arg1); + int varId = isVarExist(varList, node->arg0); + if(varId == -1){ + // TODO: throw error + } + // set arg0 as id + node->arg0 = malloc(IMMEDIATE_VAL_SIZE+1 * sizeof(char)); + sprintf(node->arg0, "%d", varId); + + node->arg1 = NULL; node->isBuilt = true; + + // get the datasize of the variable + int dataSize = getVarDatasize(varData); + if(dataSize > 1){ + // add the null terminator + dataSize++; + } + + // create a new node + instNode_t *newNode = createEmptyInstNode(); + newNode->id = node->id; + newNode->lineNb = node->lineNb; + newNode->op = OP_VAR_SIZE; + newNode->inputReg = RG_0; + + newNode->arg0 = malloc(IMMEDIATE_VAL_SIZE+1 * sizeof(char)); + sprintf(newNode->arg0, "%d", dataSize); + + newNode->isBuilt = true; + newNode->next = node->next; + node->next = newNode; + + if(dataSize == 1){ + // create a new node + instNode_t *dataNode = createEmptyInstNode(); + dataNode->id = node->id; + dataNode->lineNb = node->lineNb; + dataNode->op = OP_VAR_DATA; + dataNode->inputReg = RG_0; + + dataNode->arg0 = malloc(IMMEDIATE_VAL_SIZE+1 * sizeof(char)); + sprintf(dataNode->arg0, "%s", varData); + + dataNode->isBuilt = true; + dataNode->next = newNode->next; + newNode->next = dataNode; + + return; + } + else{ + // add the null terminator + // create a new node + instNode_t *nullNode = createEmptyInstNode(); + nullNode->id = node->id; + nullNode->lineNb = node->lineNb; + nullNode->op = OP_VAR_DATA; + nullNode->inputReg = RG_0; + + nullNode->arg0 = malloc(IMMEDIATE_VAL_SIZE + 1 * sizeof(char)); + sprintf(nullNode->arg0, "%c", '\0'); + + nullNode->isBuilt = true; + nullNode->next = newNode->next; + newNode->next = nullNode; + + // Reverse iteration over varData to create nodes + for (int i = dataSize - 1; i >= 0; i--) { + // create a new node + instNode_t *dataNode = createEmptyInstNode(); + dataNode->id = node->id; + dataNode->lineNb = node->lineNb; + dataNode->op = OP_VAR_DATA; + dataNode->inputReg = RG_0; + + dataNode->arg0 = malloc(IMMEDIATE_VAL_SIZE + 1 * sizeof(char)); + sprintf(dataNode->arg0, "%c", varData[i]); + + dataNode->isBuilt = true; + dataNode->next = newNode->next; + newNode->next = dataNode; + } + } } void buildLabel(instNode_t *node, labelList_t *labelList, error_t *errData){ @@ -64,10 +152,8 @@ void buildLabel(instNode_t *node, labelList_t *labelList, error_t *errData){ } // set arg0 as id - char buffer[8]; - sprintf(buffer, "%d", labId); - node->arg0 = (char *)malloc(sizeof(char) * 8); - strcpy(node->arg0, buffer); + node->arg0 = malloc(IMMEDIATE_VAL_SIZE+1 * sizeof(char)); + sprintf(node->arg0, "%d", labId); node->isBuilt = true; } @@ -118,10 +204,8 @@ void buildMov(instNode_t *node, varList_t *varList, error_t *errData){ node->op = OP_MOV_F_VAR; node->isInter = false; node->inputReg = RG_0; - char buffer[8]; - sprintf(buffer, "%d", varId); - node->arg0 = (char *)malloc(sizeof(char) * 8); - strcpy(node->arg0, buffer); + node->arg0 = malloc(IMMEDIATE_VAL_SIZE+1 * sizeof(char)); + sprintf(node->arg0, "%d", varId); node->arg1 = NULL; node->isBuilt = true; node->next = newNode; @@ -160,10 +244,8 @@ void buildMov(instNode_t *node, varList_t *varList, error_t *errData){ newNode->isInter = false; newNode->inputReg = RG_0; - char buffer[8]; - sprintf(buffer, "%d", varId); - newNode->arg0 = (char *)malloc(sizeof(char) * 8); - strcpy(newNode->arg0, buffer); + newNode->arg0 = malloc(IMMEDIATE_VAL_SIZE+1 * sizeof(char)); + sprintf(newNode->arg0, "%d", varId); newNode->arg1 = NULL; newNode->isBuilt = true; @@ -186,10 +268,8 @@ void buildMov(instNode_t *node, varList_t *varList, error_t *errData){ node->isInter = false; node->inputReg = RG_0; - char buffer[8]; - sprintf(buffer, "%d", varId); - node->arg0 = (char *)malloc(sizeof(char) * 8); - strcpy(node->arg0, buffer); + node->arg0 = malloc(IMMEDIATE_VAL_SIZE+1 * sizeof(char)); + sprintf(node->arg0, "%d", varId); node->arg1 = NULL; node->isBuilt = true; @@ -218,10 +298,8 @@ void buildMov(instNode_t *node, varList_t *varList, error_t *errData){ newNode->isInter = false; newNode->inputReg = RG_0; - char buffer[8]; - sprintf(buffer, "%d", varId); - newNode->arg0 = (char *)malloc(sizeof(char) * 8); - strcpy(newNode->arg0, buffer); + newNode->arg0 = malloc(IMMEDIATE_VAL_SIZE+1 * sizeof(char)); + sprintf(newNode->arg0, "%d", varId); newNode->arg1 = NULL; newNode->isBuilt = true; @@ -237,9 +315,8 @@ void buildMov(instNode_t *node, varList_t *varList, error_t *errData){ node->isInter = false; node->inputReg = RG_0; - sprintf(buffer, "%d", varId); - node->arg0 = (char *)malloc(sizeof(char) * 8); - strcpy(node->arg0, buffer); + node->arg0 = malloc(IMMEDIATE_VAL_SIZE+1 * sizeof(char)); + sprintf(node->arg0, "%d", varId); node->arg1 = NULL; node->isBuilt = true; @@ -261,10 +338,9 @@ void buildGoto(instNode_t *node, labelList_t *labelList, error_t *errData){ } // change arg0 to id - char buffer[8]; - sprintf(buffer, "%d", labId); - node->arg0 = (char *)malloc(sizeof(char) * 8); - strcpy(node->arg0, buffer); + node->arg0 = malloc(IMMEDIATE_VAL_SIZE+1 * sizeof(char)); + sprintf(node->arg0, "%d", labId); + node->arg1 = NULL; node->isBuilt = true; return; @@ -279,10 +355,9 @@ void buildCall(instNode_t *node, labelList_t *labelList, error_t *errData){ } // change arg0 to id - char buffer[8]; - sprintf(buffer, "%d", labId); - node->arg0 = (char *)malloc(sizeof(char) * 8); - strcpy(node->arg0, buffer); + node->arg0 = malloc(IMMEDIATE_VAL_SIZE+1 * sizeof(char)); + sprintf(node->arg0, "%d", labId); + node->arg1 = NULL; node->isBuilt = true; @@ -335,10 +410,10 @@ void buildOperation(instNode_t *node, varList_t *varList, error_t *errData){ node->op = OP_MOV_F_VAR; node->isInter = false; node->inputReg = RG_0; - char buffer[8]; - sprintf(buffer, "%d", varId); - node->arg0 = (char *)malloc(sizeof(char) * 8); - strcpy(node->arg0, buffer); + + node->arg0 = malloc(IMMEDIATE_VAL_SIZE+1 * sizeof(char)); + sprintf(node->arg0, "%d", varId); + node->arg1 = NULL; node->isBuilt = true; node->next = newNode; @@ -355,31 +430,6 @@ void buildOperation(instNode_t *node, varList_t *varList, error_t *errData){ return; } -bool isUnsignedInt(char *str){ - for(size_t i = 0; i < strlen(str); i++){ - if(str[i] < '0' || str[i] > '9'){ - return false; - } - } - return true; -} - -bool isFromReg(char *str){ - if(strlen(str) != 3){ - return false; - } - if(str[0] != 'R' && str[0] != 'r'){ - return false; - } - if(str[1] < 'G' || str[1] > 'g'){ - return false; - } - if(str[2] < '0' || str[2] > '7'){ - return false; - } - return true; -} - enum regKind getRegKind(char *str) { if (str == NULL || str[0] != 'r' || str[1] != 'g' || str[2] < '0' || str[2] > '7' || str[3] != '\0') { fprintf(stderr, "Error: invalid register format\n"); @@ -407,4 +457,14 @@ enum regKind getRegKind(char *str) { fprintf(stderr, "Error: unknown register\n"); exit(EXIT_FAILURE); } +} + +int getVarDatasize(char *str){ + // check if the string is a number + if(isUnsignedInt(str)){ + return 1; + } + else{ + return (int)strlen(str); + } } \ No newline at end of file diff --git a/src/builder.h b/src/builder.h index 213b5c9..5224d16 100644 --- a/src/builder.h +++ b/src/builder.h @@ -80,27 +80,22 @@ void buildCall(instNode_t *node, labelList_t *labelList, error_t *errData); void buildOperation(instNode_t *node, varList_t *varList, error_t *errData); /* - Check if the string is an unsigned int - params: - str: string to be checked -*/ -bool isUnsignedInt(char *str); - -/* - Check if the string is a register + Get the register kind params: str: string to be checked + returns: + regKind: kind of the register */ -bool isFromReg(char *str); +enum regKind getRegKind(char *str); /* - Get the register kind + Get the data size of a variable in bytes params: str: string to be checked returns: - regKind: kind of the register + int: data size */ -enum regKind getRegKind(char *str); +int getVarDatasize(char *str); #ifdef __cplusplus } diff --git a/src/stringPlus.c b/src/stringPlus.c index d24d6d7..4dedaaf 100644 --- a/src/stringPlus.c +++ b/src/stringPlus.c @@ -87,12 +87,12 @@ char *cleanString(char *str) { size_t end = size - 1; // Find the index of the first non-space, non-newline character - while (start < size && (str[start] == ' ' || str[start] == '(' || str[start] == '\n')) { + while (start < size && (str[start] == ' ' || str[start] == '(' || str[start] == '\n' || str[start] == '\"')){ start++; } // Find the index of the last non-space, non-newline character - while (end > 0 && (str[end] == ' ' || str[end] == '\n' || str[end] == ')')) { + while (end > 0 && (str[end] == ' ' || str[end] == '\n' || str[end] == ')' || str[end] == '\"')) { end--; } @@ -111,4 +111,29 @@ char *cleanString(char *str) { cleaned[cleanedSize] = '\0'; // Null-terminate the cleaned string return cleaned; -} \ No newline at end of file +} + +bool isUnsignedInt(char *str){ + for(size_t i = 0; i < strlen(str); i++){ + if(str[i] < '0' || str[i] > '9'){ + return false; + } + } + return true; +} + +bool isFromReg(char *str){ + if(strlen(str) != 3){ + return false; + } + if(str[0] != 'R' && str[0] != 'r'){ + return false; + } + if(str[1] < 'G' || str[1] > 'g'){ + return false; + } + if(str[2] < '0' || str[2] > '7'){ + return false; + } + return true; +} diff --git a/src/stringPlus.h b/src/stringPlus.h index 5319e4a..6bde731 100644 --- a/src/stringPlus.h +++ b/src/stringPlus.h @@ -1,3 +1,5 @@ +#include + /* Convert a string to binary params: @@ -50,4 +52,18 @@ char *strToString(char *arg); returns: char*: cleaned string */ -char *cleanString(char *str); \ No newline at end of file +char *cleanString(char *str); + +/* + Check if the string is an unsigned int + params: + str: string to be checked +*/ +bool isUnsignedInt(char *str); + +/* + Check if the string is a register + params: + str: string to be checked +*/ +bool isFromReg(char *str); From 63b636a90bafa8545457d638a548ba4f92c8144c Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Fri, 16 Feb 2024 14:02:04 +0100 Subject: [PATCH 17/22] Start unit test for parser - Unit test for parsing - Update several parser's functions as correction --- src/2at2.c | 19 ++---- src/ast.c | 27 ++++++++ src/ast.h | 21 ++++++ src/parser.c | 33 +++++----- test/test.cc | 179 +++++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 243 insertions(+), 36 deletions(-) diff --git a/src/2at2.c b/src/2at2.c index 5a6019e..33924e5 100644 --- a/src/2at2.c +++ b/src/2at2.c @@ -35,24 +35,13 @@ int main(int argc, char *argv[]) { // ---------- Init data ---------- // Init variables list struct - varList_t *varList = malloc(sizeof(varList_t)); - varList->size = 10; - varList->list = malloc(sizeof(var_t) * varList->size); - // Init variables list - for(size_t i = 0; i < varList->size; i++){ - varList->list[i].name = NULL; - } + varList_t *varList = createEmptyVarList(); // Init labels list struct - labelList_t *labelList = malloc(sizeof(labelList_t)); - labelList->size = 10; - labelList->list = malloc(sizeof(label_t) * labelList->size); - for(size_t i = 0; i < labelList->size; i++){ - labelList->list[i].name = NULL; - } + labelList_t *labelList = createEmptyLabelList(); + // Init instructions list struct - instList_t *instList = malloc(sizeof(instList_t)); - instList->head = NULL; + instList_t *instList = createEmptyInstList(); fprintf(stderr, "[\t10%%\t] Data initialized successfully\n"); diff --git a/src/ast.c b/src/ast.c index df79211..72b7d1b 100644 --- a/src/ast.c +++ b/src/ast.c @@ -52,6 +52,17 @@ char *getIntCode(enum interruptKind kind){ } } +varList_t *createEmptyVarList(){ + // Init variables list struct + varList_t *varList = malloc(sizeof(varList_t)); + varList->size = 10; + varList->list = malloc(sizeof(var_t) * varList->size); + // Init variables list + for(size_t i = 0; i < varList->size; i++){ + varList->list[i].name = NULL; + } +} + bool addVar(varList_t *varList, char *name, char *value){ // check if the variable already exists for(size_t i = 0; i < varList->size; i++){ @@ -105,6 +116,12 @@ int isVarExist(varList_t *varList, char *name){ return -1; } +instList_t *createEmptyInstList(){ + instList_t *instList = malloc(sizeof(instList_t)); + instList->head = NULL; + return instList; +} + instNode_t *copyInstNode(instNode_t *node){ instNode_t *newNode = (instNode_t *)malloc(sizeof(instNode_t)); if(newNode == NULL){ @@ -140,6 +157,16 @@ instNode_t *createEmptyInstNode(){ return newNode; } +labelList_t *createEmptyLabelList(){ + labelList_t *labelList = malloc(sizeof(labelList_t)); + labelList->size = 10; + labelList->list = malloc(sizeof(label_t) * labelList->size); + for(size_t i = 0; i < labelList->size; i++){ + labelList->list[i].name = NULL; + } + return labelList; +} + int addLabel(labelList_t *labelList, char *name, long nodeId){ // check if the label already exists for(size_t i = 0; i < labelList->size; i++){ diff --git a/src/ast.h b/src/ast.h index 8129878..bd98f7e 100644 --- a/src/ast.h +++ b/src/ast.h @@ -123,6 +123,13 @@ typedef struct labelList{ */ char *getIntCode(enum interruptKind kind); +/* + Create an empty variable list + returns: + varList_t: pointer to the variable list +*/ +varList_t *createEmptyVarList(); + /* Add a variable to the list params: @@ -153,6 +160,13 @@ int isVarExist(varList_t *varList, char *name); */ instNode_t *copyInstNode(instNode_t *node); +/* + Create an empty instruction list + returns: + instList_t: pointer to the instruction list +*/ +instList_t *createEmptyInstList(); + /* Create an empty instruction node returns: @@ -160,6 +174,13 @@ instNode_t *copyInstNode(instNode_t *node); */ instNode_t *createEmptyInstNode(); +/* + Create an empty label list + returns: + labelList_t: pointer to the label list +*/ +labelList_t *createEmptyLabelList(); + /* Add a label to the list params: diff --git a/src/parser.c b/src/parser.c index ce05d85..a7ba380 100644 --- a/src/parser.c +++ b/src/parser.c @@ -11,6 +11,7 @@ #include "parser.h" #define LINE_MAX_SIZE 64 +#define MAX_ARGS 2 const char* errorFile= "errors.log"; @@ -60,8 +61,7 @@ void flagsSet(char *flag, flags_t *flags){ flags->verbose = true; } else{ - fprintf(stderr, "Invalid flag\n Try 'iat2 --help' for more information\n"); - exit(EXIT_FAILURE); + // TODO: throw error } } @@ -116,13 +116,9 @@ instNode_t *parseLine(char *line, long nodeId, long lineNb, error_t *errData){ return NULL; } - instNode_t *newNode = malloc(sizeof(instNode_t)); + instNode_t *newNode = createEmptyInstNode(); newNode->id = nodeId; newNode->lineNb = lineNb; - newNode->isInter = false; - newNode->isBuilt = false; - - newNode->next = NULL; // Get the instruction char *inst = getInst(line); @@ -130,6 +126,7 @@ instNode_t *parseLine(char *line, long nodeId, long lineNb, error_t *errData){ // Get the arguments char **args = getInstArgs(line); + // Set arguments setArgs(newNode, args); @@ -371,35 +368,41 @@ char *getInst(char *line) { } char **getInstArgs(char *line) { - char **args = malloc(2 * sizeof(char *)); + char **args = malloc(MAX_ARGS * sizeof(char *)); if (!args) { fprintf(stderr, "Memory allocation error\n"); exit(EXIT_FAILURE); } + args[0] = NULL; + args[1] = NULL; - // Remove the instruction name char *token = strtok(line, " "); if (!token) { + // TODO: throw error fprintf(stderr, "Invalid input format\n"); free(args); // Free allocated memory before exit - exit(EXIT_FAILURE); + } - // Get the arguments - for (int i = 0; i < 2; i++) { + for (int i = 0; i < MAX_ARGS; i++) { token = strtok(NULL, ","); if (!token) { + if (i == 0) { + // TODO: throw error + fprintf(stderr, "Invalid input format: missing argument\n"); + return args; + } args[i] = NULL; } else { - // Allocate memory for the argument and copy it args[i] = malloc(strlen(token) + 1); if (!args[i]) { + // TODO: throw error fprintf(stderr, "Memory allocation error\n"); + // Free previously allocated memory for (int j = 0; j < i; j++) { - free(args[j]); // Free previously allocated memory + free(args[j]); } free(args); // Free args array - exit(EXIT_FAILURE); } strcpy(args[i], cleanString(token)); } diff --git a/test/test.cc b/test/test.cc index 0267a9e..dac840d 100644 --- a/test/test.cc +++ b/test/test.cc @@ -11,18 +11,185 @@ #include "parser.h" #include "builder.h" -TEST(ParseArgs, SetsHelpFlagWhenHelpOptionIsProvided) { - // Arrange - char *argv[] = {"test", "-h"}; +char * fileName = const_cast("test.cc"); + +/* + * parseArgs + */ + +TEST(parseArgs, help) { + error_t *errData = initErrorFile("errors.log", fileName); + // Test help flag + char *argv[] = {const_cast("test"), const_cast("-h")}; + int argc = sizeof(argv) / sizeof(argv[0]); + flags_t flags = parseArgs(argc, argv); + ASSERT_TRUE(flags.help); +} +TEST(parseArgs, version) { + error_t *errData = initErrorFile("errors.log", fileName); + // Test version flag + char *argv[] = {const_cast("test"), const_cast("-v")}; int argc = sizeof(argv) / sizeof(argv[0]); + flags_t flags = parseArgs(argc, argv); + ASSERT_TRUE(flags.version); +} +TEST(parseArgs, verbose) { + error_t *errData = initErrorFile("errors.log", fileName); + // Test verbose flag + char *argv[] = {const_cast("test"), const_cast("-V")}; + int argc = sizeof(argv) / sizeof(argv[0]); + flags_t flags = parseArgs(argc, argv); + ASSERT_TRUE(flags.verbose); +} +TEST(parseArgs, debug) { + error_t *errData = initErrorFile("errors.log", fileName); + // Test debug flag + char *argv[] = {const_cast("test"), const_cast("-d")}; + int argc = sizeof(argv) / sizeof(argv[0]); + flags_t flags = parseArgs(argc, argv); + ASSERT_TRUE(flags.debug); +} - // Act +TEST(parseArgs, invalidFlag) { + error_t *errData = initErrorFile("errors.log", fileName); + // Test false argv + char *argv[] = {const_cast("test"), const_cast("-a")}; + int argc = sizeof(argv) / sizeof(argv[0]); flags_t flags = parseArgs(argc, argv); + ASSERT_FALSE(flags.help); +} - // Assert - ASSERT_TRUE(flags.help); +/* + * get isntruction + */ + +TEST(getInst, normal) { + char *line = const_cast("add r1, r2, r3\n"); + + char *inst = getInst(line); + ASSERT_STREQ(inst, "add"); } +TEST(getInst, noInst) { + char *line = const_cast("r1, r2, r3\n"); + + char *inst = getInst(line); + ASSERT_STREQ(inst, "r1,"); +} + +/* + * get unstruction arguments + */ + +TEST(getArgs, normal) { + // Test input line + std::string line = "add r1, r2"; + + // Convert the string to a C-style string + char *c_line = const_cast(line.c_str()); + + // Call the function under test + char **args = getInstArgs(c_line); + + // Check each argument + ASSERT_STREQ(args[0], "r1"); + ASSERT_STREQ(args[1], "r2"); + + // Free dynamically allocated memory + for (int i = 0; i < 2; ++i) { + delete[] args[i]; + } + delete[] args; +} + +TEST(getArgs, noComma) { + // Test input line + std::string line = "add r1 r2"; + + // Convert the string to a C-style string + char *c_line = const_cast(line.c_str()); + + // Call the function under test + char **args = getInstArgs(c_line); + + // Check each argument + ASSERT_STREQ(args[0], "r1 r2"); + ASSERT_TRUE(args[1] == NULL); + + // Free dynamically allocated memory + for (int i = 0; i < 2; ++i) { + delete[] args[i]; + } + delete[] args; +} + +TEST(getArgs, noArgs) { + // Test input line + std::string line = "ret\n"; + + // Convert the string to a C-style string + char *c_line = const_cast(line.c_str()); + + // Call the function under test + char **args = getInstArgs(c_line); + + // Check each argument + ASSERT_TRUE(args[0] == NULL); + ASSERT_TRUE(args[1] == NULL); + + // Free dynamically allocated memory + for (int i = 0; i < 2; ++i) { + delete[] args[i]; + } + delete[] args; +} + +/* + * parse line + */ + +TEST(parseLine, normal) { + error_t *errData = initErrorFile("errors.log", fileName); + + char* line = const_cast("add rg1, 7"); + + instNode *node = parseLine(line, 1, 1, errData); + ASSERT_TRUE(node->id == 1); + ASSERT_TRUE(node->lineNb == 1); + ASSERT_TRUE(node->op == OP_ADD); + ASSERT_TRUE(node->inputReg == RG_1); + ASSERT_FALSE(node->isInter); + ASSERT_STREQ(node->arg0, NULL); + ASSERT_STREQ(node->arg1, "7"); +} + +// TODO: Do for all instructions +TEST(parseLine, interrupt){ + error_t *errData = initErrorFile("errors.log", fileName); + + char* line = const_cast("draw \"test\"\n"); + + instNode *node = parseLine(line, 1, 1, errData); + ASSERT_TRUE(node->id == 1); + ASSERT_TRUE(node->lineNb == 1); + ASSERT_TRUE(node->op == OP_INT); + ASSERT_TRUE(node->isInter); + ASSERT_TRUE(node->inter == INT_DRAW); + ASSERT_STREQ(node->arg0, NULL); + ASSERT_STREQ(node->arg1, "test"); +} +TEST(parseLine, opWithouArgs) { + error_t *errData = initErrorFile("errors.log", fileName); + + char* line = const_cast("ret\n"); + + instNode *node = parseLine(line, 1, 1, errData); + ASSERT_TRUE(node->id == 1); + ASSERT_TRUE(node->lineNb == 1); + ASSERT_TRUE(node->op == OP_RET); + ASSERT_TRUE(node->arg0 == NULL); + ASSERT_TRUE(node->arg1 == NULL); +} int main(int argc, char *argv[]) { ::testing::InitGoogleTest(&argc, argv); From bd3afcc808d1a14e2325f342c399bcaf47531be3 Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Sun, 18 Feb 2024 18:46:02 +0100 Subject: [PATCH 18/22] Update parsing tests Update for parsing tests and correction for several functions in parser.c and ast.c --- CMakeLists.txt | 4 +-- src/ast.c | 8 ++++-- src/ast.h | 10 ++++++- src/parser.c | 18 ++++++++---- test/test.cc | 74 ++++++++++++++------------------------------------ 5 files changed, 50 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d5f72b..ebc1971 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ set(CMAKE_C_COMPILER "gcc") project( Interpreter-AT2 - VERSION 0.0.4 + VERSION 0.1.0 LANGUAGES CXX C ) @@ -27,8 +27,8 @@ add_executable(tests src/debug.c src/error.c src/binExporter.c - src/ast.c test/test.cc + src/ast.c googletest/googletest/src/gtest-all.cc ) diff --git a/src/ast.c b/src/ast.c index 72b7d1b..6b58090 100644 --- a/src/ast.c +++ b/src/ast.c @@ -61,6 +61,7 @@ varList_t *createEmptyVarList(){ for(size_t i = 0; i < varList->size; i++){ varList->list[i].name = NULL; } + return varList; } bool addVar(varList_t *varList, char *name, char *value){ @@ -140,10 +141,10 @@ instNode_t *copyInstNode(instNode_t *node){ return newNode; } -instNode_t *createEmptyInstNode(){ +instNode_t *createEmptyInstNode() { instNode_t *newNode = (instNode_t *)malloc(sizeof(instNode_t)); - if(newNode == NULL){ - // TODO: thorw memory alloc error + if (newNode == NULL) { + fprintf(stderr, "Memory allocation error\n"); exit(EXIT_FAILURE); } newNode->id = -1; @@ -157,6 +158,7 @@ instNode_t *createEmptyInstNode(){ return newNode; } + labelList_t *createEmptyLabelList(){ labelList_t *labelList = malloc(sizeof(labelList_t)); labelList->size = 10; diff --git a/src/ast.h b/src/ast.h index bd98f7e..4bae478 100644 --- a/src/ast.h +++ b/src/ast.h @@ -6,6 +6,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + // Operation types enum opKind{ OP_MOV, @@ -200,4 +204,8 @@ int addLabel(labelList_t *labelList, char *name, long nodeId); returns: int: id of the label or -1 if it does not exist */ -int isLabelExist(labelList_t *labelList, char *name); \ No newline at end of file +int isLabelExist(labelList_t *labelList, char *name); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/parser.c b/src/parser.c index a7ba380..a1be356 100644 --- a/src/parser.c +++ b/src/parser.c @@ -369,15 +369,23 @@ char *getInst(char *line) { char **getInstArgs(char *line) { char **args = malloc(MAX_ARGS * sizeof(char *)); + // init args to NULL + for (int i = 0; i < MAX_ARGS; i++) { + args[i] = NULL; + } if (!args) { fprintf(stderr, "Memory allocation error\n"); exit(EXIT_FAILURE); } - args[0] = NULL; - args[1] = NULL; - - char *token = strtok(line, " "); - if (!token) { + char *buffer = malloc((strlen(line) + 1) * sizeof(char)); + if (!buffer) { + fprintf(stderr, "Memory allocation error\n"); + exit(EXIT_FAILURE); + } + + strcpy(buffer, line); + char *token = strtok(buffer, " "); + if (token == NULL) { // TODO: throw error fprintf(stderr, "Invalid input format\n"); free(args); // Free allocated memory before exit diff --git a/test/test.cc b/test/test.cc index dac840d..9acf82a 100644 --- a/test/test.cc +++ b/test/test.cc @@ -8,8 +8,10 @@ #include #include "gtest/gtest.h" +#include "ast.h" #include "parser.h" #include "builder.h" +#include "error.h" char * fileName = const_cast("test.cc"); @@ -83,13 +85,9 @@ TEST(getInst, noInst) { TEST(getArgs, normal) { // Test input line - std::string line = "add r1, r2"; - - // Convert the string to a C-style string - char *c_line = const_cast(line.c_str()); - + char *line = const_cast("add r1, r2"); // Call the function under test - char **args = getInstArgs(c_line); + char **args = getInstArgs(line); // Check each argument ASSERT_STREQ(args[0], "r1"); @@ -104,13 +102,10 @@ TEST(getArgs, normal) { TEST(getArgs, noComma) { // Test input line - std::string line = "add r1 r2"; - - // Convert the string to a C-style string - char *c_line = const_cast(line.c_str()); + char *line = const_cast("add r1 r2"); // Call the function under test - char **args = getInstArgs(c_line); + char **args = getInstArgs(line); // Check each argument ASSERT_STREQ(args[0], "r1 r2"); @@ -125,13 +120,13 @@ TEST(getArgs, noComma) { TEST(getArgs, noArgs) { // Test input line - std::string line = "ret\n"; - - // Convert the string to a C-style string - char *c_line = const_cast(line.c_str()); + char *line = const_cast("ret\n"); // Call the function under test - char **args = getInstArgs(c_line); + char **args = getInstArgs(line); + + std::cout << args[0] << std::endl; + std::cout << args[1] << std::endl; // Check each argument ASSERT_TRUE(args[0] == NULL); @@ -145,51 +140,24 @@ TEST(getArgs, noArgs) { } /* - * parse line + * is op */ -TEST(parseLine, normal) { - error_t *errData = initErrorFile("errors.log", fileName); +TEST(isOp, add) { + error_t *errData = initErrorFile("errors.log", fileName); + char *inst = const_cast("add"); - char* line = const_cast("add rg1, 7"); - - instNode *node = parseLine(line, 1, 1, errData); - ASSERT_TRUE(node->id == 1); - ASSERT_TRUE(node->lineNb == 1); - ASSERT_TRUE(node->op == OP_ADD); - ASSERT_TRUE(node->inputReg == RG_1); - ASSERT_FALSE(node->isInter); - ASSERT_STREQ(node->arg0, NULL); - ASSERT_STREQ(node->arg1, "7"); + instNode_t *newNode = createEmptyInstNode(); + bool isThatKind = isOp(inst, newNode, errData); + + ASSERT_TRUE(isThatKind); + ASSERT_TRUE(newNode->op == OP_ADD); } // TODO: Do for all instructions -TEST(parseLine, interrupt){ - error_t *errData = initErrorFile("errors.log", fileName); - char* line = const_cast("draw \"test\"\n"); - - instNode *node = parseLine(line, 1, 1, errData); - ASSERT_TRUE(node->id == 1); - ASSERT_TRUE(node->lineNb == 1); - ASSERT_TRUE(node->op == OP_INT); - ASSERT_TRUE(node->isInter); - ASSERT_TRUE(node->inter == INT_DRAW); - ASSERT_STREQ(node->arg0, NULL); - ASSERT_STREQ(node->arg1, "test"); -} -TEST(parseLine, opWithouArgs) { - error_t *errData = initErrorFile("errors.log", fileName); +// TODO: test build instruction - char* line = const_cast("ret\n"); - - instNode *node = parseLine(line, 1, 1, errData); - ASSERT_TRUE(node->id == 1); - ASSERT_TRUE(node->lineNb == 1); - ASSERT_TRUE(node->op == OP_RET); - ASSERT_TRUE(node->arg0 == NULL); - ASSERT_TRUE(node->arg1 == NULL); -} int main(int argc, char *argv[]) { ::testing::InitGoogleTest(&argc, argv); From 4b70492d27d2fcc93ca53e4ed7616a34cd253b22 Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Sun, 18 Feb 2024 18:49:24 +0100 Subject: [PATCH 19/22] Correct version to 0.1.1 --- CMakeLists.txt | 2 +- src/2at2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ebc1971..bc7d59d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ set(CMAKE_C_COMPILER "gcc") project( Interpreter-AT2 - VERSION 0.1.0 + VERSION 0.1.1 LANGUAGES CXX C ) diff --git a/src/2at2.c b/src/2at2.c index 33924e5..89387c0 100644 --- a/src/2at2.c +++ b/src/2at2.c @@ -12,7 +12,7 @@ #include "debug.h" #include "error.h" -#define VERSION "0.0.5" +#define VERSION "0.1.1" int main(int argc, char *argv[]) { // Init error data history From 8798c9db1d2a98d84f3df3425d965b48112e0c8f Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:38:50 +0100 Subject: [PATCH 20/22] Update debug.c Add errno missing library --- src/debug.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/debug.c b/src/debug.c index c1bd4ac..8c2836f 100644 --- a/src/debug.c +++ b/src/debug.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "debug.h" From e4a0d30e9127e2916d59f302c592cb5a5f9685c9 Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:40:57 +0100 Subject: [PATCH 21/22] Update error.c Include errno missing library --- src/error.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/error.c b/src/error.c index 508cac4..f15342a 100644 --- a/src/error.c +++ b/src/error.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "error.h" From 3f45b6ce158f8174d45d5d98da357da79367744f Mon Sep 17 00:00:00 2001 From: Maxime CARON <145995231+MaximeAlgosup@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:56:28 +0100 Subject: [PATCH 22/22] Change error_t type to asm_error_t Change error_t type to asm_error_t type to avoid conflict with already existing types --- src/2at2.c | 2 +- src/builder.c | 16 ++++++++-------- src/builder.h | 16 ++++++++-------- src/error.c | 14 +++++++------- src/error.h | 14 +++++++------- src/parser.c | 8 ++++---- src/parser.h | 8 ++++---- test/test.cc | 12 ++++++------ 8 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/2at2.c b/src/2at2.c index 89387c0..768045f 100644 --- a/src/2at2.c +++ b/src/2at2.c @@ -16,7 +16,7 @@ int main(int argc, char *argv[]) { // Init error data history - error_t *errData = initErrorFile("errors.log", argv[1]); + asm_error_t *errData = initErrorFile("errors.log", argv[1]); // ---------- Parse arguments ---------- diff --git a/src/builder.c b/src/builder.c index 4841f83..eba735d 100644 --- a/src/builder.c +++ b/src/builder.c @@ -14,7 +14,7 @@ #define IMMEDIATE_VAL_SIZE 8 -void buildProgram(instList_t *nodeList, varList_t *varList, labelList_t *labeList, error_t *errData) { +void buildProgram(instList_t *nodeList, varList_t *varList, labelList_t *labeList, asm_error_t *errData) { instNode_t *node = nodeList->head; while(node != NULL){ buildNode(node, varList, labeList, errData); @@ -25,7 +25,7 @@ void buildProgram(instList_t *nodeList, varList_t *varList, labelList_t *labeLis } } -void buildNode(instNode_t *node, varList_t *varList, labelList_t *labeList, error_t *errData) { +void buildNode(instNode_t *node, varList_t *varList, labelList_t *labeList, asm_error_t *errData) { switch(node->op){ case OP_MOV: buildMov(node, varList, errData); @@ -53,7 +53,7 @@ void buildNode(instNode_t *node, varList_t *varList, labelList_t *labeList, erro } } -void buildVar(instNode_t *node, varList_t *varList, error_t *errData){ +void buildVar(instNode_t *node, varList_t *varList, asm_error_t *errData){ // copy variable value char *varData = (char *)malloc(sizeof(char) * (strlen(node->arg1) + 1)); strcpy(varData, node->arg1); @@ -144,7 +144,7 @@ void buildVar(instNode_t *node, varList_t *varList, error_t *errData){ } } -void buildLabel(instNode_t *node, labelList_t *labelList, error_t *errData){ +void buildLabel(instNode_t *node, labelList_t *labelList, asm_error_t *errData){ // try to add the label to the list int labId = addLabel(labelList, node->arg0, node->id); if(labId == -1){ @@ -158,7 +158,7 @@ void buildLabel(instNode_t *node, labelList_t *labelList, error_t *errData){ node->isBuilt = true; } -void buildMov(instNode_t *node, varList_t *varList, error_t *errData){ +void buildMov(instNode_t *node, varList_t *varList, asm_error_t *errData){ // check if it's mov to reg if(node->arg0 == NULL){ // check if it's val -> reg @@ -329,7 +329,7 @@ void buildMov(instNode_t *node, varList_t *varList, error_t *errData){ return; } -void buildGoto(instNode_t *node, labelList_t *labelList, error_t *errData){ +void buildGoto(instNode_t *node, labelList_t *labelList, asm_error_t *errData){ // check if the label is in the list int labId = isLabelExist(labelList, node->arg0); if(labId == -1){ @@ -346,7 +346,7 @@ void buildGoto(instNode_t *node, labelList_t *labelList, error_t *errData){ return; } -void buildCall(instNode_t *node, labelList_t *labelList, error_t *errData){ +void buildCall(instNode_t *node, labelList_t *labelList, asm_error_t *errData){ // check if the label is in the list int labId = isLabelExist(labelList, node->arg0); if(labId == -1){ @@ -364,7 +364,7 @@ void buildCall(instNode_t *node, labelList_t *labelList, error_t *errData){ return; } -void buildOperation(instNode_t *node, varList_t *varList, error_t *errData){ +void buildOperation(instNode_t *node, varList_t *varList, asm_error_t *errData){ // check if the second argument is an unsigned int if(node->arg1 != NULL && isUnsignedInt(node->arg1)){ // pass argument 1 to arg0 diff --git a/src/builder.h b/src/builder.h index 5224d16..a55eee8 100644 --- a/src/builder.h +++ b/src/builder.h @@ -13,7 +13,7 @@ extern "C" { labeList: pointer to the label list errData: pointer to the error struct */ -void buildProgram(instList_t *nodeList, varList_t *varList, labelList_t *labeList, error_t *errData); +void buildProgram(instList_t *nodeList, varList_t *varList, labelList_t *labeList, asm_error_t *errData); /* Build a node @@ -23,7 +23,7 @@ void buildProgram(instList_t *nodeList, varList_t *varList, labelList_t *labeLis labeList: pointer to the label list errData: pointer to the error struct */ -void buildNode(instNode_t *node, varList_t *varList, labelList_t *labeList, error_t *errData); +void buildNode(instNode_t *node, varList_t *varList, labelList_t *labeList, asm_error_t *errData); /* Build a variable @@ -32,7 +32,7 @@ void buildNode(instNode_t *node, varList_t *varList, labelList_t *labeList, erro varList: pointer to the variable list errData: pointer to the error struct */ -void buildVar(instNode_t *node, varList_t *varList, error_t *errData); +void buildVar(instNode_t *node, varList_t *varList, asm_error_t *errData); /* Build a label @@ -41,7 +41,7 @@ void buildVar(instNode_t *node, varList_t *varList, error_t *errData); labelList: pointer to the label list errData: pointer to the error struct */ -void buildLabel(instNode_t *node, labelList_t *labelList, error_t *errData); +void buildLabel(instNode_t *node, labelList_t *labelList, asm_error_t *errData); /* Build a mov instruction @@ -50,7 +50,7 @@ void buildLabel(instNode_t *node, labelList_t *labelList, error_t *errData); varList: pointer to the variable list errData: pointer to the error struct */ -void buildMov(instNode_t *node, varList_t *varList, error_t *errData); +void buildMov(instNode_t *node, varList_t *varList, asm_error_t *errData); /* Build a goto instruction @@ -59,7 +59,7 @@ void buildMov(instNode_t *node, varList_t *varList, error_t *errData); labelList: pointer to the label list errData: pointer to the error struct */ -void buildGoto(instNode_t *node, labelList_t *labelList, error_t *errData); +void buildGoto(instNode_t *node, labelList_t *labelList, asm_error_t *errData); /* Build a call instruction @@ -68,7 +68,7 @@ void buildGoto(instNode_t *node, labelList_t *labelList, error_t *errData); labelList: pointer to the label list errData: pointer to the error struct */ -void buildCall(instNode_t *node, labelList_t *labelList, error_t *errData); +void buildCall(instNode_t *node, labelList_t *labelList, asm_error_t *errData); /* Build an operation (add, xor, etc.) @@ -77,7 +77,7 @@ void buildCall(instNode_t *node, labelList_t *labelList, error_t *errData); varList: pointer to the variable list errData: pointer to the error struct */ -void buildOperation(instNode_t *node, varList_t *varList, error_t *errData); +void buildOperation(instNode_t *node, varList_t *varList, asm_error_t *errData); /* Get the register kind diff --git a/src/error.c b/src/error.c index f15342a..18036de 100644 --- a/src/error.c +++ b/src/error.c @@ -11,8 +11,8 @@ #include "error.h" -error_t *initErrorFile(const char* out, char *inputFile){ - error_t *errData = malloc(sizeof(error_t)); +asm_error_t *initErrorFile(const char* out, char *inputFile){ + asm_error_t *errData = malloc(sizeof(asm_error_t)); errData->errors = 0; errData->inputFile = inputFile; if(out != NULL){ @@ -27,7 +27,7 @@ error_t *initErrorFile(const char* out, char *inputFile){ return errData; } -void errorInstruction(char* inst, instNode_t *node, const char* out, error_t *errData){ +void errorInstruction(char* inst, instNode_t *node, const char* out, asm_error_t *errData){ ++ errData->errors; fprintf(stderr, "Error: syntax error\n"); fprintf(stderr, "Details: %s instruction is not recognized\n", inst); @@ -54,7 +54,7 @@ void errorInstruction(char* inst, instNode_t *node, const char* out, error_t *er } } -void errorLineSize(long lineNb, const char* out, error_t *errData){ +void errorLineSize(long lineNb, const char* out, asm_error_t *errData){ ++ errData->errors; fprintf(stderr, "Error: syntax error\n"); fprintf(stderr, "Details: line must to be under 64 characters\n"); @@ -82,12 +82,12 @@ void errorLineSize(long lineNb, const char* out, error_t *errData){ } -void printErrorSummary(error_t *errData){ +void printErrorSummary(asm_error_t *errData){ fprintf(stderr, "Error summary:\n"); fprintf(stderr, "Total errors: %ld\n", errData->errors); } -void errorfnf(char* filename, const char* out, error_t *errData){ +void errorfnf(char* filename, const char* out, asm_error_t *errData){ ++ errData->errors; fprintf(stderr, "Error: file not found\n"); fprintf(stderr, "Details: file %s not found\n", filename); @@ -114,7 +114,7 @@ void errorfnf(char* filename, const char* out, error_t *errData){ exit(EXIT_FAILURE); } -void errorInvalidExt(char* filename, const char* out, error_t *errData){ +void errorInvalidExt(char* filename, const char* out, asm_error_t *errData){ ++ errData->errors; fprintf(stderr, "Error: invalid file extension\n"); fprintf(stderr, "Details: file %s has an invalid extension\n", filename); diff --git a/src/error.h b/src/error.h index 5f41745..88572cb 100644 --- a/src/error.h +++ b/src/error.h @@ -9,7 +9,7 @@ extern "C" { typedef struct errorData{ long errors; char *inputFile; -} error_t; +} asm_error_t; /* Init error file @@ -19,7 +19,7 @@ typedef struct errorData{ returns: error_t: Error history */ -error_t *initErrorFile(const char* out, char *inputFile); +asm_error_t *initErrorFile(const char* out, char *inputFile); // ---------- Parsing/ Assembling errors ---------- @@ -31,7 +31,7 @@ error_t *initErrorFile(const char* out, char *inputFile); out: Target file (can be NULL) errData: Error history */ -void errorInstruction(char* inst, instNode_t *node, const char* out, error_t *errData); +void errorInstruction(char* inst, instNode_t *node, const char* out, asm_error_t *errData); /* Throw an error when the line size is too big @@ -40,7 +40,7 @@ void errorInstruction(char* inst, instNode_t *node, const char* out, error_t *er out: Target file (can be NULL) errData: Error history */ -void errorLineSize(long lineNb, const char* out, error_t *errData); +void errorLineSize(long lineNb, const char* out, asm_error_t *errData); /* Print error summary @@ -48,7 +48,7 @@ void errorLineSize(long lineNb, const char* out, error_t *errData); errData: Error history out: Target file (can be NULL) */ -void printErrorSummary(error_t *errData); +void printErrorSummary(asm_error_t *errData); // ---------- Fatal errors ---------- @@ -60,7 +60,7 @@ void printErrorSummary(error_t *errData); out: Target file (can be NULL) errData: Error history */ -void errorfnf(char* filename, const char* out, error_t *errData); +void errorfnf(char* filename, const char* out, asm_error_t *errData); /* Throw an error when the file extension is invalid @@ -69,7 +69,7 @@ void errorfnf(char* filename, const char* out, error_t *errData); out: Target file (can be NULL) errData: Error history */ -void errorInvalidExt(char* filename, const char* out, error_t *errData); +void errorInvalidExt(char* filename, const char* out, asm_error_t *errData); #ifdef __cplusplus } diff --git a/src/parser.c b/src/parser.c index a1be356..79b52aa 100644 --- a/src/parser.c +++ b/src/parser.c @@ -65,7 +65,7 @@ void flagsSet(char *flag, flags_t *flags){ } } -void parseFile(instList_t *nodeList, char *filename, error_t *errData){ +void parseFile(instList_t *nodeList, char *filename, asm_error_t *errData){ // check if the file exists FILE *file = fopen(filename, "r"); if(file == NULL){ @@ -110,7 +110,7 @@ void parseFile(instList_t *nodeList, char *filename, error_t *errData){ fclose(file); } -instNode_t *parseLine(char *line, long nodeId, long lineNb, error_t *errData){ +instNode_t *parseLine(char *line, long nodeId, long lineNb, asm_error_t *errData){ // check if the line is empty or a comment if(line[0] == '\n' || strncmp(cleanString(line), "//", 2) == 0){ return NULL; @@ -144,7 +144,7 @@ instNode_t *parseLine(char *line, long nodeId, long lineNb, error_t *errData){ return newNode; } -bool isOp(char *inst, instNode_t *newNode, error_t *errData){ +bool isOp(char *inst, instNode_t *newNode, asm_error_t *errData){ if(strcmp(inst, "mov") == 0){ newNode->op = OP_MOV; } @@ -472,7 +472,7 @@ enum regKind strToReg(char *arg) { } } -void checkAOPFile(char* fileName, error_t *errData) { +void checkAOPFile(char* fileName, asm_error_t *errData) { size_t size = strlen(fileName); //Check if the filename ends by ".aop" and contains at least 5 characters if (size < 5 || fileName[size - 4] != '.' || fileName[size - 3] != 'a' || fileName[size - 2] != 'o' || fileName[size - 1] != 'p') { diff --git a/src/parser.h b/src/parser.h index 20f203a..b36b685 100644 --- a/src/parser.h +++ b/src/parser.h @@ -40,7 +40,7 @@ void flagsSet(char *flag, flags_t *flags); nodeList: pointer to the instruction list filename: name of the file to be parsed */ -void parseFile(instList_t *nodeList, char *filename, error_t *errData); +void parseFile(instList_t *nodeList, char *filename, asm_error_t *errData); /* Parse a line and return an instruction node @@ -49,7 +49,7 @@ void parseFile(instList_t *nodeList, char *filename, error_t *errData); returns: instNode_t: instruction node */ -instNode_t *parseLine(char *line, long nodeId, long lineNb, error_t *errData); +instNode_t *parseLine(char *line, long nodeId, long lineNb, asm_error_t *errData); /* Read the line and check if it is an operation @@ -59,7 +59,7 @@ instNode_t *parseLine(char *line, long nodeId, long lineNb, error_t *errData); returns: bool: true if it is an operation */ -bool isOp(char *inst, instNode_t *newNode, error_t *errData); +bool isOp(char *inst, instNode_t *newNode, asm_error_t *errData); /* @@ -112,7 +112,7 @@ enum regKind strToReg(char *arg); filename: name of the file to check errData: error history */ -void checkAOPFile(char* fileName, error_t *errData); +void checkAOPFile(char* fileName, asm_error_t *errData); /* Checks if a line has more than 64 characters or not diff --git a/test/test.cc b/test/test.cc index 9acf82a..976b8c6 100644 --- a/test/test.cc +++ b/test/test.cc @@ -20,7 +20,7 @@ char * fileName = const_cast("test.cc"); */ TEST(parseArgs, help) { - error_t *errData = initErrorFile("errors.log", fileName); + asm_error_t *errData = initErrorFile("errors.log", fileName); // Test help flag char *argv[] = {const_cast("test"), const_cast("-h")}; int argc = sizeof(argv) / sizeof(argv[0]); @@ -28,7 +28,7 @@ TEST(parseArgs, help) { ASSERT_TRUE(flags.help); } TEST(parseArgs, version) { - error_t *errData = initErrorFile("errors.log", fileName); + asm_error_t *errData = initErrorFile("errors.log", fileName); // Test version flag char *argv[] = {const_cast("test"), const_cast("-v")}; int argc = sizeof(argv) / sizeof(argv[0]); @@ -36,7 +36,7 @@ TEST(parseArgs, version) { ASSERT_TRUE(flags.version); } TEST(parseArgs, verbose) { - error_t *errData = initErrorFile("errors.log", fileName); + asm_error_t *errData = initErrorFile("errors.log", fileName); // Test verbose flag char *argv[] = {const_cast("test"), const_cast("-V")}; int argc = sizeof(argv) / sizeof(argv[0]); @@ -44,7 +44,7 @@ TEST(parseArgs, verbose) { ASSERT_TRUE(flags.verbose); } TEST(parseArgs, debug) { - error_t *errData = initErrorFile("errors.log", fileName); + asm_error_t *errData = initErrorFile("errors.log", fileName); // Test debug flag char *argv[] = {const_cast("test"), const_cast("-d")}; int argc = sizeof(argv) / sizeof(argv[0]); @@ -53,7 +53,7 @@ TEST(parseArgs, debug) { } TEST(parseArgs, invalidFlag) { - error_t *errData = initErrorFile("errors.log", fileName); + asm_error_t *errData = initErrorFile("errors.log", fileName); // Test false argv char *argv[] = {const_cast("test"), const_cast("-a")}; int argc = sizeof(argv) / sizeof(argv[0]); @@ -144,7 +144,7 @@ TEST(getArgs, noArgs) { */ TEST(isOp, add) { - error_t *errData = initErrorFile("errors.log", fileName); + asm_error_t *errData = initErrorFile("errors.log", fileName); char *inst = const_cast("add"); instNode_t *newNode = createEmptyInstNode();