fix semantic for printing or sth

This commit is contained in:
2025-12-03 01:50:44 +09:00
parent 75407304f8
commit 4e2fdf88f9
12 changed files with 373 additions and 53 deletions

View File

@@ -9,15 +9,9 @@
#include "globals.h" #include "globals.h"
#include "symtab.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 BucketList func_entry = NULL;
static Scope func_scope; static Scope func_scope;
static TreeNode *func_params[256]; static TreeNode *func_params[MAX_PARAM_COUNT];
static int func_param_count = 0; static int func_param_count = 0;
/* Procedure traverse is a generic recursive /* Procedure traverse is a generic recursive
@@ -60,17 +54,34 @@ static void insertNode(TreeNode *t) {
case ExpK: case ExpK:
switch (t->kind.exp) { switch (t->kind.exp) {
case IdK: 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: { case CallK: {
BucketList entry = st_lookup(t->attr.name); BucketList entry = st_lookup(t->attr.name);
if (entry == NULL) { 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 { } else {
// t->type = entry->type;// TODO: Ambiguity
t->scope = curr_scope();
st_entry_insert_line(entry, t->lineno); st_entry_insert_line(entry, t->lineno);
t->type = entry->type;
} }
t->scope = curr_scope();
} }
default: default:
break; break;
@@ -84,9 +95,20 @@ static void insertNode(TreeNode *t) {
func_scope = NULL; func_scope = NULL;
for (int i = 0; i < func_param_count; i++) { for (int i = 0; i < func_param_count; i++) {
TreeNode *param = func_params[i]; TreeNode *param = func_params[i];
func_entry->param_types[func_entry->param_count++] = param->type; func_entry->param_types[func_entry->param_count] = param->type;
if (st_lookup_current(param->attr.name) != NULL) { func_entry->param_names[func_entry->param_count] = param->attr.name;
symbolError(param, "Redefinition of a Parameter"); 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 { } else {
st_try_insert(param->attr.name, SymbolParam, param->type, param->lineno); st_try_insert(param->attr.name, SymbolParam, param->type, param->lineno);
} }
@@ -105,40 +127,60 @@ static void insertNode(TreeNode *t) {
case DeclK: case DeclK:
switch (t->kind.decl) { switch (t->kind.decl) {
case FuncK: case FuncK: {
BucketList entry;
if (st_lookup(t->attr.name) != NULL) { 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 { } else {
func_entry = st_try_insert(t->attr.name, SymbolFunc, t->type, t->lineno); func_entry = st_try_insert(t->attr.name, SymbolFunc, t->type, t->lineno);
t->scope = curr_scope(); t->scope = curr_scope();
} }
func_scope = scope_new(t->attr.name); func_scope = scope_new(t->attr.name);
//push_scope(scope_new(t->attr.name)); } break;
break;
case ArrParamK: case ArrParamK:
case NonArrParamK: { case NonArrParamK: {
if (t->type == Void) {
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; func_params[func_param_count++] = t;
} insert_param_exit:
} } break;
break;
case VarK: case VarK:
case ArrVarK: case ArrVarK: {
if (st_lookup_current(t->attr.name) != NULL) { BucketList entry = st_lookup_current(t->attr.name);
symbolError(t, "Redefinition of a Variable"); 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 { } else {
if (t->type == Void) { if (t->type == Void) {
symbolError(t, "Variable cannot be of type void"); fprintf(listing, "Error: The void-type variable is declared at line %d (name : \"%s\")\n", t->lineno, t->attr.name);
break; Error = TRUE;
} }
t->scope = curr_scope(); t->scope = curr_scope();
st_try_insert(t->attr.name, SymbolVar, t->type, t->lineno); st_try_insert(t->attr.name, SymbolVar, t->type, t->lineno);
} }
break; } break;
default: default:
break; break;
} }
@@ -192,10 +234,10 @@ static void checkNode(TreeNode *t) {
TreeNode *left = t->child[0]; TreeNode *left = t->child[0];
TreeNode *right = t->child[1]; TreeNode *right = t->child[1];
if (left->type != Integer || right->type != Integer) { 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; t->type = Integer;
} break; } break;
case ConstK: case ConstK:
t->type = Integer; t->type = Integer;
@@ -203,11 +245,16 @@ static void checkNode(TreeNode *t) {
case IdK: { case IdK: {
BucketList entry = st_lookup_from(t->attr.name, t->scope); BucketList entry = st_lookup_from(t->attr.name, t->scope);
t->type = entry->type; t->type = entry->type;
} break; } break;
case ArrIdK: { 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) { 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; t->type = IntegerArray;
@@ -217,15 +264,16 @@ static void checkNode(TreeNode *t) {
TreeNode *left = t->child[0]; TreeNode *left = t->child[0];
TreeNode *right = t->child[1]; TreeNode *right = t->child[1];
if (left->type != right->type) { 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; } break;
case CallK: { case CallK: {
BucketList entry = st_lookup_from(t->attr.name, t->scope);// not null BucketList entry = st_lookup_from(t->attr.name, t->scope);// not null
if (entry->symbolKind != SymbolFunc) { if (entry->symbolKind != SymbolFunc) {
typeError(t, "");
typeError(t, "Call to a non-function"); typeError(t, "Call to a non-function");
} }
@@ -235,7 +283,9 @@ static void checkNode(TreeNode *t) {
while (arg != NULL && i < entry->param_count) { while (arg != NULL && i < entry->param_count) {
if (arg->type != entry->param_types[i]) { 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; arg = arg->sibling;
@@ -243,11 +293,15 @@ static void checkNode(TreeNode *t) {
} }
if (arg != NULL) { 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) { } 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; t->type = entry->returnType;
} break; } break;
@@ -258,34 +312,38 @@ static void checkNode(TreeNode *t) {
case StmtK: case StmtK:
switch (t->kind.stmt) { switch (t->kind.stmt) {
case ReturnK: { case ReturnK: {
if (func_entry == NULL) { if (func_entry == NULL) {
typeError(t, "Return statement is not in a function"); fprintf(listing, "Error: Invalid return at line %d\n", t->lineno);
break; Error = TRUE;
} }
TreeNode *retval = t->child[0]; /* nullalbe */ TreeNode *retval = t->child[0]; /* nullalbe */
if (func_entry->returnType == Void) { if (func_entry->returnType == Void) {
if (retval != NULL) { 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 { } else {
if (retval == NULL) { 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) { } 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; } break;
case IterK: { case IterK: {
TreeNode *condition = t->child[0]; TreeNode *condition = t->child[0];
if (condition->type != Integer) { 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; } break;
case IfK: { case IfK: {
TreeNode *condition = t->child[0]; TreeNode *condition = t->child[0];
if (condition->type != Integer) { 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; } break;
default: default:

View File

@@ -106,7 +106,8 @@ typedef enum { TypeNameK } TypeKind;
/* ExpType is used for type checking */ /* ExpType is used for type checking */
typedef enum { Void, typedef enum { Void,
Integer, Integer,
IntegerArray IntegerArray,
Undetermined
} ExpType; } ExpType;
typedef enum { typedef enum {

View File

@@ -39,7 +39,7 @@ FILE *code;
/* allocate and set tracing flags */ /* allocate and set tracing flags */
int EchoSource = FALSE; int EchoSource = FALSE;
int TraceScan = FALSE; int TraceScan = FALSE;
int TraceParse = TRUE; int TraceParse = FALSE;
int TraceAnalyze = TRUE; int TraceAnalyze = TRUE;
int TraceCode = FALSE; int TraceCode = FALSE;

56
src/result_1.txt Normal file
View File

@@ -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

46
src/result_2.txt Normal file
View File

@@ -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

56
src/result_3.txt Normal file
View File

@@ -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

45
src/result_4.txt Normal file
View File

@@ -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

View File

@@ -40,6 +40,7 @@ typedef struct BucketListEntry {
ExpType type; ExpType type;
ExpType param_types[MAX_PARAM_COUNT]; ExpType param_types[MAX_PARAM_COUNT];
char* param_names[MAX_PARAM_COUNT];
int param_count; int param_count;
ExpType returnType; ExpType returnType;

16
src/test_1.cm Normal file
View File

@@ -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));
}

21
src/test_2.cm Normal file
View File

@@ -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]);
}
}
}

13
src/test_3.cm Normal file
View File

@@ -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);
}

7
src/test_4.cm Normal file
View File

@@ -0,0 +1,7 @@
int main(void)
{
int x[5];
x[output(5)] = 3 + 5;
return 0;
}