hello world partially parses
This commit is contained in:
parent
5d03635b93
commit
a3441f39c3
|
|
@ -2,17 +2,20 @@
|
||||||
# The top level rule indicates how to link everything together into main
|
# The top level rule indicates how to link everything together into main
|
||||||
|
|
||||||
main: main.o symbol_map.o expr.o scanner.o parser.o
|
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
|
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
|
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
|
# This pattern indicates that any .o file depends
|
||||||
# upon the .c file of the same name, and all of the .h files.
|
# 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.
|
# So, if a .o file is needed, it is built automatically.
|
||||||
|
|
||||||
%.o: %.c *.h
|
%.o: %.c *.h
|
||||||
gcc -Wall -c $< -o $@
|
gcc -g3 -Wall -c $< -o $@
|
||||||
|
|
||||||
# Only the files generated by flex and bison need explicit rules.
|
# Only the files generated by flex and bison need explicit rules.
|
||||||
|
|
||||||
|
|
|
||||||
10
lab-5/expr.c
10
lab-5/expr.c
|
|
@ -123,6 +123,8 @@ void stmt_print(struct stmt *s) {
|
||||||
if (!s)
|
if (!s)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
printf("stmt_print: %d\n", s->kind);
|
||||||
|
|
||||||
switch (s->kind) {
|
switch (s->kind) {
|
||||||
case STMT_DECL:
|
case STMT_DECL:
|
||||||
decl_print(s->decl);
|
decl_print(s->decl);
|
||||||
|
|
@ -146,6 +148,12 @@ void stmt_print(struct stmt *s) {
|
||||||
case STMT_BLOCK:
|
case STMT_BLOCK:
|
||||||
stmt_print(s->body);
|
stmt_print(s->body);
|
||||||
break;
|
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);
|
stmt_print(s->next);
|
||||||
|
|
@ -271,6 +279,8 @@ void stmt_evaluate(struct stmt *s) {
|
||||||
case STMT_BLOCK:
|
case STMT_BLOCK:
|
||||||
stmt_evaluate(s->body);
|
stmt_evaluate(s->body);
|
||||||
break;
|
break;
|
||||||
|
case STMT_SECTION:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt_evaluate(s->next);
|
stmt_evaluate(s->next);
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ struct decl {
|
||||||
struct decl *next;
|
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 {
|
struct stmt {
|
||||||
stmt_t kind;
|
stmt_t kind;
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ Clunky: Manually declare the interface to the scanner generated by flex.
|
||||||
|
|
||||||
extern char *yytext;
|
extern char *yytext;
|
||||||
extern int yylex();
|
extern int yylex();
|
||||||
// void yyerror(struct stmt *parser_result, const char*);
|
|
||||||
void yyerror(const char*);
|
void yyerror(const char*);
|
||||||
|
|
||||||
extern int yylineno;
|
extern int yylineno;
|
||||||
|
|
@ -28,8 +27,6 @@ struct stmt *parser_result = 0;
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// %parse-param {struct stmt *parser_result}
|
|
||||||
|
|
||||||
%debug
|
%debug
|
||||||
%define parse.error detailed
|
%define parse.error detailed
|
||||||
|
|
||||||
|
|
@ -86,30 +83,37 @@ struct stmt *parser_result = 0;
|
||||||
%token TOKEN_DISPLAY
|
%token TOKEN_DISPLAY
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%%
|
%%
|
||||||
file : statement_list
|
file : statement_list
|
||||||
{parser_result = $1; return 0;}
|
{parser_result = $1; return 0;}
|
||||||
;
|
;
|
||||||
statement_list : statement_list statement
|
statement_list : statement statement_list
|
||||||
{ $$ = $1; $1->next = $2; }
|
{ $$ = $1; $1->next = $2; }
|
||||||
| statement
|
| statement
|
||||||
{ $$ = $1; }
|
{ $$ = $1; }
|
||||||
;
|
;
|
||||||
statement : section
|
statement : section
|
||||||
|
{$$ = $1;}
|
||||||
| sect_data
|
| sect_data
|
||||||
|
{$$ = $1;}
|
||||||
| simple_stmt
|
| simple_stmt
|
||||||
{$$ = stmt_create(STMT_BLOCK, NULL, NULL, NULL, NULL, $1, NULL, NULL);}
|
{$$ = stmt_create(STMT_BLOCK, NULL, NULL, NULL, NULL, $1, NULL, NULL);}
|
||||||
| data_space
|
| data_space
|
||||||
|
{$$ = stmt_create(STMT_SECTION, NULL, NULL, NULL, NULL, NULL, NULL, NULL);}
|
||||||
| data_declaration
|
| data_declaration
|
||||||
|
{$$ = stmt_create(STMT_BLOCK, NULL, NULL, NULL, NULL, $1, NULL, NULL);}
|
||||||
;
|
;
|
||||||
section : type TOKEN_KEYWORD_DIVISION TOKEN_DOT
|
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
|
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
|
type : TOKEN_KEYWORD_IDENTIFICATION
|
||||||
| TOKEN_PROCEDURE
|
| TOKEN_PROCEDURE
|
||||||
| TOKEN_STOP
|
|
||||||
| TOKEN_KEYWORD_DATA
|
| TOKEN_KEYWORD_DATA
|
||||||
;
|
;
|
||||||
simple_stmt : cbl_func_stmt
|
simple_stmt : cbl_func_stmt
|
||||||
|
|
@ -163,9 +167,9 @@ booleanexpr : mathmaticalexpr TOKEN_LESS_THAN term
|
||||||
type_expr : TOKEN_IDENT
|
type_expr : TOKEN_IDENT
|
||||||
{$$ = expr_create_name(yytext);}
|
{$$ = expr_create_name(yytext);}
|
||||||
| TOKEN_INTEGER
|
| TOKEN_INTEGER
|
||||||
{$$ = expr_create_integer_literal(yytext);}
|
{$$ = expr_create_integer_literal(atoi(yytext));}
|
||||||
| TOKEN_STRING
|
| TOKEN_STRING
|
||||||
{$$ = expr_create_string_literal(atoi(yytext));}
|
{$$ = expr_create_string_literal(yytext);}
|
||||||
| TOKEN_SPACE
|
| TOKEN_SPACE
|
||||||
{$$ = expr_create_integer_literal(0);}
|
{$$ = expr_create_integer_literal(0);}
|
||||||
| TOKEN_SUB TOKEN_IDENT
|
| TOKEN_SUB TOKEN_IDENT
|
||||||
|
|
@ -225,10 +229,6 @@ data_declaration: simple_decl
|
||||||
| complex_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) {
|
void yyerror(const char* msg) {
|
||||||
fprintf(stderr, "Error | Line: %d\n%s\n",yylineno,msg);
|
fprintf(stderr, "Error | Line: %d\n%s\n",yylineno,msg);
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
// https://github.com/sheredom/utest.h/blob/master/utest.h
|
||||||
|
#include "utest.h"
|
||||||
|
#include "expr.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue