From eeb15be84dce08ae731bbd2ec906ce99f8c246a8 Mon Sep 17 00:00:00 2001 From: Leonardo Araujo Date: Sun, 5 Jan 2025 04:09:16 -0300 Subject: [PATCH] feat: enhanced error messages for undeclared identifiers --- ast.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++----------- ast.h | 3 +++ lang.y | 4 +++- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/ast.c b/ast.c index 061cb3f..510dc4c 100644 --- a/ast.c +++ b/ast.c @@ -108,6 +108,45 @@ TypeModifiers get_current_modifiers(void) return mods; } +/* Include the symbol table functions */ +extern bool set_variable(char *name, int value, TypeModifiers mod); +extern int get_variable(char *name); +extern void yyerror(const char *s); +extern void yapping(const char *format, ...); +extern void yappin(const char *format, ...); +extern void baka(const char *format, ...); +extern TypeModifiers get_variable_modifiers(const char *name); +extern int yylineno; + +/* Function implementations */ + +bool check_and_mark_identifier(ASTNode *node, const char *contextErrorMessage) +{ + if (!node->alreadyChecked) + { + node->alreadyChecked = true; + node->isValidSymbol = false; + + // Do the table lookup + for (int i = 0; i < var_count; i++) + { + if (strcmp(symbol_table[i].name, node->data.name) == 0) + { + node->isValidSymbol = true; + break; + } + } + + if (!node->isValidSymbol) + { + yylineno = yylineno - 2; + yyerror(contextErrorMessage); + } + } + + return node->isValidSymbol; +} + void execute_switch_statement(ASTNode *node) { int switch_value = evaluate_expression(node->data.switch_stmt.expression); @@ -145,17 +184,6 @@ void execute_switch_statement(ASTNode *node) } } -/* Include the symbol table functions */ -extern bool set_variable(char *name, int value, TypeModifiers mod); -extern int get_variable(char *name); -extern void yyerror(const char *s); -extern void yapping(const char *format, ...); -extern void yappin(const char *format, ...); -extern void baka(const char *format, ...); -extern TypeModifiers get_variable_modifiers(const char *name); - -/* Function implementations */ - ASTNode *create_int_node(int value) { ASTNode *node = malloc(sizeof(ASTNode)); @@ -436,6 +464,9 @@ int evaluate_expression_int(ASTNode *node) } case NODE_IDENTIFIER: { + if (!check_and_mark_identifier(node, "Undefined variable")) + exit(1); + char *name = node->data.name; for (int i = 0; i < var_count; i++) { @@ -728,6 +759,8 @@ bool is_float_expression(ASTNode *node) return false; case NODE_IDENTIFIER: { + if (!check_and_mark_identifier(node, "Undefined variable in type check")) + exit(1); for (int i = 0; i < var_count; i++) { if (strcmp(symbol_table[i].name, node->data.name) == 0) @@ -764,6 +797,8 @@ bool is_double_expression(ASTNode *node) return false; case NODE_IDENTIFIER: { + if (!check_and_mark_identifier(node, "Undefined variable in type check")) + exit(1); for (int i = 0; i < var_count; i++) { if (strcmp(symbol_table[i].name, node->data.name) == 0) diff --git a/ast.h b/ast.h index b17c106..709a586 100644 --- a/ast.h +++ b/ast.h @@ -119,6 +119,8 @@ struct ASTNode { NodeType type; TypeModifiers modifiers; + bool alreadyChecked; + bool isValidSymbol; union { int ivalue; @@ -220,6 +222,7 @@ void execute_yappin_call(ArgumentList *args); void execute_baka_call(ArgumentList *args); void free_ast(ASTNode *node); void reset_modifiers(void); +bool check_and_mark_identifier(ASTNode *node, const char *contextErrorMessage); extern TypeModifiers current_modifiers; diff --git a/lang.y b/lang.y index ca59bf1..7c0035a 100644 --- a/lang.y +++ b/lang.y @@ -1,3 +1,4 @@ +%define parse.error verbose %{ #include "ast.h" #include @@ -381,7 +382,8 @@ int main(void) { } void yyerror(const char *s) { - fprintf(stderr, "Error: %s at line %d\n", s, yylineno); + extern char *yytext; + fprintf(stderr, "Error: %s at line %d\n", s, yylineno - 1); } void yapping(const char* format, ...) {