Merge pull request #36 from UB-CSE443/Sprint3-Symbol_Table_Restructure-FE-t#NoTask

Sprint3 symbol table restructure fe t#no task
This commit is contained in:
Moroseui
2025-03-26 13:00:20 -04:00
committed by GitHub
25 changed files with 1314 additions and 379 deletions

View File

@ -41,9 +41,8 @@ test-s1:
test-s2: test-s2:
chmod +x ./check.sh chmod +x ./check.sh
$(foreach test, $(TESTS-S2), ./$(EXE) -tok $(test);) $(foreach test, $(TESTS-S2), ./$(EXE) -st $(test);)
./check.sh ./check.sh
$(foreach test, $(TESTS-S2), ./$(EXE) $(test);)
clean: clean:
rm -f *.o rm -f *.o

View File

@ -5,6 +5,11 @@
# The Translators - Spring 2025 # # The Translators - Spring 2025 #
TOK_DIR="out" TOK_DIR="out"
RED='\033[0;31m'
GREEN='\033[0;32m'
WHITE='\033[0m'
PURPLE='\033[0;35m'
ORANGE='\033[0;33m'
if [[ ! -d "$TOK_DIR" ]]; then if [[ ! -d "$TOK_DIR" ]]; then
echo "Directory $TOK_DIR does not exist." echo "Directory $TOK_DIR does not exist."
@ -19,9 +24,15 @@ for file in "$TOK_DIR"/*; do
exp="./tests/sprint$num/expected/$filename.expected" exp="./tests/sprint$num/expected/$filename.expected"
if [[ -f "$exp" ]]; then if [[ -f "$exp" ]]; then
echo -e "--------------------------------------------" diff -q "$file" "$exp" > /dev/null
echo -e "Checking $file...\n" if [[ $? -eq 0 ]]; then
diff --color=always "$file" "$exp" echo -e "${GREEN}[✔] ${PURPLE}$filename ${WHITE}passed."
echo -e "--------------------------------------------\n" else
echo -e "\n${RED}[✘] ${PURPLE}$file ${WHITE}failed with an unexpected value..."
diff --color=always "$file" "$exp"
echo -e ""
fi
else
echo -e "${ORANGE}[-] ${PURPLE}$filename ${WHITE}does not have an expected value."
fi fi
done done

View File

@ -2,21 +2,30 @@
/* The Translators - Spring 2025 */ /* The Translators - Spring 2025 */
%{ %{
#include <stdio.h> #include <stdio.h>
#include "../src/symbol_table.c" #include "../src/symbol_table.c"
#include <math.h> #include <math.h>
extern int yylex(void); extern int yylex(void);
void yyerror(const char *err); void yyerror(const char *err);
extern char* yytext; extern char* yytext;
extern int yyleng; extern int yyleng;
extern int yychar; extern int yychar;
extern SymbolTable * cur; extern SymbolTable * cur;
//char* cur_value; //char* cur_value;
//char* cur_type; //char* cur_type;
int token_tracker; int token_tracker;
extern int line_number; extern int line_number;
extern int column_number; extern int column_number;
extern FILE * yyin; extern FILE * yyin;
extern TableNode* funprime;
extern TableNode* arrayprim;
extern TableNode* recprime;
extern TableNode* funtypeprime;
extern TableNode* integ;
extern TableNode* addr;
extern TableNode* chara;
extern TableNode* stri;
extern TableNode* boo;
%} %}
//%define api.location.type {location_t} //%define api.location.type {location_t}
%locations %locations
@ -26,6 +35,9 @@
} }
%type <words> assignable
%type <words> expression
%type <words> constant
%type <words> id_or_types %type <words> id_or_types
%type <words> types %type <words> types
%token <words> ID 101 %token <words> ID 101
@ -34,7 +46,7 @@
%token <words> T_BOOLEAN 203 %token <words> T_BOOLEAN 203
%token <words> T_CHARACTER 204 %token <words> T_CHARACTER 204
%token <words> T_STRING 205 %token <words> T_STRING 205
%token <integ> C_INTEGER 301 %token <words> C_INTEGER 301
%token <words> C_NULL 302 %token <words> C_NULL 302
%token <words> C_CHARACTER 303 %token <words> C_CHARACTER 303
%token <words> C_STRING 304 %token <words> C_STRING 304
@ -110,7 +122,9 @@ definition:
TYPE ID COLON dblock TYPE ID COLON dblock
| TYPE ID COLON constant ARROW ID | TYPE ID COLON constant ARROW ID
| function_declaration | function_declaration
| TYPE ID COLON id_or_types ARROW id_or_types | TYPE ID COLON id_or_types ARROW id_or_types {
CreateEntry(cur,funtypeprime,$2,CreateFunctionTypeInfo(table_lookup(cur,$4),table_lookup(cur,$6)));
}
| ID parameter ASSIGN sblock | ID parameter ASSIGN sblock
; ;
@ -143,7 +157,7 @@ declaration_list:
; ;
declaration: declaration:
id_or_types COLON ID {CreateEntry(cur,$<words>1,$<words>3); } id_or_types COLON ID {CreateEntry(cur,table_lookup(getAncestor(cur),$<words>1),$<words>3,NULL); }
; ;
id_or_types: id_or_types:
@ -179,23 +193,33 @@ rec_op :
DOT DOT
expression: expression:
constant {printf("constant expression\n");} {$$ = $<words>1;}
constant {printf("constant expression\n");} | SUB_OR_NEG expression %prec UMINUS {printf("negative expression\n");if(strcmp($2,"integer") != 0)
| SUB_OR_NEG expression %prec UMINUS {printf("negative expression\n");} {printf("cant negate something not an integer at line %d and column %d\n",@2.first_line,@2.first_column);
| NOT expression {printf("not expression\n");} $$=strdup("undefined");}else{$$=$2;}}
| NOT expression {printf("not expression\n"); if(strcmp($2,"Boolean")==0){$$=$2;}else{$$=strdup("undefined");
printf("mismatch at line %d and column %d\n",@1.first_line,@1.first_column);}}
| expression ADD expression {printf("add expression\n");} | expression ADD expression {printf("add expression\n");}
| expression SUB_OR_NEG expression {printf("subtract expression\n");} | expression SUB_OR_NEG expression {printf("subtract expression\n");}
| expression MUL expression {printf("multiply expression\n");} | expression MUL expression {printf("multiply expression\n");}
| expression DIV expression {printf("division expression\n");} | expression DIV expression {printf("division expression\n");}
| expression REM expression {printf("remainder expression\n");} | expression REM expression {printf("remainder expression\n");}
| expression AND expression {printf("and expression\n");} | expression AND expression {printf("and expression\n");}
| expression OR expression {printf("or expression\n");} | expression OR expression {printf("or expression\n");}
| expression LESS_THAN expression {printf("less than expression\n");}
| expression EQUAL_TO expression {printf("equals check expression\n");} | expression LESS_THAN expression {printf("less than expression\n");if(strcmp($1,$3)==0 &&
| assignable {printf("assignable expression\n");} strcmp($1,"integer")==0){$$=strdup("Boolean");}else{printf("mismatch at line %d and column %d\n",@2.first_line,@2.first_column);
| L_PAREN expression R_PAREN {printf("paren expression\n");} $$=strdup("Boolean");$$=strdup("undefined");}}
| memOp assignable | expression EQUAL_TO expression {printf("equals check expression\n");
; if(strcmp($1,$3)==0){$$=strdup("Boolean");}else if((strcmp($1,"array")==0||strcmp($1,"record")==0||
strcmp($1,"function type primitive")==0) && (strcmp($3,"address")==0)){$$=strdup("Boolean");}
else{printf("mismatch at line %d and column %d\n",@2.first_line,@2.first_column);$$=strdup("undefined");}}
| assignable {printf("assignable expression\n");$$=$1;}
| L_PAREN expression R_PAREN {printf("paren expression\n");$$=$2;}
| memOp assignable {$$ = strdup("address");}
;
ablock: ablock:
@ -215,17 +239,18 @@ memOp:
constant: constant:
C_STRING C_STRING {$$ = $<words>1;}
| C_INTEGER | C_INTEGER {$$ = $<words>1;}
| C_NULL | C_NULL {$$ = $<words>1;}
| C_CHARACTER | C_CHARACTER {$$ = $<words>1;}
| C_TRUE | C_TRUE {$$ = $<words>1;}
| C_FALSE | C_FALSE {$$ = $<words>1;}
; ;
types: types:
T_STRING {printf("string of T_STRING in types is %s\n",$<words>1);} {$$ = $<words>1;} // Commented out T_String below
| T_INTEGER {printf("string of T_INTEGER in types is %s\n",$<words>1);} {$$ = $<words>1;} // T_STRING {printf("string of T_STRING in types is %s\n",$<words>1);} {$$ = $<words>1;}
T_INTEGER {printf("string of T_INTEGER in types is %s\n",$<words>1);} {$$ = $<words>1;}
| T_ADDRESS {printf("string of T_ADDRESS in types is %s\n",$<words>1);} {$$ = $<words>1;} | T_ADDRESS {printf("string of T_ADDRESS in types is %s\n",$<words>1);} {$$ = $<words>1;}
| T_CHARACTER {printf("string of T_CHARACTER in types is %s\n",$<words>1);} {$$ = $<words>1;} | T_CHARACTER {printf("string of T_CHARACTER in types is %s\n",$<words>1);} {$$ = $<words>1;}
| T_BOOLEAN {printf("string of T_BOOLEAN in types is %s\n",$<words>1);} {$$ = $<words>1;} | T_BOOLEAN {printf("string of T_BOOLEAN in types is %s\n",$<words>1);} {$$ = $<words>1;}
@ -234,31 +259,5 @@ types:
%% %%
void yyerror(const char *err) { void yyerror(const char *err) {
fprintf(stderr, "ERROR: %s at token %s at line number %d,column number %d\n", err,yytext,yylloc.first_line,yylloc.first_column); fprintf(stderr, "ERROR: %s at token %s at line number %d,column number %d\n", err,yytext,yylloc.first_line,yylloc.first_column);
} }
/*
int main(int argc, char * argv[]) {
token_tracker = 1;
cur=CreateScope(NULL,1,1);
//int a;
FILE * fp;
if(argc > 1){
fp = fopen(argv[1], "r");
yyin = fp;
} else {
fp = stdin;
yyin = fp;
}
yyparse();
//while ((a = yyparse() != EOF){
// token_tracker++;
//printf("%d = a: yytext = %s: yychar = %d, token number: %d\n", a, yytext, yychar,token_tracker);
//if(yytext[0] == '\n'){
FILE* f = fdopen(1,"w");
print_symbol_table(getAncestor(cur),f);
fclose(f);
// break;
//}
//}
return 0;
} */

