semi-complete semantic v2

This commit is contained in:
2025-12-03 04:58:41 +09:00
parent 90b7d8fcbe
commit 2b6193a2c7
11 changed files with 360 additions and 419 deletions

BIN
src/2024062806.docx Normal file

Binary file not shown.

View File

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

View File

@@ -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
View 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
View 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

View File

@@ -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");
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 curr = scope_global;
printScopeTableRecursive(listing, curr);
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);
}

View File

@@ -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

View File

@@ -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) {
if (x) {
int x;
x = fib(input());
x = 3;
} else {
int y;
y = 0;
x = 5;
}
output(x);
}
}*/

View File

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

View File

@@ -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

View File

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