semi-complete semantic

This commit is contained in:
2025-12-02 05:11:27 +09:00
parent f4501529df
commit f1fd203233
9 changed files with 567 additions and 213 deletions

View File

@@ -1,34 +1,31 @@
# Makefile for C-Minus # Makefile for C-Minus
# #
# ./lex/tiny.l --> ./cminus.l (from Project 1) # ./lex/tiny.l --> ./cminus.l (from Project 1)
# ./yacc/tiny.y --> ./cminus.y # ./yacc/tiny.y --> ./cminus.y (from Project 2)
# ./yacc/globals.h --> ./globals.h # ./yacc/globals.h --> ./globals.h (from Project 2)
CC = gcc 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 .PHONY: all clean
all: cminus_parser all: cminus_semantic
clean: 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 $(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 $(CC) $(CFLAGS) -c main.c
util.o: util.c util.h globals.h y.tab.h util.o: util.c util.h globals.h y.tab.h
$(CC) $(CFLAGS) -c util.c $(CC) $(CFLAGS) -c util.c
scan.o: scan.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 scan.c
lex.yy.o: lex.yy.c scan.h util.h globals.h y.tab.h
$(CC) $(CFLAGS) -c lex.yy.c $(CC) $(CFLAGS) -c lex.yy.c
lex.yy.c: cminus.l lex.yy.c: cminus.l
@@ -40,4 +37,10 @@ y.tab.o: y.tab.c parse.h
$(CC) $(CFLAGS) -c y.tab.c $(CC) $(CFLAGS) -c y.tab.c
y.tab.c: cminus.y 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

View File

@@ -1,34 +1,42 @@
/****************************************************/ /****************************************************/
/* File: analyze.c */ /* File: analyze.c */
/* Semantic analyzer implementation */ /* Semantic analyzer implementation */
/* for the TINY compiler */ /* for the CMinus compiler */
/* Compiler Construction: Principles and Practice */ /* Yenru0 */
/* Kenneth C. Louden */
/****************************************************/ /****************************************************/
#include "analyze.h"
#include "globals.h" #include "globals.h"
#include "symtab.h" #include "symtab.h"
#include "analyze.h"
/* counter for variable memory locations */ static void symbolError(TreeNode *t, char *message) {
static int location = 0; 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 /* Procedure traverse is a generic recursive
* syntax tree traversal routine: * syntax tree traversal routine:
* it applies preProc in preorder and postProc * it applies preProc in preorder and postProc
* in postorder to tree pointed to by t * in postorder to tree pointed to by t
*/ */
static void traverse( TreeNode * t, static void traverse(TreeNode *t,
void (* preProc) (TreeNode *), void (*preProc)(TreeNode *),
void (* postProc) (TreeNode *) ) void (*postProc)(TreeNode *)) {
{ if (t != NULL) if (t != NULL) {
{ preProc(t); preProc(t);
{ int i; {
for (i=0; i < MAXCHILDREN; i++) int i;
traverse(t->child[i],preProc,postProc); for (i = 0; i < MAXCHILDREN; i++)
traverse(t->child[i], preProc, postProc);
} }
postProc(t); postProc(t);
traverse(t->sibling,preProc,postProc); traverse(t->sibling, preProc, postProc);
} }
} }
@@ -36,43 +44,100 @@ static void traverse( TreeNode * t,
* generate preorder-only or postorder-only * generate preorder-only or postorder-only
* traversals from traverse * traversals from traverse
*/ */
static void nullProc(TreeNode * t) static void nullProc(TreeNode *t) {
{ if (t==NULL) return; if (t == NULL) return;
else return; else
return;
} }
/* Procedure insertNode inserts /* Procedure insertNode inserts
* identifiers stored in t into * identifiers stored in t into
* the symbol table * the symbol table
*/ */
static void insertNode( TreeNode * t) static void insertNode(TreeNode *t) {
{ switch (t->nodekind) //printf("Insert Node: line %d\n", t->lineno);
{ case StmtK: switch (t->nodekind) {
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;
default:
break;
}
break;
case ExpK: case ExpK:
switch (t->kind.exp) switch (t->kind.exp) {
{ case IdK: case IdK:
if (st_lookup(t->attr.name) == -1) case ArrIdK:
/* not yet in table, so treat as new definition */ case CallK: {
st_insert(t->attr.name,t->lineno,location++); BucketList entry = st_lookup(t->attr.name);
else if (entry == NULL) {
/* already in table, so ignore location, symbolError(t, "Undeclared Symbol");
add line number of use only */ } else {
st_insert(t->attr.name,t->lineno,0); // 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; break;
default: default:
break; break;
@@ -83,77 +148,168 @@ static void insertNode( TreeNode * t)
} }
} }
static void afterNode(TreeNode *t) {
if (t->nodekind == StmtK && t->kind.stmt == CompK) {
pop_scope();
}
}
/* Function buildSymtab constructs the symbol /* Function buildSymtab constructs the symbol
* table by preorder traversal of the syntax tree * table by preorder traversal of the syntax tree
*/ */
void buildSymtab(TreeNode * syntaxTree) void buildSymtab(TreeNode *syntaxTree) {
{ traverse(syntaxTree,insertNode,nullProc); st_init();
if (TraceAnalyze) BucketList entry;
{ fprintf(listing,"\nSymbol table:\n\n"); 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); printSymTab(listing);
} }
} }
static void typeError(TreeNode * t, char * message) static void typeError(TreeNode *t, char *message) {
{ fprintf(listing,"Type error at line %d: %s\n",t->lineno,message); fprintf(listing, "Type error at line %d: %s\n", t->lineno, message);
Error = TRUE; Error = TRUE;
} }
/* Procedure checkNode performs static void beforeCheckNode(TreeNode *t) {
* type checking at a single tree node 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: static void checkNode(TreeNode *t) {
switch (t->kind.exp) switch (t->nodekind) {
{ case OpK: case ExpK:
if ((t->child[0]->type != Integer) || switch (t->kind.exp) {
(t->child[1]->type != Integer)) case OpK: {
typeError(t,"Op applied to non-integer"); TreeNode *left = t->child[0];
if ((t->attr.op == EQ) || (t->attr.op == LT)) TreeNode *right = t->child[1];
t->type = Boolean; if (left->type != Integer || right->type != Integer) {
else typeError(t, "Operator applied to non-integer");
}
t->type = Integer; t->type = Integer;
break;
} break;
case ConstK: case ConstK:
case IdK:
t->type = Integer; t->type = Integer;
break; 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: default:
break; break;
} }
break; break;
case StmtK: case StmtK:
switch (t->kind.stmt) switch (t->kind.stmt) {
{ case IfK: case ReturnK: {
if (t->child[0]->type == Integer)
typeError(t->child[0],"if test is not Boolean"); if (func_entry == NULL) {
break; typeError(t, "Return statement is not in a function");
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; 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: default:
break; break;
} }
break; break;
case DeclK:
switch (t->kind.decl) {
case FuncK:
func_entry = NULL;
break;
default:
break;
}
default: default:
break; break;
} }
} }
/* Procedure typeCheck performs type checking /* Procedure typeCheck performs type checking
* by a postorder syntax tree traversal * by a postorder syntax tree traversal
*/ */
void typeCheck(TreeNode * syntaxTree) void typeCheck(TreeNode *syntaxTree) {
{ traverse(syntaxTree,nullProc,checkNode); traverse(syntaxTree, beforeCheckNode, checkNode);
} }

View File

@@ -14,6 +14,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
struct Scope;
typedef struct Scope *Scope;
#ifndef FALSE #ifndef FALSE
#define FALSE 0 #define FALSE 0
#endif #endif
@@ -103,7 +106,14 @@ 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 } ExpType; IntegerArray
} ExpType;
typedef enum {
SymbolVar,
SymbolFunc,
SymbolParam
} SymbolKind;
#define MAXCHILDREN 3 #define MAXCHILDREN 3
@@ -124,6 +134,7 @@ typedef struct treeNode {
char *name; char *name;
} attr; } attr;
ExpType type; /* for type checking of exps */ ExpType type; /* for type checking of exps */
Scope scope;
} TreeNode; } TreeNode;
/**************************************************/ /**************************************************/

