From 4e2fdf88f9c873d6811c15dda392e6112f0ca6f1 Mon Sep 17 00:00:00 2001 From: yenru0 Date: Wed, 3 Dec 2025 01:50:44 +0900 Subject: [PATCH] fix semantic for printing or sth --- src/analyze.c | 160 ++++++++++++++++++++++++++++++++--------------- src/globals.h | 3 +- src/main.c | 2 +- src/result_1.txt | 56 +++++++++++++++++ src/result_2.txt | 46 ++++++++++++++ src/result_3.txt | 56 +++++++++++++++++ src/result_4.txt | 45 +++++++++++++ src/symtab.h | 1 + src/test_1.cm | 16 +++++ src/test_2.cm | 21 +++++++ src/test_3.cm | 13 ++++ src/test_4.cm | 7 +++ 12 files changed, 373 insertions(+), 53 deletions(-) create mode 100644 src/result_1.txt create mode 100644 src/result_2.txt create mode 100644 src/result_3.txt create mode 100644 src/result_4.txt create mode 100644 src/test_1.cm create mode 100644 src/test_2.cm create mode 100644 src/test_3.cm create mode 100644 src/test_4.cm diff --git a/src/analyze.c b/src/analyze.c index b092cc1..f1f99d3 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -9,15 +9,9 @@ #include "globals.h" #include "symtab.h" -static void symbolError(TreeNode *t, char *message) { - fprintf(listing, "Symbol error at line %d: %s\n", t->lineno, message); - Error = TRUE; - exit(-1); -} - static BucketList func_entry = NULL; static Scope func_scope; -static TreeNode *func_params[256]; +static TreeNode *func_params[MAX_PARAM_COUNT]; static int func_param_count = 0; /* Procedure traverse is a generic recursive @@ -60,17 +54,34 @@ static void insertNode(TreeNode *t) { case ExpK: switch (t->kind.exp) { case IdK: - case ArrIdK: + case ArrIdK: { + BucketList entry = st_lookup(t->attr.name); + if (entry == NULL) { + fprintf(listing, "Error: undeclared variable \"%s\" is used at line %d\n", t->attr.name, t->lineno); + Error = TRUE; + + entry = st_try_insert(t->attr.name, SymbolVar, Undetermined, t->lineno); + } else { + st_entry_insert_line(entry, t->lineno); + } + + t->scope = curr_scope(); + + } break; case CallK: { BucketList entry = st_lookup(t->attr.name); if (entry == NULL) { - symbolError(t, "Undeclared Symbol"); + fprintf(listing, "Error: undeclared function \"%s\" is called at line %d\n", t->attr.name, t->lineno); + Error = TRUE; + + entry = st_try_insert(t->attr.name, SymbolFunc, Undetermined, t->lineno); + entry->param_count = -1; + entry->returnType = Undetermined; } else { - // t->type = entry->type;// TODO: Ambiguity - t->scope = curr_scope(); st_entry_insert_line(entry, t->lineno); - t->type = entry->type; } + + t->scope = curr_scope(); } default: break; @@ -84,9 +95,20 @@ static void insertNode(TreeNode *t) { func_scope = NULL; for (int i = 0; i < func_param_count; i++) { TreeNode *param = func_params[i]; - func_entry->param_types[func_entry->param_count++] = param->type; - if (st_lookup_current(param->attr.name) != NULL) { - symbolError(param, "Redefinition of a Parameter"); + func_entry->param_types[func_entry->param_count] = param->type; + func_entry->param_names[func_entry->param_count] = param->attr.name; + func_entry->param_count++; + BucketList param_entry = st_lookup_current(param->attr.name); + if (param_entry != NULL) { + fprintf(listing, "Error: Symbol \"%s\" is redefined at line %d (already defined at line", t->attr.name, t->lineno); + LineList lines = param_entry->lines; + while (lines != NULL) { + fprintf(listing, " "); + fprintf(listing, "%d", lines->lineno); + lines = lines->next; + } + fprintf(listing, ")\n"); + Error = TRUE; } else { st_try_insert(param->attr.name, SymbolParam, param->type, param->lineno); } @@ -105,40 +127,60 @@ static void insertNode(TreeNode *t) { case DeclK: switch (t->kind.decl) { - case FuncK: + case FuncK: { + BucketList entry; if (st_lookup(t->attr.name) != NULL) { - symbolError(t, "Redefinition of a Function"); + fprintf(listing, "Error: Symbol \"%s\" is redefined at line %d (already defined at line", t->attr.name, t->lineno); + LineList lines = entry->lines; + while (lines != NULL) { + fprintf(listing, " "); + fprintf(listing, "%d", lines->lineno); + lines = lines->next; + } + fprintf(listing, ")\n"); + Error = TRUE; } else { func_entry = st_try_insert(t->attr.name, SymbolFunc, t->type, t->lineno); t->scope = curr_scope(); } - func_scope = scope_new(t->attr.name); - //push_scope(scope_new(t->attr.name)); - break; + } break; case ArrParamK: case NonArrParamK: { - - if (t->type != Void) { - func_params[func_param_count++] = t; + if (t->type == Void) { + if (t->attr.name != NULL) { + fprintf(listing, "Error: The void-type parameter is declared at line %d (name : \"%s\")\n", t->lineno, t->attr.name); + Error = TRUE; + } else { + goto insert_param_exit; + } } + func_params[func_param_count++] = t; + insert_param_exit: - } - - break; + } break; case VarK: - case ArrVarK: - if (st_lookup_current(t->attr.name) != NULL) { - symbolError(t, "Redefinition of a Variable"); + case ArrVarK: { + BucketList entry = st_lookup_current(t->attr.name); + if (entry != NULL) {// ignore + fprintf(listing, "Error: Symbol \"%s\" is redefined at line %d (already defined at line", t->attr.name, t->lineno); + LineList lines = entry->lines; + while (lines != NULL) { + fprintf(listing, " "); + fprintf(listing, "%d", lines->lineno); + lines = lines->next; + } + fprintf(listing, ")\n"); + Error = TRUE; } else { if (t->type == Void) { - symbolError(t, "Variable cannot be of type void"); - break; + fprintf(listing, "Error: The void-type variable is declared at line %d (name : \"%s\")\n", t->lineno, t->attr.name); + Error = TRUE; } t->scope = curr_scope(); st_try_insert(t->attr.name, SymbolVar, t->type, t->lineno); } - break; + } break; default: break; } @@ -192,10 +234,10 @@ static void checkNode(TreeNode *t) { TreeNode *left = t->child[0]; TreeNode *right = t->child[1]; if (left->type != Integer || right->type != Integer) { - typeError(t, "Operator applied to non-integer"); + fprintf(listing, "Error: Invalid operation at line %d\n", t->lineno); + Error = TRUE; } t->type = Integer; - } break; case ConstK: t->type = Integer; @@ -203,11 +245,16 @@ static void checkNode(TreeNode *t) { case IdK: { BucketList entry = st_lookup_from(t->attr.name, t->scope); t->type = entry->type; - } break; case ArrIdK: { + BucketList entry = st_lookup_from(t->attr.name, t->scope); + if (entry->type != IntegerArray) { + fprintf(listing, "Error: Invalid array indexing at line %d (name : \"%s\"). indexing can only allowed for int[] variables\n", t->lineno, t->attr.name); + Error = TRUE; + } if (t->child[0]->type != Integer) { - typeError(t, "Array subscript is not an integer"); + fprintf(listing, "Error: Invalid array indexing at line %d (name : \"%s\"). indicies should be integer\n", t->lineno, t->attr.name); + Error = TRUE; } t->type = IntegerArray; @@ -217,15 +264,16 @@ static void checkNode(TreeNode *t) { TreeNode *left = t->child[0]; TreeNode *right = t->child[1]; if (left->type != right->type) { - typeError(t, "Assignment of different types"); + fprintf(listing, "Error: Invalid assignment at line %d\n", t->lineno); + Error = TRUE; } - t->type = left->type; - + t->type = right->type; } break; case CallK: { BucketList entry = st_lookup_from(t->attr.name, t->scope);// not null if (entry->symbolKind != SymbolFunc) { + typeError(t, ""); typeError(t, "Call to a non-function"); } @@ -235,7 +283,9 @@ static void checkNode(TreeNode *t) { while (arg != NULL && i < entry->param_count) { if (arg->type != entry->param_types[i]) { - typeError(t, "Type mismatch in argument: Expected different type"); + fprintf(listing, "Error: Invalid function call at line %d\n", t->lineno); + Error = TRUE; + goto check_callk_after; } arg = arg->sibling; @@ -243,11 +293,15 @@ static void checkNode(TreeNode *t) { } if (arg != NULL) { - typeError(t, "Too many arguments in function call"); + fprintf(listing, "Error: Invalid function call at line %d\n", t->lineno); + Error = TRUE; } else if (i < entry->param_count) { - typeError(t, "Too few arguments in function call"); + fprintf(listing, "Error: Invalid function call at line %d\n", t->lineno); + Error = TRUE; } + check_callk_after: + t->type = entry->returnType; } break; @@ -258,34 +312,38 @@ static void checkNode(TreeNode *t) { case StmtK: switch (t->kind.stmt) { case ReturnK: { - if (func_entry == NULL) { - typeError(t, "Return statement is not in a function"); - break; + fprintf(listing, "Error: Invalid return at line %d\n", t->lineno); + Error = TRUE; } TreeNode *retval = t->child[0]; /* nullalbe */ if (func_entry->returnType == Void) { if (retval != NULL) { - typeError(t, "Return with a value in a void function"); + fprintf(listing, "Error: Invalid return at line %d\n", t->lineno); + Error = TRUE; } } else { if (retval == NULL) { - typeError(t, "Return without a value in a non-void function"); + fprintf(listing, "Error: Invalid return at line %d\n", t->lineno); + Error = TRUE; } else if (retval->type != func_entry->returnType) { - typeError(t, "Return type mismatch"); + fprintf(listing, "Error: Invalid return at line %d\n", t->lineno); + Error = TRUE; } } } break; case IterK: { TreeNode *condition = t->child[0]; if (condition->type != Integer) { - typeError(t, "While condition is not of type integer"); + fprintf(listing, "Error: Invalid condition at line %d\n", t->lineno); + Error = TRUE; } } break; case IfK: { TreeNode *condition = t->child[0]; if (condition->type != Integer) { - typeError(t, "If condition is not of type integer"); + fprintf(listing, "Error: Invalid condition at line %d\n", t->lineno); + Error = TRUE; } } break; default: @@ -295,7 +353,7 @@ static void checkNode(TreeNode *t) { case DeclK: switch (t->kind.decl) { - + case FuncK: func_entry = NULL; break; diff --git a/src/globals.h b/src/globals.h index c9df1b7..2ac0507 100644 --- a/src/globals.h +++ b/src/globals.h @@ -106,7 +106,8 @@ typedef enum { TypeNameK } TypeKind; /* ExpType is used for type checking */ typedef enum { Void, Integer, - IntegerArray + IntegerArray, + Undetermined } ExpType; typedef enum { diff --git a/src/main.c b/src/main.c index 98a062a..f63adde 100644 --- a/src/main.c +++ b/src/main.c @@ -39,7 +39,7 @@ FILE *code; /* allocate and set tracing flags */ int EchoSource = FALSE; int TraceScan = FALSE; -int TraceParse = TRUE; +int TraceParse = FALSE; int TraceAnalyze = TRUE; int TraceCode = FALSE; diff --git a/src/result_1.txt b/src/result_1.txt new file mode 100644 index 0000000..9672e4e --- /dev/null +++ b/src/result_1.txt @@ -0,0 +1,56 @@ + +C-MINUS COMPILATION: test.1.txt + +Building Symbol Table... + + +< Symbol Table > + Symbol Name Symbol Kind Symbol Type Scope Name Location Line Numbers +------------- ----------- ------------- ------------ -------- ------------ +main Function void global 3 11 +input Function int global 0 0 14 14 +output Function void global 1 0 15 +gcd Function int global 2 4 7 15 +value Variable int output 0 0 +u Variable int gcd 0 4 6 7 7 +v Variable int gcd 1 4 6 7 7 7 +x Variable int main 0 13 14 15 +y Variable int main 1 13 14 15 + + +< Functions > +Function Name Return Type Parameter Name Parameter Type +------------- ------------- -------------- -------------- +main void void +input int void +output void +- - value int +gcd int +- - u int +- - v int + + +< Global Symbols > + Symbol Name Symbol Kind Symbol Type +------------- ----------- ------------- +main Function void +input Function int +output Function void +gcd Function int + + +< Scopes > + Scope Name Nested Level Symbol Name Symbol Type +------------ ------------ ------------- ----------- +output 1 value int + +gcd 1 u int +gcd 1 v int + +main 1 x int +main 1 y int + + +Checking Types... + +Type Checking Finished diff --git a/src/result_2.txt b/src/result_2.txt new file mode 100644 index 0000000..b404c49 --- /dev/null +++ b/src/result_2.txt @@ -0,0 +1,46 @@ + +C-MINUS COMPILATION: test.2.txt + +Building Symbol Table... + + +< Symbol Table > + Symbol Name Symbol Kind Symbol Type Scope Name Location Line Numbers +------------- ----------- ------------- ------------ -------- ------------ +main Function void global 2 1 +input Function int global 0 0 8 +output Function void global 1 0 18 +value Variable int output 0 0 +i Variable int main 0 3 5 6 8 10 10 13 14 16 18 +x Variable int[] main 1 3 8 16 18 + + +< Functions > +Function Name Return Type Parameter Name Parameter Type +------------- ------------- -------------- -------------- +main void void +input int void +output void +- - value int + + +< Global Symbols > + Symbol Name Symbol Kind Symbol Type +------------- ----------- ------------- +main Function void +input Function int +output Function void + + +< Scopes > + Scope Name Nested Level Symbol Name Symbol Type +------------ ------------ ------------- ----------- +output 1 value int + +main 1 i int +main 1 x int[] + + +Checking Types... + +Type Checking Finished diff --git a/src/result_3.txt b/src/result_3.txt new file mode 100644 index 0000000..794ae6f --- /dev/null +++ b/src/result_3.txt @@ -0,0 +1,56 @@ + +C-MINUS COMPILATION: test.3.txt + +Building Symbol Table... + + +< Symbol Table > + Symbol Name Symbol Kind Symbol Type Scope Name Location Line Numbers +------------- ----------- ------------- ------------ -------- ------------ +main Function int global 3 6 +input Function int global 0 0 +output Function void global 1 0 +x Function int global 2 1 12 +value Variable int output 0 0 +y Variable int x 0 1 3 +a Variable int main 0 8 12 +b Variable int main 1 9 12 +c Variable int main 2 10 12 + + +< Functions > +Function Name Return Type Parameter Name Parameter Type +------------- ------------- -------------- -------------- +main int void +input int void +output void +- - value int +x int +- - y int + + +< Global Symbols > + Symbol Name Symbol Kind Symbol Type +------------- ----------- ------------- +main Function int +input Function int +output Function void +x Function int + + +< Scopes > + Scope Name Nested Level Symbol Name Symbol Type +------------ ------------ ------------- ----------- +output 1 value int + +x 1 y int + +main 1 a int +main 1 b int +main 1 c int + + +Checking Types... +Error: Invalid function call at line 12 (name : "x") + +Type Checking Finished diff --git a/src/result_4.txt b/src/result_4.txt new file mode 100644 index 0000000..ab8fcfc --- /dev/null +++ b/src/result_4.txt @@ -0,0 +1,45 @@ + +C-MINUS COMPILATION: test.4.txt + +Building Symbol Table... + + +< Symbol Table > + Symbol Name Symbol Kind Symbol Type Scope Name Location Line Numbers +------------- ----------- ------------- ------------ -------- ------------ +main Function int global 2 1 +input Function int global 0 0 +output Function void global 1 0 4 +value Variable int output 0 0 +x Variable int[] main 0 3 4 + + +< Functions > +Function Name Return Type Parameter Name Parameter Type +------------- ------------- -------------- -------------- +main int void +input int void +output void +- - value int + + +< Global Symbols > + Symbol Name Symbol Kind Symbol Type +------------- ----------- ------------- +main Function int +input Function int +output Function void + + +< Scopes > + Scope Name Nested Level Symbol Name Symbol Type +------------ ------------ ------------- ----------- +output 1 value int + +main 1 x int[] + + +Checking Types... +Error: Invalid array indexing at line 4 (name : "x"). indices should be integer + +Type Checking Finished diff --git a/src/symtab.h b/src/symtab.h index 7d8d3f9..45e5fec 100644 --- a/src/symtab.h +++ b/src/symtab.h @@ -40,6 +40,7 @@ typedef struct BucketListEntry { ExpType type; ExpType param_types[MAX_PARAM_COUNT]; + char* param_names[MAX_PARAM_COUNT]; int param_count; ExpType returnType; diff --git a/src/test_1.cm b/src/test_1.cm new file mode 100644 index 0000000..ffcc3de --- /dev/null +++ b/src/test_1.cm @@ -0,0 +1,16 @@ +/* A program to perform Euclid's + Algorithm to computer gcd */ + +int gcd (int u, int v) +{ + if (v == 0) return u; + else return gcd(v,u-u/v*v); + /* u-u/v*v == u mod v */ +} + +void main(void k) +{ + int x; int y; + x = input(); y = input(); + output(gcd(x,y)); +} diff --git a/src/test_2.cm b/src/test_2.cm new file mode 100644 index 0000000..80bc4fa --- /dev/null +++ b/src/test_2.cm @@ -0,0 +1,21 @@ +void main(void) +{ + int i; int x[5]; + + i = 0; + while( i < 5 ) + { + x[i] = input(); + + i = i + 1; + } + + i = 0; + while( i <= 4 ) + { + if( x[i] != 0 ) + { + output(x[i]); + } + } +} diff --git a/src/test_3.cm b/src/test_3.cm new file mode 100644 index 0000000..3f17dbe --- /dev/null +++ b/src/test_3.cm @@ -0,0 +1,13 @@ +int x(int y) +{ + return y + 1; +} + +int main(void) +{ + int a; + int b; + int c; + + return x(a, b, c); +} diff --git a/src/test_4.cm b/src/test_4.cm new file mode 100644 index 0000000..96823e8 --- /dev/null +++ b/src/test_4.cm @@ -0,0 +1,7 @@ +int main(void) +{ + int x[5]; + x[output(5)] = 3 + 5; + + return 0; +}