From a3441f39c35c130f59d5cd2a803a48c0d83b6763 Mon Sep 17 00:00:00 2001 From: Riley Smith Date: Wed, 13 Nov 2024 22:42:07 -0800 Subject: [PATCH] hello world partially parses --- lab-5/Makefile | 7 ++- lab-5/expr.c | 10 ++++ lab-5/expr.h | 2 +- lab-5/main.c | 2 +- lab-5/parser.bison | 32 ++++++------ lab-5/parser_test.c | 123 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 156 insertions(+), 20 deletions(-) create mode 100644 lab-5/parser_test.c diff --git a/lab-5/Makefile b/lab-5/Makefile index 0361623..4c4f16d 100644 --- a/lab-5/Makefile +++ b/lab-5/Makefile @@ -2,17 +2,20 @@ # The top level rule indicates how to link everything together into main main: main.o symbol_map.o expr.o scanner.o parser.o - gcc main.o symbol_map.o expr.o scanner.o parser.o -o interpreter.out -lm + gcc -g3 main.o symbol_map.o expr.o scanner.o parser.o -o interpreter.out -lm test: main_test.o symbol_map.o expr.o scanner.o parser.o gcc main_test.o symbol_map.o expr.o scanner.o parser.o -o interpreter_test.out -lm +parser_test: parser_test.o symbol_map.o expr.o scanner.o parser.o + gcc parser_test.o symbol_map.o expr.o scanner.o parser.o -o parser_test.out -lm + # This pattern indicates that any .o file depends # upon the .c file of the same name, and all of the .h files. # So, if a .o file is needed, it is built automatically. %.o: %.c *.h - gcc -Wall -c $< -o $@ + gcc -g3 -Wall -c $< -o $@ # Only the files generated by flex and bison need explicit rules. diff --git a/lab-5/expr.c b/lab-5/expr.c index 6b0e94d..c9d6660 100644 --- a/lab-5/expr.c +++ b/lab-5/expr.c @@ -122,6 +122,8 @@ between the left and right nodes. void stmt_print(struct stmt *s) { if (!s) return; + + printf("stmt_print: %d\n", s->kind); switch (s->kind) { case STMT_DECL: @@ -146,6 +148,12 @@ void stmt_print(struct stmt *s) { case STMT_BLOCK: stmt_print(s->body); break; + case STMT_SECTION: + printf("section\n"); + printf("body: %p\n", s->body); + printf("expr: %p\n", s->expr); + printf("next: %p\n", s->next); + break; } stmt_print(s->next); @@ -271,6 +279,8 @@ void stmt_evaluate(struct stmt *s) { case STMT_BLOCK: stmt_evaluate(s->body); break; + case STMT_SECTION: + break; } stmt_evaluate(s->next); diff --git a/lab-5/expr.h b/lab-5/expr.h index 99d8461..42d0863 100644 --- a/lab-5/expr.h +++ b/lab-5/expr.h @@ -60,7 +60,7 @@ struct decl { struct decl *next; }; -typedef enum { STMT_BLOCK, STMT_DECL, STMT_EXPR, STMT_IF, STMT_PRINT } stmt_t; +typedef enum { STMT_BLOCK, STMT_DECL, STMT_EXPR, STMT_IF, STMT_PRINT, STMT_SECTION } stmt_t; struct stmt { stmt_t kind; diff --git a/lab-5/main.c b/lab-5/main.c index 1a4d24d..cc05425 100644 --- a/lab-5/main.c +++ b/lab-5/main.c @@ -26,7 +26,7 @@ int main(int argc, char *argv[]) { if (yyparse() == 0) { printf("Parse successful: "); - if (parser_result != NULL) { + if (parser_result != NULL) { stmt_print(parser_result); printf("\n"); printf("Running the program, results in: "); diff --git a/lab-5/parser.bison b/lab-5/parser.bison index 480271d..0699648 100644 --- a/lab-5/parser.bison +++ b/lab-5/parser.bison @@ -19,7 +19,6 @@ Clunky: Manually declare the interface to the scanner generated by flex. extern char *yytext; extern int yylex(); -// void yyerror(struct stmt *parser_result, const char*); void yyerror(const char*); extern int yylineno; @@ -28,8 +27,6 @@ struct stmt *parser_result = 0; %} -// %parse-param {struct stmt *parser_result} - %debug %define parse.error detailed @@ -86,30 +83,37 @@ struct stmt *parser_result = 0; %token TOKEN_DISPLAY + %% -file : statement_list - {parser_result = $1; return 0;} +file : statement_list + {parser_result = $1; return 0;} ; -statement_list : statement_list statement - { $$ = $1; $1->next = $2; } +statement_list : statement statement_list + { $$ = $1; $1->next = $2; } | statement - { $$ = $1; } + { $$ = $1; } ; statement : section + {$$ = $1;} | sect_data + {$$ = $1;} | simple_stmt {$$ = stmt_create(STMT_BLOCK, NULL, NULL, NULL, NULL, $1, NULL, NULL);} | data_space + {$$ = stmt_create(STMT_SECTION, NULL, NULL, NULL, NULL, NULL, NULL, NULL);} | data_declaration + {$$ = stmt_create(STMT_BLOCK, NULL, NULL, NULL, NULL, $1, NULL, NULL);} ; section : type TOKEN_KEYWORD_DIVISION TOKEN_DOT - | type TOKEN_RUN TOKEN_DOT + {$$ = stmt_create(STMT_SECTION, NULL, NULL, NULL, NULL, NULL, NULL, NULL);} + | TOKEN_STOP TOKEN_RUN TOKEN_DOT + {$$ = stmt_create(STMT_SECTION, NULL, NULL, NULL, NULL, NULL, NULL, NULL);} ; sect_data : TOKEN_PROGRAM_ID TOKEN_DOT TOKEN_IDENT TOKEN_DOT + {$$ = stmt_create(STMT_SECTION, NULL, NULL, NULL, NULL, NULL, NULL, NULL);} ; type : TOKEN_KEYWORD_IDENTIFICATION | TOKEN_PROCEDURE - | TOKEN_STOP | TOKEN_KEYWORD_DATA ; simple_stmt : cbl_func_stmt @@ -163,9 +167,9 @@ booleanexpr : mathmaticalexpr TOKEN_LESS_THAN term type_expr : TOKEN_IDENT {$$ = expr_create_name(yytext);} | TOKEN_INTEGER - {$$ = expr_create_integer_literal(yytext);} + {$$ = expr_create_integer_literal(atoi(yytext));} | TOKEN_STRING - {$$ = expr_create_string_literal(atoi(yytext));} + {$$ = expr_create_string_literal(yytext);} | TOKEN_SPACE {$$ = expr_create_integer_literal(0);} | TOKEN_SUB TOKEN_IDENT @@ -225,10 +229,6 @@ data_declaration: simple_decl | complex_decl ; %% -// void yyerror(struct stmt *parser_result, const char* msg) { -// fprintf(stderr, "Error | Line: %d\n%s\n",yylineno,msg); -// } - void yyerror(const char* msg) { fprintf(stderr, "Error | Line: %d\n%s\n",yylineno,msg); } \ No newline at end of file diff --git a/lab-5/parser_test.c b/lab-5/parser_test.c new file mode 100644 index 0000000..c9c8fe6 --- /dev/null +++ b/lab-5/parser_test.c @@ -0,0 +1,123 @@ +// https://github.com/sheredom/utest.h/blob/master/utest.h +#include "utest.h" +#include "expr.h" +#include + +extern int yyparse(); + +typedef struct yy_buffer_state *YY_BUFFER_STATE; +extern int yyrestart(); +extern YY_BUFFER_STATE yy_scan_buffer(char *str, int i); +extern YY_BUFFER_STATE yy_scan_string(char *str); +extern void yy_delete_buffer(YY_BUFFER_STATE buffer); +extern FILE *yyin; +extern int yylineno; + +UTEST_MAIN(); + +UTEST(parser, math) { + // Must include the null character to terminate input + char string[] = "COMPUTE A = (b ** 2) - (4 * a * c)\0"; + YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string)); + + yylineno = 1; + int result = yyparse(); + + yy_delete_buffer(buffer); + + // Assert the result to test correctness + ASSERT_EQ(result, 0); +} + +UTEST(parser, hello) { + // Read sample file as input + yyin = fopen("samples/hello-world.cbl", "r"); + yyrestart(yyin); + ASSERT_TRUE(yyin); + + yylineno = 1; + int result = yyparse(); + + // Assert the result to test correctness + ASSERT_EQ(result, 0); +} + +UTEST(parser, print) { + // Must include the null character to terminate input + char string[] = "DISPLAY 'Hello World!'\0"; + YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string)); + + yylineno = 1; + int result = yyparse(); + + yy_delete_buffer(buffer); + + // Assert the result to test correctness + ASSERT_EQ(result, 0); +} + +UTEST(parser, branching) { + // Must include the null character to terminate input + char string[] = "IF A > B DISPLAY 'A is greater than B' ELSE DISPLAY 'B is greater than A'\0"; + YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string)); + + yylineno = 1; + int result = yyparse(); + + yy_delete_buffer(buffer); + + // Assert the result to test correctness + ASSERT_EQ(result, 0); +} + +UTEST(parser, looping) { + char string[] = "PERFORM VARYING I FROM 1 BY 1 UNTIL I > 10\0"; + YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string)); + + yylineno = 1; + int result = yyparse(); + + yy_delete_buffer(buffer); + + // Assert the result to test correctness + ASSERT_EQ(result, 0); +} + +UTEST(parser, assignment) { + char string[] = "MOVE I TO A(I) MOVE 1 TO I COMPUTE discriminant = (b ** 2) - (4 * a * c)\0"; + YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string)); + + yylineno = 1; + int result = yyparse(); + + yy_delete_buffer(buffer); + + // Assert the result to test correctness + ASSERT_EQ(result, 0); +} + +UTEST(parser, sorting) { + // Read sample file as input + yyin = fopen("samples/sorting-snippet.cbl", "r"); + yyrestart(yyin); + ASSERT_TRUE(yyin); + + yylineno = 1; + int result = yyparse(); + + // Assert the result to test correctness + ASSERT_EQ(result, 0); +} + +UTEST(parser, quadratic) { + // Read sample file as input + yyin = fopen("samples/quadratic-snippet.cbl", "r"); + yyrestart(yyin); + ASSERT_TRUE(yyin); + + yylineno = 1; + int result = yyparse(); + + // Assert the result to test correctness + ASSERT_EQ(result, 0); +}