fix semantic for printing or sth
This commit is contained in:
160
src/analyze.c
160
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;
|
||||
|
||||
@@ -106,7 +106,8 @@ typedef enum { TypeNameK } TypeKind;
|
||||
/* ExpType is used for type checking */
|
||||
typedef enum { Void,
|
||||
Integer,
|
||||
IntegerArray
|
||||
IntegerArray,
|
||||
Undetermined
|
||||
} ExpType;
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
56
src/result_1.txt
Normal file
56
src/result_1.txt
Normal 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
46
src/result_2.txt
Normal 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
56
src/result_3.txt
Normal 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
45
src/result_4.txt
Normal 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
|
||||
@@ -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;
|
||||
|
||||
|
||||
16
src/test_1.cm
Normal file
16
src/test_1.cm
Normal 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
21
src/test_2.cm
Normal 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
13
src/test_3.cm
Normal 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
7
src/test_4.cm
Normal file
@@ -0,0 +1,7 @@
|
||||
int main(void)
|
||||
{
|
||||
int x[5];
|
||||
x[output(5)] = 3 + 5;
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user