diff --git a/src/2024062806.docx b/src/2024062806.docx new file mode 100644 index 0000000..66787cb Binary files /dev/null and b/src/2024062806.docx differ diff --git a/src/analyze.c b/src/analyze.c index f1f99d3..9d7ec5c 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -117,7 +117,10 @@ static void insertNode(TreeNode *t) { func_scope = NULL; func_param_count = 0; } 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; default: @@ -149,7 +152,7 @@ static void insertNode(TreeNode *t) { case NonArrParamK: { 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); + fprintf(listing, "Error: The void-type variable is declared at line %d (name : \"%s\")\n", t->lineno, t->attr.name); Error = TRUE; } else { goto insert_param_exit; @@ -171,6 +174,7 @@ static void insertNode(TreeNode *t) { lines = lines->next; } fprintf(listing, ")\n"); + st_entry_insert_line(entry, t->lineno); Error = TRUE; } else { if (t->type == Void) { @@ -204,14 +208,19 @@ void buildSymtab(TreeNode *syntaxTree) { BucketList entry; entry = st_try_insert("input", SymbolFunc, Integer, 0); entry->param_count = 0; + entry->returnType = Integer; entry = st_try_insert("output", SymbolFunc, Void, 0); + entry->returnType = Void; entry->param_types[0] = Integer; + entry->param_names[0] = "value"; entry->param_count = 1; + push_scope(scope_new("output")); + st_try_insert("value", SymbolParam, Integer, 0); + pop_scope(); traverse(syntaxTree, insertNode, afterNode); if (TraceAnalyze) { - fprintf(listing, "\nSymbol table:\n\n"); printSymTab(listing); } } @@ -234,7 +243,7 @@ static void checkNode(TreeNode *t) { TreeNode *left = t->child[0]; TreeNode *right = t->child[1]; 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; } t->type = Integer; @@ -253,28 +262,33 @@ static void checkNode(TreeNode *t) { Error = TRUE; } 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; } - t->type = IntegerArray; - + t->type = Integer; } break; case AssignK: { TreeNode *left = t->child[0]; TreeNode *right = t->child[1]; - if (left->type != right->type) { - fprintf(listing, "Error: Invalid assignment at line %d\n", t->lineno); + if (left->type == Integer && right->type == Integer) { + + } 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; } + 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"); + fprintf(listing, "Error: Invalid function call at line %d (name : \"%s\")\n", t->lineno, t->attr.name); + Error = TRUE; + goto check_callk_after; } TreeNode *arg = t->child[0]; @@ -283,7 +297,7 @@ static void checkNode(TreeNode *t) { while (arg != NULL && i < entry->param_count) { 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; goto check_callk_after; } @@ -293,10 +307,10 @@ static void checkNode(TreeNode *t) { } 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; } 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; } @@ -335,14 +349,14 @@ static void checkNode(TreeNode *t) { case IterK: { TreeNode *condition = t->child[0]; 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; } } break; case IfK: { TreeNode *condition = t->child[0]; 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; } } break; diff --git a/src/lex/tiny.l b/src/lex/tiny.l deleted file mode 100644 index aa96caa..0000000 --- a/src/lex/tiny.l +++ /dev/null @@ -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; -} - diff --git a/src/res.txt b/src/res.txt new file mode 100644 index 0000000..6f4c76a --- /dev/null +++ b/src/res.txt @@ -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 diff --git a/src/sample.txt b/src/sample.txt new file mode 100644 index 0000000..4ef881a --- /dev/null +++ b/src/sample.txt @@ -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 diff --git a/src/symtab.c b/src/symtab.c index 505329c..9393ea1 100644 --- a/src/symtab.c +++ b/src/symtab.c @@ -178,35 +178,52 @@ BucketList st_lookup_from(char *name, Scope scope) { return NULL; /* not found */ } -static void printEntry(FILE *listing, BucketList entry) { +static void printEntry(FILE *listing, Scope scope, BucketList entry) { if (entry == NULL) return; - fprintf(listing, "%-14s", entry->name); + fprintf(listing, "%-13s", entry->name); + fprintf(listing, " "); switch (entry->symbolKind) { case SymbolVar: - fprintf(listing, "|%-13s", "Var"); + fprintf(listing, "%-11s", "Variable"); break; case SymbolFunc: - fprintf(listing, "|%-13s", "Func"); + fprintf(listing, "%-11s", "Function"); break; case SymbolParam: - fprintf(listing, "|%-13s", "Param"); + fprintf(listing, "%-11s", "Variable"); break; } - switch (entry->type) { + fprintf(listing, " "); + ExpType type; + if (entry->symbolKind == SymbolFunc) { + type = entry->returnType; + } else { + type = entry->type; + } + switch (type) { case Void: - fprintf(listing, "|%-11s", "void"); + fprintf(listing, "%-13s", "void"); break; case Integer: - fprintf(listing, "|%-11s", "int"); + fprintf(listing, "%-13s", "int"); break; case IntegerArray: - fprintf(listing, "|%-11s", "int[]"); + fprintf(listing, "%-13s", "int[]"); 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; while (t != NULL) { - fprintf(listing, "%d ", t->lineno); + fprintf(listing, "%3d", t->lineno); + fprintf(listing, " "); t = t->next; } fprintf(listing, "\n"); @@ -218,13 +235,14 @@ static void printScopeTable(FILE *listing, Scope scope) { for (int i = 0; i < SYMTAB_SIZE; ++i) { BucketList l = scope->hashTable[i]; while (l != NULL) { + printEntry(listing, scope, l); count++; l = l->next; } } - + /* if (count > 0) { - BucketList *entries = (BucketList *)malloc(sizeof(BucketList) * count); + BucketList *entries = (BucketList *) malloc(sizeof(BucketList) * count); int idx = 0; for (int i = 0; i < SYMTAB_SIZE; ++i) { BucketList l = scope->hashTable[i]; @@ -245,15 +263,16 @@ static void printScopeTable(FILE *listing, Scope scope) { } for (int i = 0; i < count; ++i) { - printEntry(listing, entries[i]); + printEntry(listing, scope, entries[i]); } 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; fprintf(listing, "Scope Name: %s, Depth: %d\n", scope->name, scope->depth); 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; Scope current_scope = scope_global; @@ -295,12 +314,193 @@ static void printScopeTableRecursive(FILE *listing, Scope scope) { } } -void printSymTab(FILE *listing) { - fprintf(listing, "Scope Table"); - fprintf(listing, "------------------------------------------------------------\n"); - fprintf(listing, "Variable Name Symbol Kind Type Location Line Numbers\n"); - fprintf(listing, "------------------------------------------------------------\n"); - - Scope curr = scope_global; - printScopeTableRecursive(listing, curr); +static void printFunctionTableRecursive(FILE *listing, Scope scope) { + for (int i = 0; i < SYMTAB_SIZE; ++i) { + BucketList entry = scope->hashTable[i]; + while (entry != NULL) { + 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 child = scope->child; + 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); } diff --git a/src/symtab.h b/src/symtab.h index ebfefcb..cb313a9 100644 --- a/src/symtab.h +++ b/src/symtab.h @@ -14,8 +14,7 @@ */ #define SYMTAB_SIZE 211 -#define MAX_SCOPE_DEPTH 32 -#define MAX_SCOPE_COUNT 1557 +#define MAX_SCOPE_DEPTH 1557 #define MAX_PARAM_COUNT 13 @@ -134,10 +133,6 @@ BucketList st_lookup(char *name); */ 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 index b9d09e9..2e575b5 100644 --- a/src/test.cm +++ b/src/test.cm @@ -1,13 +1,16 @@ -int fib(int n) { - if (n <= 0) { - return 1; - } else { - return fib(n * fib(n - 1)); - } +int main(void) +{ + x(1, 2); } - +/* int main(void) { - int x; - x = fib(input()); + if (x) { + int x; + x = 3; + } else { + int y; + y = 0; + x = 5; + } output(x); -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/test_1.cm b/src/test_1.cm index ffcc3de..f9764cb 100644 --- a/src/test_1.cm +++ b/src/test_1.cm @@ -1,6 +1,3 @@ -/* A program to perform Euclid's - Algorithm to computer gcd */ - int gcd (int u, int v) { if (v == 0) return u; diff --git a/src/yacc/globals.h b/src/yacc/globals.h deleted file mode 100644 index cdd41c7..0000000 --- a/src/yacc/globals.h +++ /dev/null @@ -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 -#include -#include -#include - -/* 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 diff --git a/src/yacc/tiny.y b/src/yacc/tiny.y deleted file mode 100644 index b1d6bc0..0000000 --- a/src/yacc/tiny.y +++ /dev/null @@ -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; -} -