diff --git a/src/2024062806.md b/out/parse.md similarity index 100% rename from src/2024062806.md rename to out/parse.md diff --git a/src/2024062806.pdf b/out/parse.pdf similarity index 100% rename from src/2024062806.pdf rename to out/parse.pdf diff --git a/src/Makefile b/src/Makefile index 86a7bc0..5618022 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,34 +1,31 @@ # Makefile for C-Minus # # ./lex/tiny.l --> ./cminus.l (from Project 1) -# ./yacc/tiny.y --> ./cminus.y -# ./yacc/globals.h --> ./globals.h +# ./yacc/tiny.y --> ./cminus.y (from Project 2) +# ./yacc/globals.h --> ./globals.h (from Project 2) CC = gcc -CFLAGS = -W -Wall +CFLAGS = -W -Wall -g -OBJS = main.o util.o lex.yy.o y.tab.o +OBJS = main.o util.o lex.yy.o y.tab.o symtab.o analyze.o .PHONY: all clean -all: cminus_parser +all: cminus_semantic clean: - rm -vf cminus_parser *.o lex.yy.c y.tab.c y.tab.h y.output + rm -vf cminus_semantic *.o lex.yy.c y.tab.c y.tab.h y.output -cminus_parser: $(OBJS) +cminus_semantic: $(OBJS) $(CC) $(CFLAGS) $(OBJS) -o $@ -lfl -main.o: main.c globals.h util.h scan.h parse.h y.tab.h +main.o: main.c globals.h util.h scan.h parse.h y.tab.h analyze.h $(CC) $(CFLAGS) -c main.c util.o: util.c util.h globals.h y.tab.h $(CC) $(CFLAGS) -c util.c -scan.o: scan.c scan.h util.h globals.h y.tab.h - $(CC) $(CFLAGS) -c scan.c - -lex.yy.o: lex.yy.c scan.h util.h globals.h y.tab.h +lex.yy.o: lex.yy.c scan.h globals.h y.tab.h util.h $(CC) $(CFLAGS) -c lex.yy.c lex.yy.c: cminus.l @@ -40,4 +37,10 @@ y.tab.o: y.tab.c parse.h $(CC) $(CFLAGS) -c y.tab.c y.tab.c: cminus.y - yacc -d -Wcounterexamples -v cminus.y + yacc -d -v cminus.y + +analyze.o: analyze.c analyze.h globals.h y.tab.h symtab.h util.h + $(CC) $(CFLAGS) -c analyze.c + +symtab.o: symtab.c symtab.h + $(CC) $(CFLAGS) -c symtab.c diff --git a/src/analyze.c b/src/analyze.c index 61d2400..b092cc1 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -1,159 +1,315 @@ /****************************************************/ /* File: analyze.c */ /* Semantic analyzer implementation */ -/* for the TINY compiler */ -/* Compiler Construction: Principles and Practice */ -/* Kenneth C. Louden */ +/* for the CMinus compiler */ +/* Yenru0 */ /****************************************************/ +#include "analyze.h" #include "globals.h" #include "symtab.h" -#include "analyze.h" -/* counter for variable memory locations */ -static int location = 0; +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 int func_param_count = 0; /* Procedure traverse is a generic recursive * syntax tree traversal routine: * it applies preProc in preorder and postProc * in postorder to tree pointed to by t */ -static void traverse( TreeNode * t, - void (* preProc) (TreeNode *), - void (* postProc) (TreeNode *) ) -{ if (t != NULL) - { preProc(t); - { int i; - for (i=0; i < MAXCHILDREN; i++) - traverse(t->child[i],preProc,postProc); +static void traverse(TreeNode *t, + void (*preProc)(TreeNode *), + void (*postProc)(TreeNode *)) { + if (t != NULL) { + preProc(t); + { + int i; + for (i = 0; i < MAXCHILDREN; i++) + traverse(t->child[i], preProc, postProc); + } + postProc(t); + traverse(t->sibling, preProc, postProc); } - postProc(t); - traverse(t->sibling,preProc,postProc); - } } /* nullProc is a do-nothing procedure to * generate preorder-only or postorder-only * traversals from traverse */ -static void nullProc(TreeNode * t) -{ if (t==NULL) return; - else return; +static void nullProc(TreeNode *t) { + if (t == NULL) return; + else + return; } /* Procedure insertNode inserts * identifiers stored in t into * the symbol table */ -static void insertNode( TreeNode * t) -{ switch (t->nodekind) - { case StmtK: - switch (t->kind.stmt) - { case AssignK: - case ReadK: - if (st_lookup(t->attr.name) == -1) - /* not yet in table, so treat as new definition */ - st_insert(t->attr.name,t->lineno,location++); - else - /* already in table, so ignore location, - add line number of use only */ - st_insert(t->attr.name,t->lineno,0); - break; +static void insertNode(TreeNode *t) { + //printf("Insert Node: line %d\n", t->lineno); + switch (t->nodekind) { + case ExpK: + switch (t->kind.exp) { + case IdK: + case ArrIdK: + case CallK: { + BucketList entry = st_lookup(t->attr.name); + if (entry == NULL) { + symbolError(t, "Undeclared Symbol"); + } else { + // t->type = entry->type;// TODO: Ambiguity + t->scope = curr_scope(); + st_entry_insert_line(entry, t->lineno); + t->type = entry->type; + } + } + default: + break; + } + break; + case StmtK: + switch (t->kind.stmt) { + case CompK: + if (func_scope != NULL) { + push_scope(func_scope); + 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"); + } else { + st_try_insert(param->attr.name, SymbolParam, param->type, param->lineno); + } + } + func_entry = NULL; + func_scope = NULL; + func_param_count = 0; + } else { + push_scope(scope_new("compound")); + } + break; + default: + break; + } + break; + + case DeclK: + switch (t->kind.decl) { + case FuncK: + if (st_lookup(t->attr.name) != NULL) { + symbolError(t, "Redefinition of a Function"); + } 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; + case ArrParamK: + case NonArrParamK: { + + if (t->type != Void) { + func_params[func_param_count++] = t; + } + + } + + break; + case VarK: + case ArrVarK: + if (st_lookup_current(t->attr.name) != NULL) { + symbolError(t, "Redefinition of a Variable"); + } else { + if (t->type == Void) { + symbolError(t, "Variable cannot be of type void"); + break; + } + t->scope = curr_scope(); + st_try_insert(t->attr.name, SymbolVar, t->type, t->lineno); + } + break; + default: + break; + } + break; default: - break; - } - break; - case ExpK: - switch (t->kind.exp) - { case IdK: - if (st_lookup(t->attr.name) == -1) - /* not yet in table, so treat as new definition */ - st_insert(t->attr.name,t->lineno,location++); - else - /* already in table, so ignore location, - add line number of use only */ - st_insert(t->attr.name,t->lineno,0); - break; - default: - break; - } - break; - default: - break; - } + break; + } +} + +static void afterNode(TreeNode *t) { + if (t->nodekind == StmtK && t->kind.stmt == CompK) { + pop_scope(); + } } /* Function buildSymtab constructs the symbol * table by preorder traversal of the syntax tree */ -void buildSymtab(TreeNode * syntaxTree) -{ traverse(syntaxTree,insertNode,nullProc); - if (TraceAnalyze) - { fprintf(listing,"\nSymbol table:\n\n"); - printSymTab(listing); - } +void buildSymtab(TreeNode *syntaxTree) { + st_init(); + BucketList entry; + entry = st_try_insert("input", SymbolFunc, Integer, 0); + entry->param_count = 0; + + entry = st_try_insert("output", SymbolFunc, Void, 0); + entry->param_types[0] = Integer; + entry->param_count = 1; + + traverse(syntaxTree, insertNode, afterNode); + if (TraceAnalyze) { + fprintf(listing, "\nSymbol table:\n\n"); + printSymTab(listing); + } } -static void typeError(TreeNode * t, char * message) -{ fprintf(listing,"Type error at line %d: %s\n",t->lineno,message); - Error = TRUE; +static void typeError(TreeNode *t, char *message) { + fprintf(listing, "Type error at line %d: %s\n", t->lineno, message); + Error = TRUE; } -/* Procedure checkNode performs - * type checking at a single tree node - */ -static void checkNode(TreeNode * t) -{ switch (t->nodekind) - { case ExpK: - switch (t->kind.exp) - { case OpK: - if ((t->child[0]->type != Integer) || - (t->child[1]->type != Integer)) - typeError(t,"Op applied to non-integer"); - if ((t->attr.op == EQ) || (t->attr.op == LT)) - t->type = Boolean; - else - t->type = Integer; - break; - case ConstK: - case IdK: - t->type = Integer; - break; - default: - break; - } - break; - case StmtK: - switch (t->kind.stmt) - { case IfK: - if (t->child[0]->type == Integer) - typeError(t->child[0],"if test is not Boolean"); - break; - case AssignK: - if (t->child[0]->type != Integer) - typeError(t->child[0],"assignment of non-integer value"); - break; - case WriteK: - if (t->child[0]->type != Integer) - typeError(t->child[0],"write of non-integer value"); - break; - case RepeatK: - if (t->child[1]->type == Integer) - typeError(t->child[1],"repeat test is not Boolean"); - break; - default: - break; - } - break; - default: - break; +static void beforeCheckNode(TreeNode *t) { + if (t->nodekind == DeclK && t->kind.decl == FuncK) { + func_entry = st_lookup(t->attr.name); + } +} +static void checkNode(TreeNode *t) { + switch (t->nodekind) { + case ExpK: + switch (t->kind.exp) { + case OpK: { + TreeNode *left = t->child[0]; + TreeNode *right = t->child[1]; + if (left->type != Integer || right->type != Integer) { + typeError(t, "Operator applied to non-integer"); + } + t->type = Integer; - } + } break; + case ConstK: + t->type = Integer; + break; + case IdK: { + BucketList entry = st_lookup_from(t->attr.name, t->scope); + t->type = entry->type; + + } break; + case ArrIdK: { + if (t->child[0]->type != Integer) { + typeError(t, "Array subscript is not an integer"); + } + t->type = IntegerArray; + + } break; + + case AssignK: { + TreeNode *left = t->child[0]; + TreeNode *right = t->child[1]; + if (left->type != right->type) { + typeError(t, "Assignment of different types"); + } + t->type = left->type; + + } break; + case CallK: { + BucketList entry = st_lookup_from(t->attr.name, t->scope);// not null + + if (entry->symbolKind != SymbolFunc) { + typeError(t, "Call to a non-function"); + } + + TreeNode *arg = t->child[0]; + + int i = 0;// 파라미터 인덱스 + + while (arg != NULL && i < entry->param_count) { + if (arg->type != entry->param_types[i]) { + typeError(t, "Type mismatch in argument: Expected different type"); + } + + arg = arg->sibling; + i++; + } + + if (arg != NULL) { + typeError(t, "Too many arguments in function call"); + } else if (i < entry->param_count) { + typeError(t, "Too few arguments in function call"); + } + + t->type = entry->returnType; + + } break; + default: + break; + } + break; + case StmtK: + switch (t->kind.stmt) { + case ReturnK: { + + if (func_entry == NULL) { + typeError(t, "Return statement is not in a function"); + break; + } + TreeNode *retval = t->child[0]; /* nullalbe */ + if (func_entry->returnType == Void) { + if (retval != NULL) { + typeError(t, "Return with a value in a void function"); + } + } else { + if (retval == NULL) { + typeError(t, "Return without a value in a non-void function"); + } else if (retval->type != func_entry->returnType) { + typeError(t, "Return type mismatch"); + } + } + } break; + case IterK: { + TreeNode *condition = t->child[0]; + if (condition->type != Integer) { + typeError(t, "While condition is not of type integer"); + } + } break; + case IfK: { + TreeNode *condition = t->child[0]; + if (condition->type != Integer) { + typeError(t, "If condition is not of type integer"); + } + } break; + default: + break; + } + break; + + case DeclK: + switch (t->kind.decl) { + + case FuncK: + func_entry = NULL; + break; + default: + break; + } + default: + break; + } } /* Procedure typeCheck performs type checking * by a postorder syntax tree traversal */ -void typeCheck(TreeNode * syntaxTree) -{ traverse(syntaxTree,nullProc,checkNode); +void typeCheck(TreeNode *syntaxTree) { + traverse(syntaxTree, beforeCheckNode, checkNode); } diff --git a/src/globals.h b/src/globals.h index 37446ee..c9df1b7 100644 --- a/src/globals.h +++ b/src/globals.h @@ -14,6 +14,9 @@ #include #include +struct Scope; +typedef struct Scope *Scope; + #ifndef FALSE #define FALSE 0 #endif @@ -103,7 +106,14 @@ typedef enum { TypeNameK } TypeKind; /* ExpType is used for type checking */ typedef enum { Void, Integer, - IntegerArray } ExpType; + IntegerArray +} ExpType; + +typedef enum { + SymbolVar, + SymbolFunc, + SymbolParam +} SymbolKind; #define MAXCHILDREN 3 @@ -124,6 +134,7 @@ typedef struct treeNode { char *name; } attr; ExpType type; /* for type checking of exps */ + Scope scope; } TreeNode; /**************************************************/ diff --git a/src/main.c b/src/main.c index a94af77..98a062a 100644 --- a/src/main.c +++ b/src/main.c @@ -10,7 +10,7 @@ /* set NO_PARSE to TRUE to get a scanner-only compiler */ #define NO_PARSE FALSE /* set NO_ANALYZE to TRUE to get a parser-only compiler */ -#define NO_ANALYZE TRUE +#define NO_ANALYZE FALSE /* set NO_CODE to TRUE to get a compiler that does not * generate code @@ -40,7 +40,7 @@ FILE *code; int EchoSource = FALSE; int TraceScan = FALSE; int TraceParse = TRUE; -int TraceAnalyze = FALSE; +int TraceAnalyze = TRUE; int TraceCode = FALSE; int Error = FALSE; diff --git a/src/symtab.c b/src/symtab.c index 86b9f49..aa472a7 100644 --- a/src/symtab.c +++ b/src/symtab.c @@ -4,8 +4,6 @@ /* (allows only one symbol table) */ /* Symbol table is implemented as a chained */ /* hash table */ -/* Compiler Construction: Principles and Practice */ -/* Kenneth C. Louden */ /****************************************************/ #include "symtab.h" @@ -13,6 +11,17 @@ #include #include +Scope scope_stack[MAX_SCOPE_DEPTH]; +int scope_stack_top = -1; +Scope scope_global;// no sibling no parent + +void st_init(void) { + scope_global = scope_new("global"); + scope_global->depth = 0; + scope_stack_top = 0; + scope_stack[scope_stack_top] = scope_global; +} + /* SHIFT is the power of two used as multiplier in hash function */ #define SHIFT 4 @@ -28,79 +37,213 @@ static int hash(char *key) { return temp; } -Scope curr_scope(void) { - if (top_stack == -1) { - return NULL; +Scope scope_new(char *scope_name) {// it + Scope new_scope = (Scope) malloc(sizeof(struct Scope)); + new_scope->name = scope_name; + new_scope->depth = -1; + new_scope->parent = NULL; + new_scope->child = NULL; + new_scope->child_last = NULL; + new_scope->next_sibling = NULL; + + new_scope->location = 0; + return new_scope; +} + +void pop_scope(void) { + if (scope_stack_top == -1) {// empty + return; } else { - return scope_stack[top_stack]; + scope_stack[scope_stack_top] = NULL; + scope_stack_top--; } } -/* Procedure st_insert inserts line numbers and - * memory locations into the symbol table - * loc = memory location is inserted only the - * first time, otherwise ignored - */ -void st_insert(char *name, int lineno, int loc) { +void push_scope(Scope scope) { + if (scope_stack_top == MAX_SCOPE_DEPTH - 1) {// full + return; + } else { + Scope before = curr_scope(); + if (before->child == NULL) { + before->child = scope; + before->child_last = scope; + } else { + before->child_last->next_sibling = scope; + before->child_last = scope; + } + scope->parent = before; + scope->depth = before->depth + 1; + + scope_stack_top++; + scope_stack[scope_stack_top] = scope; + } +} + +Scope curr_scope(void) { + if (scope_stack_top == -1) { + return NULL; + } else { + return scope_stack[scope_stack_top]; + } +} + +BucketList st_try_insert(char *name, SymbolKind symbolkind, ExpType type, int lineno) { int h = hash(name); + Scope scope = curr_scope(); + BucketList *hashTable = scope->hashTable; BucketList l = hashTable[h]; while ((l != NULL) && (strcmp(name, l->name) != 0)) l = l->next; - if (l == NULL) /* variable not yet in table */ - { - l = (BucketList) malloc(sizeof(struct BucketListRec)); + if (l == NULL) { /* variable not yet in table */ + l = (BucketList) malloc(sizeof(struct BucketListEntry)); l->name = name; - l->lines = (LineList) malloc(sizeof(struct LineListRec)); + l->symbolKind = symbolkind; + l->lines = (LineList) malloc(sizeof(struct LineListEntry)); l->lines->lineno = lineno; - l->memloc = loc; + l->symbolKind = symbolkind; + if (symbolkind == SymbolFunc) { + l->type = Void; + l->returnType = type; + l->param_count = 0; + } else { + l->type = type; + l->returnType = type; + } + l->lines->next = NULL; + l->memloc = scope->location; + scope->location++; l->next = hashTable[h]; hashTable[h] = l; - } else /* found in table, so just add line number */ - { + } else { /* found in table, so just add line number */ LineList t = l->lines; - while (t->next != NULL) t = t->next; - t->next = (LineList) malloc(sizeof(struct LineListRec)); + while (t->next != NULL) + t = t->next; + t->next = (LineList) malloc(sizeof(struct LineListEntry)); t->next->lineno = lineno; t->next->next = NULL; } -} /* st_insert */ + return l; +} -/* Function st_lookup returns the memory - * location of a variable or -1 if not found - */ -int st_lookup(char *name) { +void st_entry_insert_line(BucketList entry, int lineno) { + if (entry == NULL) return; + LineList t = entry->lines; + while (t->next != NULL) + t = t->next; + t->next = (LineList) malloc(sizeof(struct LineListEntry)); + t->next->lineno = lineno; + t->next->next = NULL; +} + +BucketList st_lookup_current(char *name) { int h = hash(name); + Scope scope = curr_scope(); + BucketList *hashTable = scope->hashTable; BucketList l = hashTable[h]; while ((l != NULL) && (strcmp(name, l->name) != 0)) l = l->next; - if (l == NULL) return -1; - else - return l->memloc; + + return l; } -/* Procedure printSymTab prints a formatted - * listing of the symbol table contents - * to the listing file - */ -void printSymTab(FILE *listing) { - int i; - fprintf(listing, "Variable Name Location Line Numbers\n"); - fprintf(listing, "------------- -------- ------------\n"); - for (i = 0; i < SYMTAB_SIZE; ++i) { - if (hashTable[i] != NULL) { - BucketList l = hashTable[i]; - while (l != NULL) { - LineList t = l->lines; - fprintf(listing, "%-14s ", l->name); - fprintf(listing, "%-8d ", l->memloc); - while (t != NULL) { - fprintf(listing, "%4d ", t->lineno); - t = t->next; - } - fprintf(listing, "\n"); - l = l->next; +BucketList st_lookup(char *name) { + int h = hash(name); + Scope scope = curr_scope(); + while (scope != NULL) { + BucketList *hashTable = scope->hashTable; + BucketList l = hashTable[h]; + while ((l != NULL) && (strcmp(name, l->name) != 0)) + l = l->next; + if (l != NULL) { + return l; + } + scope = scope->parent; + } + return NULL; /* not found */ +} + +BucketList st_lookup_from(char *name, Scope scope) { + int h = hash(name); + while (scope != NULL) { + BucketList *hashTable = scope->hashTable; + BucketList l = hashTable[h]; + while ((l != NULL) && (strcmp(name, l->name) != 0)) + l = l->next; + if (l != NULL) { + return l; + } + scope = scope->parent; + } + return NULL; /* not found */ +} + +void printScope(FILE *listing, Scope scope) { + if (scope == NULL) return; + fprintf(listing, "Scope Name: %s, Depth: %d\n", scope->name, scope->depth); + fprintf(listing, "-----------------------------------------\n"); + fprintf(listing, "Variable Name Symbol Kind Type Location Line Numbers\n"); + fprintf(listing, "------------------------------------------------------------\n"); + + for (int i = 0; i < SYMTAB_SIZE; i++) { + BucketList l = scope->hashTable[i]; + while (l != NULL) { + fprintf(listing, "%-14s", l->name); + switch (l->symbolKind) { + case SymbolVar: + fprintf(listing, "%-13s", "Variable"); + break; + case SymbolFunc: + fprintf(listing, "%-13s", "Function"); + break; + case SymbolParam: + fprintf(listing, "%-13s", "Parameter"); + break; } + switch (l->type) { + case Void: + fprintf(listing, "%-11s", "void"); + break; + case Integer: + fprintf(listing, "%-11s", "int"); + break; + case IntegerArray: + fprintf(listing, "%-11s", "int[]"); + break; + } + fprintf(listing, "%-9d", l->memloc); + LineList t = l->lines; + while (t != NULL) { + fprintf(listing, "%d ", t->lineno); + t = t->next; + } + fprintf(listing, "\n"); + l = l->next; } } -} /* printSymTab */ + fprintf(listing, "\n"); +} + +static void printScopeRecursive(FILE *listing, Scope scope) { + if (scope == NULL) return; + + printScope(listing, scope); + + Scope child = scope->child; + while (child != NULL) { + printScopeRecursive(listing, child); + child = child->next_sibling; + } +} + +void printScopeTree(FILE *listing) { + if (scope_global == NULL) return; + + Scope current_scope = scope_global; + + printScopeRecursive(listing, current_scope); +} + +void printSymTab(FILE *listing) { + printScopeTree(listing); +} diff --git a/src/symtab.h b/src/symtab.h index 26661a9..7d8d3f9 100644 --- a/src/symtab.h +++ b/src/symtab.h @@ -9,16 +9,23 @@ #include "globals.h" -/* SYMTAB_SIZE is the size of the hash table */ +/** + * it is the size of the hash table +*/ #define SYMTAB_SIZE 211 +#define MAX_SCOPE_DEPTH 32 +#define MAX_SCOPE_COUNT 1557 + +#define MAX_PARAM_COUNT 13 + /* the list of line numbers of the source * code in which a variable is referenced */ typedef struct LineListEntry { int lineno; struct LineListEntry *next; -} *LineList; +} * LineList; /* The record in the bucket lists for * each variable, including name, @@ -29,61 +36,80 @@ typedef struct LineListEntry { typedef struct BucketListEntry { char *name; LineList lines; + SymbolKind symbolKind; + ExpType type; + ExpType param_types[MAX_PARAM_COUNT]; + int param_count; + ExpType returnType; + int memloc; /* memory location for variable */ struct BucketListEntry *next; -} *BucketList; +} * BucketList; -typedef struct Scope { +struct Scope { char *name; int depth; + struct Scope *parent; + struct Scope *child; + struct Scope *child_last; + struct Scope *next_sibling; + + int location; BucketList hashTable[SYMTAB_SIZE]; -} *Scope; +}; -Scope scope_global; +extern Scope scope_global;// no sibling no parent -static Scope scope_list[SYMTAB_SIZE]; -static int size_list = 0; +extern Scope scope_stack[MAX_SCOPE_DEPTH]; +extern int scope_stack_top; -static Scope scope_stack[SYMTAB_SIZE]; -static int top_stack = -1; +/** + * before using the symbol table, initialize the global scope + */ +void st_init(void); /** * create a new scope with given name + * @note it does not link parent or insert into stack/list * @param scope_name: name of the scope * @return the created scope */ Scope scope_new(char *scope_name); /** - * pop the current scope from the scope stack + * pop the current scope from the scope stack */ void pop_scope(void); /** * push a scope into the scope stack + * @note it does link the parent or siblings to construct tree * @param scope: the scope to be pushed */ void push_scope(Scope scope); /** - * insert a scope into the scope list - */ -void insert_scope_to_list(Scope scope); -/** - * get the top of the scope stack + * get the top of the scope stack wit * @return the current scope or NULL if the stack is empty */ Scope curr_scope(void); /** - * insert a variable into the symbol table - * or update a variable if it already exists - * @param scope_name name of the scope + * insert a variable into the symbol table of the current scope + * or add a line number if it already exists * @param name name of the variable + * @param symbolkind kind of the symbol * @param type type of the variable * @param lineno line number of the variable - * @param loc memory location of the variable * @return 0 if success, -1 if failure */ -int st_try_insert(char *name, ExpType type, int loc); +BucketList st_try_insert(char *name, SymbolKind symbolkind, ExpType type, int lineno); + +/** + * insert a line number into the variable's line list + * @param entry the bucket list entry of the variable + * @param lineno the line number to be inserted + */ +void st_entry_insert_line(BucketList entry, int lineno); + /** * lookup a variable in the current scope * @param name name of the variable to lookup @@ -91,22 +117,24 @@ int st_try_insert(char *name, ExpType type, int loc); */ BucketList st_lookup_current(char *name); /** - * lookup a variable from the given scope to root + * lookup a variable from the top scope to root * @param name name of the variable to lookup * @return the bucket list entry of the variable or NULL if not found */ BucketList st_lookup(char *name); + /** - * find a scope from the scope list - * @param scope_name name of the scope to find - * @return the scope or NULL if not found - */ -Scope find_scope(char *scope_name); -/** - * Procedure printSymTab prints a formatted - * listing of the symbol table contents - * to the listing file + * lookup a variable from the given scope to root + * @param name name of the variable to lookup + * @param scope the scope to start lookup from + * @return the bucket list entry of the variable or NULL if not found */ +BucketList st_lookup_from(char *name, Scope scope); + +void printScope(FILE *listing, Scope scope); + +void printScopeTree(FILE *listing); + void printSymTab(FILE *listing); #endif diff --git a/src/test.cm b/src/test.cm new file mode 100644 index 0000000..b9d09e9 --- /dev/null +++ b/src/test.cm @@ -0,0 +1,13 @@ +int fib(int n) { + if (n <= 0) { + return 1; + } else { + return fib(n * fib(n - 1)); + } +} + +int main(void) { + int x; + x = fib(input()); + output(x); +} \ No newline at end of file