diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a6fca1a --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +*.tok +*.o +alpha +flex.h +grammar.tab.c +grammar.tab.h +.vscode +out +tmp +parser +*.save \ No newline at end of file diff --git a/Grammar-FE-t-NoTask b/Grammar-FE-t-NoTask new file mode 100644 index 0000000..1ad478e --- /dev/null +++ b/Grammar-FE-t-NoTask @@ -0,0 +1,35 @@ +* Dev + Sprint1-TokenLocationLogic-NoTask + Sprint1-TokenizeConstantsAndLiterals-FE-t#03 + Sprint2-BlockHandlingGrammar-FE-t#34 + Sprint2-CombineGrammarAndMakeAndRunner-BE-NoTask# + Sprint2-NewFormatPlusGrammar-FE-t#NoTask + Sprint2-PrintOutErrorTokenPositions-NoTask + Sprint2-Symbol_Table_Setup-FE-t#32 + Token_Error_Logic-No_Task + main + remotes/origin/Dev + remotes/origin/HEAD -> origin/main + remotes/origin/Sprint1-BasicProgSetup-FE-t#06 + remotes/origin/Sprint1-BasicProgSetupFix-t#06 + remotes/origin/Sprint1-HelpInput-FE-t#18 + remotes/origin/Sprint1-TokenLocationLogic-NoTask + remotes/origin/Sprint1-TokenizeConstantsAndLiterals-FE-t#03 + remotes/origin/Sprint1-TokenizeID_MainFunction-FE-t#04 + remotes/origin/Sprint1-TokenizeOperators-FE-t#08 + remotes/origin/Sprint1-Type/Keywards-FE-t#07 + remotes/origin/Sprint1-punctuation/grouping-FE-t#09 + remotes/origin/Sprint2-AssignableAndMemory-FE-t#39 + remotes/origin/Sprint2-BlockHandlingGrammar-FE-t#34 + remotes/origin/Sprint2-CombineGrammarAndMakeAndRunner-BE-NoTask# + remotes/origin/Sprint2-CommandLineHandling-FE-t#33 + remotes/origin/Sprint2-CompoundStmntGrmmr-FE-t#36 + remotes/origin/Sprint2-FunctionDefinition-FE-t#38 + remotes/origin/Sprint2-Infrastructure-FE-t#30 + remotes/origin/Sprint2-NewFormatPlusGrammar-FE-t#NoTask + remotes/origin/Sprint2-PrintOutErrorTokenPositions-NoTask + remotes/origin/Sprint2-SymbolTableOperations-FE-t#29 + remotes/origin/Sprint2-Symbol_Table_Setup-FE-t#32 + remotes/origin/Sprint2-addingTests-t#00 + remotes/origin/Token_Error_Logic-No_Task + remotes/origin/main diff --git a/Makefile b/Makefile index a9544ee..fe8f769 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,59 @@ -# Basic Makefile example from flex documentation -- provides explicit rules -# Creates "myprogram" from "scan.l" and "myprogram.c" -# -#LEX=flex -#myprogram: scan.o myprogram.o - #$(CC) -o $@ $(LDFLAGS) $^ -#myprogram.o: myprogram.c - #$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $^ -#scan.o: scan.c - #$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $^ -#scan.c: scan.l - #$(LEX) $(LFLAGS) -o $@ $^ -#clean: - #$(RM) *.o scan.c +CC := gcc +FLEX := flex +LEX := src/lexicalStructure.lex +EXE := alpha +CFLAGS := +YACC := bison + +TESTS-S1 := $(wildcard tests/sprint1/test/*.alpha) +TESTS-S2 := $(wildcard tests/sprint2/test/*.alpha) + +compiler: clean runner + +tmp/grammar.tab.c: src/grammar.y + mkdir -p tmp + $(YACC) -d src/grammar.y + mv grammar.tab.c tmp/ + mv grammar.tab.h tmp/ + +tmp/lex.yy.c: src/lexicalStructure.lex tmp/grammar.tab.c + $(FLEX) -o tmp/lex.yy.c $(LEX) + mv flex.h tmp/ + +tmp/runner.o: src/runner.c src/runner.h tmp/flex.h + $(CC) $(CFLAGS) -o tmp/runner.o -c src/runner.c + +tmp/symbol_table.o: src/symbol_table.c src/symbol_table.h + $(CC) $(CFLAGS) -o tmp/symbol_table.o -c src/symbol_table.c + +runner: tmp/lex.yy.c tmp/runner.o tmp/symbol_table.o + $(CC) $(CFLAGS) -o $(EXE) tmp/runner.o tmp/grammar.tab.c tmp/lex.yy.c + +debug: CFLAGS += -DDEBUG=1 +debug: clean compiler + +test: test-s1 test-s2 + +test-s1: + chmod +x ./check.sh + $(foreach test, $(TESTS-S1), ./$(EXE) -tok $(test);) + ./check.sh + +test-s2: + chmod +x ./check.sh + $(foreach test, $(TESTS-S2), ./$(EXE) -tok $(test);) + ./check.sh + $(foreach test, $(TESTS-S2), ./$(EXE) $(test);) + +clean: + rm -f *.o + rm -f lex.yy.c + rm -f $(EXE) + rm -f flex.h + rm -f *.tok + rm -f grammar.tab.c + rm -f grammar.tab.h + rm -f *.st + rm -rf out + rm -rf tmp + rm -f parser \ No newline at end of file diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..525582f --- /dev/null +++ b/README.MD @@ -0,0 +1,17 @@ +# The Translators α Compiler +#### Members: Annie Slenker, Meyer Simon, Partho Bhattacharya, & Scarlett Kadan + +## Lexical Analyzer +* **Undefined Behavior:** + * Spaces are not required between tokens. For instance, an INTEGER and an ID are valid even if there is no space between them +``` +Input: *5variable* +Output: 2 14 301 "5" + 1 1 101 "variable" +``` + +## Syntax Analyzer +* *Incomplete* + +## Symbol Table +* *TODO: Create diagram.* \ No newline at end of file diff --git a/check.sh b/check.sh new file mode 100755 index 0000000..b8b138c --- /dev/null +++ b/check.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Diff-Check Tool # +# Checks if outputed TOK = exp # +# The Translators - Spring 2025 # + +TOK_DIR="out" + +if [[ ! -d "$TOK_DIR" ]]; then + echo "Directory $TOK_DIR does not exist." + 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 + echo -e "--------------------------------------------" + echo -e "Checking $file...\n" + diff --color=always "$file" "$exp" + echo -e "--------------------------------------------\n" + fi +done \ No newline at end of file diff --git a/lexicalStructure.lex b/lexicalStructure.lex deleted file mode 100644 index c41b8ce..0000000 --- a/lexicalStructure.lex +++ /dev/null @@ -1,12 +0,0 @@ -/* Lexical Analysis with Flex (2.6.0) We used some of the code from this manual */ -/* so we placed the citation here. */ -/* definitions */ -%option noyywrap - %{ - #include - %} - -%% -//rules -%% -//user code diff --git a/runner b/runner new file mode 100755 index 0000000..2e82053 Binary files /dev/null and b/runner differ diff --git a/runner.c b/runner.c deleted file mode 100644 index e69de29..0000000 diff --git a/src/grammar.y b/src/grammar.y new file mode 100644 index 0000000..3e9bc44 --- /dev/null +++ b/src/grammar.y @@ -0,0 +1,264 @@ +/* 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; +%} +//%define api.location.type {location_t} +%locations +%union { + int integ; + char * words; +} + + +%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 dblock + | TYPE ID COLON constant ARROW ID + | function_declaration + | TYPE ID COLON id_or_types ARROW id_or_types + | ID parameter ASSIGN sblock + ; + +function_declaration: + FUNCTION ID COLON ID + | EXTERNAL FUNCTION ID COLON ID + ; + +parameter: + L_PAREN ID R_PAREN + | AS L_PAREN idlist R_PAREN + ; + +idlist: + ID COMMA idlist + | ID + ; + +sblock: + L_BRACE {cur = CreateScope(cur,@1.first_line,@1.first_column);} statement_list {cur = getParent(cur);} R_BRACE + | L_BRACE {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 {CreateEntry(cur,$1,$3); } + ; + +id_or_types: + ID {printf("string of id in id_or_type is %s\n",$1);} {$$ = $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 + | RETURN expression + ; + +assignable: + ID + | assignable ablock + | assignable rec_op ID + ; + +rec_op : + DOT + +expression: + + constant {printf("constant expression\n");} + | SUB_OR_NEG expression %prec UMINUS {printf("negative expression\n");} + | NOT expression {printf("not expression\n");} + | expression ADD expression {printf("add expression\n");} + | expression SUB_OR_NEG expression {printf("subtract expression\n");} + | expression MUL expression {printf("multiply expression\n");} + | expression DIV expression {printf("division expression\n");} + | expression REM expression {printf("remainder expression\n");} + | expression AND expression {printf("and 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");} + | assignable {printf("assignable expression\n");} + | L_PAREN expression R_PAREN {printf("paren expression\n");} + | memOp assignable + ; + + +ablock: + L_PAREN argument_list R_PAREN + ; + +argument_list: + expression COMMA argument_list + | expression + ; + + +memOp: + RESERVE {printf("reserve expression\n");} + | RELEASE {printf("release expression\n");} + ; + + +constant: + C_STRING + | C_INTEGER + | C_NULL + | C_CHARACTER + | C_TRUE + | C_FALSE + ; + +types: + 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); +} +/* +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; +} */ diff --git a/src/lexicalStructure.lex b/src/lexicalStructure.lex new file mode 100644 index 0000000..eac2840 --- /dev/null +++ b/src/lexicalStructure.lex @@ -0,0 +1,98 @@ +/* Lexical Analyzer with Flex (1.6.0) */ +/* The Translators - Spring 2025 */ + +%option noyywrap +%option header-file="flex.h" +%option yylineno +%{ + #include + #include "../tmp/grammar.tab.h" + #include "../src/symbol_table.h" + #ifndef DEBUG + #define DEBUG 0 + #endif + extern SymbolTable * cur; + extern FILE* tok_flag; + extern void incr(int lnum,int cnum, int tok); + extern void print_tok(int tok); + + int line_number = 1, column_number = 1; + int yycolumn = 1; + #define YY_USER_ACTION { \ + yylloc.first_line = yylineno; \ + yylloc.last_line = yylineno; \ + yylloc.first_column = yycolumn; \ + yylloc.last_column = yycolumn + yyleng - 1; \ + yycolumn += yyleng; } +%} + +STARCOM [^\*]|\*+[^\)\*]+ +PARENCOM [^\)]|[^\*\)]+\)+ +COMMENT \(\*{STARCOM}*\*\)|\(\*{PARENCOM}*\*\) +ID [A-Za-z_][0-9A-Za-z_]* +DIGIT [0-9] +CHAR \\n|\\t|\\'|[^'\n\t\\]|\\\\ +SCHAR \\n|\\t|\\\"|[^\"\n\\] + +%% + +"integer" {if(DEBUG) {printf( "T_INTEGER: %s (%d)\n", yytext, T_INTEGER);} else {if(tok_flag != NULL){print_tok(T_INTEGER);}incr(line_number,column_number,T_INTEGER);yylval.words = strdup(yytext);return T_INTEGER;}} +"address" {if(DEBUG) {printf( "T_ADDRESS: %s (%d)\n", yytext, T_ADDRESS);} else {if(tok_flag != NULL){print_tok(T_ADDRESS);}incr(line_number,column_number,T_ADDRESS);yylval.words = strdup(yytext);return T_ADDRESS;}} +"Boolean" {if(DEBUG) {printf( "T_BOOLEAN: %s (%d)\n", yytext, T_BOOLEAN);} else {if(tok_flag != NULL){print_tok(T_INTEGER);}incr(line_number,column_number,T_INTEGER);yylval.words = strdup(yytext);return T_BOOLEAN;}} +"character" {if(DEBUG) {printf( "T_CHARACTER: %s (%d)\n", yytext, T_CHARACTER);} else {if(tok_flag != NULL){print_tok(T_CHARACTER);}incr(line_number,column_number,T_CHARACTER);yylval.words = strdup(yytext);return T_CHARACTER;}} + +"while" {if(DEBUG) {printf( "WHILE: %s (%d)\n", yytext, WHILE);} else {if(tok_flag != NULL){print_tok(WHILE);}incr(line_number,column_number,WHILE);return WHILE;}} +"if" {if(DEBUG) {printf( "IF: %s (%d)\n", yytext, IF);} else {if(tok_flag != NULL){print_tok(IF);}incr(line_number,column_number,IF);return IF;}} +"then" {if(DEBUG) {printf( "THEN: %s (%d)\n", yytext, THEN);} else {if(tok_flag != NULL){print_tok(THEN);}incr(line_number,column_number,THEN);return THEN;}} +"else" {if(DEBUG) {printf( "ELSE: %s (%d)\n", yytext, ELSE);} else {if(tok_flag != NULL){print_tok(ELSE);}incr(line_number,column_number,ELSE);return ELSE;}} +"type" {if(DEBUG) {printf( "TYPE: %s (%d)\n", yytext, TYPE);} else {if(tok_flag != NULL){print_tok(TYPE);}incr(line_number,column_number,TYPE);return TYPE;}} +"function" {if(DEBUG) {printf( "FUNCTION: %s (%d)\n", yytext, FUNCTION);} else {if(tok_flag != NULL){print_tok(FUNCTION);}incr(line_number,column_number,FUNCTION);return FUNCTION;}} +"return" {if(DEBUG) {printf( "RETURN: %s (%d)\n", yytext, RETURN);} else {if(tok_flag != NULL){print_tok(RETURN);}incr(line_number,column_number,RETURN);return RETURN;}} +"external" {if(DEBUG) {printf( "EXTERNAL: %s (%d)\n", yytext, EXTERNAL);} else {if(tok_flag != NULL){print_tok(EXTERNAL);}incr(line_number,column_number,EXTERNAL);return EXTERNAL;}} +"as" {if(DEBUG) {printf( "AS: %s (%d)\n", yytext, AS);} else {if(tok_flag != NULL){print_tok(AS);}incr(line_number,column_number,AS);return AS;}} + +"release" {if(DEBUG) {printf( "RELEASE: %s (%d)\n", yytext, RELEASE);} else {if(tok_flag != NULL){print_tok(RELEASE);}incr(line_number,column_number,RELEASE);return RELEASE;}} +"reserve" {if(DEBUG) {printf( "RESERVE: %s (%d)\n", yytext, RESERVE);} else {if(tok_flag != NULL){print_tok(RESERVE);}incr(line_number,column_number,RESERVE);return RESERVE;}} + +"+" {if(DEBUG) {printf( "ADD: %s (%d)\n", yytext, ADD);} else {if(tok_flag != NULL){print_tok(ADD);}incr(line_number,column_number,ADD);return ADD;}} +"-" {if(DEBUG) {printf( "SUB_OR_NEG: %s (%d)\n", yytext, SUB_OR_NEG);} else {if(tok_flag != NULL){print_tok(SUB_OR_NEG);}incr(line_number,column_number,SUB_OR_NEG);return SUB_OR_NEG;}} +"*" {if(DEBUG) {printf( "MUL: %s (%d)\n", yytext, MUL);} else {if(tok_flag != NULL){print_tok(MUL);}incr(line_number,column_number,MUL);return MUL;}} +"/" {if(DEBUG) {printf( "DIV: %s (%d)\n", yytext, DIV);} else {if(tok_flag != NULL){print_tok(DIV);}incr(line_number,column_number,DIV);return DIV;}} +"%" {if(DEBUG) {printf( "REM: %s (%d)\n", yytext, REM);} else {if(tok_flag != NULL){print_tok(REM);}incr(line_number,column_number,REM);return REM;}} +"<" {if(DEBUG) {printf( "LESS_THAN: %s (%d)\n", yytext, LESS_THAN);} else {if(tok_flag != NULL){print_tok(LESS_THAN);}incr(line_number,column_number,LESS_THAN);return LESS_THAN;}} +"=" {if(DEBUG) {printf( "EQUAL_TO: %s (%d)\n", yytext, EQUAL_TO);} else {if(tok_flag != NULL){print_tok(EQUAL_TO);}incr(line_number,column_number,EQUAL_TO);return EQUAL_TO;}} +":=" {if(DEBUG) {printf( "ASSIGN: %s (%d)\n", yytext, ASSIGN);} else {if(tok_flag != NULL){print_tok(ASSIGN);}incr(line_number,column_number,ASSIGN);return ASSIGN;}} +"!" {if(DEBUG) {printf( "NOT: %s (%d)\n", yytext, NOT);} else {if(tok_flag != NULL){print_tok(NOT);}incr(line_number,column_number,NOT);return NOT;}} +"&" {if(DEBUG) {printf( "AND: %s (%d)\n", yytext, AND);} else {if(tok_flag != NULL){print_tok(AND);}incr(line_number,column_number,AND);return AND;}} +"|" {if(DEBUG) {printf( "OR: %s (%d)\n", yytext, OR);} else {if(tok_flag != NULL){print_tok(OR);}incr(line_number,column_number,OR);return OR;}} +"." {if(DEBUG) {printf( "DOT: %s (%d)\n", yytext, DOT);} else {if(tok_flag != NULL){print_tok(DOT);}incr(line_number,column_number,DOT);return DOT;}} + +";" {if(DEBUG) {printf( "SEMI_COLON: %s (%d)\n", yytext, SEMI_COLON);} else {if(tok_flag != NULL){print_tok(SEMI_COLON);}incr(line_number,column_number,SEMI_COLON);return SEMI_COLON;}} +":" {if(DEBUG) {printf( "COLON: %s (%d)\n", yytext, COLON);} else {if(tok_flag != NULL){print_tok(COLON);}incr(line_number,column_number,COLON);return COLON;}} +"," {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;}} + +{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;}} +'{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;}} +\"{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;}} +{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( "R_PAREN: %s (%d)\n", yytext, R_PAREN);} else {if(tok_flag != NULL){print_tok(R_PAREN);}incr(line_number,column_number,R_PAREN);return R_PAREN;}} +"[" {if(DEBUG) {printf( "L_BRACKET: %s (%d)\n", yytext, L_BRACKET);} else {if(tok_flag != NULL){print_tok(L_BRACKET);}incr(line_number,column_number,L_BRACKET);return L_BRACKET;}} +"]" {if(DEBUG) {printf( "R_BRACKET: %s (%d)\n", yytext, R_BRACKET);} else {if(tok_flag != NULL){print_tok(R_BRACKET);}incr(line_number,column_number,R_BRACKET);return R_BRACKET;}} +"{" {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;}} + +"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;}} +"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;}} +"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;}} + +{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;}} + +\n {yycolumn=1;incr(line_number,column_number,0);} +\t {incr(line_number,column_number,0);} +" " {incr(line_number,column_number,0);} +. {incr(line_number,column_number,0);} + +%% diff --git a/src/runner.c b/src/runner.c new file mode 100644 index 0000000..2110d23 --- /dev/null +++ b/src/runner.c @@ -0,0 +1,206 @@ +/* Runner File - Compiles alpha Compiler */ +/* The Translators - Spring 2025 */ + +#include "runner.h" + +int main(int argc, char *argv[]) { + if (argc == 1) { + fprintf(stderr, INVALID); + return -1; + } + + else if (argc == 2) { + if (is_help(argv[1])) { + return 0; + } else if (is_alpha_file(argv[1], strlen(argv[1])) == 0) { + no_flag = SET_FLAG; + alpha_file = fopen(argv[1], "r"); + } else { + fprintf(stderr, INVALID); + return -1; + } + } + + else { + if (is_alpha_file(argv[argc - 1], strlen(argv[argc - 1])) != 0) { + fprintf(stderr, INVALID); + return -1; + } else { + for (int i = 1; i < argc - 1; i++) { + if (check_flag(argv[i], argv[argc - 1]) != 0) { + fprintf(stderr, "INVALID FLAG(S): Use -help to view valid inputs \n"); + return -1; + } + } + alpha_file = fopen(argv[argc - 1], "r"); + } + } + return run(alpha_file); +} + +int check_flag(char *arg, char *alpha) { + if (strcmp("-tok", arg) == 0) { + if (tok_flag == NULL) { + return new_file(arg, alpha); + } + fprintf(stderr, "FLAGS REPEAT\n"); + return -1; + } else if (strcmp("-st", arg) == 0) { + if (st_flag == NULL) { + return new_file(arg, alpha); + } + fprintf(stderr, "FLAGS REPEAT\n"); + return -1; + } else { + fprintf(stderr, "INVALID FLAG: Use -help for valid inputs\n"); + return -1; + } +} + +void incr(int lnum,int cnum, int tok){ + //if (tok == COMMENT) { + for (int i = 0; i < yyleng; i++) { + if (yytext[i] == '\n') { + line_number++; + column_number = 0; + } + column_number++; + } +// }else{ +// column_number += yyleng; +// } +} +void print_tok(int tok){ +fprintf(tok_flag, "%d %d %3d \"%s\"\n", line_number, column_number,tok, yytext); +} +int run(FILE *alpha) { + int token; + top = cur = CreateScope(NULL, 1, 1); + + // If file is not found + if (alpha == NULL) { + fprintf(stderr, "INPUT FILE NOT FOUND\n"); + return -1; + } + yyin = alpha; + + // TOK FLAG + if (tok_flag != NULL) { + while (0 != (token = yylex())) { + //if (tok_flag != NULL) { + // fprintf(tok_flag, "%d %d %3d \"%s\"\n", line_number, column_number, + // token, yytext); + //} + /*if (token == COMMENT) { + for (int i = 0; i < yyleng; i++) { + if (yytext[i] == '\n') { + line_number++; + column_number = 0; + } + column_number++; + } + continue; + } + if (token == 1999) { + printf( + "On line number %d and column number %d we have an invalid " + "character:%s\n", + line_number, column_number, yytext); + } + column_number += yyleng; */ + } + fclose(tok_flag); + + if (yyin != NULL) { + fclose(yyin); + } + return 0; + } + + if (st_flag != NULL) { + // output symbol table, file pointer is + // print_symbol_table(top,st_flag); + } + + yyparse(); + FILE *f = fdopen(1, "w"); + print_symbol_table(getAncestor(cur), f); + fclose(f); + + if (yyin != NULL) { + fclose(yyin); + } + + return 0; +} + +bool is_help(char *input) { + if (strcmp(input, "-help") == 0) { + printf("%s", HELP); + return true; + } + + return false; +} + +int new_file(char *arg, char *alpha) { + int type_len; + const char *basename = alpha; + const char *slash = strchr(alpha, '/'); + + while (slash != NULL) { + basename = slash + 1; + slash = strchr(basename, '/'); + } + + mkdir("./out", 0777); + + char *new_basename = calloc(strlen(basename) + 5, sizeof(char)); + strcpy(new_basename, "./out/"); + strcat(new_basename, basename); + basename = new_basename; + + if (strcmp(arg, "-tok") == 0) { + type_len = TOK_LEN; + } else if (strcmp(arg, "-st") == 0) { + type_len = ST_LEN; + } else { + fprintf(stderr, "INVALID FLAG: Use -help to view valid inputs\n"); + return -1; + } + + // calculate lengths + int basename_len = strlen(basename); + char *file_name = + calloc(basename_len - ALPHA_OFFSET + type_len + 2, sizeof(char)); + + // coy filename and add extension + strncpy(file_name, basename, basename_len - ALPHA_OFFSET); + strcat(file_name, "."); + strcat(file_name, arg + 1); + + if (strcmp(arg, "-tok") == 0) { + tok_flag = fopen(file_name, "w"); + } else if (strcmp(arg, "-st") == 0) { + st_flag = fopen(file_name, "w"); + } + return 0; +} + +int is_alpha_file(char *alpha, int file_len) { + if (strcmp(".alpha", alpha + sizeof(char) * (file_len - ALPHA_OFFSET)) != 0) { + return -1; // not alpha file + } + return 0; // is alpha file +} + +void enter_scope(int line, int column) { + cur = CreateScope(cur, line, column); +} +void exit_scope() { + if (cur->Parent_Scope == NULL) { + printf("Can't close top"); + return; + } + cur = cur->Parent_Scope; +} diff --git a/src/runner.h b/src/runner.h new file mode 100644 index 0000000..9f66407 --- /dev/null +++ b/src/runner.h @@ -0,0 +1,52 @@ +/* Runner File - Compiles alpha Compiler */ +/* The Translators - Spring 2025 */ + +#define ALPHA_OFFSET 6 +#define TOK_LEN 3 +#define ST_LEN 2 +#define HELP \ + "HELP:\nHow to run the alpha compiler:\n./alpha [options] program\nValid " \ + "options:\n-tok output the token number, token, line number, and column " \ + "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 INVALID \ + "INVALID INPUT: Include a .alpha file or use -help for more inputs \n" + +#include +#include +#include +#include +#include + +#include "../tmp/flex.h" +#include "symbol_table.h" +//#include "typedefs.h" +#include "../tmp/grammar.tab.h" + +extern int line_number, column_number; +extern char *yytext; +extern FILE *yyin; +int arg; + +SymbolTable *top; +SymbolTable *cur; + +// int main(int argc, char* argv[]); +char *is_tok(int argc, char *argv[]); +// int is_alpha_file(char *file, int file_len); +void enter_scope(int, int); +void exit_scope(void); + +FILE *alpha_file; +FILE *tok_flag = NULL; +FILE *st_flag = NULL; +int no_flag = 0; + +int main(int argc, char *argv[]); +int new_file(char *arg, char *alpha); +int is_alpha_file(char *alpha, int file_len); +bool is_help(char *input); +int run(FILE *alpha); +int check_flag(char *arg, char *alpha); diff --git a/src/symbol_table.c b/src/symbol_table.c new file mode 100644 index 0000000..fa0e6bb --- /dev/null +++ b/src/symbol_table.c @@ -0,0 +1,198 @@ +/* Symbol Table */ +/* The Translators - Spring 2025 */ + +#include "symbol_table.h" + +#include +#include +#include +char * typey = "type"; +char * funy = "function"; +SymbolTable* CreateScope(SymbolTable* ParentScope, int Line, int Column) { + SymbolTable* table = (SymbolTable*)malloc(sizeof(SymbolTable)); + table->Line_Number = Line; + table->Column_Number = Column; + table->Parent_Scope = ParentScope; + table->Children_Scope = NULL; + table->entries = NULL; + if (ParentScope != NULL) { + if (ParentScope->Children_Scope == NULL) { + ListOfTable* newEntry = (ListOfTable*)malloc(sizeof(ListOfTable)); + newEntry->next = NULL; + // newEntry->prev = NULL; + newEntry->table = table; + ParentScope->Children_Scope = newEntry; + } else { + ListOfTable* newEntry = (ListOfTable*)malloc(sizeof(ListOfTable)); + // newEntry->prev = NULL; + newEntry->table = table; + ListOfTable* oldEntry = ParentScope->Children_Scope; + ParentScope->Children_Scope = newEntry; + newEntry->next = oldEntry; + } + } + return table; +} + +//create entry just for things below top level scope +TableNode* CreateEntry(SymbolTable* table, char* typeOf, char* id) { + +if(table ==NULL || table->Parent_Scope == NULL){ + printf("Null reference to table given for create entry or given top level scope which is invalid\n"); + 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; +} + TableNode* newEntry = (TableNode*)malloc(sizeof(TableNode)); + newEntry->theType = topDef->theName; + newEntry->theName = id; + if (table->entries == NULL) { + table->entries = newEntry; + return newEntry; + } else { + TableNode* oldEntry = table->entries; + table->entries = newEntry; + newEntry->next = oldEntry; + return newEntry; + } +} + +//we use false for type defs and true for functions for parameter of typeOf +TableNode* Define(SymbolTable* table, bool typeOf, char* id) { +if(table ==NULL || table->Parent_Scope != NULL){ + printf("No valid table given for header defs\n"); + return NULL; +} + + + TableNode* newEntry = (TableNode*)malloc(sizeof(TableNode)); + +//possible issues with referencing text instead of heap +if(typeOf == 0){ + newEntry->theType = typey; +} +if (typeOf == 1){ + newEntry->theType = funy; +} +if(table_lookup(table,id) != NULL){ + printf("already defined at the top level, can't define duplicate names\n"); + return NULL; +} + newEntry->theName = id; + if (table->entries == NULL) { + table->entries = newEntry; + return newEntry; + } else { + TableNode* oldEntry = table->entries; + table->entries = newEntry; + newEntry->next = oldEntry; + return newEntry; + } + +} + +TableNode* table_lookup(SymbolTable* table, char* x) { + TableNode* entrie = table->entries; + for (; entrie != NULL; entrie = entrie->next) { + if (!strcmp(entrie->theName, x)) { + return entrie; + } + } + return NULL; +} +TableNode* look_up(SymbolTable* table, char* x) { + if (table == NULL) { + return NULL; + } + TableNode* ret = table_lookup(table, x); + if (ret != NULL) { + return ret; + } + return look_up(table->Parent_Scope, x); +} + +void print_symbol_table(SymbolTable* table, FILE* file_ptr) { + if (table->Parent_Scope == NULL) { + fprintf(file_ptr, "%-17s: %-6s : %-6s : %-21s: %-28s\n", "NAME", "SCOPE", + "PARENT", "TYPE", "Extra annotation"); + } + TableNode* entrie = table->entries; + fprintf(file_ptr, + "-----------------:--------:--------:----------------------:---------" + "--------------------\n"); + int parant_scope = 0; + int current_scope = 0; + if (table->Parent_Scope != NULL) { + parant_scope = table->Parent_Scope->Line_Number * 1000 + + table->Parent_Scope->Column_Number; + current_scope = table->Line_Number * 1000 + table->Column_Number; + } else { + current_scope = 1001; + } + if ( entrie == NULL ) { + fprintf(file_ptr, "%-17s: %06d : %06d : %-21s: %-28s\n", "", + current_scope, parant_scope, "", "Empty Scope"); + } + for (; entrie != NULL; entrie = entrie->next) { + if (parant_scope == 0) { + fprintf(file_ptr, "%-17s: %06d : : %-21s: %-28s\n", + entrie->theName, current_scope, entrie->theType, + "Extra annotation"); + } else { + fprintf(file_ptr, "%-17s: %06d : %06d : %-21s: %-28s\n", entrie->theName, + current_scope, parant_scope, entrie->theType, "Extra annotation"); + } + } + if (table->Children_Scope != NULL) { + ListOfTable* node = table->Children_Scope; + for (; node != NULL; node = node->next) { + print_symbol_table(node->table, file_ptr); + } + } + if (table->Parent_Scope == NULL) { + fprintf(file_ptr, + "-----------------:--------:--------:----------------------:-------" + "----------------------\n"); + } +} + +SymbolTable* getAncestor(SymbolTable* table) { + if (table->Parent_Scope == NULL) { + // if table has no parent, return itself + return table; + } else { + // call function recursively to grab ancestor + return getAncestor(table->Parent_Scope); + } +} + +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; } +char* getType(TableNode* tn) { return tn->theType; } +char* getName(TableNode* tn) { return tn->theName; } +int getLine(SymbolTable* st) { return st->Line_Number; } +int getColumn(SymbolTable* st) { return st->Column_Number; } +// uncomment the below main function along with the headers above for a simple +// standalone test of table and entry creation + +/* + int main(){ + char* String = "STRING"; + char* X = "X"; + SymbolTable* Second = CreateScope(NULL, 2,2); + printf("Line number is %d, Column number of scope is + %d\n",Second->Line_Number,Second->Column_Number); TableNode* First_Entry = + CreateEntry(Second,String,X); + + printf("The type of the first entry is %s\n",First_Entry->theType); + return 0; + } + */ diff --git a/src/symbol_table.h b/src/symbol_table.h new file mode 100644 index 0000000..03028ad --- /dev/null +++ b/src/symbol_table.h @@ -0,0 +1,42 @@ +#include +#include +#include +#include + +typedef struct ListOfTable { + struct SymbolTable* table; + // struct ListOfTable* prev; + struct ListOfTable* next; +} ListOfTable; + +typedef struct TableNode { + char* theType; + char* theName; + struct TableNode* next; +} TableNode; + +typedef struct SymbolTable { + TableNode* entries; + struct SymbolTable* Parent_Scope; + struct ListOfTable* Children_Scope; + int Line_Number; + int Column_Number; +} SymbolTable; + +SymbolTable* CreateScope(SymbolTable* ParentScope, int Line, int Column); +TableNode* CreateEntry(SymbolTable* table, char* typeOf, char* id); +TableNode* table_lookup(SymbolTable* table, char* x); +TableNode* look_up(SymbolTable* table, char* x); +void print_symbol_table(SymbolTable* table, FILE* file_ptr); + +SymbolTable* getAncestor(SymbolTable* table); +SymbolTable* getParent(SymbolTable* st); +ListOfTable* getChildren(SymbolTable* st); +SymbolTable* getFirstChild(ListOfTable* lt); +ListOfTable* getRestOfChildren(ListOfTable* lt); +TableNode* getFirstEntry(SymbolTable* st); +TableNode* getNextEntry(TableNode* tn); +char* getType(TableNode* tn); +char* getName(TableNode* tn); +int getLine(SymbolTable* st); +int getColumn(SymbolTable* st); diff --git a/typedefs.h b/src/typedefs.h similarity index 100% rename from typedefs.h rename to src/typedefs.h diff --git a/tests/sprint1/expected/sp1_comment_fix1.expected b/tests/sprint1/expected/sp1_comment_fix1.expected new file mode 100644 index 0000000..07d66e1 --- /dev/null +++ b/tests/sprint1/expected/sp1_comment_fix1.expected @@ -0,0 +1 @@ + daskmskdfm \ No newline at end of file diff --git a/tests/sprint1/test/sp1_comment_fix1.alpha b/tests/sprint1/test/sp1_comment_fix1.alpha new file mode 100644 index 0000000..910a538 --- /dev/null +++ b/tests/sprint1/test/sp1_comment_fix1.alpha @@ -0,0 +1 @@ +(***) \ No newline at end of file diff --git a/tests/sprint1/test/sp1_comment_fix2.alpha b/tests/sprint1/test/sp1_comment_fix2.alpha new file mode 100644 index 0000000..bd710e9 --- /dev/null +++ b/tests/sprint1/test/sp1_comment_fix2.alpha @@ -0,0 +1 @@ +(*(**)*) \ No newline at end of file diff --git a/tests/sprint1/test/sp1_comment_issues.alpha b/tests/sprint1/test/sp1_comment_issues.alpha new file mode 100644 index 0000000..e968d93 --- /dev/null +++ b/tests/sprint1/test/sp1_comment_issues.alpha @@ -0,0 +1,7 @@ +(*(**)*) +(***) +(******)(*\kpp*********) +((*((*)) +(***)(*) +(* *) +(***)))))))*(*))))))))*)) diff --git a/tests/sprint1/test/sp1_comments.alpha b/tests/sprint1/test/sp1_comments.alpha new file mode 100644 index 0000000..1111428 --- /dev/null +++ b/tests/sprint1/test/sp1_comments.alpha @@ -0,0 +1,9 @@ +(* hello *) +(* hello *) +(* I'd think this is a legal "string" that contains several \n \t +escaped characters, isn't it? *) +(* \ *) +(* *) +(*{COMMENT}+ *) +(* * *) +(* (hello) *) \ No newline at end of file diff --git a/test1.txt b/tests/sprint1/test/sp1_general_token.alpha similarity index 100% rename from test1.txt rename to tests/sprint1/test/sp1_general_token.alpha diff --git a/tests/sprint1/test/sp1_keywords.alpha b/tests/sprint1/test/sp1_keywords.alpha new file mode 100644 index 0000000..ff18168 --- /dev/null +++ b/tests/sprint1/test/sp1_keywords.alpha @@ -0,0 +1,29 @@ +while +While +whiLe +if +IF +If +iF +then +Then +theN +else +eLse +elSe +Else +type +Type +tyPe +function +Function +functioN +return +Return +returN +external +External +exteRnal +as +As +aS diff --git a/tests/sprint1/test/sp1_operators.alpha b/tests/sprint1/test/sp1_operators.alpha new file mode 100644 index 0000000..b985387 --- /dev/null +++ b/tests/sprint1/test/sp1_operators.alpha @@ -0,0 +1,23 @@ ++ +- +* +/ +\ +% +< +> += +:= +=: +: += +! +& +| +. +relEASE +release +RELEASE +reserve +RESERVE +reSERVe \ No newline at end of file diff --git a/tests/sprint1/test/sp1_other_punc.alpha b/tests/sprint1/test/sp1_other_punc.alpha new file mode 100644 index 0000000..bd1f2de --- /dev/null +++ b/tests/sprint1/test/sp1_other_punc.alpha @@ -0,0 +1,6 @@ +; +: +, +-> +->> +--> \ No newline at end of file diff --git a/tests/sprint1/test/sp1_punc_grouping.alpha b/tests/sprint1/test/sp1_punc_grouping.alpha new file mode 100644 index 0000000..45dfb99 --- /dev/null +++ b/tests/sprint1/test/sp1_punc_grouping.alpha @@ -0,0 +1,42 @@ +) +a) +)a +)* +*) + +(* jellsls + well this seems to work + + + *) + +( +a( +(a +(* +*( + + +{ +a{ +{a +{* +*{ +} +a} +}a +}* +*} + + + +[ +a[ +[a +[* +*[ +] +a] +]a +]* +*] diff --git a/tests/sprint1/test/sp1_real_alpha_file1.alpha b/tests/sprint1/test/sp1_real_alpha_file1.alpha new file mode 100644 index 0000000..51d5d08 --- /dev/null +++ b/tests/sprint1/test/sp1_real_alpha_file1.alpha @@ -0,0 +1,28 @@ +type rec: [integer: x; integer: y] +type T1: integer -> integer +type T2: rec -> integer +function foo : T1 +function bar1 : T2 +function bar2 : T2 +foo(x) := { + return x * x; + } +bar1(a) := { + return a.x * a.y; + } +bar2 as (r,s) := { + return r * s; + } +entry(arg) := { + [ integer: result ; rec: w] + result := foo(5); + w := reserve(w); (* see types.alpha – reserve returns a value of type address, + which can be assigned to array and record variables + *) + w.x := 5; + w.y := 7; + result := bar1(w); (* pass w (a rec type value) to bar1 *) + result := bar2(5,7); (* implicitly build a rec type value, assign 5 and 7 to fields x and y, but call them r and s *) + + return 0; +} diff --git a/tests/sprint1/test/sp1_real_alpha_file2.alpha b/tests/sprint1/test/sp1_real_alpha_file2.alpha new file mode 100644 index 0000000..0beb2af --- /dev/null +++ b/tests/sprint1/test/sp1_real_alpha_file2.alpha @@ -0,0 +1,26 @@ +(* Type definitions *) +type string: 1 -> character +type int2int: integer -> integer +type string2int: string -> integer +(* Function prototypes +They use the above type definitions +*) +function square : int2int +function entry : string2int +(* Function definition +Functions must be declared before they are defined +*) +square(x) := { +return x * x; +} +(* Function definition +entry is the first function called +*) +entry(arg) := { +input = 7; +expected = 49; +actual := square(input); +rseult := expected = actual; +return 0; +[ integer: input; integer: expected; integer: actual; boolean: result; string: input ] +} diff --git a/tests/sprint1/test/sp1_simple_int.alpha b/tests/sprint1/test/sp1_simple_int.alpha new file mode 100644 index 0000000..127f0a6 --- /dev/null +++ b/tests/sprint1/test/sp1_simple_int.alpha @@ -0,0 +1,5 @@ +45 +123 +8392 +40 40 + 200 50 21783 diff --git a/tests/sprint1/test/sp1_simple_literals.alpha b/tests/sprint1/test/sp1_simple_literals.alpha new file mode 100644 index 0000000..4c5b0b2 --- /dev/null +++ b/tests/sprint1/test/sp1_simple_literals.alpha @@ -0,0 +1,47 @@ +"this is a string" 721398 'g' '/n' (* should print 3 tokens before this *) +' +' +12893 "this is not a string (*one valid token before this*) +(* spacey comment here +over multiple lines +will it work? *) false +" +''' +'\' +false +(**) +''' +nullfalse +"nulltrue +null +'7' +true +'189 +'\t' +'"' +'/' +'\n' +'\'' +'\t' +'\\' +'n' +'\' +'fdsf' +(*/jnewjno2893u86^ Lots of random characters /n /t '") *) +' +' +' ' +''' +"STRINGwithnotSPaces" +' ' +'\ ' +"J" +"" +" " +\"\" +"{SCHAR}" +"SCHAR" +"[SCHAR]" +"FINAL: I'd think this is a legal \"string\" that contains \n \t several escaped characters, isn't it?" +"I'd think this is a legal \"string\" that contains several \\n \t escaped characters, isn't it?" +nullLike diff --git a/tests/sprint1/test/sp1_variables.alpha b/tests/sprint1/test/sp1_variables.alpha new file mode 100644 index 0000000..26db6c0 --- /dev/null +++ b/tests/sprint1/test/sp1_variables.alpha @@ -0,0 +1,10 @@ +valid1 +Valid2 +_valid3 +_valid_name_4 +VALID +0Invalid +1invalid +"invalid +invalid= +String \ No newline at end of file diff --git a/tests/sprint2/other/calc.h b/tests/sprint2/other/calc.h new file mode 100644 index 0000000..2580e93 --- /dev/null +++ b/tests/sprint2/other/calc.h @@ -0,0 +1,48 @@ +/* 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; + } +} diff --git a/tests/sprint2/other/test.c b/tests/sprint2/other/test.c new file mode 100644 index 0000000..0d9b343 --- /dev/null +++ b/tests/sprint2/other/test.c @@ -0,0 +1,74 @@ +#include +#include +#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; +} + diff --git a/tests/sprint2/other/testGrammar.y b/tests/sprint2/other/testGrammar.y new file mode 100644 index 0000000..04f8f17 --- /dev/null +++ b/tests/sprint2/other/testGrammar.y @@ -0,0 +1,41 @@ +%{ + #include /* For printf, etc. */ + #include /* 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 NUM /* Double precision number. */ +%token VAR FUN /* Symbol table pointer: variable/function. */ +%nterm 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. */ +%% diff --git a/tests/sprint2/test/sp2_integer_binary_op.alpha b/tests/sprint2/test/sp2_integer_binary_op.alpha new file mode 100644 index 0000000..39e00a6 --- /dev/null +++ b/tests/sprint2/test/sp2_integer_binary_op.alpha @@ -0,0 +1,15 @@ +entry(arg) := { + [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1] + x := 3 + 2 * 8; + x := 3 - 2 / 8; + x := 3 * 2 % 8; + x := 3 * 2 % 8; + x := 3 % 2 * 8; + x := 3 + 2 - 8; + arr2 := 1 * reserve x; + arr2 := release x; + b2 := 3 < 2; + b1 := 1 = 2; + b2 := !(3 < 2); + b1 := 6<7 & 7=7; +} diff --git a/tests/sprint2/test/sp2_library.alpha b/tests/sprint2/test/sp2_library.alpha new file mode 100644 index 0000000..9bacd6c --- /dev/null +++ b/tests/sprint2/test/sp2_library.alpha @@ -0,0 +1,30 @@ +(* At compiler start-up your program should create symbol table entries for the four primitive types: + Boolean (1 byte) + character (1 byte) + integer (4 bytes) + address (8 bytes) +You should #include this file at the start of your alpha file. +Some useful types are defined below. +*) +type string: 1 -> character +type BooleanXBoolean: [Boolean: x, y] +type characterXcharacter: [character: x, y] +type integerXinteger: [integer: x, y] + +type Boolean2Boolean: Boolean -> Boolean +type integer2integer: integer -> integer +type character2integer: character -> integer +type Boolean2integer: Boolean -> integer +type string2integer: string -> integer +type integerXinteger2integer: integerXinteger -> integer +type integerXinteger2Boolean: integerXinteger -> Boolean +type characterXcharacter2Boolean: characterXcharacter -> Boolean +type BooleanXBoolean2Boolean: BooleanXBoolean -> Boolean +type integer2address: integer -> address +type address2integer: address -> integer +external function printInteger: integer2integer +external function printCharacter: character2integer +external function printBoolean: Boolean2integer +external function reserve: integer2address +external function release: address2integer +function entry: string2integer diff --git a/tests/sprint2/test/sp2_llnode.alpha b/tests/sprint2/test/sp2_llnode.alpha new file mode 100644 index 0000000..6b4912e --- /dev/null +++ b/tests/sprint2/test/sp2_llnode.alpha @@ -0,0 +1,74 @@ +type rec: [integer: x; integer: y] +type T1: integer -> integer +type T2: rec -> integer + +type llnode: [llnode: prev; integer: val; llnode: next] +type list: integer -> llnode + +function foo : T1 +function bar1 : T2 +function bar2 : T2 +function make_list : list +make_list(a) := { + [integer:orig_a; address: ret; address: curr; address: temp] + if (a < 0 | a = 0) then { + return null; + } else { + ret := reserve llnode; + ret.prev := null; + ret.next := null; + ret.val := a; + while (0 < a) { + temp := reserve llnode; + temp.prev := null; + temp.next := null; + temp.val := val; + if (a = orig_a) then { + ret.next := temp; + temp.prev := ret; + curr := temp; + } else { + curr.next := temp; + temp.prev := curr; + curr := temp; + } + a := a - 1; + } + return ret; + } +} + + +foo(x) := { + return x * x; + } +bar1(a) := { + return a.x * a.y; + } + +bar2 as (r,s) := { + if (r < s) then { + while (!(r < s)) { + r := r + 1; + } + } else { + [integer: x] + x := 0; + while (x < 10) { + r := r + s; + } + } + return r * s; + } +entry(arg) := { + [ integer: result ; rec: w; llnode: li] + li := make_list(6); + result := foo(5); + w := reserve w; + w.x := 5; + w.y := 7; + result := bar1(w); + result := bar2(5,7); + + return 0; +} diff --git a/tests/sprint2/test/sp2_one_line.alpha b/tests/sprint2/test/sp2_one_line.alpha new file mode 100644 index 0000000..9031b5f --- /dev/null +++ b/tests/sprint2/test/sp2_one_line.alpha @@ -0,0 +1 @@ +type rec: [integer: x; integer: y] type T1: integer -> integer type T2: rec -> integer function foo : T1 function bar1 : T2 function bar2 : T2 foo(x) := { return x * x; } bar1(a) := { return a.x * a.y; } bar2 as (r,s) := { return r * s; } entry(arg) := { [ integer: result ; rec: w] result := foo(5); w := reserve w; w.x := 5; w.y := 7; result := bar1(w); result := bar2(5,7); return 0; } diff --git a/tests/sprint2/test/sp2_presidence.alpha b/tests/sprint2/test/sp2_presidence.alpha new file mode 100644 index 0000000..9b2ef86 --- /dev/null +++ b/tests/sprint2/test/sp2_presidence.alpha @@ -0,0 +1,4 @@ +entry(arg) := { + [integer:x] + x := 3 + 2 * 8; +} diff --git a/tests/sprint2/test/sp2_simple.alpha b/tests/sprint2/test/sp2_simple.alpha new file mode 100644 index 0000000..0b214c3 --- /dev/null +++ b/tests/sprint2/test/sp2_simple.alpha @@ -0,0 +1,5 @@ + +entry(arg) := { + [int : x] + return 0; +}