View File

@@ -10,7 +10,7 @@
/* set NO_PARSE to TRUE to get a scanner-only compiler */ /* set NO_PARSE to TRUE to get a scanner-only compiler */
#define NO_PARSE FALSE #define NO_PARSE FALSE
/* set NO_ANALYZE to TRUE to get a parser-only compiler */ /* 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 /* set NO_CODE to TRUE to get a compiler that does not
* generate code * generate code
@@ -40,7 +40,7 @@ FILE *code;
int EchoSource = FALSE; int EchoSource = FALSE;
int TraceScan = FALSE; int TraceScan = FALSE;
int TraceParse = TRUE; int TraceParse = TRUE;
int TraceAnalyze = FALSE; int TraceAnalyze = TRUE;
int TraceCode = FALSE; int TraceCode = FALSE;
int Error = FALSE; int Error = FALSE;

View File

@@ -4,8 +4,6 @@
/* (allows only one symbol table) */ /* (allows only one symbol table) */
/* Symbol table is implemented as a chained */ /* Symbol table is implemented as a chained */
/* hash table */ /* hash table */
/* Compiler Construction: Principles and Practice */
/* Kenneth C. Louden */
/****************************************************/ /****************************************************/
#include "symtab.h" #include "symtab.h"
@@ -13,6 +11,17 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
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 /* SHIFT is the power of two used as multiplier
in hash function */ in hash function */
#define SHIFT 4 #define SHIFT 4
@@ -28,79 +37,213 @@ static int hash(char *key) {
return temp; return temp;
} }
Scope curr_scope(void) { Scope scope_new(char *scope_name) {// it
if (top_stack == -1) { Scope new_scope = (Scope) malloc(sizeof(struct Scope));
return NULL; 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 { } else {
return scope_stack[top_stack]; scope_stack[scope_stack_top] = NULL;
scope_stack_top--;
} }
} }
/* Procedure st_insert inserts line numbers and void push_scope(Scope scope) {
* memory locations into the symbol table if (scope_stack_top == MAX_SCOPE_DEPTH - 1) {// full
* loc = memory location is inserted only the return;
* first time, otherwise ignored } else {
*/ Scope before = curr_scope();
void st_insert(char *name, int lineno, int loc) { 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); int h = hash(name);
Scope scope = curr_scope();
BucketList *hashTable = scope->hashTable;
BucketList l = hashTable[h]; BucketList l = hashTable[h];
while ((l != NULL) && (strcmp(name, l->name) != 0)) while ((l != NULL) && (strcmp(name, l->name) != 0))
l = l->next; l = l->next;
if (l == NULL) /* variable not yet in table */ if (l == NULL) { /* variable not yet in table */
{ l = (BucketList) malloc(sizeof(struct BucketListEntry));
l = (BucketList) malloc(sizeof(struct BucketListRec));
l->name = name; 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->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->lines->next = NULL;
l->memloc = scope->location;
scope->location++;
l->next = hashTable[h]; l->next = hashTable[h];
hashTable[h] = l; 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; LineList t = l->lines;
while (t->next != NULL) t = t->next; while (t->next != NULL)
t->next = (LineList) malloc(sizeof(struct LineListRec)); t = t->next;
t->next = (LineList) malloc(sizeof(struct LineListEntry));
t->next->lineno = lineno; t->next->lineno = lineno;
t->next->next = NULL; t->next->next = NULL;
} }
} /* st_insert */ return l;
}
/* Function st_lookup returns the memory void st_entry_insert_line(BucketList entry, int lineno) {
* location of a variable or -1 if not found if (entry == NULL) return;
*/ LineList t = entry->lines;
int st_lookup(char *name) { 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); int h = hash(name);
Scope scope = curr_scope();
BucketList *hashTable = scope->hashTable;
BucketList l = hashTable[h]; BucketList l = hashTable[h];
while ((l != NULL) && (strcmp(name, l->name) != 0)) while ((l != NULL) && (strcmp(name, l->name) != 0))
l = l->next; l = l->next;
if (l == NULL) return -1;
else return l;
return l->memloc;
} }
/* Procedure printSymTab prints a formatted BucketList st_lookup(char *name) {
* listing of the symbol table contents int h = hash(name);
* to the listing file Scope scope = curr_scope();
*/ while (scope != NULL) {
void printSymTab(FILE *listing) { BucketList *hashTable = scope->hashTable;
int i; BucketList l = hashTable[h];
fprintf(listing, "Variable Name Location Line Numbers\n"); while ((l != NULL) && (strcmp(name, l->name) != 0))
fprintf(listing, "------------- -------- ------------\n"); l = l->next;
for (i = 0; i < SYMTAB_SIZE; ++i) { if (l != NULL) {
if (hashTable[i] != NULL) { return l;
BucketList l = hashTable[i]; }
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) { 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; LineList t = l->lines;
fprintf(listing, "%-14s ", l->name);
fprintf(listing, "%-8d ", l->memloc);
while (t != NULL) { while (t != NULL) {
fprintf(listing, "%4d ", t->lineno); fprintf(listing, "%d ", t->lineno);
t = t->next; t = t->next;
} }
fprintf(listing, "\n"); fprintf(listing, "\n");
l = l->next; l = l->next;
} }
} }
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;
} }
} /* printSymTab */ }
void printScopeTree(FILE *listing) {
if (scope_global == NULL) return;
Scope current_scope = scope_global;
printScopeRecursive(listing, current_scope);
}
void printSymTab(FILE *listing) {
printScopeTree(listing);
}