View File

@ -72,9 +72,9 @@ SCHAR \\n|\\t|\\\"|[^\"\n\\]
"," {if(DEBUG) {printf( "COMMA: %s (%d)\n", yytext, COMMA);} else {if(tok_flag != NULL){print_tok(COMMA);}incr(line_number,column_number,COMMA);return COMMA;}} "," {if(DEBUG) {printf( "COMMA: %s (%d)\n", yytext, COMMA);} else {if(tok_flag != NULL){print_tok(COMMA);}incr(line_number,column_number,COMMA);return COMMA;}}
"->" {if(DEBUG) {printf( "ARROW: %s (%d)\n", yytext, ARROW);} else {if(tok_flag != NULL){print_tok(ARROW);}incr(line_number,column_number,ARROW);return ARROW;}} "->" {if(DEBUG) {printf( "ARROW: %s (%d)\n", yytext, ARROW);} else {if(tok_flag != NULL){print_tok(ARROW);}incr(line_number,column_number,ARROW);return ARROW;}}
{DIGIT}+ {if(DEBUG) {printf( "C_INTEGER: %s (%d)\n", yytext, C_INTEGER);} else {if(tok_flag != NULL){print_tok(C_INTEGER);}incr(line_number,column_number,C_INTEGER);yylval.integ = atoi(yytext);return C_INTEGER;}} {DIGIT}+ {if(DEBUG) {printf( "C_INTEGER: %s (%d)\n", yytext, C_INTEGER);} else {if(tok_flag != NULL){print_tok(C_INTEGER);}incr(line_number,column_number,C_INTEGER);yylval.words = strdup("integer");return C_INTEGER;}}
'{CHAR}' {if(DEBUG) {printf( "C_CHARACTER: %s (%d)\n", yytext, C_CHARACTER);} else {if(tok_flag != NULL){print_tok(C_CHARACTER);}incr(line_number,column_number,C_CHARACTER);return C_CHARACTER;}} '{CHAR}' {if(DEBUG) {printf( "C_CHARACTER: %s (%d)\n", yytext, C_CHARACTER);} else {if(tok_flag != NULL){print_tok(C_CHARACTER);}incr(line_number,column_number,C_CHARACTER);yylval.words = strdup("character");return C_CHARACTER;}}
\"{SCHAR}*\" {if(DEBUG) {printf( "C_STRING: %s (%d)\n", yytext, C_STRING);} else {if(tok_flag != NULL){print_tok(C_STRING);}incr(line_number,column_number,C_STRING);return C_STRING;}} \"{SCHAR}*\" {if(DEBUG) {printf( "C_STRING: %s (%d)\n", yytext, C_STRING);} else {if(tok_flag != NULL){print_tok(C_STRING);}incr(line_number,column_number,C_STRING);yylval.words = strdup("string");return C_STRING;}}
{COMMENT} {if(DEBUG) {printf( "COMMENT: %s (%d)\n", yytext, COMMENT);} else {if(tok_flag != NULL){print_tok(COMMENT);}incr(line_number,column_number,COMMENT);/*return COMMENT;*/}} {COMMENT} {if(DEBUG) {printf( "COMMENT: %s (%d)\n", yytext, COMMENT);} else {if(tok_flag != NULL){print_tok(COMMENT);}incr(line_number,column_number,COMMENT);/*return COMMENT;*/}}
"(" {if(DEBUG) {printf( "L_PAREN: %s (%d)\n", yytext, L_PAREN);} else {if(tok_flag != NULL){print_tok(L_PAREN);}incr(line_number,column_number,L_PAREN);return L_PAREN;}} "(" {if(DEBUG) {printf( "L_PAREN: %s (%d)\n", yytext, L_PAREN);} else {if(tok_flag != NULL){print_tok(L_PAREN);}incr(line_number,column_number,L_PAREN);return L_PAREN;}}
@ -84,9 +84,9 @@ SCHAR \\n|\\t|\\\"|[^\"\n\\]
"{" {if(DEBUG) {printf( "L_BRACE: %s (%d)\n", yytext, L_BRACE);} else {if(tok_flag != NULL){print_tok(L_BRACE);}incr(line_number,column_number,L_BRACE);return L_BRACE;}} "{" {if(DEBUG) {printf( "L_BRACE: %s (%d)\n", yytext, L_BRACE);} else {if(tok_flag != NULL){print_tok(L_BRACE);}incr(line_number,column_number,L_BRACE);return L_BRACE;}}
"}" {if(DEBUG) {printf( "R_BRACE: %s (%d)\n", yytext, R_BRACE);} else {if(tok_flag != NULL){print_tok(R_BRACE);}incr(line_number,column_number,R_BRACE);return R_BRACE;}} "}" {if(DEBUG) {printf( "R_BRACE: %s (%d)\n", yytext, R_BRACE);} else {if(tok_flag != NULL){print_tok(R_BRACE);}incr(line_number,column_number,R_BRACE);return R_BRACE;}}
"true" {if(DEBUG) {printf( "C_TRUE: %s (%d)\n", yytext, C_TRUE);} else {if(tok_flag != NULL){print_tok(C_TRUE);}incr(line_number,column_number,C_TRUE);yylval.words = strdup(yytext);return C_TRUE;}} "true" {if(DEBUG) {printf( "C_TRUE: %s (%d)\n", yytext, C_TRUE);} else {if(tok_flag != NULL){print_tok(C_TRUE);}incr(line_number,column_number,C_TRUE);yylval.words = strdup("Boolean");return C_TRUE;}}
"false" {if(DEBUG) {printf( "C_FALSE: %s (%d)\n", yytext, C_FALSE);} else {if(tok_flag != NULL){print_tok(C_FALSE);}incr(line_number,column_number,C_FALSE);yylval.words = strdup(yytext);return C_FALSE;}} "false" {if(DEBUG) {printf( "C_FALSE: %s (%d)\n", yytext, C_FALSE);} else {if(tok_flag != NULL){print_tok(C_FALSE);}incr(line_number,column_number,C_FALSE);yylval.words = strdup("Boolean");return C_FALSE;}}
"null" {if(DEBUG) {printf( "C_NULL: %s (%d)\n", yytext, C_NULL);} else {if(tok_flag != NULL){print_tok(C_NULL);}incr(line_number,column_number,C_NULL);yylval.words = strdup(yytext);return C_NULL;}} "null" {if(DEBUG) {printf( "C_NULL: %s (%d)\n", yytext, C_NULL);} else {if(tok_flag != NULL){print_tok(C_NULL);}incr(line_number,column_number,C_NULL);yylval.words = strdup("address");return C_NULL;}}
{ID} {if(DEBUG) {printf( "ID: %s (%d)\n", yytext, ID);} else {if(tok_flag != NULL){print_tok(ID);}incr(line_number,column_number,ID);yylval.words = strdup(yytext); return ID;}} {ID} {if(DEBUG) {printf( "ID: %s (%d)\n", yytext, ID);} else {if(tok_flag != NULL){print_tok(ID);}incr(line_number,column_number,ID);yylval.words = strdup(yytext); return ID;}}

View File

