semi-complete semantic v2
This commit is contained in:
BIN
src/2024062806.docx
Normal file
BIN
src/2024062806.docx
Normal file
Binary file not shown.
@@ -117,7 +117,10 @@ static void insertNode(TreeNode *t) {
|
|||||||
func_scope = NULL;
|
func_scope = NULL;
|
||||||
func_param_count = 0;
|
func_param_count = 0;
|
||||||
} else {
|
} else {
|
||||||
push_scope(scope_new("compound"));
|
char *parent_scope_name = curr_scope()->name;
|
||||||
|
char *new_name = (char *) malloc(255);
|
||||||
|
snprintf(new_name, 255, "%s.%d", parent_scope_name, curr_scope()->child_count);
|
||||||
|
push_scope(scope_new(new_name));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -149,7 +152,7 @@ static void insertNode(TreeNode *t) {
|
|||||||
case NonArrParamK: {
|
case NonArrParamK: {
|
||||||
if (t->type == Void) {
|
if (t->type == Void) {
|
||||||
if (t->attr.name != NULL) {
|
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);
|
fprintf(listing, "Error: The void-type variable is declared at line %d (name : \"%s\")\n", t->lineno, t->attr.name);
|
||||||
Error = TRUE;
|
Error = TRUE;
|
||||||
} else {
|
} else {
|
||||||
goto insert_param_exit;
|
goto insert_param_exit;
|
||||||
@@ -171,6 +174,7 @@ static void insertNode(TreeNode *t) {
|
|||||||
lines = lines->next;
|
lines = lines->next;
|
||||||
}
|
}
|
||||||
fprintf(listing, ")\n");
|
fprintf(listing, ")\n");
|
||||||
|
st_entry_insert_line(entry, t->lineno);
|
||||||
Error = TRUE;
|
Error = TRUE;
|
||||||
} else {
|
} else {
|
||||||
if (t->type == Void) {
|
if (t->type == Void) {
|
||||||
@@ -204,14 +208,19 @@ void buildSymtab(TreeNode *syntaxTree) {
|
|||||||
BucketList entry;
|
BucketList entry;
|
||||||
entry = st_try_insert("input", SymbolFunc, Integer, 0);
|
entry = st_try_insert("input", SymbolFunc, Integer, 0);
|
||||||
entry->param_count = 0;
|
entry->param_count = 0;
|
||||||
|
entry->returnType = Integer;
|
||||||
|
|
||||||
entry = st_try_insert("output", SymbolFunc, Void, 0);
|
entry = st_try_insert("output", SymbolFunc, Void, 0);
|
||||||
|
entry->returnType = Void;
|
||||||
entry->param_types[0] = Integer;
|
entry->param_types[0] = Integer;
|
||||||
|
entry->param_names[0] = "value";
|
||||||
entry->param_count = 1;
|
entry->param_count = 1;
|
||||||
|
|
||||||
|
push_scope(scope_new("output"));
|
||||||
|
st_try_insert("value", SymbolParam, Integer, 0);
|
||||||
|
pop_scope();
|
||||||
traverse(syntaxTree, insertNode, afterNode);
|
traverse(syntaxTree, insertNode, afterNode);
|
||||||
if (TraceAnalyze) {
|
if (TraceAnalyze) {
|
||||||
fprintf(listing, "\nSymbol table:\n\n");
|
|
||||||
printSymTab(listing);
|
printSymTab(listing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,7 +243,7 @@ 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) {
|
||||||
fprintf(listing, "Error: Invalid operation at line %d\n", t->lineno);
|
fprintf(listing, "Error: invalid operation at line %d\n", t->lineno);
|
||||||
Error = TRUE;
|
Error = TRUE;
|
||||||
}
|
}
|
||||||
t->type = Integer;
|
t->type = Integer;
|
||||||
@@ -253,28 +262,33 @@ static void checkNode(TreeNode *t) {
|
|||||||
Error = TRUE;
|
Error = TRUE;
|
||||||
}
|
}
|
||||||
if (t->child[0]->type != Integer) {
|
if (t->child[0]->type != Integer) {
|
||||||
fprintf(listing, "Error: Invalid array indexing at line %d (name : \"%s\"). indicies should be integer\n", t->lineno, t->attr.name);
|
fprintf(listing, "Error: Invalid array indexing at line %d (name : \"%s\"). indices should be integer\n", t->lineno, t->attr.name);
|
||||||
Error = TRUE;
|
Error = TRUE;
|
||||||
}
|
}
|
||||||
t->type = IntegerArray;
|
t->type = Integer;
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case AssignK: {
|
case AssignK: {
|
||||||
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 == Integer && right->type == Integer) {
|
||||||
fprintf(listing, "Error: Invalid assignment at line %d\n", t->lineno);
|
|
||||||
|
} else if (left->type == IntegerArray && right->type == IntegerArray) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
fprintf(listing, "Error: invalid assignment at line %d. cannot assign to array variable\n", t->lineno);
|
||||||
Error = TRUE;
|
Error = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
t->type = right->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, "");
|
fprintf(listing, "Error: Invalid function call at line %d (name : \"%s\")\n", t->lineno, t->attr.name);
|
||||||
typeError(t, "Call to a non-function");
|
Error = TRUE;
|
||||||
|
goto check_callk_after;
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeNode *arg = t->child[0];
|
TreeNode *arg = t->child[0];
|
||||||
@@ -283,7 +297,7 @@ 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]) {
|
||||||
fprintf(listing, "Error: Invalid function call at line %d\n", t->lineno);
|
fprintf(listing, "Error: Invalid function call at line %d (name : \"%s\")\n", t->lineno, t->attr.name);
|
||||||
Error = TRUE;
|
Error = TRUE;
|
||||||
goto check_callk_after;
|
goto check_callk_after;
|
||||||
}
|
}
|
||||||
@@ -293,10 +307,10 @@ static void checkNode(TreeNode *t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (arg != NULL) {
|
if (arg != NULL) {
|
||||||
fprintf(listing, "Error: Invalid function call at line %d\n", t->lineno);
|
fprintf(listing, "Error: Invalid function call at line %d (name : \"%s\")\n", t->lineno, t->attr.name);
|
||||||
Error = TRUE;
|
Error = TRUE;
|
||||||
} else if (i < entry->param_count) {
|
} else if (i < entry->param_count) {
|
||||||
fprintf(listing, "Error: Invalid function call at line %d\n", t->lineno);
|
fprintf(listing, "Error: Invalid function call at line %d (name : \"%s\")\n", t->lineno, t->attr.name);
|
||||||
Error = TRUE;
|
Error = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,14 +349,14 @@ static void checkNode(TreeNode *t) {
|
|||||||
case IterK: {
|
case IterK: {
|
||||||
TreeNode *condition = t->child[0];
|
TreeNode *condition = t->child[0];
|
||||||
if (condition->type != Integer) {
|
if (condition->type != Integer) {
|
||||||
fprintf(listing, "Error: Invalid condition at line %d\n", t->lineno);
|
fprintf(listing, "Error: invalid condition at line %d\n", t->lineno);
|
||||||
Error = TRUE;
|
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) {
|
||||||
fprintf(listing, "Error: Invalid condition at line %d\n", t->lineno);
|
fprintf(listing, "Error: invalid condition at line %d\n", t->lineno);
|
||||||
Error = TRUE;
|
Error = TRUE;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
/****************************************************/
|
|
||||||
/* File: tiny.l */
|
|
||||||
/* Lex specification for TINY */
|
|
||||||
/* Compiler Construction: Principles and Practice */
|
|
||||||
/* Kenneth C. Louden */
|
|
||||||
/****************************************************/
|
|
||||||
|
|
||||||
%{
|
|
||||||
#include "globals.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "scan.h"
|
|
||||||
/* lexeme of identifier or reserved word */
|
|
||||||
char tokenString[MAXTOKENLEN+1];
|
|
||||||
%}
|
|
||||||
|
|
||||||
digit [0-9]
|
|
||||||
number {digit}+
|
|
||||||
letter [a-zA-Z]
|
|
||||||
identifier {letter}+
|
|
||||||
newline \n
|
|
||||||
whitespace [ \t]+
|
|
||||||
|
|
||||||
%%
|
|
||||||
|
|
||||||
"if" {return IF;}
|
|
||||||
"then" {return THEN;}
|
|
||||||
"else" {return ELSE;}
|
|
||||||
"end" {return END;}
|
|
||||||
"repeat" {return REPEAT;}
|
|
||||||
"until" {return UNTIL;}
|
|
||||||
"read" {return READ;}
|
|
||||||
"write" {return WRITE;}
|
|
||||||
":=" {return ASSIGN;}
|
|
||||||
"=" {return EQ;}
|
|
||||||
"<" {return LT;}
|
|
||||||
"+" {return PLUS;}
|
|
||||||
"-" {return MINUS;}
|
|
||||||
"*" {return TIMES;}
|
|
||||||
"/" {return OVER;}
|
|
||||||
"(" {return LPAREN;}
|
|
||||||
")" {return RPAREN;}
|
|
||||||
";" {return SEMI;}
|
|
||||||
{number} {return NUM;}
|
|
||||||
{identifier} {return ID;}
|
|
||||||
{newline} {lineno++;}
|
|
||||||
{whitespace} {/* skip whitespace */}
|
|
||||||
"{" { char c;
|
|
||||||
do
|
|
||||||
{ c = input();
|
|
||||||
if (c == EOF) break;
|
|
||||||
if (c == '\n') lineno++;
|
|
||||||
} while (c != '}');
|
|
||||||
}
|
|
||||||
. {return ERROR;}
|
|
||||||
|
|
||||||
%%
|
|
||||||
|
|
||||||
TokenType getToken(void)
|
|
||||||
{ static int firstTime = TRUE;
|
|
||||||
TokenType currentToken;
|
|
||||||
if (firstTime)
|
|
||||||
{ firstTime = FALSE;
|
|
||||||
lineno++;
|
|
||||||
yyin = source;
|
|
||||||
yyout = listing;
|
|
||||||
}
|
|
||||||
currentToken = yylex();
|
|
||||||
strncpy(tokenString,yytext,MAXTOKENLEN);
|
|
||||||
if (TraceScan) {
|
|
||||||
fprintf(listing,"\t%d: ",lineno);
|
|
||||||
printToken(currentToken,tokenString);
|
|
||||||
}
|
|
||||||
return currentToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
47
src/res.txt
Normal file
47
src/res.txt
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
C-MINUS COMPILATION: ./test.cm
|
||||||
|
|
||||||
|
Building Symbol Table...
|
||||||
|
Error: undeclared function "x" is called at line 3
|
||||||
|
|
||||||
|
|
||||||
|
< 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
|
||||||
|
value Variable int output 0 0
|
||||||
|
x Function undetermined main 0 3
|
||||||
|
|
||||||
|
|
||||||
|
< Functions >
|
||||||
|
Function Name Return Type Parameter Name Parameter Type
|
||||||
|
------------- ------------- -------------- --------------
|
||||||
|
main int void
|
||||||
|
input int void
|
||||||
|
output void
|
||||||
|
- - value int
|
||||||
|
x undetermined undetermined
|
||||||
|
|
||||||
|
|
||||||
|
< 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 void
|
||||||
|
|
||||||
|
|
||||||
|
Checking Types...
|
||||||
|
Error: Invalid function call at line 3 (name : "x")
|
||||||
|
|
||||||
|
Type Checking Finished
|
||||||
44
src/sample.txt
Normal file
44
src/sample.txt
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
C-MINUS COMPILATION: ./testcase/3_Semantic_Makefile_Testcase/mytest.8.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
|
||||||
|
value Variable int output 0 0
|
||||||
|
x Variable int main 0 2 3
|
||||||
|
|
||||||
|
|
||||||
|
< 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 function call at line 3 (name : "x")
|
||||||
|
|
||||||
|
Type Checking Finished
|
||||||
248
src/symtab.c
248
src/symtab.c
@@ -178,35 +178,52 @@ BucketList st_lookup_from(char *name, Scope scope) {
|
|||||||
return NULL; /* not found */
|
return NULL; /* not found */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printEntry(FILE *listing, BucketList entry) {
|
static void printEntry(FILE *listing, Scope scope, BucketList entry) {
|
||||||
if (entry == NULL) return;
|
if (entry == NULL) return;
|
||||||
fprintf(listing, "%-14s", entry->name);
|
fprintf(listing, "%-13s", entry->name);
|
||||||
|
fprintf(listing, " ");
|
||||||
switch (entry->symbolKind) {
|
switch (entry->symbolKind) {
|
||||||
case SymbolVar:
|
case SymbolVar:
|
||||||
fprintf(listing, "|%-13s", "Var");
|
fprintf(listing, "%-11s", "Variable");
|
||||||
break;
|
break;
|
||||||
case SymbolFunc:
|
case SymbolFunc:
|
||||||
fprintf(listing, "|%-13s", "Func");
|
fprintf(listing, "%-11s", "Function");
|
||||||
break;
|
break;
|
||||||
case SymbolParam:
|
case SymbolParam:
|
||||||
fprintf(listing, "|%-13s", "Param");
|
fprintf(listing, "%-11s", "Variable");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (entry->type) {
|
fprintf(listing, " ");
|
||||||
|
ExpType type;
|
||||||
|
if (entry->symbolKind == SymbolFunc) {
|
||||||
|
type = entry->returnType;
|
||||||
|
} else {
|
||||||
|
type = entry->type;
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
case Void:
|
case Void:
|
||||||
fprintf(listing, "|%-11s", "void");
|
fprintf(listing, "%-13s", "void");
|
||||||
break;
|
break;
|
||||||
case Integer:
|
case Integer:
|
||||||
fprintf(listing, "|%-11s", "int");
|
fprintf(listing, "%-13s", "int");
|
||||||
break;
|
break;
|
||||||
case IntegerArray:
|
case IntegerArray:
|
||||||
fprintf(listing, "|%-11s", "int[]");
|
fprintf(listing, "%-13s", "int[]");
|
||||||
break;
|
break;
|
||||||
|
case Undetermined:
|
||||||
|
fprintf(listing, "%-13s", "undetermined");
|
||||||
}
|
}
|
||||||
fprintf(listing, "|%-9d|", entry->memloc);
|
//
|
||||||
|
fprintf(listing, " ");
|
||||||
|
fprintf(listing, "%-12s", scope->name);
|
||||||
|
//
|
||||||
|
fprintf(listing, " ");
|
||||||
|
fprintf(listing, "%-8d", entry->memloc);
|
||||||
|
fprintf(listing, " ");
|
||||||
LineList t = entry->lines;
|
LineList t = entry->lines;
|
||||||
while (t != NULL) {
|
while (t != NULL) {
|
||||||
fprintf(listing, "%d ", t->lineno);
|
fprintf(listing, "%3d", t->lineno);
|
||||||
|
fprintf(listing, " ");
|
||||||
t = t->next;
|
t = t->next;
|
||||||
}
|
}
|
||||||
fprintf(listing, "\n");
|
fprintf(listing, "\n");
|
||||||
@@ -218,13 +235,14 @@ static void printScopeTable(FILE *listing, Scope scope) {
|
|||||||
for (int i = 0; i < SYMTAB_SIZE; ++i) {
|
for (int i = 0; i < SYMTAB_SIZE; ++i) {
|
||||||
BucketList l = scope->hashTable[i];
|
BucketList l = scope->hashTable[i];
|
||||||
while (l != NULL) {
|
while (l != NULL) {
|
||||||
|
printEntry(listing, scope, l);
|
||||||
count++;
|
count++;
|
||||||
l = l->next;
|
l = l->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
BucketList *entries = (BucketList *)malloc(sizeof(BucketList) * count);
|
BucketList *entries = (BucketList *) malloc(sizeof(BucketList) * count);
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for (int i = 0; i < SYMTAB_SIZE; ++i) {
|
for (int i = 0; i < SYMTAB_SIZE; ++i) {
|
||||||
BucketList l = scope->hashTable[i];
|
BucketList l = scope->hashTable[i];
|
||||||
@@ -245,15 +263,16 @@ static void printScopeTable(FILE *listing, Scope scope) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
printEntry(listing, entries[i]);
|
printEntry(listing, scope, entries[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(entries);
|
free(entries);
|
||||||
}
|
}
|
||||||
fprintf(listing, "\n");
|
*/
|
||||||
|
//fprintf(listing, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void printScope(FILE *listing, Scope scope) {
|
static void printScope(FILE *listing, Scope scope) {
|
||||||
if (scope == NULL) return;
|
if (scope == NULL) return;
|
||||||
fprintf(listing, "Scope Name: %s, Depth: %d\n", scope->name, scope->depth);
|
fprintf(listing, "Scope Name: %s, Depth: %d\n", scope->name, scope->depth);
|
||||||
fprintf(listing, "-----------------------------------------\n");
|
fprintf(listing, "-----------------------------------------\n");
|
||||||
@@ -275,7 +294,7 @@ static void printScopeRecursive(FILE *listing, Scope scope) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printScopeTree(FILE *listing) {
|
static void printScopeTree(FILE *listing) {
|
||||||
if (scope_global == NULL) return;
|
if (scope_global == NULL) return;
|
||||||
|
|
||||||
Scope current_scope = scope_global;
|
Scope current_scope = scope_global;
|
||||||
@@ -295,12 +314,193 @@ static void printScopeTableRecursive(FILE *listing, Scope scope) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printSymTab(FILE *listing) {
|
static void printFunctionTableRecursive(FILE *listing, Scope scope) {
|
||||||
fprintf(listing, "Scope Table");
|
for (int i = 0; i < SYMTAB_SIZE; ++i) {
|
||||||
fprintf(listing, "------------------------------------------------------------\n");
|
BucketList entry = scope->hashTable[i];
|
||||||
fprintf(listing, "Variable Name Symbol Kind Type Location Line Numbers\n");
|
while (entry != NULL) {
|
||||||
fprintf(listing, "------------------------------------------------------------\n");
|
if (entry->symbolKind == SymbolFunc) {
|
||||||
|
fprintf(listing, "%-13s", entry->name);
|
||||||
|
fprintf(listing, " ");
|
||||||
|
switch (entry->returnType) {
|
||||||
|
case Void:
|
||||||
|
fprintf(listing, "%-13s", "void");
|
||||||
|
break;
|
||||||
|
case Integer:
|
||||||
|
fprintf(listing, "%-13s", "int");
|
||||||
|
break;
|
||||||
|
case IntegerArray:
|
||||||
|
fprintf(listing, "%-13s", "int[]");
|
||||||
|
break;
|
||||||
|
case Undetermined:
|
||||||
|
fprintf(listing, "%-13s", "undetermined");
|
||||||
|
}
|
||||||
|
if (entry->param_count == -1) {
|
||||||
|
fprintf(listing, " ");
|
||||||
|
fprintf(listing, "%-14s", "undetermined");
|
||||||
|
entry = entry->next;
|
||||||
|
fprintf(listing, "\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (entry->param_count == 0) {
|
||||||
|
fprintf(listing, " ");
|
||||||
|
fprintf(listing, "%-14s", "void");
|
||||||
|
entry = entry->next;
|
||||||
|
fprintf(listing, "\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fprintf(listing, " \n");
|
||||||
|
for (int j = 0; j < entry->param_count; j++) {
|
||||||
|
fprintf(listing, "- - ");
|
||||||
|
fprintf(listing, " %-14s", entry->param_names[j]);
|
||||||
|
fprintf(listing, " ");
|
||||||
|
switch (entry->param_types[j]) {
|
||||||
|
case Void:
|
||||||
|
fprintf(listing, "%-14s", "void");
|
||||||
|
break;
|
||||||
|
case Integer:
|
||||||
|
fprintf(listing, "%-14s", "int");
|
||||||
|
break;
|
||||||
|
case IntegerArray:
|
||||||
|
fprintf(listing, "%-14s", "int[]");
|
||||||
|
break;
|
||||||
|
case Undetermined:
|
||||||
|
fprintf(listing, "%-14s", "undetermined");
|
||||||
|
}
|
||||||
|
fprintf(listing, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Scope curr = scope_global;
|
Scope child = scope->child;
|
||||||
printScopeTableRecursive(listing, curr);
|
while (child != NULL) {
|
||||||
|
printFunctionTableRecursive(listing, child);
|
||||||
|
child = child->next_sibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void printFunctionTable(FILE *listing) {
|
||||||
|
if (scope_global == NULL) return;
|
||||||
|
|
||||||
|
printFunctionTableRecursive(listing, scope_global);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void printGlobalSymbols(FILE *listing) {
|
||||||
|
if (scope_global == NULL) return;
|
||||||
|
|
||||||
|
for (int i = 0; i < SYMTAB_SIZE; ++i) {
|
||||||
|
BucketList entry = scope_global->hashTable[i];
|
||||||
|
while (entry != NULL) {
|
||||||
|
fprintf(listing, "%-13s ", entry->name);
|
||||||
|
|
||||||
|
switch (entry->symbolKind) {
|
||||||
|
case SymbolVar:
|
||||||
|
fprintf(listing, "%-11s ", "Variable");
|
||||||
|
break;
|
||||||
|
case SymbolFunc:
|
||||||
|
fprintf(listing, "%-11s ", "Function");
|
||||||
|
break;
|
||||||
|
case SymbolParam:
|
||||||
|
fprintf(listing, "%-11s ", "Variable");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ExpType type;
|
||||||
|
if (entry->symbolKind == SymbolFunc) {
|
||||||
|
type = entry->returnType;
|
||||||
|
} else {
|
||||||
|
type = entry->type;
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case Void:
|
||||||
|
fprintf(listing, "%-13s", "void");
|
||||||
|
break;
|
||||||
|
case Integer:
|
||||||
|
fprintf(listing, "%-13s", "int");
|
||||||
|
break;
|
||||||
|
case IntegerArray:
|
||||||
|
fprintf(listing, "%-13s", "int[]");
|
||||||
|
break;
|
||||||
|
case Undetermined:
|
||||||
|
fprintf(listing, "%-13s", "undetermined");
|
||||||
|
}
|
||||||
|
fprintf(listing, "\n");
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void printScopeTableAdvancedRecursive(FILE *listing, Scope scope) {
|
||||||
|
if (scope == NULL) return;
|
||||||
|
int no_sym = TRUE;
|
||||||
|
for (int i = 0; i < SYMTAB_SIZE; ++i) {
|
||||||
|
BucketList entry = scope->hashTable[i];
|
||||||
|
while (entry != NULL) {
|
||||||
|
no_sym = FALSE;
|
||||||
|
fprintf(listing, "%-12s", scope->name);
|
||||||
|
fprintf(listing, " ");
|
||||||
|
fprintf(listing, "%-12d", scope->depth);
|
||||||
|
fprintf(listing, " ");
|
||||||
|
fprintf(listing, "%-13s", entry->name);
|
||||||
|
fprintf(listing, " ");
|
||||||
|
switch (entry->type) {
|
||||||
|
case Void:
|
||||||
|
fprintf(listing, "%-11s", "void");
|
||||||
|
break;
|
||||||
|
case Integer:
|
||||||
|
fprintf(listing, "%-11s", "int");
|
||||||
|
break;
|
||||||
|
case IntegerArray:
|
||||||
|
fprintf(listing, "%-11s", "int[]");
|
||||||
|
break;
|
||||||
|
case Undetermined:
|
||||||
|
fprintf(listing, "%-11s", "undetermined");
|
||||||
|
}
|
||||||
|
fprintf(listing, "\n");
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!no_sym) fprintf(listing, "\n");
|
||||||
|
|
||||||
|
Scope child = scope->child;
|
||||||
|
while (child != NULL) {
|
||||||
|
printScopeTableAdvancedRecursive(listing, child);
|
||||||
|
child = child->next_sibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void printScopeTableAdvanced(FILE *listing) {
|
||||||
|
if (scope_global == NULL) return;
|
||||||
|
|
||||||
|
Scope current_scope;
|
||||||
|
|
||||||
|
current_scope = scope_global->child;
|
||||||
|
|
||||||
|
while (current_scope != NULL) {
|
||||||
|
printScopeTableAdvancedRecursive(listing, current_scope);
|
||||||
|
current_scope = current_scope->next_sibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printSymTab(FILE *listing) {
|
||||||
|
Scope curr = scope_global;
|
||||||
|
fprintf(listing, "\n\n< Symbol Table >\n");
|
||||||
|
fprintf(listing, " Symbol Name Symbol Kind Symbol Type Scope Name Location Line Numbers\n");
|
||||||
|
fprintf(listing, "------------- ----------- ------------- ------------ -------- ------------\n");
|
||||||
|
printScopeTableRecursive(listing, curr);
|
||||||
|
|
||||||
|
fprintf(listing, "\n\n< Functions >\n");
|
||||||
|
fprintf(listing, "Function Name Return Type Parameter Name Parameter Type\n");
|
||||||
|
fprintf(listing, "------------- ------------- -------------- --------------\n");
|
||||||
|
printFunctionTable(listing);
|
||||||
|
|
||||||
|
fprintf(listing, "\n\n< Global Symbols >\n");
|
||||||
|
fprintf(listing, " Symbol Name Symbol Kind Symbol Type\n");
|
||||||
|
fprintf(listing, "------------- ----------- -------------\n");
|
||||||
|
printGlobalSymbols(listing);
|
||||||
|
|
||||||
|
fprintf(listing, "\n\n< Scopes >\n");
|
||||||
|
fprintf(listing, " Scope Name Nested Level Symbol Name Symbol Type\n");
|
||||||
|
fprintf(listing, "------------ ------------ ------------- -----------\n");
|
||||||
|
printScopeTableAdvanced(listing);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
#define SYMTAB_SIZE 211
|
#define SYMTAB_SIZE 211
|
||||||
|
|
||||||
#define MAX_SCOPE_DEPTH 32
|
#define MAX_SCOPE_DEPTH 1557
|
||||||
#define MAX_SCOPE_COUNT 1557
|
|
||||||
|
|
||||||
#define MAX_PARAM_COUNT 13
|
#define MAX_PARAM_COUNT 13
|
||||||
|
|
||||||
@@ -134,10 +133,6 @@ BucketList st_lookup(char *name);
|
|||||||
*/
|
*/
|
||||||
BucketList st_lookup_from(char *name, Scope scope);
|
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
|
||||||
|
|||||||
21
src/test.cm
21
src/test.cm
@@ -1,13 +1,16 @@
|
|||||||
int fib(int n) {
|
int main(void)
|
||||||
if (n <= 0) {
|
{
|
||||||
return 1;
|
x(1, 2);
|
||||||
} else {
|
|
||||||
return fib(n * fib(n - 1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
if (x) {
|
||||||
int x;
|
int x;
|
||||||
x = fib(input());
|
x = 3;
|
||||||
|
} else {
|
||||||
|
int y;
|
||||||
|
y = 0;
|
||||||
|
x = 5;
|
||||||
|
}
|
||||||
output(x);
|
output(x);
|
||||||
}
|
}*/
|
||||||
@@ -1,6 +1,3 @@
|
|||||||
/* A program to perform Euclid's
|
|
||||||
Algorithm to computer gcd */
|
|
||||||
|
|
||||||
int gcd (int u, int v)
|
int gcd (int u, int v)
|
||||||
{
|
{
|
||||||
if (v == 0) return u;
|
if (v == 0) return u;
|
||||||
|
|||||||
@@ -1,120 +0,0 @@
|
|||||||
/****************************************************/
|
|
||||||
/* File: globals.h */
|
|
||||||
/* Yacc/Bison Version */
|
|
||||||
/* Global types and vars for TINY compiler */
|
|
||||||
/* must come before other include files */
|
|
||||||
/* Compiler Construction: Principles and Practice */
|
|
||||||
/* Kenneth C. Louden */
|
|
||||||
/****************************************************/
|
|
||||||
|
|
||||||
#ifndef _GLOBALS_H_
|
|
||||||
#define _GLOBALS_H_
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/* Yacc/Bison generates internally its own values
|
|
||||||
* for the tokens. Other files can access these values
|
|
||||||
* by including the tab.h file generated using the
|
|
||||||
* Yacc/Bison option -d ("generate header")
|
|
||||||
*
|
|
||||||
* The YYPARSER flag prevents inclusion of the tab.h
|
|
||||||
* into the Yacc/Bison output itself
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef YYPARSER
|
|
||||||
|
|
||||||
/* the name of the following file may change */
|
|
||||||
#include "y.tab.h"
|
|
||||||
|
|
||||||
/* ENDFILE is implicitly defined by Yacc/Bison,
|
|
||||||
* and not included in the tab.h file
|
|
||||||
*/
|
|
||||||
#define ENDFILE 0
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FALSE
|
|
||||||
#define FALSE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
#define TRUE 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* MAXRESERVED = the number of reserved words */
|
|
||||||
#define MAXRESERVED 8
|
|
||||||
|
|
||||||
/* Yacc/Bison generates its own integer values
|
|
||||||
* for tokens
|
|
||||||
*/
|
|
||||||
typedef int TokenType;
|
|
||||||
|
|
||||||
extern FILE* source; /* source code text file */
|
|
||||||
extern FILE* listing; /* listing output text file */
|
|
||||||
extern FILE* code; /* code text file for TM simulator */
|
|
||||||
|
|
||||||
extern int lineno; /* source line number for listing */
|
|
||||||
|
|
||||||
/**************************************************/
|
|
||||||
/*********** Syntax tree for parsing ************/
|
|
||||||
/**************************************************/
|
|
||||||
|
|
||||||
typedef enum {StmtK,ExpK} NodeKind;
|
|
||||||
typedef enum {IfK,RepeatK,AssignK,ReadK,WriteK} StmtKind;
|
|
||||||
typedef enum {OpK,ConstK,IdK} ExpKind;
|
|
||||||
|
|
||||||
/* ExpType is used for type checking */
|
|
||||||
typedef enum {Void,Integer,Boolean} ExpType;
|
|
||||||
|
|
||||||
#define MAXCHILDREN 3
|
|
||||||
|
|
||||||
typedef struct treeNode
|
|
||||||
{ struct treeNode * child[MAXCHILDREN];
|
|
||||||
struct treeNode * sibling;
|
|
||||||
int lineno;
|
|
||||||
NodeKind nodekind;
|
|
||||||
union { StmtKind stmt; ExpKind exp;} kind;
|
|
||||||
union { TokenType op;
|
|
||||||
int val;
|
|
||||||
char * name; } attr;
|
|
||||||
ExpType type; /* for type checking of exps */
|
|
||||||
} TreeNode;
|
|
||||||
|
|
||||||
/**************************************************/
|
|
||||||
/*********** Flags for tracing ************/
|
|
||||||
/**************************************************/
|
|
||||||
|
|
||||||
/* EchoSource = TRUE causes the source program to
|
|
||||||
* be echoed to the listing file with line numbers
|
|
||||||
* during parsing
|
|
||||||
*/
|
|
||||||
extern int EchoSource;
|
|
||||||
|
|
||||||
/* TraceScan = TRUE causes token information to be
|
|
||||||
* printed to the listing file as each token is
|
|
||||||
* recognized by the scanner
|
|
||||||
*/
|
|
||||||
extern int TraceScan;
|
|
||||||
|
|
||||||
/* TraceParse = TRUE causes the syntax tree to be
|
|
||||||
* printed to the listing file in linearized form
|
|
||||||
* (using indents for children)
|
|
||||||
*/
|
|
||||||
extern int TraceParse;
|
|
||||||
|
|
||||||
/* TraceAnalyze = TRUE causes symbol table inserts
|
|
||||||
* and lookups to be reported to the listing file
|
|
||||||
*/
|
|
||||||
extern int TraceAnalyze;
|
|
||||||
|
|
||||||
/* TraceCode = TRUE causes comments to be written
|
|
||||||
* to the TM code file as code is generated
|
|
||||||
*/
|
|
||||||
extern int TraceCode;
|
|
||||||
|
|
||||||
/* Error = TRUE prevents further passes if an error occurs */
|
|
||||||
extern int Error;
|
|
||||||
#endif
|
|
||||||
164
src/yacc/tiny.y
164
src/yacc/tiny.y
@@ -1,164 +0,0 @@
|
|||||||
/****************************************************/
|
|
||||||
/* File: tiny.y */
|
|
||||||
/* The TINY Yacc/Bison specification file */
|
|
||||||
/* Compiler Construction: Principles and Practice */
|
|
||||||
/* Kenneth C. Louden */
|
|
||||||
/****************************************************/
|
|
||||||
%{
|
|
||||||
#define YYPARSER /* distinguishes Yacc output from other code files */
|
|
||||||
|
|
||||||
#include "globals.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "scan.h"
|
|
||||||
#include "parse.h"
|
|
||||||
|
|
||||||
#define YYSTYPE TreeNode *
|
|
||||||
static char * savedName; /* for use in assignments */
|
|
||||||
static int savedLineNo; /* ditto */
|
|
||||||
static TreeNode * savedTree; /* stores syntax tree for later return */
|
|
||||||
static int yylex(void); // added 11/2/11 to ensure no conflict with lex
|
|
||||||
|
|
||||||
%}
|
|
||||||
|
|
||||||
%token IF THEN ELSE END REPEAT UNTIL READ WRITE
|
|
||||||
%token ID NUM
|
|
||||||
%token ASSIGN EQ LT PLUS MINUS TIMES OVER LPAREN RPAREN SEMI
|
|
||||||
%token ERROR
|
|
||||||
|
|
||||||
%% /* Grammar for TINY */
|
|
||||||
|
|
||||||
program : stmt_seq
|
|
||||||
{ savedTree = $1;}
|
|
||||||
;
|
|
||||||
stmt_seq : stmt_seq SEMI stmt
|
|
||||||
{ YYSTYPE t = $1;
|
|
||||||
if (t != NULL)
|
|
||||||
{ while (t->sibling != NULL)
|
|
||||||
t = t->sibling;
|
|
||||||
t->sibling = $3;
|
|
||||||
$$ = $1; }
|
|
||||||
else $$ = $3;
|
|
||||||
}
|
|
||||||
| stmt { $$ = $1; }
|
|
||||||
;
|
|
||||||
stmt : if_stmt { $$ = $1; }
|
|
||||||
| repeat_stmt { $$ = $1; }
|
|
||||||
| assign_stmt { $$ = $1; }
|
|
||||||
| read_stmt { $$ = $1; }
|
|
||||||
| write_stmt { $$ = $1; }
|
|
||||||
| error { $$ = NULL; }
|
|
||||||
;
|
|
||||||
if_stmt : IF exp THEN stmt_seq END
|
|
||||||
{ $$ = newStmtNode(IfK);
|
|
||||||
$$->child[0] = $2;
|
|
||||||
$$->child[1] = $4;
|
|
||||||
}
|
|
||||||
| IF exp THEN stmt_seq ELSE stmt_seq END
|
|
||||||
{ $$ = newStmtNode(IfK);
|
|
||||||
$$->child[0] = $2;
|
|
||||||
$$->child[1] = $4;
|
|
||||||
$$->child[2] = $6;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
repeat_stmt : REPEAT stmt_seq UNTIL exp
|
|
||||||
{ $$ = newStmtNode(RepeatK);
|
|
||||||
$$->child[0] = $2;
|
|
||||||
$$->child[1] = $4;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
assign_stmt : ID { savedName = copyString(tokenString);
|
|
||||||
savedLineNo = lineno; }
|
|
||||||
ASSIGN exp
|
|
||||||
{ $$ = newStmtNode(AssignK);
|
|
||||||
$$->child[0] = $4;
|
|
||||||
$$->attr.name = savedName;
|
|
||||||
$$->lineno = savedLineNo;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
read_stmt : READ ID
|
|
||||||
{ $$ = newStmtNode(ReadK);
|
|
||||||
$$->attr.name =
|
|
||||||
copyString(tokenString);
|
|
||||||
}
|
|
||||||
;
|
|
||||||
write_stmt : WRITE exp
|
|
||||||
{ $$ = newStmtNode(WriteK);
|
|
||||||
$$->child[0] = $2;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
exp : simple_exp LT simple_exp
|
|
||||||
{ $$ = newExpNode(OpK);
|
|
||||||
$$->child[0] = $1;
|
|
||||||
$$->child[1] = $3;
|
|
||||||
$$->attr.op = LT;
|
|
||||||
}
|
|
||||||
| simple_exp EQ simple_exp
|
|
||||||
{ $$ = newExpNode(OpK);
|
|
||||||
$$->child[0] = $1;
|
|
||||||
$$->child[1] = $3;
|
|
||||||
$$->attr.op = EQ;
|
|
||||||
}
|
|
||||||
| simple_exp { $$ = $1; }
|
|
||||||
;
|
|
||||||
simple_exp : simple_exp PLUS term
|
|
||||||
{ $$ = newExpNode(OpK);
|
|
||||||
$$->child[0] = $1;
|
|
||||||
$$->child[1] = $3;
|
|
||||||
$$->attr.op = PLUS;
|
|
||||||
}
|
|
||||||
| simple_exp MINUS term
|
|
||||||
{ $$ = newExpNode(OpK);
|
|
||||||
$$->child[0] = $1;
|
|
||||||
$$->child[1] = $3;
|
|
||||||
$$->attr.op = MINUS;
|
|
||||||
}
|
|
||||||
| term { $$ = $1; }
|
|
||||||
;
|
|
||||||
term : term TIMES factor
|
|
||||||
{ $$ = newExpNode(OpK);
|
|
||||||
$$->child[0] = $1;
|
|
||||||
$$->child[1] = $3;
|
|
||||||
$$->attr.op = TIMES;
|
|
||||||
}
|
|
||||||
| term OVER factor
|
|
||||||
{ $$ = newExpNode(OpK);
|
|
||||||
$$->child[0] = $1;
|
|
||||||
$$->child[1] = $3;
|
|
||||||
$$->attr.op = OVER;
|
|
||||||
}
|
|
||||||
| factor { $$ = $1; }
|
|
||||||
;
|
|
||||||
factor : LPAREN exp RPAREN
|
|
||||||
{ $$ = $2; }
|
|
||||||
| NUM
|
|
||||||
{ $$ = newExpNode(ConstK);
|
|
||||||
$$->attr.val = atoi(tokenString);
|
|
||||||
}
|
|
||||||
| ID { $$ = newExpNode(IdK);
|
|
||||||
$$->attr.name =
|
|
||||||
copyString(tokenString);
|
|
||||||
}
|
|
||||||
| error { $$ = NULL; }
|
|
||||||
;
|
|
||||||
|
|
||||||
%%
|
|
||||||
|
|
||||||
int yyerror(char * message)
|
|
||||||
{ fprintf(listing,"Syntax error at line %d: %s\n",lineno,message);
|
|
||||||
fprintf(listing,"Current token: ");
|
|
||||||
printToken(yychar,tokenString);
|
|
||||||
Error = TRUE;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* yylex calls getToken to make Yacc/Bison output
|
|
||||||
* compatible with ealier versions of the TINY scanner
|
|
||||||
*/
|
|
||||||
static int yylex(void)
|
|
||||||
{ return getToken(); }
|
|
||||||
|
|
||||||
TreeNode * parse(void)
|
|
||||||
{ yyparse();
|
|
||||||
return savedTree;
|
|
||||||
}
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user