diff --git a/Makefile b/Makefile index e91f705..6fefed1 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,7 @@ clean: rm -rf out rm -rf tmp rm -f *.s + rm -f *.out tmp: mkdir -p tmp diff --git a/src/grammar.h b/src/grammar.h index 94f43b1..2b7b03c 100644 --- a/src/grammar.h +++ b/src/grammar.h @@ -8,6 +8,7 @@ #include "../src/symbol_table.h" extern FILE *asc_flag; extern bool tc_flag; +extern void insert_code_line(char * error_message, int line_number); typedef enum { ERROR_RUNTIME = 1, diff --git a/src/grammar.y b/src/grammar.y index 3dda42f..2751080 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -106,6 +106,7 @@ program: prototype_or_definition_list + | error { yyerrok; } ; @@ -115,12 +116,17 @@ prototype_or_definition_list: | definition prototype_or_definition_list | prototype | definition + | error { yyerrok; } ; prototype: - L_PAREN EXTERNAL R_PAREN FUNCTION ID COLON ID; + L_PAREN EXTERNAL R_PAREN FUNCTION ID COLON ID + + | error { yyerrok; } + + ; @@ -259,7 +265,7 @@ definition: } } - ; + ; function_declaration: FUNCTION ID COLON ID @@ -285,6 +291,7 @@ function_declaration: } } + ; @@ -344,6 +351,9 @@ idlist: printdebug("Type of entry is %s", getType(entry)); printdebug("tag is %d", getAdInfoType(entry)); } + + | error { yyerrok; } + ; @@ -391,6 +401,9 @@ sblock: } R_BRACE {$$ = $5;} + + | error { yyerrok; } + ; @@ -408,13 +421,20 @@ dblock: printdebug("Created a new scope when seeing a dblock"); } } - declaration_list R_BRACKET; + declaration_list R_BRACKET + + | error { yyerrok; } + + ; declaration_list: declaration SEMI_COLON declaration_list | declaration + + | error { yyerrok; } + ; @@ -452,6 +472,9 @@ declaration: CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); } } + + | error { yyerrok; } + ; @@ -468,6 +491,9 @@ id_or_types: printdebug("string of type is %s in types pattern of id_or_type rule.",getName((TableNode*)$1)); $$ = (TableNode*)$1; } + + | error { yyerrok; } + ; @@ -503,6 +529,7 @@ compound_statement statement_list { | simple_statement SEMI_COLON { $$ = $1; } + ; @@ -523,9 +550,11 @@ WHILE L_PAREN expression R_PAREN sblock { $$ = undefined; } } - | sblock { + + | sblock { $$ = $1; } + ; @@ -557,7 +586,10 @@ simple_statement: } -| RETURN expression {$$ = getTypeEntry((TableNode*)$2);} + | RETURN expression {$$ = getTypeEntry((TableNode*)$2);} + + | error { yyerrok; } + ; @@ -565,6 +597,9 @@ simple_statement: rec_op: DOT + | error { yyerrok; } + + ; ablock: @@ -573,6 +608,9 @@ ablock: $$ = $2; printdebug("ablock is %d", $$); } + + | error { yyerrok; } + ; @@ -591,6 +629,9 @@ argument_list: CreateEntry(cur,getAdInfoType((TableNode*)$1),(TableNode*)$1, getName((TableNode*)$1), NULL); $$ = 1; printdebug("[ARGUMENT_LIST] argument list is %d", $$); } + + | error { yyerrok; } + ; @@ -786,6 +827,8 @@ expression: $$=undefined; } } + + | error { yyerrok; } ; @@ -969,6 +1012,8 @@ assignable: printdebug("[ASSIGNABLE - RULE 3] record = name: %s | field = %s", getName((TableNode*)($1)), getName((TableNode*)$3)); } + | error { yyerrok; } + ; @@ -984,6 +1029,8 @@ memOp: printdebug("release expression"); } + | error { yyerrok; } + ; @@ -1043,7 +1090,7 @@ constant: printdebug("string of C_FALSE in constant is false"); $$ = node; } - + ; @@ -1071,8 +1118,7 @@ types: { $$ = $1; printdebug("string of T_BOOLEAN in types is %s",getName((TableNode*)$1)); - } - + } ; %% @@ -1104,24 +1150,50 @@ void throw_error(ErrorType error_type, const char *format, ...) { break; } + if (asc_flag) { + /* yyerror(""); */ + int needed = snprintf(NULL, 0, " LINE (%d:%d) ** %s ERROR: ", line, column, error_name); + char *error_message = malloc(needed + 1); + snprintf(error_message, needed + 1, " LINE (%d:%d) ** %s ERROR: ", line, column, error_name); - if (tc_flag) { - yyerror(""); - if (asc_flag != NULL) { - fprintf(asc_flag, "(%d:%d) ** %s ERROR: ", line, column, error_name); - va_list args; - va_start(args, format); - vfprintf(asc_flag, format, args); + va_list args; + va_start(args, format); + va_list args_copy; + va_copy(args_copy, args); + int needed2 = vsnprintf(NULL, 0, format, args_copy) + 1; + va_end(args_copy); + + char *error_message2 = malloc(needed2); + if (error_message2 == NULL) { + fprintf(stderr, "Memory allocation failed\n"); va_end(args); - fprintf(asc_flag, "\n"); - } else { - fprintf(stderr, "%s(%d:%d) ** %s ERROR%s: %s", COLOR_RED, line, column, error_name, COLOR_WHITE, COLOR_YELLOW); - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); - fprintf(stderr, "%s\n", COLOR_WHITE); + return; } + + vsnprintf(error_message2, needed2, format, args); + va_end(args); + + int total_needed = needed + needed2 + 2; + char *total_error_message = malloc(total_needed); + if (total_error_message == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + free(error_message); + free(error_message2); + return; + } + + snprintf(total_error_message, total_needed, "%s%s\n\n", error_message, error_message2); + if (tc_flag) { + insert_code_line(total_error_message, line); + } else { + if (error_type != ERROR_TYPE) { + insert_code_line(total_error_message, line); + } + } + + free(error_message); + free(error_message2); + free(total_error_message); } } @@ -1132,11 +1204,13 @@ void yyerror(const char *err) { // Grammar Fallback Case if (strcmp(err, "syntax error") == 0) { if (asc_flag != NULL) { - fprintf(asc_flag, "(%d:%d) ** SYNTAX ERROR: Incorrect syntax at token '%s'\n", line, column, yytext); + int needed = snprintf(NULL, 0, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token '%s'\n\n", line, column, yytext); + char *error_message = malloc(needed + 1); + snprintf(error_message, needed + 1, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token '%s'\n\n", line, column, yytext); + insert_code_line(error_message, line); } else { - fprintf(stderr, "%s(%d:%d) ** SYNTAX ERROR%s: Incorrect syntax at token '%s%s%s'\n", - COLOR_RED, line, column, COLOR_WHITE, COLOR_YELLOW, yytext, COLOR_WHITE); + fprintf(stderr, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token %s\n\n", line, column, yytext); } } } diff --git a/src/runner.c b/src/runner.c index afeeb73..a74c424 100644 --- a/src/runner.c +++ b/src/runner.c @@ -2,8 +2,7 @@ /* The Translators - Spring 2025 */ #include "runner.h" -FILE *ir_flag = NULL; -//Constant_Stack *head = NULL; + int main(int argc, char *argv[]) { if (argc == 1) { fprintf(stderr, INVALID); @@ -36,7 +35,6 @@ int main(int argc, char *argv[]) { alpha_file = fopen(argv[argc - 1], "r"); } } - cg_flag = fopen("cg.s", "w"); return run(alpha_file); } @@ -127,8 +125,6 @@ int run(FILE *alpha) { fseek(alpha, 0, SEEK_SET); - // print_code_lines(); - yyin = alpha; yyparse(); @@ -140,15 +136,14 @@ int run(FILE *alpha) { } if (st_flag != NULL) { + printdebug("[-st] Symbol Table is enabled."); print_symbol_table(top, st_flag); - emit_as_file(stdout, begin); fclose(st_flag); - generate(); - fclose(cg_flag); } if (asc_flag != NULL) { printdebug("[-asc] Annotated Source Code is enabled."); + print_code_lines(); fclose(asc_flag); } @@ -157,14 +152,16 @@ int run(FILE *alpha) { } if (ir_flag != NULL) { - printf("Flag -ir is not implemented yet\n"); + printdebug("[-ir] Intermediate code is enabled."); + emit_as_file(ir_flag, begin); fclose(ir_flag); } - //if (cg_flag != NULL) { - // printf("Flag -cg is not implemented yet\n"); - //fclose(cg_flag); - //} + if (cg_flag != NULL) { + printdebug("[-cg] Code generation is enabled."); + generate(); + fclose(cg_flag); + } if (yyin != NULL) { fclose(yyin); @@ -250,7 +247,26 @@ int is_alpha_file(char *alpha, int file_len) { return 0; // is alpha file } -void insert_code_line(char *line, int line_number) { +void insert_code_line(char * error_message, int line_number) { + CodeLine *error_line = malloc(sizeof(CodeLine)); + error_line->line_number = line_number; + error_line->line = malloc(strlen(error_message) + 1); + strcpy(error_line->line, error_message); + error_line->next = NULL; + error_line->is_error = true; + + if (error_line == NULL || code_head == NULL) return; + + int line = error_line->line_number; + CodeLine *current = code_head; + while (current != NULL) { + if (current->line_number == line) { + CodeLine *next_code_line = current->next; + current->next = error_line; + error_line->next = next_code_line; + } + current = current->next; + } } void append_code_line(CodeLine *code_line) { @@ -268,9 +284,18 @@ void append_code_line(CodeLine *code_line) { } void print_code_lines() { + if (code_head == NULL) { + printf("No code lines to print.\n"); + return; + } + CodeLine *current = code_head; while (current != NULL) { - printf("%d %03d: %s", current->line_number, current->line); + if (current->is_error) { + fprintf(asc_flag, "%s", current->line); + } else { + fprintf(asc_flag, "%03d: %s", current->line_number, current->line); + } current = current->next; } } diff --git a/src/runner.h b/src/runner.h index d5531bd..9971eed 100644 --- a/src/runner.h +++ b/src/runner.h @@ -52,6 +52,7 @@ FILE *alpha_file; FILE *tok_flag = NULL; FILE *st_flag = NULL; FILE *asc_flag = NULL; +FILE *ir_flag = NULL; FILE *cg_flag = NULL; bool tc_flag = false; bool DEBUG = false; @@ -105,6 +106,6 @@ typedef struct CodeLine { CodeLine *code_head; char *file_read_line(FILE *fp); -void insert_code_line(char *line, int line_number); +void insert_code_line(char * error_message, int line_number); void append_code_line(CodeLine *code_line); void print_code_lines(); \ No newline at end of file diff --git a/tests/sprint2/test/sp2_llnode.alpha b/tests/sprint2/test/sp2_llnode.alpha index 3ecfb11..c611b3c 100644 --- a/tests/sprint2/test/sp2_llnode.alpha +++ b/tests/sprint2/test/sp2_llnode.alpha @@ -21,7 +21,7 @@ make_list (a) := { } else { ret := reserve ret; ret.prev := null; - ret.next := null; + ret.next :s= null;g ret.val := a; while (0 < a) { temp := reserve temp; diff --git a/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha b/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha index 2adb394..a804c23 100644 --- a/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha +++ b/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha @@ -8,12 +8,12 @@ entry (arg) := { x := 3 + 2 * 8; x := 3 - 2 / 8; - x := a * 2 % 8; + x := a * 2 % 8;s b2 := 3 * 2 % 8; x := 3 % 2 * 8; x := 3 + arr - 8; - x := r.x; - x := a.x; + x := r.x; + x := a.x; return 0; }