@ -2,6 +2,13 @@
/* The Translators - Spring 2025 */ /* The Translators - Spring 2025 */
#include "runner.h" #include "runner.h"
extern TableNode *funprime;
extern TableNode *arrayprim;
extern TableNode *integ;
extern TableNode *addr;
extern TableNode *chara;
extern TableNode *stri;
extern TableNode *boo;
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (argc == 1) { if (argc == 1) {
@ -22,13 +29,16 @@ int main(int argc, char *argv[]) {
} }
else { else {
if (is_alpha_file(argv[argc - 1], strlen(argv[argc - 1])) != 0) { if (is_alpha_file(argv[argc - 1], strlen(argv[argc - 1])) !=
0) {
fprintf(stderr, INVALID); fprintf(stderr, INVALID);
return -1; return -1;
} else { } else {
for (int i = 1; i < argc - 1; i++) { for (int i = 1; i < argc - 1; i++) {
if (check_flag(argv[i], argv[argc - 1]) != 0) { if (check_flag(argv[i], argv[argc - 1]) != 0) {
fprintf(stderr, "INVALID FLAG(S): Use -help to view valid inputs \n"); fprintf(stderr,
"INVALID FLAG(S): Use -help to "
"view valid inputs \n");
return -1; return -1;
} }
} }
@ -57,25 +67,26 @@ int check_flag(char *arg, char *alpha) {
} }
} }
void incr(int lnum,int cnum, int tok){ void incr(int lnum, int cnum, int tok) {
//if (tok == COMMENT) { // if (tok == COMMENT) {
for (int i = 0; i < yyleng; i++) { for (int i = 0; i < yyleng; i++) {
if (yytext[i] == '\n') { if (yytext[i] == '\n') {
line_number++; line_number++;
column_number = 0; column_number = 0;
} }
column_number++; column_number++;
} }
// }else{ // }else{
// column_number += yyleng; // column_number += yyleng;
// } // }
} }
void print_tok(int tok){ void print_tok(int tok) {
fprintf(tok_flag, "%d %d %3d \"%s\"\n", line_number, column_number,tok, yytext); fprintf(tok_flag, "%d %d %3d \"%s\"\n", line_number, column_number, tok,
yytext);
} }
int run(FILE *alpha) { int run(FILE *alpha) {
int token; int token;
top = cur = CreateScope(NULL, 1, 1); top = cur = init(CreateScope(NULL, 1, 1));
// If file is not found // If file is not found
if (alpha == NULL) { if (alpha == NULL) {
@ -87,10 +98,11 @@ int run(FILE *alpha) {
// TOK FLAG // TOK FLAG
if (tok_flag != NULL) { if (tok_flag != NULL) {
while (0 != (token = yylex())) { while (0 != (token = yylex())) {
//if (tok_flag != NULL) { // if (tok_flag != NULL) {
// fprintf(tok_flag, "%d %d %3d \"%s\"\n", line_number, column_number, // fprintf(tok_flag, "%d %d %3d \"%s\"\n",
// token, yytext); // line_number, column_number,
//} // token, yytext);
// }
/*if (token == COMMENT) { /*if (token == COMMENT) {
for (int i = 0; i < yyleng; i++) { for (int i = 0; i < yyleng; i++) {
if (yytext[i] == '\n') { if (yytext[i] == '\n') {
@ -103,9 +115,10 @@ int run(FILE *alpha) {
} }
if (token == 1999) { if (token == 1999) {
printf( printf(
"On line number %d and column number %d we have an invalid " "On line number %d and column
"character:%s\n", number %d we have an invalid " "character:%s\n",
line_number, column_number, yytext); line_number, column_number,
yytext);
} }
column_number += yyleng; */ column_number += yyleng; */
} }
@ -118,8 +131,13 @@ int run(FILE *alpha) {
} }
if (st_flag != NULL) { if (st_flag != NULL) {
// output symbol table, file pointer is yyparse();
// print_symbol_table(top,st_flag); print_symbol_table(getAncestor(cur), st_flag);
fclose(st_flag);
if (yyin != NULL) {
fclose(yyin);
}
return 0;
} }
yyparse(); yyparse();
@ -165,14 +183,15 @@ int new_file(char *arg, char *alpha) {
} else if (strcmp(arg, "-st") == 0) { } else if (strcmp(arg, "-st") == 0) {
type_len = ST_LEN; type_len = ST_LEN;
} else { } else {
fprintf(stderr, "INVALID FLAG: Use -help to view valid inputs\n"); fprintf(stderr,
"INVALID FLAG: Use -help to view valid inputs\n");
return -1; return -1;
} }
// calculate lengths // calculate lengths
int basename_len = strlen(basename); int basename_len = strlen(basename);
char *file_name = char *file_name =
calloc(basename_len - ALPHA_OFFSET + type_len + 2, sizeof(char)); calloc(basename_len - ALPHA_OFFSET + type_len + 2, sizeof(char));
// coy filename and add extension // coy filename and add extension
strncpy(file_name, basename, basename_len - ALPHA_OFFSET); strncpy(file_name, basename, basename_len - ALPHA_OFFSET);
@ -188,15 +207,14 @@ int new_file(char *arg, char *alpha) {
} }
int is_alpha_file(char *alpha, int file_len) { int is_alpha_file(char *alpha, int file_len) {
if (strcmp(".alpha", alpha + sizeof(char) * (file_len - ALPHA_OFFSET)) != 0) { if (strcmp(".alpha",
return -1; // not alpha file alpha + sizeof(char) * (file_len - ALPHA_OFFSET)) != 0) {
return -1; // not alpha file
} }
return 0; // is alpha file return 0; // is alpha file
} }
void enter_scope(int line, int column) { void enter_scope(int line, int column) { cur = CreateScope(cur, line, column); }
cur = CreateScope(cur, line, column);
}
void exit_scope() { void exit_scope() {
if (cur->Parent_Scope == NULL) { if (cur->Parent_Scope == NULL) {
printf("Can't close top"); printf("Can't close top");

View File

@ -5,14 +5,18 @@
#define TOK_LEN 3 #define TOK_LEN 3
#define ST_LEN 2 #define ST_LEN 2
#define HELP \ #define HELP \
"HELP:\nHow to run the alpha compiler:\n./alpha [options] program\nValid " \ "HELP:\nHow to run the alpha compiler:\n./alpha [options] " \
"options:\n-tok output the token number, token, line number, and column " \ "program\nValid " \
"number for each of the tokens to the .tok file\n-st output the symbol " \ "options:\n-tok output the token number, token, line number, and " \
"table for the program to the .st file\n-help print this message and exit " \ "column " \
"the alpha compiler\n" "number for each of the tokens to the .tok file\n-st output the " \
"symbol " \
"table for the program to the .st file\n-help print this message " \
"and exit " \
"the alpha compiler\n"
#define SET_FLAG 1 // Used to set flags for arg types #define SET_FLAG 1 // Used to set flags for arg types
#define INVALID \ #define INVALID \
"INVALID INPUT: Include a .alpha file or use -help for more inputs \n" "INVALID INPUT: Include a .alpha file or use -help for more inputs \n"
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
@ -22,7 +26,7 @@
#include "../tmp/flex.h" #include "../tmp/flex.h"
#include "symbol_table.h" #include "symbol_table.h"
//#include "typedefs.h" // #include "typedefs.h"
#include "../tmp/grammar.tab.h" #include "../tmp/grammar.tab.h"
extern int line_number, column_number; extern int line_number, column_number;

View File

@ -6,10 +6,244 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
char * typey = "type"; char *typey = "type";
char * funy = "function"; char *funy = "function";
SymbolTable* CreateScope(SymbolTable* ParentScope, int Line, int Column) { TableNode *funprime;
SymbolTable* table = (SymbolTable*)malloc(sizeof(SymbolTable)); TableNode *arrayprim;
extern SymbolTable *cur;
TableNode *integ;
TableNode *addr;
TableNode *chara;
TableNode *stri;
TableNode *boo;
TableNode *recprime;
TableNode *funtypeprime;
typedef enum {
// First 4 below are primitive types that are all encapsulated in
// primitive type
// TYPE_INTEGER,
// TYPE_CHARACTER,
// TYPE_BOOLEAN,
// TYPE_ADDRESS,
// Type String is an array of char enclosed in double quotes per lexer
TYPE_STRING,
// Array can be multidimensional. Information should be stored here
TYPE_ARRAY,
// Record is user defined types
TYPE_RECORD,
// Declaring what type a particular function is without as
TYPE_FUNCTION_DECLARATION,
// Declaring what type a particular function is with as
// TYPE_AS_FUNCTION_DECLARATION,
// Declaring what type a function is (what the parameters and output
// are)
TYPE_FUNCTION_TYPE,
// The Type being pointed to by the first 4 above that only stores the
// size
TYPE_PRIMITIVE,
//likely NULL
TYPE_ALL_ELSE
} types;
/* put in symbol_table.h
typedef struct{
int size; if(strcmp(getType(tn),getName(integ))==0){
return
}
}primitive_info;
typedef struct{
int length;
char* location;
}string_info;
typedef struct{
int numofdimensions;
//the above value tells you how long the below array is. For example if num
of dimensions is 5, I can store 1,3,2,5,9 to define > int* sizesofdimensions;
TableNode* typeofarray;
}array_info;
typedef struct{
//similar to above we define a record to hold the number of elements and an
array of tablenodes (types) that it contains in the order specified by the user
int numofelements;
TableNode* listoftypes;
}record_info;
typedef struct{
int startlinenumber;
bool regularoras;
}function_declaration_info;
typedef struct{
TableNode* parameter;
TableNode* returntype;
}function_type_info;
typedef union {
PrimAdInfo* primitive_info;
ArrayAdInfo* array_info;
RecAdInfo* record_info;
StringAdInfo* string_info;
FunDecAdInfo* func_dec_info;
FunTypeAdInfo* func_type_info;
}AdInfo;
*/
// primitive additional info only stores the size of that type
AdInfo *CreatePrimitiveInfo(int size) {
AdInfo *info = (AdInfo *)malloc(sizeof(AdInfo));
info->PrimAdInfo = (primitive_info *)malloc(sizeof(primitive_info));
info->PrimAdInfo->size = size;
return info;
}
// only gets the size of a primitive type
int getPrimSize(TableNode *definition) {
if (strcmp(getType(definition), "primitive") != 0) {
printf("not checking the size of a primitive -- invalid op\n");
return 0;
}
return definition->additionalinfo->PrimAdInfo->size;
}
// probably don't need the below structure since can create from an array
/*string_info* CreateStringInfo(int length, char* loc){
string_info* stringy = (string_info*)malloc(sizeof(string_info));
stringy.length=length;
char* location = loc;
return stringy;
}
*/
// Only information stored in array info is the number of dimensions and the
// type stored in the array per professor, the actual size of the array is
// calculated at runtime so bounds checking only needs to be done then
AdInfo *CreateArrayInfo(int dim, /*int* sizes,*/ TableNode *type) {
AdInfo *info = (AdInfo *)malloc(sizeof(AdInfo));
info->ArrayAdInfo = (array_info *)malloc(sizeof(array_info));
info->ArrayAdInfo->numofdimensions = dim;
info->ArrayAdInfo->typeofarray = type;
// avoiding storing any types like below
// int* dimensionsizes = loc;
return info;
}
// This gets the number of dimensions from array info
int getNumArrDim(TableNode *definition) {
if (strcmp(getType(definition), "array") != 0) {
printf("not checking the dim of an array -- invalid op\n");
return 0;
}
return definition->additionalinfo->ArrayAdInfo->numofdimensions;
}
// This gets the type stored in an array from arrtype. It returns a reference to
// the entry of that type
TableNode *getArrType(TableNode *definition) {
if (strcmp(getType(definition), "array") != 0) {
printf("not checking the type of an array -- invalid op\n");
return NULL;
}
return definition->additionalinfo->ArrayAdInfo->typeofarray;
}
// Record type currently stores the number of elements as well as the types, in
// order, of what make up that type in an array. Unfortunately this second part
// should probably instead be replaced by a reference to a scope in which those
// elements are found.
AdInfo *CreateRecordInfo(int length, TableNode *typesarray) {
AdInfo *info = (AdInfo *)malloc(sizeof(AdInfo));
info->RecAdInfo = (record_info *)malloc(sizeof(record_info));
info->RecAdInfo->numofelements = length;
// replace below with reference to a scope, not an array
info->RecAdInfo->listoftypes = typesarray;
return info;
}
// This gets the number of elements that make up a record.
// Perhaps this may not be needed since we need to iterate over all elements
// anyways.
int getRecLength(TableNode *definition) {
if (strcmp(getType(definition), "record") != 0) {
printf("not checking the length of an record -- invalid op\n");
return 0;
}
return definition->additionalinfo->RecAdInfo->numofelements;
}
// This gets the array. Needs to up be updated to get the scope instead
TableNode *getRecList(TableNode *definition) {
if (strcmp(getType(definition), "record") != 0) {
printf("not checking the list of types of a record -- invalid "
"op\n");
return NULL;
}
return definition->additionalinfo->RecAdInfo->listoftypes;
}
// below function takes a bool to see if parameter should be decomposed or not
// note that functions only take one input and have one output
// using "as" the input record can be decomposed to give the illusion of
// multiple inputs Below function also has the line number where the function is
// first defined
AdInfo *CreateFunctionDeclarationInfo(int line, bool asorregular) {
AdInfo *info = (AdInfo *)malloc(sizeof(AdInfo));
info->FunDecAdInfo = (function_declaration_info *)malloc(
sizeof(function_declaration_info));
info->FunDecAdInfo->startlinenumber = line;
info->FunDecAdInfo->regularoras = asorregular;
return info;
}
// gets the line at which the function was first defined. (Can be used to print
// out in table if needed)
int getStartLine(TableNode *definition) {
if (strcmp(getType(definition), "function primitive") != 0) {
printf("not checking the start line of a function -- invalid "
"op\n");
return 0;
}
return definition->additionalinfo->FunDecAdInfo->startlinenumber;
}
// checks if "as" keyword was used for function definition. Either 0 or 1 for
// not used or used.
bool getAsKeyword(TableNode *definition) {
if (strcmp(getType(definition), "function primitive") != 0) {
printf("not checking if a function is called with as or not -- "
"invalid op\n");
return NULL;
}
return definition->additionalinfo->FunDecAdInfo->regularoras;
}
// stores the type of a function (parameter type and return type)
AdInfo *CreateFunctionTypeInfo(TableNode *parameter, TableNode *returntype) {
AdInfo *info = (AdInfo *)malloc(sizeof(AdInfo));
info->FunTypeAdInfo =
(function_type_info *)malloc(sizeof(function_type_info));
info->FunTypeAdInfo->parameter = parameter;
info->FunTypeAdInfo->returntype = returntype;
return info;
}
// returns parameter type of a function
TableNode *getParameter(TableNode *definition) {
if (strcmp(getType(definition), "function type primitive") != 0) {
printf(
"not checking the parameter of a function -- invalid op\n");
return NULL;
}
return definition->additionalinfo->FunTypeAdInfo->parameter;
}
// returns return type of a function
TableNode *getReturn(TableNode *definition) {
if (strcmp(getType(definition), "function type primitive") != 0) {
printf("not checking the return of a function -- invalid op\n");
return NULL;
}
return definition->additionalinfo->FunTypeAdInfo->returntype;
}
// creates a new scope (not the top scope though)
SymbolTable *CreateScope(SymbolTable *ParentScope, int Line, int Column) {
SymbolTable *table = (SymbolTable *)malloc(sizeof(SymbolTable));
table->Line_Number = Line; table->Line_Number = Line;
table->Column_Number = Column; table->Column_Number = Column;
table->Parent_Scope = ParentScope; table->Parent_Scope = ParentScope;
@ -17,16 +251,18 @@ SymbolTable* CreateScope(SymbolTable* ParentScope, int Line, int Column) {
table->entries = NULL; table->entries = NULL;
if (ParentScope != NULL) { if (ParentScope != NULL) {
if (ParentScope->Children_Scope == NULL) { if (ParentScope->Children_Scope == NULL) {
ListOfTable* newEntry = (ListOfTable*)malloc(sizeof(ListOfTable)); ListOfTable *newEntry =
(ListOfTable *)malloc(sizeof(ListOfTable));
newEntry->next = NULL; newEntry->next = NULL;
// newEntry->prev = NULL; // newEntry->prev = NULL;
newEntry->table = table; newEntry->table = table;
ParentScope->Children_Scope = newEntry; ParentScope->Children_Scope = newEntry;
} else { } else {
ListOfTable* newEntry = (ListOfTable*)malloc(sizeof(ListOfTable)); ListOfTable *newEntry =
(ListOfTable *)malloc(sizeof(ListOfTable));
// newEntry->prev = NULL; // newEntry->prev = NULL;
newEntry->table = table; newEntry->table = table;
ListOfTable* oldEntry = ParentScope->Children_Scope; ListOfTable *oldEntry = ParentScope->Children_Scope;
ParentScope->Children_Scope = newEntry; ParentScope->Children_Scope = newEntry;
newEntry->next = oldEntry; newEntry->next = oldEntry;
} }
@ -34,38 +270,190 @@ SymbolTable* CreateScope(SymbolTable* ParentScope, int Line, int Column) {
return table; return table;
} }
//create entry just for things below top level scope // create entry just for things below top level scope
TableNode* CreateEntry(SymbolTable* table, char* typeOf, char* id) { // This function defines the integer, address, character, and bool primitive
// types
SymbolTable *init(SymbolTable *start) {
if (start->Parent_Scope != NULL) {
printf(
"Cannot initialize a scope that is not the parent scope\n");
return NULL;
}
integ = (TableNode *)malloc(sizeof(TableNode));
addr = (TableNode *)malloc(sizeof(TableNode));
chara = (TableNode *)malloc(sizeof(TableNode));
stri = (TableNode *)malloc(sizeof(TableNode));
boo = (TableNode *)malloc(sizeof(TableNode));
// TableNode* arr = (TableNode*)malloc(sizeof(SymbolTable));
start->entries = integ;
integ->next = addr;
addr->next = chara;
chara->next = stri;
stri->next = boo;
// boo->next = arr;
boo->next = NULL;
if(table ==NULL /*|| table->Parent_Scope == NULL*/){ integ->theName = "integer";
printf("Null reference to table given for create entry or given top level scope which is invalid\n"); addr->theName = "address";
return NULL; chara->theName = "character";
boo->theName = "Boolean";
stri->theName = "string";
// arr->theName= "array"
// root TableNode that all are pointing to but not in table
// This is only to solve the issue that all entries must have a name and
// a type and the type must point to an actual table entry Again, this
// primitive table entry isn't in the top scope. It is outside the top
// scope and is only there to facilitate the fact that these are
// primitive
TableNode *prime = (TableNode *)malloc(sizeof(TableNode));
prime->theName = "primitive";
prime->theType = NULL;
prime->additionalinfo = NULL;
prime->next = NULL;
// not sure exatly how to get array types to look right so using a dummy
// Table Node below and updating the print symbol table function to
// access the additional information to print for array types, similar
// to function types when printing symbol table, if array is seen
arrayprim = (TableNode *)malloc(sizeof(TableNode));
arrayprim->theName = "array";
arrayprim->theType = NULL;
arrayprim->additionalinfo = NULL;
prime->next = NULL;
// funprime = CreateEntry(NULL,NULL,strdup("function primitive"),NULL);
// similar workaround to arrays above
funprime = (TableNode *)malloc(sizeof(TableNode));
funprime->theName = "primitive function";
funprime->theType = NULL;
funprime->additionalinfo = NULL;
funprime->next = NULL;
// record
recprime = (TableNode *)malloc(sizeof(TableNode));
recprime->theName = "record";
recprime->theType = NULL;
recprime->additionalinfo = NULL;
recprime->next = NULL;
funtypeprime = (TableNode *)malloc(sizeof(TableNode));
funtypeprime->theName = "primitive function type";
funtypeprime->theType = NULL;
funtypeprime->additionalinfo = NULL;
funtypeprime->next = NULL;
integ->theType = prime;
addr->theType = prime;
chara->theType = prime;
stri->theType = arrayprim;
boo->theType = prime;
// arr->theType=arrayprim;
// filling in all the values for the additional info for initial types
// These numbers below for create primitive specifically are supposed to
// be the size of these primitive types. We can change these if needed
// to not be hard coded numbers as a reminder, stri below is defined as
// a one dimensional array of characters
integ->additionalinfo = CreatePrimitiveInfo(4);
addr->additionalinfo = CreatePrimitiveInfo(8);
chara->additionalinfo = CreatePrimitiveInfo(1);
stri->additionalinfo = CreateArrayInfo(1, chara);
boo->additionalinfo = CreatePrimitiveInfo(1);
// addr->additionalinfo = CreatePrimitiveInfo(8);
start->Line_Number = 1;
start->Column_Number = 1;
start->Parent_Scope = NULL;
start->Children_Scope = NULL;
return start;
} }
/*TableNode* topDef = (table_lookup(getAncestor(table),typeOf)); /*
if(topDef == NULL){ TableNode* integ;
printf("This type is not defined at the top level\n"); TableNode* addr;
return NULL; TableNode* chara;
}*/ TableNode* stri;
TableNode* newEntry = (TableNode*)malloc(sizeof(TableNode)); TableNode* boo;
//newEntry->theType = topDef->theName; TableNode* recprime;
newEntry->theType=typeOf; TableNode* funtypeprime;
newEntry->theName = id; */
if (table->entries == NULL) {
table->entries = newEntry; int getAdInfoType(TableNode* tn){
return newEntry; if(strcmp(getType(tn),getName(integ))==0){
} else { return TYPE_PRIMITIVE;
TableNode* oldEntry = table->entries; }
table->entries = newEntry; if(strcmp(getType(tn),getName(addr))==0){
newEntry->next = oldEntry; return TYPE_PRIMITIVE;
return newEntry; }
} if(strcmp(getType(tn),getName(chara))==0){
return TYPE_PRIMITIVE;
}
if(strcmp(getType(tn),getName(stri))==0){
return TYPE_ARRAY;
}
if(strcmp(getType(tn),getName(boo))==0){
return TYPE_PRIMITIVE;
}
if(strcmp(getType(tn),getName(recprime))==0){
return TYPE_RECORD;
}
if(strcmp(getType(tn),getName(funtypeprime))==0){
return TYPE_FUNCTION_TYPE;
}
if(strcmp(getType(tn),getName(arrayprim))==0){
return TYPE_ARRAY;
}
else{
return TYPE_FUNCTION_DECLARATION;
}
} }
TableNode *CreateEntry(SymbolTable *table, TableNode *typeOf, char *id,
AdInfo *ad) {
if (table == NULL) {
printf("Null reference to table");
return NULL;
}
/*
TableNode* topDef = (table_lookup(getAncestor(table),typeOf));
if(topDef == NULL){
printf("This type is not defined at the top level\n");
return NULL;
}
*/
if (typeOf == NULL) {
printf("This is not pointing to a proper definition\n");
return NULL;
}
TableNode *newEntry = (TableNode *)malloc(sizeof(TableNode));
newEntry->theType = typeOf /*topDef*/;
newEntry->theName = id;
newEntry->additionalinfo = ad;
if (table->entries == NULL) {
table->entries = newEntry;
return newEntry;
} else {
TableNode *oldEntry = table->entries;
table->entries = newEntry;
newEntry->next = oldEntry;
return newEntry;
}
}
char *getType(TableNode *tn) { return tn->theType->theName; }
char *getName(TableNode *tn) { return tn->theName; }
int getLine(SymbolTable *st) { return st->Line_Number; }
int getColumn(SymbolTable *st) { return st->Column_Number; }
/*
//we use false for type defs and true for functions for parameter of typeOf //we use false for type defs and true for functions for parameter of typeOf
TableNode* Define(SymbolTable* table, bool typeOf, char* id) { TableNode* Define(SymbolTable* table, bool typeOf, char* id) {
if(table ==NULL || table->Parent_Scope != NULL){ if(table ==NULL || table->Parent_Scope != NULL){
printf("No valid table given for header defs\n"); printf("No valid table given for header defs\n");
return NULL; return NULL;
} }
@ -73,14 +461,14 @@ if(table ==NULL || table->Parent_Scope != NULL){
//possible issues with referencing text instead of heap //possible issues with referencing text instead of heap
if(typeOf == 0){ if(typeOf == 0){
newEntry->theType = typey; newEntry->theType = typey;
} }
if (typeOf == 1){ if (typeOf == 1){
newEntry->theType = funy; newEntry->theType = funy;
} }
if(table_lookup(table,id) != NULL){ if(table_lookup(table,id) != NULL){
printf("already defined at the top level, can't define duplicate names\n"); printf("already defined at the top level, can't define duplicate
return NULL; names\n"); return NULL;
} }
newEntry->theName = id; newEntry->theName = id;
if (table->entries == NULL) { if (table->entries == NULL) {
@ -94,9 +482,9 @@ if(table_lookup(table,id) != NULL){
} }
} }
*/
TableNode* table_lookup(SymbolTable* table, char* x) { TableNode *table_lookup(SymbolTable *table, char *x) {
TableNode* entrie = table->entries; TableNode *entrie = table->entries;
for (; entrie != NULL; entrie = entrie->next) { for (; entrie != NULL; entrie = entrie->next) {
if (!strcmp(entrie->theName, x)) { if (!strcmp(entrie->theName, x)) {
return entrie; return entrie;
@ -104,63 +492,71 @@ TableNode* table_lookup(SymbolTable* table, char* x) {
} }
return NULL; return NULL;
} }
TableNode* look_up(SymbolTable* table, char* x) { TableNode *look_up(SymbolTable *table, char *x) {
if (table == NULL) { if (table == NULL) {
return NULL; return NULL;
} }
TableNode* ret = table_lookup(table, x); TableNode *ret = table_lookup(table, x);
if (ret != NULL) { if (ret != NULL) {
return ret; return ret;
} }
return look_up(table->Parent_Scope, x); return look_up(table->Parent_Scope, x);
} }
void print_symbol_table(SymbolTable* table, FILE* file_ptr) { void print_symbol_table(SymbolTable *table, FILE *file_ptr) {
if (table->Parent_Scope == NULL) { if (table->Parent_Scope == NULL) {
fprintf(file_ptr, "%-17s: %-6s : %-6s : %-21s: %-28s\n", "NAME", "SCOPE", fprintf(file_ptr, "%-17s: %-6s : %-6s : %-21s: %-28s\n", "NAME",
"PARENT", "TYPE", "Extra annotation"); "SCOPE", "PARENT", "TYPE", "Extra annotation");
} }
TableNode* entrie = table->entries; TableNode *entrie = table->entries;
fprintf(file_ptr, fprintf(file_ptr, "-----------------:--------:--------:----------------"
"-----------------:--------:--------:----------------------:---------" "------:---------"
"--------------------\n"); "--------------------\n");
int parant_scope = 0; int parant_scope = 0;
int current_scope = 0; int current_scope = 0;
if (table->Parent_Scope != NULL) { if (table->Parent_Scope != NULL) {
parant_scope = table->Parent_Scope->Line_Number * 1000 + parant_scope = table->Parent_Scope->Line_Number * 1000 +
table->Parent_Scope->Column_Number; table->Parent_Scope->Column_Number;
current_scope = table->Line_Number * 1000 + table->Column_Number; current_scope =
table->Line_Number * 1000 + table->Column_Number;
} else { } else {
current_scope = 1001; current_scope = 1001;
} }
if ( entrie == NULL ) { if (entrie == NULL) {
fprintf(file_ptr, "%-17s: %06d : %06d : %-21s: %-28s\n", "", fprintf(file_ptr, "%-17s: %06d : %06d : %-21s: %-28s\n", "",
current_scope, parant_scope, "", "Empty Scope"); current_scope, parant_scope, "", "Empty Scope");
} }
for (; entrie != NULL; entrie = entrie->next) { for (; entrie != NULL; entrie = entrie->next) {
if (parant_scope == 0) { if (parant_scope == 0) {
fprintf(file_ptr, "%-17s: %06d : : %-21s: %-28s\n", /*have to update*/ if (strcmp(entrie->theType->theName,
entrie->theName, current_scope, entrie->theType, "function primitive") ||
"Extra annotation"); strcmp(entrie->theType->theName,
"array")) {
}
fprintf(file_ptr,
"%-17s: %06d : : %-21s: %-28s\n",
entrie->theName, current_scope,
entrie->theType->theName, "Extra annotation");
} else { } else {
fprintf(file_ptr, "%-17s: %06d : %06d : %-21s: %-28s\n", entrie->theName, fprintf(file_ptr, "%-17s: %06d : %06d : %-21s: %-28s\n",
current_scope, parant_scope, entrie->theType, "Extra annotation"); entrie->theName, current_scope, parant_scope,
entrie->theType->theName, "Extra annotation");
} }
} }
if (table->Children_Scope != NULL) { if (table->Children_Scope != NULL) {
ListOfTable* node = table->Children_Scope; ListOfTable *node = table->Children_Scope;
for (; node != NULL; node = node->next) { for (; node != NULL; node = node->next) {
print_symbol_table(node->table, file_ptr); print_symbol_table(node->table, file_ptr);
} }
} }
if (table->Parent_Scope == NULL) { if (table->Parent_Scope == NULL) {
fprintf(file_ptr, fprintf(file_ptr, "-----------------:--------:--------:--------"
"-----------------:--------:--------:----------------------:-------" "--------------:-------"
"----------------------\n"); "----------------------\n");
} }
} }
SymbolTable* getAncestor(SymbolTable* table) { SymbolTable *getAncestor(SymbolTable *table) {
if (table->Parent_Scope == NULL) { if (table->Parent_Scope == NULL) {
// if table has no parent, return itself // if table has no parent, return itself
return table; return table;
@ -170,17 +566,78 @@ SymbolTable* getAncestor(SymbolTable* table) {
} }
} }
SymbolTable* getParent(SymbolTable* st) { return st->Parent_Scope; } SymbolTable *removeEntry(SymbolTable *scope, char *search) {
ListOfTable* getChildren(SymbolTable* st) { return st->Children_Scope; } if (scope == NULL) {
SymbolTable* getFirstChild(ListOfTable* lt) { return lt->table; } return NULL;
ListOfTable* getRestOfChildren(ListOfTable* lt) { return lt->next; } }
TableNode* getFirstEntry(SymbolTable* st) { return st->entries; } if (scope->entries == NULL) {
TableNode* getNextEntry(TableNode* tn) { return tn->next; } return scope;
char* getType(TableNode* tn) { return tn->theType; } }
char* getName(TableNode* tn) { return tn->theName; }
int getLine(SymbolTable* st) { return st->Line_Number; } TableNode *prev = NULL;
int getColumn(SymbolTable* st) { return st->Column_Number; } TableNode *now = scope->entries;
while (now != NULL) {
if (strcmp(getName(now), search) == 0) {
if (prev == NULL) {
scope->entries = getNextEntry(now);
return scope;
} else {
prev->next = now->next;
return scope;
}
}
prev = now;
now = now->next;
}
return scope;
}
bool typeCheck(char *firstID, char *secondID) {
TableNode *entry1 = look_up(cur, firstID);
TableNode *entry2 = look_up(cur, secondID);
if (entry1 == NULL) {
printf("first type not defined\n");
return false;
}
if (entry2 == NULL) {
printf("second type not defined\n");
return false;
}
if (table_lookup(getAncestor(cur), getType(look_up(cur, firstID))) ==
table_lookup(getAncestor(cur), getType(look_up(cur, secondID)))) {
if (strcmp(getType(look_up(cur, firstID)), "array") == 0) {
if (look_up(cur, firstID)
->additionalinfo->ArrayAdInfo
->numofdimensions ==
look_up(cur, secondID)
->additionalinfo->ArrayAdInfo
->numofdimensions &&
look_up(cur, firstID)
->additionalinfo->ArrayAdInfo
->typeofarray ==
look_up(cur, secondID)
->additionalinfo->ArrayAdInfo
->typeofarray) {
return true;
} else {
return false;
}
}
return true;
}
return false;
}
SymbolTable *getParent(SymbolTable *st) { return st->Parent_Scope; }
ListOfTable *getChildren(SymbolTable *st) { return st->Children_Scope; }
SymbolTable *getFirstChild(ListOfTable *lt) { return lt->table; }
ListOfTable *getRestOfChildren(ListOfTable *lt) { return lt->next; }
TableNode *getFirstEntry(SymbolTable *st) { return st->entries; }
TableNode *getNextEntry(TableNode *tn) { return tn->next; }
// uncomment the below main function along with the headers above for a simple // uncomment the below main function along with the headers above for a simple
// standalone test of table and entry creation // standalone test of table and entry creation

View File

@ -3,40 +3,101 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
struct TableNode;
typedef struct {
int size;
} primitive_info;
/*This structure can be subsumed into the structure below (1-d array of chars)
typedef struct{
//shouldn't need to store any values since would be compiled at runtime
//int length;
//char* location;
}string_info;
*/
typedef struct {
int numofdimensions;
// the above value tells you how long the below array is. For example if
// num of dimensions is 5, I can store 1,3,2,5,9 to define > int*
// arr; shouldn't need to store any values (like sizes of dimenions or
// the location int* sizesofdimensions; do have to store type of array
struct TableNode *typeofarray;
} array_info;
typedef struct {
// similar to above we define a record to hold the number of elements
// and an array of tablenodes (types) that it contains in the >
int numofelements;
struct TableNode *listoftypes;
} record_info;
typedef struct {
int startlinenumber;
bool regularoras;
} function_declaration_info;
typedef struct {
struct TableNode *parameter;
struct TableNode *returntype;
} function_type_info;
typedef union {
primitive_info *PrimAdInfo;
array_info *ArrayAdInfo;
record_info *RecAdInfo;
// string_info* StringAdInfo;
function_declaration_info *FunDecAdInfo;
function_type_info *FunTypeAdInfo;
} AdInfo;
typedef struct ListOfTable { typedef struct ListOfTable {
struct SymbolTable* table; struct SymbolTable *table;
// struct ListOfTable* prev; // struct ListOfTable* prev;
struct ListOfTable* next; struct ListOfTable *next;
} ListOfTable; } ListOfTable;
typedef struct TableNode { typedef struct TableNode {
char* theType; // reference to the type entry that this is
char* theName; struct TableNode *theType;
struct TableNode* next; char *theName;
AdInfo *additionalinfo;
struct TableNode *next;
} TableNode; } TableNode;
typedef struct SymbolTable { typedef struct SymbolTable {
TableNode* entries; TableNode *entries;
struct SymbolTable* Parent_Scope; struct SymbolTable *Parent_Scope;
struct ListOfTable* Children_Scope; struct ListOfTable *Children_Scope;
int Line_Number; int Line_Number;
int Column_Number; int Column_Number;
} SymbolTable; } SymbolTable;
SymbolTable* CreateScope(SymbolTable* ParentScope, int Line, int Column); SymbolTable *CreateScope(SymbolTable *ParentScope, int Line, int Column);
TableNode* CreateEntry(SymbolTable* table, char* typeOf, char* id); TableNode *table_lookup(SymbolTable *table, char *x);
TableNode* table_lookup(SymbolTable* table, char* x); TableNode *look_up(SymbolTable *table, char *x);
TableNode* look_up(SymbolTable* table, char* x); void print_symbol_table(SymbolTable *table, FILE *file_ptr);
void print_symbol_table(SymbolTable* table, FILE* file_ptr);
SymbolTable* getAncestor(SymbolTable* table); SymbolTable *getAncestor(SymbolTable *table);
SymbolTable* getParent(SymbolTable* st); SymbolTable *getParent(SymbolTable *st);
ListOfTable* getChildren(SymbolTable* st); ListOfTable *getChildren(SymbolTable *st);
SymbolTable* getFirstChild(ListOfTable* lt); SymbolTable *getFirstChild(ListOfTable *lt);
ListOfTable* getRestOfChildren(ListOfTable* lt); ListOfTable *getRestOfChildren(ListOfTable *lt);
TableNode* getFirstEntry(SymbolTable* st); TableNode *getFirstEntry(SymbolTable *st);
TableNode* getNextEntry(TableNode* tn); TableNode *getNextEntry(TableNode *tn);
char* getType(TableNode* tn); SymbolTable *init(SymbolTable *scope);
char* getName(TableNode* tn); int getPrimSize(TableNode *definition);
int getLine(SymbolTable* st); int getNumArrDim(TableNode *definition);
int getColumn(SymbolTable* st); TableNode *getArrType(TableNode *definition);
int getRecLength(TableNode *definition);
TableNode *getRecList(TableNode *definition);
int getStartLine(TableNode *definition);
bool getAsKeyword(TableNode *definition);
TableNode *getParameter(TableNode *definition);
TableNode *getReturn(TableNode *definition);
char *getType(TableNode *tn);
char *getName(TableNode *tn);
int getLine(SymbolTable *st);
int getColumn(SymbolTable *st);

View File

@ -1 +1 @@
daskmskdfm 1 1 700 "(***)"

View File

@ -0,0 +1,3 @@
1 1 700 "(*(**)"
1 7 603 "*"
1 8 502 ")"

View File

@ -0,0 +1,22 @@
1 1 700 "(*(**)"
1 7 603 "*"
1 8 502 ")"
2 1 700 "(***)"
3 1 700 "(******)"
3 9 700 "(*\kpp*********)"
4 1 501 "("
4 2 700 "(*((*)"
4 8 502 ")"
5 1 700 "(***)"
5 6 700 "(*)
(* *)"
7 1 700 "(***)"
7 6 502 ")"
7 7 502 ")"
7 8 502 ")"
7 9 502 ")"
7 10 502 ")"
7 11 502 ")"
7 12 603 "*"
7 13 700 "(*))))))))*)"
7 25 502 ")"

View File

@ -0,0 +1,9 @@
1 1 700 "(* hello *)"
2 1 700 "(* hello *)"
3 1 700 "(* I'd think this is a legal "string" that contains several \n \t
escaped characters, isn't it? *)"
5 1 700 "(* \ *)"
6 1 700 "(* *)"
7 1 700 "(*{COMMENT}+ *)"
8 1 700 "(* * *)"
9 1 700 "(* (hello) *)"

View File

@ -0,0 +1,68 @@
1 1 101 "This"
1 6 101 "is"
1 9 101 "a"
1 11 101 "test"
2 1 301 "9"
2 2 101 "combined"
2 11 301 "7"
2 12 101 "okens"
3 1 301 "12345"
4 1 301 "893247892"
5 1 101 "combined"
5 10 101 "DueToUnknownChar"
5 27 101 "_validtoken"
5 39 101 "__validtoken1"
5 53 101 "_valid_token2"
5 67 101 "validToken3_"
6 1 305 "true"
6 6 306 "false"
7 1 302 "null"
7 6 401 "while"
7 12 609 "!"
7 13 101 "wrong"
7 19 402 "if"
7 22 101 "when"
8 1 404 "else"
8 6 405 "type"
8 11 406 "function"
9 1 407 "return"
9 9 408 "external"
9 25 409 "as"
10 1 101 "string"
10 8 101 "_NOte_that_was_not_reserved"
11 1 501 "("
11 2 503 "["
11 3 502 ")"
11 4 504 "]"
11 5 505 "{"
11 6 506 "}"
11 7 508 ":"
11 8 507 ";"
11 9 509 ","
11 10 510 "->"
12 1 601 "+"
12 2 602 "-"
12 3 603 "*"
12 4 604 "/"
12 5 605 "%"
13 1 606 "<"
13 2 607 "="
14 1 608 ":="
15 2 101 "This"
15 7 101 "is"
15 10 101 "not"
15 14 101 "a"
15 16 101 "valid"
16 1 101 "String"
17 1 304 ""This is a valid String""
18 1 609 "!"
18 2 611 "|"
19 1 612 "."
19 2 612 "."
20 1 700 "(* this is a comment *)"
21 1 501 "("
21 2 603 "*"
21 3 101 "Not"
21 7 101 "a"
21 9 101 "comment"
22 3 610 "&"

View File

@ -0,0 +1,29 @@
1 1 401 "while"
2 1 101 "While"
3 1 101 "whiLe"
4 1 402 "if"
5 1 101 "IF"
6 1 101 "If"
7 1 101 "iF"
8 1 403 "then"
9 1 101 "Then"
10 1 101 "theN"
11 1 404 "else"
12 1 101 "eLse"
13 1 101 "elSe"
14 1 101 "Else"
15 1 405 "type"
16 1 101 "Type"
17 1 101 "tyPe"
18 1 406 "function"
19 1 101 "Function"
20 1 101 "functioN"
21 1 407 "return"
22 1 101 "Return"
23 1 101 "returN"
24 1 408 "external"
25 1 101 "External"
26 1 101 "exteRnal"
27 1 409 "as"
28 1 101 "As"
29 1 101 "aS"

View File

@ -0,0 +1,22 @@
1 1 601 "+"
2 1 602 "-"
3 1 603 "*"
4 1 604 "/"
6 1 605 "%"
7 1 606 "<"
9 1 607 "="
10 1 608 ":="
11 1 607 "="
11 2 508 ":"
12 1 508 ":"
13 1 607 "="
14 1 609 "!"
15 1 610 "&"
16 1 611 "|"
17 1 612 "."
18 1 101 "relEASE"
19 1 614 "release"
20 1 101 "RELEASE"
21 1 613 "reserve"
22 1 101 "RESERVE"
23 1 101 "reSERVe"

View File

@ -0,0 +1,7 @@
1 1 507 ";"
2 1 508 ":"
3 1 509 ","
4 1 510 "->"
5 1 510 "->"
6 1 602 "-"
6 2 510 "->"

View File

@ -0,0 +1,59 @@
1 1 502 ")"
2 1 101 "a"
2 2 502 ")"
3 1 502 ")"
3 2 101 "a"
4 1 502 ")"
4 2 603 "*"
5 1 603 "*"
5 2 502 ")"
7 1 700 "(* jellsls
well this seems to work
*)"
13 1 501 "("
14 1 101 "a"
14 2 501 "("
15 1 501 "("
15 2 101 "a"
16 1 501 "("
16 2 603 "*"
17 1 603 "*"
17 2 501 "("
20 1 505 "{"
21 1 101 "a"
21 2 505 "{"
22 1 505 "{"
22 2 101 "a"
23 1 505 "{"
23 2 603 "*"
24 1 603 "*"
24 2 505 "{"
25 1 506 "}"
26 1 101 "a"
26 2 506 "}"
27 1 506 "}"
27 2 101 "a"
28 1 506 "}"
28 2 603 "*"
29 1 603 "*"
29 2 506 "}"
33 1 503 "["
34 1 101 "a"
34 2 503 "["
35 1 503 "["
35 2 101 "a"
36 1 503 "["
36 2 603 "*"
37 1 603 "*"
37 2 503 "["
38 1 504 "]"
39 1 101 "a"
39 2 504 "]"
40 1 504 "]"
40 2 101 "a"
41 1 504 "]"
41 2 603 "*"
42 1 603 "*"
42 2 504 "]"

View File

@ -0,0 +1,145 @@
1 1 405 "type"
1 6 101 "rec"
1 9 508 ":"
1 11 503 "["
1 12 201 "integer"
1 19 508 ":"
1 21 101 "x"
1 22 507 ";"
1 24 201 "integer"
1 31 508 ":"
1 33 101 "y"
1 34 504 "]"
2 1 405 "type"
2 6 101 "T1"
2 8 508 ":"
2 10 201 "integer"
2 18 510 "->"
2 21 201 "integer"
3 1 405 "type"
3 6 101 "T2"
3 8 508 ":"
3 10 101 "rec"
3 14 510 "->"
3 17 201 "integer"
4 1 406 "function"
4 10 101 "foo"
4 14 508 ":"
4 16 101 "T1"
5 1 406 "function"
5 10 101 "bar1"
5 15 508 ":"
5 17 101 "T2"
6 1 406 "function"
6 10 101 "bar2"
6 15 508 ":"
6 17 101 "T2"
7 1 101 "foo"
7 4 501 "("
7 5 101 "x"
7 6 502 ")"
7 8 608 ":="
7 11 505 "{"
8 2 407 "return"
8 9 101 "x"
8 11 603 "*"
8 13 101 "x"
8 14 507 ";"
9 9 506 "}"
10 1 101 "bar1"
10 5 501 "("
10 6 101 "a"
10 7 502 ")"
10 9 608 ":="
10 12 505 "{"
11 9 407 "return"
11 16 101 "a"
11 17 612 "."
11 18 101 "x"
11 20 603 "*"
11 22 101 "a"
11 23 612 "."
11 24 101 "y"
11 25 507 ";"
12 9 506 "}"
13 1 101 "bar2"
13 6 409 "as"
13 9 501 "("
13 10 101 "r"
13 11 509 ","
13 12 101 "s"
13 13 502 ")"
13 15 608 ":="
13 18 505 "{"
14 9 407 "return"
14 16 101 "r"
14 18 603 "*"
14 20 101 "s"
14 21 507 ";"
15 9 506 "}"
16 1 101 "entry"
16 6 501 "("
16 7 101 "arg"
16 10 502 ")"
16 12 608 ":="
16 15 505 "{"
17 9 503 "["
17 11 201 "integer"
17 18 508 ":"
17 20 101 "result"
17 27 507 ";"
17 29 101 "rec"
17 32 508 ":"
17 34 101 "w"
17 35 504 "]"
18 9 101 "result"
18 16 608 ":="
18 19 101 "foo"
18 22 501 "("
18 23 301 "5"
18 24 502 ")"
18 25 507 ";"
19 9 101 "w"
19 11 608 ":="
19 14 613 "reserve"
19 21 501 "("
19 22 101 "w"
19 23 502 ")"
19 24 507 ";"
19 26 700 "(* see types.alpha reserve returns a value of type address,
which can be assigned to array and record variables
*)"
22 9 101 "w"
22 10 612 "."
22 11 101 "x"
22 13 608 ":="
22 16 301 "5"
22 17 507 ";"
23 9 101 "w"
23 10 612 "."
23 11 101 "y"
23 13 608 ":="
23 16 301 "7"
23 17 507 ";"
24 9 101 "result"
24 16 608 ":="
24 19 101 "bar1"
24 23 501 "("
24 24 101 "w"
24 25 502 ")"
24 26 507 ";"
24 28 700 "(* pass w (a rec type value) to bar1 *)"
25 9 101 "result"
25 16 608 ":="
25 19 101 "bar2"
25 23 501 "("
25 24 301 "5"
25 25 509 ","
25 26 301 "7"
25 27 502 ")"
25 28 507 ";"
25 30 700 "(* implicitly build a rec type value, assign 5 and 7 to fields x and y, but call them r and s *)"
27 9 407 "return"
27 16 301 "0"
27 17 507 ";"
28 1 506 "}"

View File

@ -0,0 +1,100 @@
1 1 700 "(* Type definitions *)"
2 1 405 "type"
2 6 101 "string"
2 12 508 ":"
2 14 301 "1"
2 16 510 "->"
2 19 204 "character"
3 1 405 "type"
3 6 101 "int2int"
3 13 508 ":"
3 15 201 "integer"
3 23 510 "->"
3 26 201 "integer"
4 1 405 "type"
4 6 101 "string2int"
4 16 508 ":"
4 18 101 "string"
4 25 510 "->"
4 28 201 "integer"
5 1 700 "(* Function prototypes
They use the above type definitions
*)"
8 1 406 "function"
8 10 101 "square"
8 17 508 ":"
8 19 101 "int2int"
9 1 406 "function"
9 10 101 "entry"
9 16 508 ":"
9 18 101 "string2int"
10 1 700 "(* Function definition
Functions must be declared before they are defined
*)"
13 1 101 "square"
13 7 501 "("
13 8 101 "x"
13 9 502 ")"
13 11 608 ":="
13 14 505 "{"
14 1 407 "return"
14 8 101 "x"
14 10 603 "*"
14 12 101 "x"
14 13 507 ";"
15 1 506 "}"
16 1 700 "(* Function definition
entry is the first function called
*)"
19 1 101 "entry"
19 6 501 "("
19 7 101 "arg"
19 10 502 ")"
19 12 608 ":="
19 15 505 "{"
20 1 101 "input"
20 7 607 "="
20 9 301 "7"
20 10 507 ";"
21 1 101 "expected"
21 10 607 "="
21 12 301 "49"
21 14 507 ";"
22 1 101 "actual"
22 8 608 ":="
22 11 101 "square"
22 17 501 "("
22 18 101 "input"
22 23 502 ")"
22 24 507 ";"
23 1 101 "rseult"
23 8 608 ":="
23 11 101 "expected"
23 20 607 "="
23 22 101 "actual"
23 28 507 ";"
24 1 407 "return"
24 8 301 "0"
24 9 507 ";"
25 1 503 "["
25 3 201 "integer"
25 10 508 ":"
25 12 101 "input"
25 17 507 ";"
25 19 201 "integer"
25 26 508 ":"
25 28 101 "expected"
25 36 507 ";"
25 38 201 "integer"
25 45 508 ":"
25 47 101 "actual"
25 53 507 ";"
25 55 101 "boolean"
25 62 508 ":"
25 64 101 "result"
25 70 507 ";"
25 72 101 "string"
25 78 508 ":"
25 80 101 "input"
25 86 504 "]"
26 1 506 "}"

View File

@ -0,0 +1,8 @@
1 1 301 "45"
2 1 301 "123"
3 1 301 "8392"
4 1 301 "40"
4 4 301 "40"
5 2 301 "200"
5 6 301 "50"
5 9 301 "21783"

View File

@ -0,0 +1,64 @@
1 1 304 ""this is a string""
1 20 301 "721398"
1 27 303 "'g'"
1 32 604 "/"
1 33 101 "n"
1 36 700 "(* should print 3 tokens before this *)"
4 1 301 "12893"
4 8 101 "this"
4 13 101 "is"
4 16 101 "not"
4 20 101 "a"
4 22 101 "string"
4 29 700 "(*one valid token before this*)"
5 1 700 "(* spacey comment here
over multiple lines
will it work? *)"
7 18 306 "false"
11 1 306 "false"
12 1 700 "(**)"
14 1 101 "nullfalse"
15 2 101 "nulltrue"
16 1 302 "null"
17 1 303 "'7'"
18 1 305 "true"
19 2 301 "189"
20 1 303 "'\t'"
21 1 303 "'"'"
22 1 303 "'/'"
23 1 303 "'\n'"
24 1 303 "'\''"
25 1 303 "'\t'"
26 1 303 "'\\'"
27 1 303 "'n'"
29 2 101 "fdsf"
30 1 700 "(*/jnewjno2893u86^ Lots of random characters /n /t '") *)"
35 1 304 ""STRINGwithnotSPaces""
36 1 303 "' '"
38 1 304 ""J""
39 1 304 """"
40 1 304 "" ""
42 1 304 ""{SCHAR}""
43 1 304 ""SCHAR""
44 1 304 ""[SCHAR]""
45 1 304 ""FINAL: I'd think this is a legal \"string\" that contains \n \t several escaped characters, isn't it?""
46 2 101 "I"
46 4 101 "d"
46 6 101 "think"
46 12 101 "this"
46 17 101 "is"
46 20 101 "a"
46 22 101 "legal"
46 30 101 "string"
46 39 101 "that"
46 44 101 "contains"
46 53 101 "several"
46 63 101 "n"
46 66 101 "t"
46 68 101 "escaped"
46 76 101 "characters"
46 86 509 ","
46 88 101 "isn"
46 92 101 "t"
46 94 101 "it"
47 1 101 "nullLike"

View File

@ -0,0 +1,13 @@
1 1 101 "valid1"
2 1 101 "Valid2"
3 1 101 "_valid3"
4 1 101 "_valid_name_4"
5 1 101 "VALID"
6 1 301 "0"
6 2 101 "Invalid"
7 1 301 "1"
7 2 101 "invalid"
8 2 101 "invalid"
9 1 101 "invalid"
9 8 607 "="
10 1 101 "String"

View File

@ -1,48 +0,0 @@
/* Function type. */
typedef double (func_t) (double);
/* Data type for links in the chain of symbols. */
struct symrec
{
char *name; /* name of symbol */
int type; /* type of symbol: either VAR or FUN */
union
{
double var; /* value of a VAR */
func_t *fun; /* value of a FUN */
} value;
struct symrec *next; /* link field */
};
typedef struct symrec symrec;
/* The symbol table: a chain of 'struct symrec'. */
extern symrec *sym_table;
symrec *putsym (char const *name, int sym_type);
symrec *getsym (char const *name);
struct init
{
char const *name;
func_t *fun;
};
struct init const funs[] =
{
{ "atan", atan },
{ "cos", cos },
{ "exp", exp },
{ "ln", log },
{ "sin", sin },
{ "sqrt", sqrt },
{ 0, 0 },
};
/* The symbol table: a chain of 'struct symrec'. */
symrec *sym_table;
/* Put functions in table. */
static void
init_table (void)
{
for (int i = 0; funs[i].name; i++)
{
symrec *ptr = putsym (funs[i].name, FUN);
ptr->value.fun = funs[i].fun;
}
}

View File

@ -1,74 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include "symbol_table.h"
int main(void){
char *prim = strdup("primitive");
char *inte = strdup("integer");
SymbolTable * parant = CreateScope(NULL, 1,1);
char *boole = strdup("Boolean");
char *chare = strdup("character");
char *str = strdup("string");
char *arg = strdup("arg");
char *one_to_char = strdup("1 -> character");
char *int_to_int = strdup("integer -> integer");
char *int2int = strdup("int2int");
char *str_to_int = strdup("string -> integer");
char *str2int = strdup("string2int");
char *square = strdup("square");
char *string2int = strdup("string2int");
char *entry = strdup("entry");
char *x = strdup("x");
char *input = strdup("input");
char *expected = strdup("expected");
char *actual = strdup("actual");
char *$_und_type = strdup("$_undefined_type");
char *result = strdup("result");
char *BOO = strdup("BOO");
char *YAZOO = strdup("YAZOO");
CreateEntry(parant, prim, boole);
CreateEntry(parant, prim, chare);
CreateEntry(parant, prim, inte);
CreateEntry(parant, one_to_char, str);
CreateEntry(parant, int_to_int, int2int);
CreateEntry(parant, str_to_int, str2int);
CreateEntry(parant, int2int, square);
CreateEntry(parant, string2int, entry);
SymbolTable * child = CreateScope(parant, 14,14);
CreateEntry(child, inte, x);
SymbolTable * second = CreateScope(parant, 21,15);
CreateEntry(second, str, arg);
CreateEntry(second, inte, input);
CreateEntry(second, inte, expected);
CreateEntry(second, inte, actual);
CreateEntry(second, $_und_type, result);
SymbolTable * third = CreateScope(second, 33,44);
CreateEntry(third, BOO, arg);
CreateEntry(third, YAZOO, input);
TableNode *ret = table_lookup(third, "arg");
printf("%s == %s\n", ret->theName, "arg");
ret = table_lookup(third, "hello");
printf("This should be nil %p != %s\n", ret, "BOO");
ret = look_up(second, "input");
printf("%s == %s\n", ret->theName, "input");
ret = look_up(second, "square");
printf("%s == %s\n", ret->theName, "square");
ret = look_up(second, "spuare");
printf("This should be nil %p == %s\n", ret, "square");
print_symbol_table(parant, stderr);
free(inte);
free(boole);
free(prim);
free(str);
free(chare);
free(arg);
return 0;
}

View File

@ -1,41 +0,0 @@
%{
#include <stdio.h> /* For printf, etc. */
#include <math.h> /* For pow, used in the grammar. */
#include "calc.h" /* Contains definition of 'symrec'. */
int yylex (void);
void yyerror (char const *);
%}
%define api.value.type union /* Generate YYSTYPE from these types: */
%token <double> NUM /* Double precision number. */
%token <symrec*> VAR FUN /* Symbol table pointer: variable/function. */
%nterm <double> exp
%precedence '='
%left '-' '+'
%left '*' '/'
%precedence NEG /* negation--unary minus */
%right '^' /* exponentiation */
%% /* The grammar follows. */
input:
%empty
| input line
;
line:
'\n'
| exp '\n' { printf ("%.10g\n", $1); }
| error '\n' { yyerrok; }
;
exp:
NUM
| VAR { $$ = $1->value.var; }
| VAR '=' exp { $$ = $3; $1->value.var = $3; }
| FUN '(' exp ')' { $$ = $1->value.fun ($3); }
| exp '+' exp { $$ = $1 + $3; }
| exp '-' exp { $$ = $1 - $3; }
| exp '*' exp { $$ = $1 * $3; }
| exp '/' exp { $$ = $1 / $3; }
| '-' exp %prec NEG { $$ = -$2; }
| exp '^' exp { $$ = pow ($1, $3); }
| '(' exp ')' { $$ = $2; }
;
/* End of grammar. */
%%