diff --git a/Codes_en_COREC/tests/test8.corec b/Codes_en_COREC/tests/test8.corec index c984638df609aea40f6bbd52b454cd46f3df51c5..5fc568f43b4bd7b9c1c293b2faa0cd17caf4bba7 100644 --- a/Codes_en_COREC/tests/test8.corec +++ b/Codes_en_COREC/tests/test8.corec @@ -1,6 +1,6 @@ // Conditions (if else ternaire..) -prog test5{ +prog test8{ def Main { Rec : { a = 10; diff --git a/Makefile b/Makefile index b4084eaa2b2c9bd356443e4ed705ec0ef0050128..0d4f308f974a838effee9648301b7d7555518c94 100644 --- a/Makefile +++ b/Makefile @@ -47,9 +47,17 @@ test_corec: all ./$(Compilateur_COREC) -tos < $(DIR_IN)/ProdMat.corec > $(DIR_OUT)/output6.asm ./$(Compilateur_COREC) -tos < $(DIR_IN)/SystTriang.corec > $(DIR_OUT)/output7.asm -test: allDev # Change to allDev if u want to display the lex tokens +test: all # Change to allDev if u want to display the lex tokens ./$(Compilateur_COREC) -tos -o $(DIR_OUT)/output$(num).asm < $(DIR_IN)/tests/test$(num).corec +testTo: all + @tmp=1; \ + while [ $$tmp -le $(num) ]; do \ + echo "running test $$tmp"; \ + ./$(Compilateur_COREC) -tos -o $(DIR_OUT)/output$$tmp.asm < $(DIR_IN)/tests/test$$tmp.corec; \ + tmp=$$(( $$tmp + 1 )); \ + done; + check: all valgrind --track-origins=yes -s ./$(Compilateur_COREC) -tos -o $(DIR_OUT)/output$(num).asm < $(DIR_IN)/tests/test$(num).corec diff --git a/README.md b/README.md index f4d9cd14cbdde078291d1d72650b5d0341400242..8c38f7524adbfc9e73d245b20dbb1a934376ce7b 100644 --- a/README.md +++ b/README.md @@ -31,37 +31,39 @@ sudo apt install bison sudo apt install default-jdk ``` - - MIPS simulator : - Download [MARS : MIPS java simulator on moodle unistra](https://moodle.unistra.fr/pluginfile.php/916605/mod_folder/content/0/Mars4_5.jar?forcedownload=1). + Download [MARS : MIPS java simulator on moodle unistra](https://moodle.unistra.fr/pluginfile.php/916605/mod_folder/content/0/Mars4_5.jar?forcedownload=1) and deplace it in the root of the project. ## Implemented Features -### Branch gencode_1 +### 1. branch test1 - Definition of local variable in the loc section of functions. **(TO DO :TRANSLATE IN MIPS but do not do here the float value)** - Affectation of integer value. **(TO DO :TRANSLATE IN MIPS but do not do here the float value)** - Print and printstr functions. **(TO DO :TRANSLATE IN MIPS)** -### Branch gencode_2 +### 2. branch test2 - Operation on variable (except arrays) -> (+,-,*,/). **(TO DO :TRANSLATE IN MIPS)** - Assignement operation on variable (except arrays) -> (+=,-=,*=,/=). **(TO DO :TRANSLATE IN MIPS)** -### Branch gencode_3-4 +### 3. branch test3 - Affectation and definition of local 1D array. **(TO DO :TRANSLATE IN MIPS)** +### 4. branch test4 - Operation with and on local 1D array. **(TO DO :TRANSLATE IN MIPS)** - print function works on array. **(TO DO :TRANSLATE IN MIPS)** - +### 5. branch test5 - float value as singleton array. **(TO DO :TRANSLATE IN MIPS)** - Cast integer in float if integer affectation to arrays or multiplication of a float and an integer. (Implicit) -- Multi dimensional array. **(TO DO :TRANSLATE IN MIPS)** - -## To Do -1. Translate intermediate code of the gencode_1 branch in mips. -2. Translate intermediate code of the gencode_2 branch in mips. -3. Translate intermediate code of the gencode_3 branch in mips. -4. Add to the symtable in the beginning of the programm COREC key words (def, prog, Loc, Rec, ...) to recognize without the lex. **Not sure** -5. Possibility to add an attribut to the symbol struc for temporary variable and variable to know what, the affectation value type is (Maybe with an enum). -This would provide a better +### 6. branch test6 +- Affectation multi dimensional array. **(TO DO :TRANSLATE IN MIPS)** +### 7. branch test7 +- Operations on multi dimensional array. **(TO DO :TRANSLATE IN MIPS)** +See in the [test report](./docs/tests.md) file the report on COREC tests features and error detection. +## To Do +1. Translate intermediate code of the testN branch in mips. +2. Add to the symtable in the beginning of the programm COREC key words (def, prog, Loc, Rec, ...) to recognize without the lex. **Not sure** +3. Possibility to add an attribut of type variable (INT, FLOAT, ARRAY) to the symbol structure for temporary variable and variable, to know what, the affectation value type is (Maybe with an enum). And when declare, the variable are set to none. +This would provide a better error detection of implicit cast. +4. Call of functions (verify arguments, etc) ## Makefile commands - `make` -> compile the source files @@ -74,6 +76,7 @@ This would provide a better For developpment (add tokens display in the lex file): - `test num=N` -> run project executable and test it on `Codes_en_COREC/tests/testN.corec` file. By default, `num` is equal to 1. +- `testTo num=N` -> run project executable and test it on every `Codes_en_COREC/tests/testX.corec` files where X <= N. By default, `num` is equal to 1. - `testErr num=N` -> run project executable and test it on `Codes_en_COREC/testsErrors/testNErr.corec` file. By default, `num` is equal to 1. The test should return an error by the compiler. - `check num=N` -> run project executable and check valgrind error on `Codes_en_COREC/tests/testN.corec` file. By default, `num` is equal to 1. - `checkErr num=N` -> run project executable and check valgrind error on `Codes_en_COREC/testsErrors/testNErr.corec` file. By default, `num` is equal to 1. The test should return an error by the compiler. diff --git a/corec.y b/corec.y index 73a514a4bfb53b0b5ab8cafdc6b0bfc07a540d23..daa750362ef8c7cfcf3fab07aba74660285447c6 100644 --- a/corec.y +++ b/corec.y @@ -5,12 +5,18 @@ extern void yyerror(const char * s); extern int yylex(); +// Store the current function struct symbol* symb_scope_function; +// Boolean if we are in a print call uint8_t isPrintCall = 0; + +// Store the dimension or indexes when we call or declare an array struct symbol** tabArrayDim = NULL; +// Store the length of the array unsigned int arraySizeLength; +// Function to call if we try to do exit(1). She frees the memory unlike exit() void exit_safely(){ if(tabArrayDim!=NULL){ free(tabArrayDim); @@ -122,8 +128,9 @@ void exit_safely(){ %% PROG : - prog ID left_curly_bracket LFONC - def Main + prog ID left_curly_bracket + LFONC // Definition of functions + def Main // Definition of the main function { struct symbol* id = symtable_get(SYMTAB,"Main",symb_scope_function); if ( id != NULL ){ @@ -142,6 +149,7 @@ LFONC : | %empty ; FONC : + // Declaration of a function ID def ID { struct symbol* id = symtable_get(SYMTAB,$2,symb_scope_function); @@ -150,7 +158,7 @@ FONC : exit_safely(); } id = symtable_put_name(SYMTAB,$2); - symb_scope_function = id; + symb_scope_function = id; // Change the current function gencode(CODE,DEF_FUNCTION,id,NULL,NULL); } @@ -166,9 +174,10 @@ LDECL : LDECL comma DECL | DECL ; -DECL : +DECL : // Section Loc declaration of arguments ID { + // Declare a variable without affectation struct symbol* id = symtable_get(SYMTAB,$1,symb_scope_function); if ( id != NULL ){ fprintf(stderr, "Error at line %u in function '%s': Variable '%s' is already declared.\n",lineNumber,symb_scope_function->u.name,$1); @@ -178,47 +187,52 @@ DECL : } | ID aff E { + // Declare a variable with affectation of value struct symbol* id = symtable_get(SYMTAB,$1,symb_scope_function); - if($3.ptr->kind == CONSTANT_FLOAT){ // Test if affectation a float to an array - if(id == NULL){ + + // Errors detection + if($3.ptr->kind == CONSTANT_FLOAT){ // Float = array + if(id == NULL){ // Test if the variable ID is already declare fprintf(stderr, "Error at line %u in function '%s': Try to declare variable '%s' as a float (array of dimension and lenght 1) but the size isn't declare. You may prefer to do this : '(%s,1), '%s'=%0.2f'.\n",lineNumber,symb_scope_function->u.name,$1,$1,$1,$3.ptr->u.value_float); exit_safely(); } - else if(id->kind != ARRAY){ + else if(id->kind != ARRAY){ // Test if the variable ID isn't an array (cannot affect an array value (float) to a non array variable) fprintf(stderr, "Error at line %u in function '%s': Try assigning at variable '%s' a float value (an array of dimension and lenght 1) but '%s' isn't an array.\n",lineNumber,symb_scope_function->u.name,$1,$1); exit_safely(); } } - else if($3.ptr->kind == ARRAY || $3.isEArray){ - if(id == NULL){ + else if($3.ptr->kind == ARRAY || $3.isEArray){ // Affectation is an array + if(id == NULL){ // Test if the variable ID is already declare fprintf(stderr, "Error at line %u in function '%s': Try to declare variable '%s' as an integer but the affectation value is an array.\n",lineNumber,symb_scope_function->u.name,$1); exit_safely(); } - else if(id->kind != ARRAY){ + else if(id->kind != ARRAY){ // Test if ID isn't an array fprintf(stderr, "Error at line %u in function '%s': Try assigning an array variable '%s' to a non array type variable '%s'.\n",lineNumber,symb_scope_function->u.name,$3.ptr->u.arr.name,$1); exit_safely(); } } else{ // Test if affectation value isn't a float and array - if (id != NULL){ + if (id != NULL){ // Test if the variable ID is already declare fprintf(stderr, "Error at line %u in function '%s': Variable '%s' is already declared.\n",lineNumber,symb_scope_function->u.name,$1); exit_safely(); } + // Create a local variable name = ID in the scope of the 'symb_scope_function' id = symtable_put_loc(SYMTAB,$1,symb_scope_function); } - if(id->kind == ARRAY){ // Handle if ID is an implicit array(array -> array[0]) + if(id->kind == ARRAY){ // Handle if ID is an implicit array(array -> array[0]) (ID is already declare, not by symtable_put_loc three instructions above) struct symbol* const_0 = symtable_const_int(SYMTAB,0); gencode(CODE,AFF_ARRAY,id,const_0,$3.ptr); } - else + else // ID isn't an array gencode(CODE,COPY,id,$3.ptr,NULL); } - | { + | // Array declaration + { // Initialization of variables, need to store the size of the different dimensions of the array arraySizeLength =3; - tabArrayDim = (struct symbol**)malloc(arraySizeLength*sizeof(struct symbol*)); + tabArrayDim = (struct symbol**)malloc(arraySizeLength*sizeof(struct symbol*)); // Should be free after utilization and sets to NULL if(tabArrayDim==NULL){ fprintf(stderr,"Memory allocation bug.\n"); exit_safely(); @@ -226,6 +240,7 @@ DECL : } ARRAY { + // Error detection struct symbol* id = symtable_get(SYMTAB,$2.name,symb_scope_function); if ( id != NULL ){ fprintf(stderr, "Error at line %u in function '%s': Array '%s' is already declared.\n",lineNumber,symb_scope_function->u.name,id->u.arr.name); @@ -236,7 +251,7 @@ DECL : exit_safely(); } - // Compute the ND array length for a 1D array allocation + // Compute the ND array length for a 1D array allocation (dim1*dim2*...*dimN with 3 addresses code) struct symbol* size=NULL; if($2.dim == 1){ //1D array doesn't need temporary operation size = tabArrayDim[0]; @@ -259,6 +274,7 @@ DECL : ($2.dim%2 == 0)?(size = tmpImpair):(size = tmpPair); } + // Create a variable of type array inside the scope of the 'symb_scope_function' struct symbol* arr = symtable_put_array(SYMTAB,$2.name,$2.dim,tabArrayDim,size,symb_scope_function); gencode(CODE,ALLOCATE_ARRAY,arr,NULL,NULL); @@ -267,16 +283,17 @@ DECL : } ; -ARRAY : +ARRAY : // Array declaration shape (ID, length_dim1, length_dim2, ..., length_dimN) left_parenthesis ID comma DLIST right_parenthesis { $$.dim = $4.dim; strcpy($$.name,$2); } ; -DLIST : +DLIST : // length_dim1, length_dim2, ..., length_dimN DLIST comma E - { + { + // Error detection if($3.ptr->kind == CONSTANT_FLOAT){ fprintf(stderr, "Error at line %u in function '%s': Try to allocate an array with a float length value.\n",lineNumber,symb_scope_function->u.name); exit_safely(); @@ -295,7 +312,7 @@ DLIST : fprintf(stderr, "Error at line %u in function '%s': Try to allocate an array with a float length value.\n",lineNumber,symb_scope_function->u.name); exit_safely(); } - $$.dim = 1; + $$.dim = 1; // Call first by the parsing so we init here the number of dimension storage tabArrayDim[$$.dim-1] = $1.ptr; } ; @@ -337,20 +354,20 @@ D : REC : rec BLOCKINST - | %empty + | %empty // Error dectection -> Function without a rec section { fprintf(stderr, "Error at line %u in function '%s': Unexpected end of function (shouldn't be empty).\n",lineNumber,symb_scope_function->u.name); exit_safely(); } ; -BLOCKINST : +BLOCKINST : // Bloc of instructions left_curly_bracket LISTEI right_curly_bracket | I ; LISTEI : - LISTEI semicolon I + LISTEI semicolon I // Last instruction hasn't a semilocon after | I - | %empty + | %empty // Error detection -> Rec section empty { fprintf(stderr, "Error at line %u in function '%s': Unexpected end of rec section (shouldn't be empty).\n",lineNumber,symb_scope_function->u.name); exit_safely(); @@ -358,15 +375,15 @@ LISTEI : ; I : COND - | AFFECTATION - | CALL // appel de fonction - | read_f left_parenthesis ID right_parenthesis - | print left_parenthesis {isPrintCall = 1;} CALL right_parenthesis + | AFFECTATION // Affectation of variables + | CALL // Call of functions or variables + | read_f left_parenthesis ID right_parenthesis // Read + | print left_parenthesis {isPrintCall = 1;} CALL right_parenthesis // Print variable (printing out var of functions ins't implement yet) { gencode(CODE,CALL_PRINT,$4.ptr,NULL,NULL); } - | print left_parenthesis PRECINST right_parenthesis - | printstr left_parenthesis chaine right_parenthesis + | print left_parenthesis PRECINST right_parenthesis // Print ? + | printstr left_parenthesis chaine right_parenthesis // Prinstr { struct symbol* id = symtable_get(SYMTAB,$3,symb_scope_function); if ( id == NULL ) @@ -400,17 +417,18 @@ OPAFF: ; AFFECTATION : - ARRAYREF OPAFF E + ARRAYREF OPAFF E // Assignement operation of E to an array element { - // No assignement operation when length and dimension >1 - // Compute the Arrays [+-/*] E and store it in a temporary variable struct symbol* tmp1; struct symbol* tmp2; tmp1 = newtemp(SYMTAB); tmp2 = newtemp(SYMTAB); - + + // Copy in a temporary var the value of ARRAYREF gencode(CODE,COPY_ARRAY,tmp1,$1.ptr1,$1.ptr2); + + // Find what assignement operation we are (OPAFF) and copy the operation in tmp2 switch($2.opnum){ case 1: gencode(CODE,BOP_PLUS,tmp2,tmp1,$3.ptr); @@ -438,14 +456,15 @@ AFFECTATION : break; } - // Copy the temp in the variable + // Copy the tmp2 in the array memory gencode(CODE,AFF_ARRAY,$1.ptr1,$1.ptr2,tmp2); } - | ID OPAFF E + | ID OPAFF E // Assignement operation of E to ID { struct symbol* tmpArr; struct symbol* id = symtable_get(SYMTAB,$1,symb_scope_function); struct symbol* t = NULL; + // Errors detection if ( id == NULL ){ fprintf(stderr, "Error at line %u in function '%s': Variable '%s' is not declared, neither as an argument, nor as a local variable.\n",lineNumber,symb_scope_function->u.name,$1); exit_safely(); @@ -509,7 +528,7 @@ AFFECTATION : else gencode(CODE,COPY,id,tmp,NULL); } - | ARRAYREF aff E + | ARRAYREF aff E // Affectation of E to an array element { struct symbol* t = NULL; @@ -523,10 +542,11 @@ AFFECTATION : gencode(CODE,AFF_ARRAY,$1.ptr1,$1.ptr2,t); } - | ID aff E + | ID aff E // Affectation of A to ID { struct symbol* id = symtable_get(SYMTAB,$1,symb_scope_function); + // Errors detection if ( id == NULL ){ fprintf(stderr, "Error at line %u in function '%s': Variable '%s' is not declared, neither as an argument, nor as a local variable.\n",lineNumber,symb_scope_function->u.name,$1); exit_safely(); @@ -554,27 +574,25 @@ AFFECTATION : ; CALL : - ID left_parenthesis LCALL right_parenthesis + ID left_parenthesis LCALL right_parenthesis // Call of functions { - // Appel de fonctions $$.ptr = NULL; } - | ID + | ID // Call variables { - // Appel de variable struct symbol* id = symtable_get(SYMTAB,$1,symb_scope_function); if ( id == NULL ){ fprintf(stderr, "Error at line %u in function '%s': Variable '%s' is not declared, neither as an argument, nor as a local variable.\n",lineNumber,symb_scope_function->u.name,$1); exit_safely(); } - if(id->kind == ARRAY && !isPrintCall){ + if(id->kind == ARRAY && !isPrintCall){ // If ID is an implicit array and we isn't in a print, we add [0] after ID : ID[0] $$.isEArray = 1; $$.ptr = newtemp(SYMTAB); struct symbol* const_0 = symtable_const_int(SYMTAB,0); gencode(CODE,COPY_ARRAY,$$.ptr,id,const_0); } - else + else // Else if we are in a print with an array or we just a normal variable, we just call ID $$.ptr = id; isPrintCall = 0; @@ -590,8 +608,8 @@ LCALL : PRECINST : mod entier %prec formatmod ; -ARRAYREF : - ID left_bracket ELIST right_bracket +ARRAYREF : // Array indexing + ID left_bracket ELIST right_bracket // ID[...] { // $$.ptr1 -> The ID symbol // $$.ptr2 -> The index symbol @@ -617,84 +635,83 @@ ARRAYREF : // Compute the ND array indexes to one index for an 1D array struct symbol* index; - if($3.dim == 1){ //1D array doesn't need temporary operation - index = tabArrayDim[0]; - } else{ //ND arrays, except 1D array, require temporary operation - struct symbol* kIndex1Dpair; - struct symbol* kIndex1Dimpaire; - - index=newtemp(SYMTAB); - for(unsigned int k=0;k<$3.dim;k++){ - // Get K+1dim index - struct symbol* kIndexND = tabArrayDim[k]; - if(kIndexND->kind==CONSTANT_INT && id->u.arr.size[k]->kind==CONSTANT_INT){ - if(kIndexND->u.value_int >= id->u.arr.size[k]->u.value_int){ - fprintf(stderr, "Error at line %u in function '%s': Array '%s' can not be accessed with a number superior than the size of the array\n",lineNumber,symb_scope_function->u.name,$1); - exit_safely(); - } + struct symbol* kIndex1Dpair; + struct symbol* kIndex1Dimpaire; + + index=newtemp(SYMTAB); + for(unsigned int k=0;k<$3.dim;k++){ + // Get K+1dim index + struct symbol* kIndexND = tabArrayDim[k]; + + // Error detection + if(kIndexND->kind==CONSTANT_INT && id->u.arr.size[k]->kind==CONSTANT_INT){ + if(kIndexND->u.value_int >= id->u.arr.size[k]->u.value_int){ + fprintf(stderr, "Error at line %u in function '%s': Array '%s' can not be accessed with a number greater than the size of his dimension %d\n",lineNumber,symb_scope_function->u.name,$1,k+1); + exit_safely(); } + } - // Compute shift - struct symbol* shift; - if(k == $3.dim-1){ - shift = NULL; - } else if(k+1 == $3.dim-1){ - shift = id->u.arr.size[k+1]; + // Compute shift + struct symbol* shift; + if(k == $3.dim-1){ + shift = NULL; + } else if(k+1 == $3.dim-1){ + shift = id->u.arr.size[k+1]; + } else{ + struct symbol* tmpPair; + struct symbol* tmpImpair; + if(k%2==0){ + tmpPair = newtemp(SYMTAB); + tmpImpair; + gencode(CODE,BOP_MULT,tmpPair,id->u.arr.size[k+1],id->u.arr.size[k+2]); } else{ - struct symbol* tmpPair; - struct symbol* tmpImpair; - if(k%2==0){ + tmpPair; + tmpImpair = newtemp(SYMTAB); + gencode(CODE,BOP_MULT,tmpImpair,id->u.arr.size[k+1],id->u.arr.size[k+2]); + } + for(unsigned int j=k+3;j<$3.dim;j++){ + id->u.arr.size[j]; + if(j%2 == 0){ tmpPair = newtemp(SYMTAB); - tmpImpair; - gencode(CODE,BOP_MULT,tmpPair,id->u.arr.size[k+1],id->u.arr.size[k+2]); + gencode(CODE,BOP_MULT,tmpPair,tmpImpair,id->u.arr.size[j]); } else{ - tmpPair; tmpImpair = newtemp(SYMTAB); - gencode(CODE,BOP_MULT,tmpImpair,id->u.arr.size[k+1],id->u.arr.size[k+2]); - } - for(unsigned int j=k+3;j<$3.dim;j++){ - id->u.arr.size[j]; - if(j%2 == 0){ - tmpPair = newtemp(SYMTAB); - gencode(CODE,BOP_MULT,tmpPair,tmpImpair,id->u.arr.size[j]); - } else{ - tmpImpair = newtemp(SYMTAB); - gencode(CODE,BOP_MULT,tmpImpair,tmpPair,id->u.arr.size[j]); - } - } - - (($3.dim-1)%2==0)?(shift = tmpPair):(shift = tmpImpair); + gencode(CODE,BOP_MULT,tmpImpair,tmpPair,id->u.arr.size[j]); + } } - // Compute the addition of the last iteration with the current - if(k%2==0){ // Attention : shift can be NULL - if(k==0){ // If k equal 0, there isn't a previous iteration - if(shift!=NULL){ - gencode(CODE,BOP_MULT,index,kIndexND,shift); - } else{ - gencode(CODE,COPY,index,kIndexND,NULL); - } + (($3.dim-1)%2==0)?(shift = tmpPair):(shift = tmpImpair); + } + + // Compute the addition of the last iteration with the current + if(k%2==0){ // Attention : shift can be NULL + if(k==0){ // If k equal 0, there isn't a previous iteration + if(shift!=NULL){ + gencode(CODE,BOP_MULT,index,kIndexND,shift); } else{ - kIndex1Dpair = newtemp(SYMTAB); - if(shift!=NULL){ - gencode(CODE,BOP_MULT,kIndex1Dpair,kIndexND,shift); - } else{ - gencode(CODE,COPY,kIndex1Dpair,kIndexND,NULL); - } - gencode(CODE,BOP_PLUS,index,index,kIndex1Dpair); + gencode(CODE,COPY,index,kIndexND,NULL); } } else{ - kIndex1Dimpaire = newtemp(SYMTAB); + kIndex1Dpair = newtemp(SYMTAB); if(shift!=NULL){ - gencode(CODE,BOP_MULT,kIndex1Dimpaire,kIndexND,shift); + gencode(CODE,BOP_MULT,kIndex1Dpair,kIndexND,shift); } else{ - gencode(CODE,COPY,kIndex1Dimpaire,kIndexND,NULL); + gencode(CODE,COPY,kIndex1Dpair,kIndexND,NULL); } - gencode(CODE,BOP_PLUS,index,index,kIndex1Dimpaire); + gencode(CODE,BOP_PLUS,index,index,kIndex1Dpair); } + } else{ + kIndex1Dimpaire = newtemp(SYMTAB); + if(shift!=NULL){ + gencode(CODE,BOP_MULT,kIndex1Dimpaire,kIndexND,shift); + } else{ + gencode(CODE,COPY,kIndex1Dimpaire,kIndexND,NULL); + } + gencode(CODE,BOP_PLUS,index,index,kIndex1Dimpaire); } } - + + // Free memory free(tabArrayDim); tabArrayDim = NULL; if(index == NULL){ @@ -708,9 +725,10 @@ ARRAYREF : } ; -ELIST : - ELIST comma E +ELIST : // Indexing list + ELIST comma E // [...,E,E,E,E] { + // Error detection, array cannot be accessed with a float value if($3.ptr->kind == CONSTANT_FLOAT){ fprintf(stderr, "Error at line %u in function '%s': Try to access an array with a float index.\n",lineNumber,symb_scope_function->u.name); exit_safely(); @@ -747,7 +765,7 @@ ELIST : } ; -E : +E : E plus T { $$.ptr = newtemp(SYMTAB);