From 982a8a045424cd402ff78aff152513f991100ead Mon Sep 17 00:00:00 2001 From: Scarlett Date: Fri, 28 Mar 2025 18:22:05 -0400 Subject: [PATCH 1/2] init --- src/grammar.y~ | 373 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 373 insertions(+) create mode 100644 src/grammar.y~ diff --git a/src/grammar.y~ b/src/grammar.y~ new file mode 100644 index 0000000..5238aac --- /dev/null +++ b/src/grammar.y~ @@ -0,0 +1,373 @@ + +/* Syntax Analyzer with Bison (3.8.2) */ +/* The Translators - Spring 2025 */ + +%{ + #include + #include "../src/symbol_table.c" + #include + extern int yylex(void); + void yyerror(const char *err); + extern char* yytext; + extern int yyleng; + extern int yychar; + extern SymbolTable * cur; + //char* cur_value; + //char* cur_type; + int token_tracker; + extern int line_number; + extern int column_number; + 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; + TableNode * tn; +%} +//%define api.location.type {location_t} +%locations +%union { + int integ; + char * words; +} + + +%type assignable +%type expression +%type constant +%type id_or_types +%type types +%token ID 101 +%token T_INTEGER 201 +%token T_ADDRESS 202 +%token T_BOOLEAN 203 +%token T_CHARACTER 204 +%token T_STRING 205 +%token C_INTEGER 301 +%token C_NULL 302 +%token C_CHARACTER 303 +%token C_STRING 304 +%token C_TRUE 305 +%token C_FALSE 306 +%token WHILE 401 +%token IF 402 +%token THEN 403 +%token ELSE 404 +%token TYPE 405 +%token FUNCTION 406 +%token RETURN 407 +%token EXTERNAL 408 +%token AS 409 +%token L_PAREN 501 +%token R_PAREN 502 +%token L_BRACKET 503 +%token R_BRACKET 504 +%token L_BRACE 505 +%token R_BRACE 506 +%token SEMI_COLON 507 +%token COLON 508 +%token COMMA 509 +%token ARROW 510 +%token MUL 603 +%token DIV 604 +%token REM 605 +%token ADD 601 +%token LESS_THAN 606 +%token EQUAL_TO 607 +%token AND 610 +%token OR 611 +%token ASSIGN 608 +%token SUB_OR_NEG 602 +%token NOT 609 +%token DOT 612 +%token RESERVE 613 +%token RELEASE 614 +%token COMMENT 700 + +//precedence order +%left ASSIGN +%left OR +%left AND +%left EQUAL_TO +%left LESS_THAN +%left ADD SUB_OR_NEG +%left MUL DIV REM +%precedence NOT +%precedence UMINUS +%precedence DOT +%precedence RESERVE RELEASE + + + +%% + +program: + prototype_or_definition_list + ; + +prototype_or_definition_list: + prototype prototype_or_definition_list + | definition prototype_or_definition_list + | prototype + | definition + ; + +prototype: + L_PAREN EXTERNAL R_PAREN FUNCTION ID COLON ID; + +definition: +TYPE ID COLON {tn = CreateEntry(getAncestor(cur), recprime, $2, CreateRecordInfo(0, cur = CreateScope(cur, 0, 0))); + if (table_lookup(getAncestor(cur), $2) == NULL) { + printf("rec not found \n"); + } + }dblock { setRecSize(table_lookup(getParent(cur), $2), getRecSize(cur)); + cur = getParent(cur);} + | TYPE ID COLON C_INTEGER ARROW id_or_types { CreateEntry(cur, arrayprim, $2, CreateArrayInfo($4, look_up(cur, $6)));} + | function_declaration + | TYPE ID COLON id_or_types ARROW id_or_types { + CreateEntry(cur,funtypeprime,$2,CreateFunctionTypeInfo(table_lookup(cur,$4),table_lookup(cur,$6))); + } + | ID { + TableNode *node = table_lookup(getAncestor(cur), $1); + if (node == NULL || getAdInfoType(node) != TYPE_FUNCTION_DECLARATION) { + printf("function not declared at line %d, column %d\n", @1.first_line, @1.first_column); + } else { + setStartLine(node, @1.first_line); + setAsKeyword(node, false); + } + cur = CreateScope(cur, 0, 0); + } L_PAREN ID { + CreateEntry(cur, getParameter(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $1)))), $4, NULL); + }R_PAREN ASSIGN sblock + | ID { + TableNode *node = table_lookup(getAncestor(cur), $1); + if (node == NULL) { + printf("null check\n"); + } + if (node == NULL || getAdInfoType(node) != TYPE_FUNCTION_DECLARATION) { + printf("function not declared at line %d, column %d\n", @1.first_line, @1.first_column); + } else { + setStartLine(node, @1.first_line); + setAsKeyword(node, false); + } + cur = CreateScope(cur, 0, 0); + }AS L_PAREN { + TableNode *parameter = getParameter(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $1)))); + if (parameter == NULL || getAdInfoType(parameter) != TYPE_RECORD) { + printf("function defined with as, but parameter is not a record at line %d, column %d\n", @1.first_line, @1.first_column); + } else { + for (TableNode* entry = getFirstEntry(getRecList(parameter)); entry!= NULL; entry = getNextEntry(entry)){ + CreateEntry(cur, entry, NULL, NULL); + } + } + } idlist R_PAREN ASSIGN sblock + ; + + +function_declaration: + FUNCTION ID COLON ID {CreateEntry(cur, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false));} + | EXTERNAL FUNCTION ID COLON ID {CreateEntry(cur, look_up(cur, $5), $3, NULL);} + ; + + +idlist: + ID { + TableNode *entry = getFirstEntry(cur); + while (getName(entry) != NULL) { + entry = getNextEntry(entry); + } + if (getNextEntry(entry) == NULL) { + printf("too many parameters at line %d column %d\n", @1.first_line, @1.first_column); + } + addName(entry, $1); + } COMMA idlist + | ID { + + TableNode *entry = getFirstEntry(cur); + while (getName(entry) != NULL) { + entry = getNextEntry(entry); + } + if (getNextEntry(entry) != NULL) { + printf("too many parameters at line %d column %d\n", @1.first_line, @1.first_column); + } + addName(entry, $1); + } + ; + + +sblock: +L_BRACE {if (getLine(cur) != 0 && getColumn(cur))cur = CreateScope(cur,@1.first_line,@1.first_column);} statement_list {cur = getParent(cur);} R_BRACE + | L_BRACE {if (getLine(cur) != 0 && getColumn(cur))cur = CreateScope(cur,@1.first_line,@1.first_column);} dblock + {printf("seen sblock with dblock\n");} statement_list {cur = getParent(cur);} R_BRACE + ; + +dblock: + L_BRACKET declaration_list R_BRACKET; + +declaration_list: + declaration SEMI_COLON declaration_list + | declaration + ; + +declaration: + id_or_types COLON ID {printf("ID/TYPE: %s, ID: %s\n", $1, $3) ; CreateEntry(cur,table_lookup(getAncestor(cur),$1),$3,NULL); } + ; + +id_or_types: + ID {printf("string of id in id_or_type is %s\n",$1); $$ = getType(look_up(cur,$1));} + | types {printf("string of type in id_or_type is %s\n",$1);} {$$ = $1;} + ; + +statement_list: + compound_statement statement_list + | compound_statement + | simple_statement SEMI_COLON statement_list + | simple_statement SEMI_COLON + ; + +compound_statement: + WHILE L_PAREN expression R_PAREN sblock + | IF L_PAREN expression R_PAREN THEN sblock ELSE sblock + | sblock //{printf("seen a compound statement rule\n");} + ; + +simple_statement: + assignable ASSIGN expression {if(strcmp($1, $3) == 0){ + } else { + printf("Mismatch at line %d and column%d\n", @2.first_line, @2.first_column); + }} + + | RETURN expression + ; + +assignable: + ID {$$ = getType(look_up(cur,$1));} + | assignable ablock {$$ = getName(getReturn(look_up(cur, $1)));} + | assignable rec_op ID {if(undefined != table_lookup(getRecList(look_up(cur, $1)), $3)){ + {$$ = getName(table_lookup(getRecList(look_up(cur, $1)), $3));}};} + ; + +rec_op : + DOT + +expression: + constant {printf("constant expression\n");} {$$ = $1;} + + | SUB_OR_NEG expression %prec UMINUS {printf("negative expression\n");if(strcmp($2,"integer") != 0) + {printf("cant negate something not an integer at line %d and column %d\n",@2.first_line,@2.first_column); + $$=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. Invalid type being negated is %s\n", + @1.first_line,@1.first_column,$2);}} + + | expression ADD expression + {printf("add expression\n");if(strcmp($1,$3)==0 && strcmp($1,"integer")==0){$$=strdup("integer");} + else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", + @2.first_line,@2.first_column,$1,$3); + $$=strdup("undefined");}} + + | expression SUB_OR_NEG expression + {printf("sub or neg expression\n");if(strcmp($1,$3)==0 &&strcmp($1,"integer")==0){$$=strdup("integer");} + else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", + @2.first_line,@2.first_column,$1,$3); + $$=strdup("undefined");}} + + | expression MUL expression + {printf("multiply expression\n"); + if(strcmp($1,$3)==0 &&strcmp($1,"integer")==0){$$=strdup("integer");} + else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", + @2.first_line,@2.first_column,$1,$3); + $$=strdup("undefined");}} + + | expression DIV expression + {printf("divide expression\n");if(strcmp($1,$3)==0 && strcmp($1,"integer")==0){$$=strdup("integer");} + else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", + @2.first_line,@2.first_column,$1,$3); + $$=strdup("undefined");}} + + | expression REM expression + {printf("remainder expression\n");if(strcmp($1,$3)==0 && strcmp($1,"integer")==0){$$=strdup("integer");} + else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", + @2.first_line,@2.first_column,$1,$3); + $$=strdup("undefined");}} + + | expression AND expression + {printf("AND expression\n");if(strcmp($1,$3)==0 && strcmp($1,"Boolean")==0){$$=strdup("Boolean");} + else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", + @2.first_line,@2.first_column,$1,$3); + $$=strdup("undefined");}} + + | expression OR expression + {printf("OR\n");if(strcmp($1,$3)==0 && + strcmp($1,"Boolean")==0){$$=strdup("Boolean");} + else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", + @2.first_line,@2.first_column,$1,$3); + $$=strdup("undefined");}} + + | expression LESS_THAN expression + {printf("less than expression\n");if(strcmp($1,$3)==0 && + strcmp($1,"integer")==0){$$=strdup("Boolean");} + else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", + @2.first_line,@2.first_column,$1,$3); + $$=strdup("undefined");}} + + | 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. Invalid types %s and %s\n", + @2.first_line,@2.first_column,$1,$3);$$=strdup("undefined");}} + + | assignable {printf("assignable expression. current type is %s\n",$1);$$=$1;} + + | L_PAREN expression R_PAREN {printf("paren expression. current type is %s\n",$2);$$=$2;} + + | memOp assignable {$$ = strdup("address");} + ; + + +ablock: +L_PAREN argument_list {$$ = $2;} R_PAREN + ; + +argument_list: +expression COMMA argument_list {$$ = $3 + 1;} +| expression {$$ = 1;} + ; + + +memOp: + RESERVE {printf("reserve expression\n");} + | RELEASE {printf("release expression\n");} + ; + + +constant: + C_STRING {$$ = $1;} + | C_INTEGER {$$ = "integer";} + | C_NULL {$$ = $1;} + | C_CHARACTER {$$ = $1;} + | C_TRUE {$$ = $1;} + | C_FALSE {$$ = $1;} + ; + +types: + // Commented out T_String below + // T_STRING {printf("string of T_STRING in types is %s\n",$1);} {$$ = $1;} + T_INTEGER {printf("string of T_INTEGER in types is %s\n",$1);} {$$ = $1;} + | T_ADDRESS {printf("string of T_ADDRESS in types is %s\n",$1);} {$$ = $1;} + | T_CHARACTER {printf("string of T_CHARACTER in types is %s\n",$1);} {$$ = $1;} + | T_BOOLEAN {printf("string of T_BOOLEAN in types is %s\n",$1);} {$$ = $1;} + ; + +%% + +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); +} From ad4f55c2bf5005d7bc38655d0573d0f572b0c98d Mon Sep 17 00:00:00 2001 From: Scarlett Date: Fri, 28 Mar 2025 20:38:21 -0400 Subject: [PATCH 2/2] HUGE Makefile updates! --- Makefile | 33 +- check.sh | 73 ++-- src/grammar.y~ | 373 ------------------ src/symbol_table.c | 2 +- test.sh | 166 ++++++++ ..._mistake.alpha => sp2_carls_mistake.alpha} | 0 ...id_recop.alpha => sp2_invalid_recop.alpha} | 0 ...elease.alpha => sp2_invalid_release.alpha} | 0 ...pha => sp2_valid_assignable_and_mem.alpha} | 0 9 files changed, 242 insertions(+), 405 deletions(-) delete mode 100644 src/grammar.y~ create mode 100755 test.sh rename tests/sprint2/test/{test_carls_mistake.alpha => sp2_carls_mistake.alpha} (100%) rename tests/sprint2/test/{test_invalid_recop.alpha => sp2_invalid_recop.alpha} (100%) rename tests/sprint2/test/{test_invalid_release.alpha => sp2_invalid_release.alpha} (100%) rename tests/sprint2/test/{test_valid_assignable_and_mem.alpha => sp2_valid_assignable_and_mem.alpha} (100%) diff --git a/Makefile b/Makefile index c58b895..0f04da9 100644 --- a/Makefile +++ b/Makefile @@ -6,8 +6,9 @@ CFLAGS := YACC := bison TESTS-S1 := $(wildcard tests/sprint1/test/*.alpha) -TESTS-S3 := $(wildcard tests/sprint3/test/*.alpha) TESTS-S2 := $(wildcard tests/sprint2/test/*.alpha) +TESTS-S3 := $(wildcard tests/sprint3/test/*.alpha) +TESTS-S4 := $(wildcard tests/sprint4/test/*.alpha) compiler: clean runner @@ -33,22 +34,38 @@ runner: tmp/lex.yy.c tmp/runner.o tmp/symbol_table.o debug: CFLAGS += -DDEBUG=1 debug: clean compiler -test: test-s1 test-s2 test-s3 +test: + chmod +x ./check.sh + chmod +x ./test.sh + $(foreach test, $(TESTS-S1), (./$(EXE) -tok $(test) || true);) + ./test.sh sp2 + ./test.sh sp3 + ./test.sh sp4 + ./check.sh test-s1: chmod +x ./check.sh - for test in $(TESTS-S1); do ./$(EXE) -tok $$test || echo "Test $$test failed but continuing"; done - ./check.sh + chmod +x ./test.sh + $(foreach test, $(TESTS-S1), (./$(EXE) -tok $(test) || true);) + ./check.sh sp1 test-s2: chmod +x ./check.sh - for test in $(TESTS-S2); do ./$(EXE) -st $$test || echo "Test $$test failed but continuing"; done - ./check.sh + chmod +x ./test.sh + ./test.sh sp2 + ./check.sh sp2 test-s3: chmod +x ./check.sh - for test in $(TESTS-S3); do ./$(EXE) -st $$test || echo "Test $$test failed but continuing"; done - ./check.sh + chmod +x ./test.sh + ./test.sh sp3 + ./check.sh sp3 + +test-s4: + chmod +x ./check.sh + chmod +x ./test.sh + ./test.sh sp4 + ./check.sh sp4 clean: rm -f *.o diff --git a/check.sh b/check.sh index f325421..bac18ec 100755 --- a/check.sh +++ b/check.sh @@ -5,34 +5,61 @@ # The Translators - Spring 2025 # TOK_DIR="out" +NOCOLOR='\033[0m' RED='\033[0;31m' GREEN='\033[0;32m' -WHITE='\033[0m' -PURPLE='\033[0;35m' ORANGE='\033[0;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +LIGHTGRAY='\033[0;37m' +DARKGRAY='\033[1;30m' +LIGHTRED='\033[1;31m' +LIGHTGREEN='\033[1;32m' +YELLOW='\033[1;33m' +LIGHTBLUE='\033[1;34m' +LIGHTPURPLE='\033[1;35m' +LIGHTCYAN='\033[1;36m' +WHITE='\033[1;37m' + +compare_files() { + local file="$1" + local filename=$(basename -- "$file") + filename="${filename%.*}" + local num=${filename:2:1} + local exp="./tests/sprint$num/expected/$filename.expected" + + if [[ -f "$exp" ]]; then + diff -q "$file" "$exp" > /dev/null + if [[ $? -eq 0 ]]; then + echo -e "${GREEN}[✔] ${PURPLE}$filename ${WHITE}passed.${NOCOLOR}" + else + echo -e "\n${RED}[✘] ${PURPLE}$file ${WHITE}failed with an unexpected value...${NOCOLOR}" + diff --color=always "$file" "$exp" + echo -e "" + fi + else + echo -e "${ORANGE}[-] ${PURPLE}$filename ${WHITE}does not have an expected value.${NOCOLOR}" + fi +} if [[ ! -d "$TOK_DIR" ]]; then - echo "Directory $TOK_DIR does not exist." + echo -e "${RED}[ERROR] ${YELLOW}Directory $TOK_DIR does not exist.${NOCOLOR}" exit 1 fi -echo -e "\n" -for file in "$TOK_DIR"/*; do - filename=$(basename -- "$file") - filename="${filename%.*}" - num=${filename:2:1} - exp="./tests/sprint$num/expected/$filename.expected" - - if [[ -f "$exp" ]]; then - diff -q "$file" "$exp" > /dev/null - if [[ $? -eq 0 ]]; then - echo -e "${GREEN}[✔] ${PURPLE}$filename ${WHITE}passed." - 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 -done \ No newline at end of file +if [[ $# -eq 0 ]]; then + for file in "$TOK_DIR"/*; do + compare_files "$file" + done +elif [[ $# -eq 1 ]]; then + prefix="$1" + for file in "$TOK_DIR"/"$prefix"*; do + if [[ -f "$file" ]]; then + compare_files "$file" + fi + done +else + echo -e "${LIGHTBLUE}Usage: $0 [sp#]${NOCOLOR}" + exit 1 +fi \ No newline at end of file diff --git a/src/grammar.y~ b/src/grammar.y~ deleted file mode 100644 index 5238aac..0000000 --- a/src/grammar.y~ +++ /dev/null @@ -1,373 +0,0 @@ - -/* Syntax Analyzer with Bison (3.8.2) */ -/* The Translators - Spring 2025 */ - -%{ - #include - #include "../src/symbol_table.c" - #include - extern int yylex(void); - void yyerror(const char *err); - extern char* yytext; - extern int yyleng; - extern int yychar; - extern SymbolTable * cur; - //char* cur_value; - //char* cur_type; - int token_tracker; - extern int line_number; - extern int column_number; - 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; - TableNode * tn; -%} -//%define api.location.type {location_t} -%locations -%union { - int integ; - char * words; -} - - -%type assignable -%type expression -%type constant -%type id_or_types -%type types -%token ID 101 -%token T_INTEGER 201 -%token T_ADDRESS 202 -%token T_BOOLEAN 203 -%token T_CHARACTER 204 -%token T_STRING 205 -%token C_INTEGER 301 -%token C_NULL 302 -%token C_CHARACTER 303 -%token C_STRING 304 -%token C_TRUE 305 -%token C_FALSE 306 -%token WHILE 401 -%token IF 402 -%token THEN 403 -%token ELSE 404 -%token TYPE 405 -%token FUNCTION 406 -%token RETURN 407 -%token EXTERNAL 408 -%token AS 409 -%token L_PAREN 501 -%token R_PAREN 502 -%token L_BRACKET 503 -%token R_BRACKET 504 -%token L_BRACE 505 -%token R_BRACE 506 -%token SEMI_COLON 507 -%token COLON 508 -%token COMMA 509 -%token ARROW 510 -%token MUL 603 -%token DIV 604 -%token REM 605 -%token ADD 601 -%token LESS_THAN 606 -%token EQUAL_TO 607 -%token AND 610 -%token OR 611 -%token ASSIGN 608 -%token SUB_OR_NEG 602 -%token NOT 609 -%token DOT 612 -%token RESERVE 613 -%token RELEASE 614 -%token COMMENT 700 - -//precedence order -%left ASSIGN -%left OR -%left AND -%left EQUAL_TO -%left LESS_THAN -%left ADD SUB_OR_NEG -%left MUL DIV REM -%precedence NOT -%precedence UMINUS -%precedence DOT -%precedence RESERVE RELEASE - - - -%% - -program: - prototype_or_definition_list - ; - -prototype_or_definition_list: - prototype prototype_or_definition_list - | definition prototype_or_definition_list - | prototype - | definition - ; - -prototype: - L_PAREN EXTERNAL R_PAREN FUNCTION ID COLON ID; - -definition: -TYPE ID COLON {tn = CreateEntry(getAncestor(cur), recprime, $2, CreateRecordInfo(0, cur = CreateScope(cur, 0, 0))); - if (table_lookup(getAncestor(cur), $2) == NULL) { - printf("rec not found \n"); - } - }dblock { setRecSize(table_lookup(getParent(cur), $2), getRecSize(cur)); - cur = getParent(cur);} - | TYPE ID COLON C_INTEGER ARROW id_or_types { CreateEntry(cur, arrayprim, $2, CreateArrayInfo($4, look_up(cur, $6)));} - | function_declaration - | TYPE ID COLON id_or_types ARROW id_or_types { - CreateEntry(cur,funtypeprime,$2,CreateFunctionTypeInfo(table_lookup(cur,$4),table_lookup(cur,$6))); - } - | ID { - TableNode *node = table_lookup(getAncestor(cur), $1); - if (node == NULL || getAdInfoType(node) != TYPE_FUNCTION_DECLARATION) { - printf("function not declared at line %d, column %d\n", @1.first_line, @1.first_column); - } else { - setStartLine(node, @1.first_line); - setAsKeyword(node, false); - } - cur = CreateScope(cur, 0, 0); - } L_PAREN ID { - CreateEntry(cur, getParameter(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $1)))), $4, NULL); - }R_PAREN ASSIGN sblock - | ID { - TableNode *node = table_lookup(getAncestor(cur), $1); - if (node == NULL) { - printf("null check\n"); - } - if (node == NULL || getAdInfoType(node) != TYPE_FUNCTION_DECLARATION) { - printf("function not declared at line %d, column %d\n", @1.first_line, @1.first_column); - } else { - setStartLine(node, @1.first_line); - setAsKeyword(node, false); - } - cur = CreateScope(cur, 0, 0); - }AS L_PAREN { - TableNode *parameter = getParameter(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $1)))); - if (parameter == NULL || getAdInfoType(parameter) != TYPE_RECORD) { - printf("function defined with as, but parameter is not a record at line %d, column %d\n", @1.first_line, @1.first_column); - } else { - for (TableNode* entry = getFirstEntry(getRecList(parameter)); entry!= NULL; entry = getNextEntry(entry)){ - CreateEntry(cur, entry, NULL, NULL); - } - } - } idlist R_PAREN ASSIGN sblock - ; - - -function_declaration: - FUNCTION ID COLON ID {CreateEntry(cur, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false));} - | EXTERNAL FUNCTION ID COLON ID {CreateEntry(cur, look_up(cur, $5), $3, NULL);} - ; - - -idlist: - ID { - TableNode *entry = getFirstEntry(cur); - while (getName(entry) != NULL) { - entry = getNextEntry(entry); - } - if (getNextEntry(entry) == NULL) { - printf("too many parameters at line %d column %d\n", @1.first_line, @1.first_column); - } - addName(entry, $1); - } COMMA idlist - | ID { - - TableNode *entry = getFirstEntry(cur); - while (getName(entry) != NULL) { - entry = getNextEntry(entry); - } - if (getNextEntry(entry) != NULL) { - printf("too many parameters at line %d column %d\n", @1.first_line, @1.first_column); - } - addName(entry, $1); - } - ; - - -sblock: -L_BRACE {if (getLine(cur) != 0 && getColumn(cur))cur = CreateScope(cur,@1.first_line,@1.first_column);} statement_list {cur = getParent(cur);} R_BRACE - | L_BRACE {if (getLine(cur) != 0 && getColumn(cur))cur = CreateScope(cur,@1.first_line,@1.first_column);} dblock - {printf("seen sblock with dblock\n");} statement_list {cur = getParent(cur);} R_BRACE - ; - -dblock: - L_BRACKET declaration_list R_BRACKET; - -declaration_list: - declaration SEMI_COLON declaration_list - | declaration - ; - -declaration: - id_or_types COLON ID {printf("ID/TYPE: %s, ID: %s\n", $1, $3) ; CreateEntry(cur,table_lookup(getAncestor(cur),$1),$3,NULL); } - ; - -id_or_types: - ID {printf("string of id in id_or_type is %s\n",$1); $$ = getType(look_up(cur,$1));} - | types {printf("string of type in id_or_type is %s\n",$1);} {$$ = $1;} - ; - -statement_list: - compound_statement statement_list - | compound_statement - | simple_statement SEMI_COLON statement_list - | simple_statement SEMI_COLON - ; - -compound_statement: - WHILE L_PAREN expression R_PAREN sblock - | IF L_PAREN expression R_PAREN THEN sblock ELSE sblock - | sblock //{printf("seen a compound statement rule\n");} - ; - -simple_statement: - assignable ASSIGN expression {if(strcmp($1, $3) == 0){ - } else { - printf("Mismatch at line %d and column%d\n", @2.first_line, @2.first_column); - }} - - | RETURN expression - ; - -assignable: - ID {$$ = getType(look_up(cur,$1));} - | assignable ablock {$$ = getName(getReturn(look_up(cur, $1)));} - | assignable rec_op ID {if(undefined != table_lookup(getRecList(look_up(cur, $1)), $3)){ - {$$ = getName(table_lookup(getRecList(look_up(cur, $1)), $3));}};} - ; - -rec_op : - DOT - -expression: - constant {printf("constant expression\n");} {$$ = $1;} - - | SUB_OR_NEG expression %prec UMINUS {printf("negative expression\n");if(strcmp($2,"integer") != 0) - {printf("cant negate something not an integer at line %d and column %d\n",@2.first_line,@2.first_column); - $$=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. Invalid type being negated is %s\n", - @1.first_line,@1.first_column,$2);}} - - | expression ADD expression - {printf("add expression\n");if(strcmp($1,$3)==0 && strcmp($1,"integer")==0){$$=strdup("integer");} - else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", - @2.first_line,@2.first_column,$1,$3); - $$=strdup("undefined");}} - - | expression SUB_OR_NEG expression - {printf("sub or neg expression\n");if(strcmp($1,$3)==0 &&strcmp($1,"integer")==0){$$=strdup("integer");} - else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", - @2.first_line,@2.first_column,$1,$3); - $$=strdup("undefined");}} - - | expression MUL expression - {printf("multiply expression\n"); - if(strcmp($1,$3)==0 &&strcmp($1,"integer")==0){$$=strdup("integer");} - else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", - @2.first_line,@2.first_column,$1,$3); - $$=strdup("undefined");}} - - | expression DIV expression - {printf("divide expression\n");if(strcmp($1,$3)==0 && strcmp($1,"integer")==0){$$=strdup("integer");} - else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", - @2.first_line,@2.first_column,$1,$3); - $$=strdup("undefined");}} - - | expression REM expression - {printf("remainder expression\n");if(strcmp($1,$3)==0 && strcmp($1,"integer")==0){$$=strdup("integer");} - else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", - @2.first_line,@2.first_column,$1,$3); - $$=strdup("undefined");}} - - | expression AND expression - {printf("AND expression\n");if(strcmp($1,$3)==0 && strcmp($1,"Boolean")==0){$$=strdup("Boolean");} - else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", - @2.first_line,@2.first_column,$1,$3); - $$=strdup("undefined");}} - - | expression OR expression - {printf("OR\n");if(strcmp($1,$3)==0 && - strcmp($1,"Boolean")==0){$$=strdup("Boolean");} - else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", - @2.first_line,@2.first_column,$1,$3); - $$=strdup("undefined");}} - - | expression LESS_THAN expression - {printf("less than expression\n");if(strcmp($1,$3)==0 && - strcmp($1,"integer")==0){$$=strdup("Boolean");} - else{printf("mismatch at line %d and column %d. Invalid types %s and %s.\n", - @2.first_line,@2.first_column,$1,$3); - $$=strdup("undefined");}} - - | 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. Invalid types %s and %s\n", - @2.first_line,@2.first_column,$1,$3);$$=strdup("undefined");}} - - | assignable {printf("assignable expression. current type is %s\n",$1);$$=$1;} - - | L_PAREN expression R_PAREN {printf("paren expression. current type is %s\n",$2);$$=$2;} - - | memOp assignable {$$ = strdup("address");} - ; - - -ablock: -L_PAREN argument_list {$$ = $2;} R_PAREN - ; - -argument_list: -expression COMMA argument_list {$$ = $3 + 1;} -| expression {$$ = 1;} - ; - - -memOp: - RESERVE {printf("reserve expression\n");} - | RELEASE {printf("release expression\n");} - ; - - -constant: - C_STRING {$$ = $1;} - | C_INTEGER {$$ = "integer";} - | C_NULL {$$ = $1;} - | C_CHARACTER {$$ = $1;} - | C_TRUE {$$ = $1;} - | C_FALSE {$$ = $1;} - ; - -types: - // Commented out T_String below - // T_STRING {printf("string of T_STRING in types is %s\n",$1);} {$$ = $1;} - T_INTEGER {printf("string of T_INTEGER in types is %s\n",$1);} {$$ = $1;} - | T_ADDRESS {printf("string of T_ADDRESS in types is %s\n",$1);} {$$ = $1;} - | T_CHARACTER {printf("string of T_CHARACTER in types is %s\n",$1);} {$$ = $1;} - | T_BOOLEAN {printf("string of T_BOOLEAN in types is %s\n",$1);} {$$ = $1;} - ; - -%% - -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); -} diff --git a/src/symbol_table.c b/src/symbol_table.c index 7f8849b..cdcbd30 100644 --- a/src/symbol_table.c +++ b/src/symbol_table.c @@ -921,4 +921,4 @@ TableNode *getNextEntry(TableNode *tn) { return tn->next; } printf("The type of the first entry is %s\n",First_Entry->theType); return 0; } - */ + */ \ No newline at end of file diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..e35809e --- /dev/null +++ b/test.sh @@ -0,0 +1,166 @@ +#!/bin/bash + +# Test Tool # +# The Translators - Spring 2025 # + +RED='\033[0;31m' +GREEN='\033[0;32m' +ORANGE='\033[0;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +LIGHTGRAY='\033[0;37m' +DARKGRAY='\033[1;30m' +LIGHTRED='\033[1;31m' +LIGHTGREEN='\033[1;32m' +YELLOW='\033[1;33m' +LIGHTBLUE='\033[1;34m' +LIGHTPURPLE='\033[1;35m' +LIGHTCYAN='\033[1;36m' +WHITE='\033[1;37m' + +if [ ! -f "./alpha" ]; then + echo -e "${RED}[ERROR] ${YELLOW}File ./alpha not found!${WHITE}" + exit 1 +fi + +if [ ! -d "./out" ]; then + mkdir -p out +fi + +SWITCH=${YELLOW} +count=0 + +switchfunc() { + if [ $count -eq 0 ]; then + count=1 + SWITCH=${YELLOW} + else + count=0 + SWITCH='\033[0;35m' + fi +} + +if [ $# -eq 0 ]; then + echo -e "${YELLOW}[INFO] ${WHITE}Running all tests...${WHITE}" + echo -e "${YELLOW}[INFO] ${ORANGE}Testing SPRINT-1 ---------------------------\n${WHITE}" + for file in ./tests/sprint1/test/*; do + if [ -f "$file" ]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n" + switchfunc + fi + done + echo -e "" + + echo -e "${YELLOW}[INFO] ${ORANGE}Testing SPRINT-2 ---------------------------\n${WHITE}" + for file in ./tests/sprint2/test/*; do + if [ -f "$file" ]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n" + switchfunc + fi + done + echo -e "" + + echo -e "${YELLOW}[INFO] ${ORANGE}Testing SPRINT-3 ---------------------------\n${WHITE}" + for file in ./tests/sprint3/test/*; do + if [ -f "$file" ]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n" + switchfunc + fi + done + echo -e "" + + echo -e "${YELLOW}[INFO] ${ORANGE}Testing SPRINT-4 ---------------------------\n${WHITE}" + for file in ./tests/sprint4/test/*; do + if [ -f "$file" ]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n${WHITE}" + switchfunc + fi + done + +else + if [ "$1" == "--help" ]; then + echo -e "${YELLOW}[INFO] ${WHITE}Usage: ./test.sh [prefix]" + echo -e "${YELLOW}[INFO] ${WHITE}--help: show this help message" + echo -e "${YELLOW}[INFO] ${WHITE}--file : run test with file" + exit 0 + fi + if [[ "$1" == "--file" ]]; then + shift + if [ $# -eq 0 ]; then + echo -e "${RED}[ERROR] ${YELLOW}No file specified!${WHITE}" + exit 1 + fi + if [ -f "$1" ]; then + filename=$(basename -- "$1") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st "$1" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}" + exit 1 + else + echo -e "${RED}[ERROR] ${YELLOW}File $1 not found!${WHITE}" + exit 1 + fi + fi + + if [[ "$1" == "sp1" ]]; then + echo -e "${YELLOW}[INFO] ${WHITE}Running tests with prefix $1..." + for file in ./tests/sprint1/test/*; do + if [[ "$file" == *"$1"* ]]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n" + switchfunc + fi + done + elif [[ "$1" == "sp2" ]]; then + echo -e "${YELLOW}[INFO] ${WHITE}Running tests with prefix $1..." + for file in ./tests/sprint2/test/*; do + if [[ "$file" == *"$1"* ]]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n" + switchfunc + fi + done + elif [[ "$1" == "sp3" ]]; then + echo -e "${YELLOW}[INFO] ${WHITE}Running tests with prefix $1..." + for file in ./tests/sprint3/test/*; do + if [[ "$file" == *"$1"* ]]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n" + switchfunc + fi + done + elif [[ "$1" == "sp4" ]]; then + echo -e "${YELLOW}[INFO] ${WHITE}Running tests with prefix $1..." + for file in ./tests/sprint4/test/*; do + if [[ "$file" == *"$1"* ]]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n" + switchfunc + fi + done + else + echo -e "${RED}[ERROR] ${YELLOW}Invalid prefix $1!${WHITE}" + exit 1 + fi +fi \ No newline at end of file diff --git a/tests/sprint2/test/test_carls_mistake.alpha b/tests/sprint2/test/sp2_carls_mistake.alpha similarity index 100% rename from tests/sprint2/test/test_carls_mistake.alpha rename to tests/sprint2/test/sp2_carls_mistake.alpha diff --git a/tests/sprint2/test/test_invalid_recop.alpha b/tests/sprint2/test/sp2_invalid_recop.alpha similarity index 100% rename from tests/sprint2/test/test_invalid_recop.alpha rename to tests/sprint2/test/sp2_invalid_recop.alpha diff --git a/tests/sprint2/test/test_invalid_release.alpha b/tests/sprint2/test/sp2_invalid_release.alpha similarity index 100% rename from tests/sprint2/test/test_invalid_release.alpha rename to tests/sprint2/test/sp2_invalid_release.alpha diff --git a/tests/sprint2/test/test_valid_assignable_and_mem.alpha b/tests/sprint2/test/sp2_valid_assignable_and_mem.alpha similarity index 100% rename from tests/sprint2/test/test_valid_assignable_and_mem.alpha rename to tests/sprint2/test/sp2_valid_assignable_and_mem.alpha