View File

@@ -9,16 +9,23 @@
#include "globals.h" #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 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 /* the list of line numbers of the source
* code in which a variable is referenced * code in which a variable is referenced
*/ */
typedef struct LineListEntry { typedef struct LineListEntry {
int lineno; int lineno;
struct LineListEntry *next; struct LineListEntry *next;
} *LineList; } * LineList;
/* The record in the bucket lists for /* The record in the bucket lists for
* each variable, including name, * each variable, including name,
@@ -29,28 +36,43 @@ typedef struct LineListEntry {
typedef struct BucketListEntry { typedef struct BucketListEntry {
char *name; char *name;
LineList lines; LineList lines;
SymbolKind symbolKind;
ExpType type; ExpType type;
ExpType param_types[MAX_PARAM_COUNT];
int param_count;
ExpType returnType;
int memloc; /* memory location for variable */ int memloc; /* memory location for variable */
struct BucketListEntry *next; struct BucketListEntry *next;
} *BucketList; } * BucketList;
typedef struct Scope { struct Scope {
char *name; char *name;
int depth; int depth;
struct Scope *parent; struct Scope *parent;
struct Scope *child;
struct Scope *child_last;
struct Scope *next_sibling;
int location;
BucketList hashTable[SYMTAB_SIZE]; BucketList hashTable[SYMTAB_SIZE];
} *Scope; };
Scope scope_global; extern Scope scope_global;// no sibling no parent
static Scope scope_list[SYMTAB_SIZE]; extern Scope scope_stack[MAX_SCOPE_DEPTH];
static int size_list = 0; 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 * 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 * @param scope_name: name of the scope
* @return the created scope * @return the created scope
*/ */
@@ -61,29 +83,33 @@ Scope scope_new(char *scope_name);
void pop_scope(void); void pop_scope(void);
/** /**
* push a scope into the scope stack * 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 * @param scope: the scope to be pushed
*/ */
void push_scope(Scope scope); void push_scope(Scope scope);
/** /**
* insert a scope into the scope list * get the top of the scope stack wit
*/
void insert_scope_to_list(Scope scope);
/**
* get the top of the scope stack
* @return the current scope or NULL if the stack is empty * @return the current scope or NULL if the stack is empty
*/ */
Scope curr_scope(void); Scope curr_scope(void);
/** /**
* insert a variable into the symbol table * insert a variable into the symbol table of the current scope
* or update a variable if it already exists * or add a line number if it already exists
* @param scope_name name of the scope
* @param name name of the variable * @param name name of the variable
* @param symbolkind kind of the symbol
* @param type type of the variable * @param type type of the variable
* @param lineno line number of the variable * @param lineno line number of the variable
* @param loc memory location of the variable
* @return 0 if success, -1 if failure * @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 * lookup a variable in the current scope
* @param name name of the variable to lookup * @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); 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 * @param name name of the variable to lookup
* @return the bucket list entry of the variable or NULL if not found * @return the bucket list entry of the variable or NULL if not found
*/ */
BucketList st_lookup(char *name); BucketList st_lookup(char *name);
/** /**
* find a scope from the scope list * lookup a variable from the given scope to root
* @param scope_name name of the scope to find * @param name name of the variable to lookup
* @return the scope or NULL if not found * @param scope the scope to start lookup from
*/ * @return the bucket list entry of the variable 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
*/ */
BucketList st_lookup_from(char *name, Scope scope);
void printScope(FILE *listing, Scope scope);
void printScopeTree(FILE *listing);
void printSymTab(FILE *listing); void printSymTab(FILE *listing);
#endif #endif

13
src/test.cm Normal file
View File

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