From a5f6aaf1fa1fbdf2f8b9ff1924c347721d5a6c56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind?= Date: Sat, 12 Mar 2022 19:21:38 +0100 Subject: [PATCH] added my own from ps3 --- exercises/04/vslc/include/ir.h | 12 +- exercises/04/vslc/include/vslc.h | 1 + exercises/04/vslc/src/parser.y | 445 +++++++++++------- exercises/04/vslc/src/vslc.c | 1 + .../vslc/vsl_programs/ps2-parser/if_else.ast | 0 5 files changed, 298 insertions(+), 161 deletions(-) delete mode 100644 exercises/04/vslc/vsl_programs/ps2-parser/if_else.ast diff --git a/exercises/04/vslc/include/ir.h b/exercises/04/vslc/include/ir.h index 78150e1..aa8d1ef 100644 --- a/exercises/04/vslc/include/ir.h +++ b/exercises/04/vslc/include/ir.h @@ -10,8 +10,16 @@ typedef struct n { struct n **children; } node_t; -// Export the initializer function, it is needed by the parser -void node_init ( +/**Export the initializer function, it is needed by the parser + * @param *nd node to initialize + * @param type type of node (see nodetype.h) + * @param *data associated data. Declared void to allow any type + * @param n_children number of children + * @param ... variable argument list of child nodes (node_t *) + * + * @return Pointer to the initialized node + * */ +node_t* node_init ( node_t *nd, node_index_t type, void *data, uint64_t n_children, ... ); diff --git a/exercises/04/vslc/include/vslc.h b/exercises/04/vslc/include/vslc.h index 35403d1..1d61514 100644 --- a/exercises/04/vslc/include/vslc.h +++ b/exercises/04/vslc/include/vslc.h @@ -25,6 +25,7 @@ int yyerror ( const char *error ); /* These are defined in the parser generated by bison */ extern int yylineno; extern int yylex ( void ); +extern int yylex_destroy( void ); extern char yytext[]; /* Global state */ diff --git a/exercises/04/vslc/src/parser.y b/exercises/04/vslc/src/parser.y index f1abcc8..bb05a2a 100644 --- a/exercises/04/vslc/src/parser.y +++ b/exercises/04/vslc/src/parser.y @@ -1,176 +1,303 @@ %{ #include -#define N0C(n,t,d) do { \ - node_init ( n = malloc(sizeof(node_t)), t, d, 0 ); \ -} while ( false ) -#define N1C(n,t,d,a) do { \ - node_init ( n = malloc(sizeof(node_t)), t, d, 1, a ); \ -} while ( false ) -#define N2C(n,t,d,a,b) do { \ - node_init ( n = malloc(sizeof(node_t)), t, d, 2, a, b ); \ -} while ( false ) -#define N3C(n,t,d,a,b,c) do { \ - node_init ( n = malloc(sizeof(node_t)), t, d, 3, a, b, c ); \ -} while ( false ) - +#define NODE(type, data, n_children, children...) node_init(malloc(sizeof(node_t)), type, data, n_children, ##children) %} -%left '|' -%left '^' -%left '&' +%define api.value.type {node_t} +%token FUNC PRINT RETURN CONTINUE IF THEN ELSE WHILE DO OPENBLOCK CLOSEBLOCK +%token VAR NUMBER IDENTIFIER STRING + +%left '|' '&' '^' %left '+' '-' %left '*' '/' %nonassoc UMINUS %right '~' -%expect 1 +//%expect 1 -%token FUNC PRINT RETURN CONTINUE IF THEN ELSE WHILE DO OPENBLOCK CLOSEBLOCK -%token VAR NUMBER IDENTIFIER STRING +%nonassoc IF THEN +%nonassoc ELSE + +/* Tried fixing vscode complaining about the type for the non-terminals, didn't work +%union { + node_t* node; +} + +%type global_list global +%type statement_list print_list expression_list variable_list argument_list parameter_list declaration_list +%type function statement block +%type assignment_statement return_statement print_statement null_statement if_statement while_statement +%type relation expression declaration print_item identifier number string +*/ %% -program : - global_list { N1C ( root, PROGRAM, NULL, $1 ); } - ; -global_list : - global { N1C ( $$, GLOBAL_LIST, NULL, $1 ); } - | global_list global { N2C ( $$, GLOBAL_LIST, NULL, $1, $2 ); } - ; + +program: + global_list { + root = NODE(PROGRAM, NULL, 1, $1); + } + ; + +global_list: + global { + $$ = NODE(GLOBAL_LIST, NULL, 1, $1); + } + | global_list global { + $$ = NODE(GLOBAL_LIST, NULL, 2, $1, $2); + } + ; + global: - function { N1C ( $$, GLOBAL, NULL, $1 ); } - | declaration { N1C ( $$, GLOBAL, NULL, $1 ); } - ; -statement_list : - statement { N1C ( $$, STATEMENT_LIST, NULL, $1 ); } - | statement_list statement { N2C ( $$, STATEMENT_LIST, NULL, $1, $2 ); } - ; -print_list : - print_item { N1C ( $$, PRINT_LIST, NULL, $1 ); } - | print_list ',' print_item { N2C ( $$, PRINT_LIST, NULL, $1, $3 ); } - ; -expression_list : - expression { N1C ( $$, EXPRESSION_LIST, NULL, $1 ); } - | expression_list ',' expression { N2C($$, EXPRESSION_LIST, NULL, $1, $3); } - ; -variable_list : - identifier { N1C ( $$, VARIABLE_LIST, NULL, $1 ); } - | variable_list ',' identifier { N2C ( $$, VARIABLE_LIST, NULL, $1, $3 ); } - ; -argument_list : - expression_list { N1C ( $$, ARGUMENT_LIST, NULL, $1 ); } - | /* epsilon */ { $$ = NULL; } - ; -parameter_list : - variable_list { N1C ( $$, PARAMETER_LIST, NULL, $1 ); } - | /* epsilon */ { $$ = NULL; } - ; -declaration_list : - declaration { N1C ( $$, DECLARATION_LIST, NULL, $1 ); } - | declaration_list declaration { N2C ($$, DECLARATION_LIST, NULL, $1, $2); } - ; -function : - FUNC identifier '(' parameter_list ')' statement - { N3C ( $$, FUNCTION, NULL, $2, $4, $6 ); } - ; -statement : - assignment_statement { N1C ( $$, STATEMENT, NULL, $1 ); } - | return_statement { N1C ( $$, STATEMENT, NULL, $1 ); } - | print_statement { N1C ( $$, STATEMENT, NULL, $1 ); } - | if_statement { N1C ( $$, STATEMENT, NULL, $1 ); } - | while_statement { N1C ( $$, STATEMENT, NULL, $1 ); } - | null_statement { N1C ( $$, STATEMENT, NULL, $1 ); } - | block { N1C ( $$, STATEMENT, NULL, $1 ); } - ; -block : - OPENBLOCK declaration_list statement_list CLOSEBLOCK - { N2C ($$, BLOCK, NULL, $2, $3); } - | OPENBLOCK statement_list CLOSEBLOCK { N1C ($$, BLOCK, NULL, $2 ); } - ; -assignment_statement : - identifier ':' '=' expression - { N2C ( $$, ASSIGNMENT_STATEMENT, NULL, $1, $4 ); } - | identifier '+' '=' expression - { N2C ( $$, ADD_STATEMENT, NULL, $1, $4 ); } - | identifier '-' '=' expression - { N2C ( $$, SUBTRACT_STATEMENT, NULL, $1, $4 ); } - | identifier '*' '=' expression - { N2C ( $$, MULTIPLY_STATEMENT, NULL, $1, $4 ); } - | identifier '/' '=' expression - { N2C ( $$, DIVIDE_STATEMENT, NULL, $1, $4 ); } - ; -return_statement : - RETURN expression - { N1C ( $$, RETURN_STATEMENT, NULL, $2 ); } - ; -print_statement : - PRINT print_list - { N1C ( $$, PRINT_STATEMENT, NULL, $2 ); } - ; -null_statement : - CONTINUE - { N0C ( $$, NULL_STATEMENT, NULL ); } - ; -if_statement : - IF relation THEN statement - { N2C ( $$, IF_STATEMENT, NULL, $2, $4 ); } - | IF relation THEN statement ELSE statement - { N3C ( $$, IF_STATEMENT, NULL, $2, $4, $6 ); } - ; -while_statement : - WHILE relation DO statement - { N2C ( $$, WHILE_STATEMENT, NULL, $2, $4 ); } - ; + function { + $$ = NODE(GLOBAL, NULL, 1, $1); + } + | declaration { + $$ = NODE(GLOBAL, NULL, 1, $1); + } + ; + +statement_list: + statement { + $$ = NODE(STATEMENT_LIST, NULL, 1, $1); + } + | statement_list statement { + $$ = NODE(STATEMENT_LIST, NULL, 2, $1, $2); + } + ; + +print_list: + print_item { + $$ = NODE(PRINT_LIST, NULL, 1, $1); + } + | print_list ',' print_item { + $$ = NODE(PRINT_LIST, NULL, 2, $1, $3); + } + ; + +expression_list: + expression { + $$ = NODE(EXPRESSION_LIST, NULL, 1, $1); + } + | expression_list ',' expression { + $$ = NODE(EXPRESSION_LIST, NULL, 2, $1, $3); + } + ; + +variable_list: + identifier { + $$ = NODE(VARIABLE_LIST, NULL, 1, $1); + } + | variable_list ',' identifier { + $$ = NODE(VARIABLE_LIST, NULL, 2, $1, $3); + } + ; + +argument_list: + expression_list { + $$ = NODE(ARGUMENT_LIST, NULL, 1, $1); + } + | /* epsilon */ { + $$ = NODE(ARGUMENT_LIST, NULL, 0); + } + ; + +parameter_list: + variable_list { + $$ = NODE(PARAMETER_LIST, NULL, 1, $1); + } + | /* epsilon */ { + $$ = NODE(PARAMETER_LIST, NULL, 0); + } + ; + +declaration_list: + declaration { + $$ = NODE(DECLARATION_LIST, NULL, 1, $1); + } + | declaration_list declaration { + $$ = NODE(DECLARATION_LIST, NULL, 2, $1, $2); + } + ; + +function: + FUNC identifier '(' parameter_list ')' statement { + $$ = NODE(FUNCTION, NULL, 3, $2, $4, $6); + } + ; + +statement: + assignment_statement { + $$ = NODE(STATEMENT, NULL, 1, $1); + } + | return_statement { + $$ = NODE(STATEMENT, NULL, 1, $1); + } + | print_statement { + $$ = NODE(STATEMENT, NULL, 1, $1); + } + | if_statement { + $$ = NODE(STATEMENT, NULL, 1, $1); + } + | while_statement { + $$ = NODE(STATEMENT, NULL, 1, $1); + } + | null_statement { + $$ = NODE(STATEMENT, NULL, 1, $1); + } + | block { + $$ = NODE(STATEMENT, NULL, 1, $1); + } + ; + +block: + OPENBLOCK declaration_list statement_list CLOSEBLOCK { + $$ = NODE(BLOCK, NULL, 2, $2, $3); + } + | OPENBLOCK statement_list CLOSEBLOCK { + $$ = NODE(BLOCK, NULL, 1, $2); + } + ; + +assignment_statement: + identifier ':' '=' expression { + $$ = NODE(ASSIGNMENT_STATEMENT, NULL, 2, $1, $4); + } + | identifier '+' '=' expression { + $$ = NODE(ADD_STATEMENT, NULL, 2, $1, $4); + } + | identifier '-' '=' expression { + $$ = NODE(SUBTRACT_STATEMENT, NULL, 2, $1, $4); + } + | identifier '*' '=' expression { + $$ = NODE(MULTIPLY_STATEMENT, NULL, 2, $1, $4); + } + | identifier '/' '=' expression { + $$ = NODE(DIVIDE_STATEMENT, NULL, 2, $1, $4); + } + ; + +return_statement: + RETURN expression { + $$ = NODE(RETURN_STATEMENT, NULL, 1, $2); + } + ; + +print_statement: + PRINT print_list { + $$ = NODE(PRINT_STATEMENT, NULL, 1, $2); + } + ; + +null_statement: + CONTINUE { + $$ = NODE(NULL_STATEMENT, NULL, 0); + } + ; + +if_statement: + IF relation THEN statement { + $$ = NODE(IF_STATEMENT, NULL, 2, $2, $4); + } + | IF relation THEN statement ELSE statement { + $$ = NODE(IF_STATEMENT, NULL, 3, $2, $4, $6); + } + ; + +while_statement: + WHILE relation DO statement { + $$ = NODE(WHILE_STATEMENT, NULL, 2, $2, $4); + } + ; + relation: - expression '=' expression - { N2C ( $$, RELATION, strdup("="), $1, $3 ); } - | expression '<' expression - { N2C ( $$, RELATION, strdup("<"), $1, $3 ); } - | expression '>' expression - { N2C ( $$, RELATION, strdup(">"), $1, $3 ); } - ; -expression : - expression '|' expression - { N2C ( $$, EXPRESSION, strdup("|"), $1, $3 ); } - | expression '^' expression - { N2C ( $$, EXPRESSION, strdup("^"), $1, $3 ); } - | expression '&' expression - { N2C ( $$, EXPRESSION, strdup("&"), $1, $3 ); } - | expression '+' expression - { N2C ( $$, EXPRESSION, strdup("+"), $1, $3 ); } - | expression '-' expression - { N2C ( $$, EXPRESSION, strdup("-"), $1, $3 ); } - | expression '*' expression - { N2C ( $$, EXPRESSION, strdup("*"), $1, $3 ); } - | expression '/' expression - { N2C ( $$, EXPRESSION, strdup("/"), $1, $3 ); } - | '-' expression %prec UMINUS - { N1C ( $$, EXPRESSION, strdup("-"), $2 ); } - | '~' expression %prec UMINUS - { N1C ( $$, EXPRESSION, strdup("~"), $2 ); } - | '(' expression ')' { $$ = $2; } - | number { N1C ( $$, EXPRESSION, NULL, $1 ); } - | identifier - { N1C ( $$, EXPRESSION, NULL, $1 ); } - | identifier '(' argument_list ')' - { N2C ( $$, EXPRESSION, NULL, $1, $3 ); } - ; -declaration : - VAR variable_list { N1C ( $$, DECLARATION, NULL, $2 ); } - ; -print_item : - expression - { N1C ( $$, PRINT_ITEM, NULL, $1 ); } - | string - { N1C ( $$, PRINT_ITEM, NULL, $1 ); } - ; -identifier: IDENTIFIER { N0C($$, IDENTIFIER_DATA, strdup(yytext) ); } -number: NUMBER - { - int64_t *value = malloc ( sizeof(int64_t) ); - *value = strtol ( yytext, NULL, 10 ); - N0C($$, NUMBER_DATA, value ); - } -string: STRING { N0C($$, STRING_DATA, strdup(yytext) ); } + expression '=' expression { + $$ = NODE(RELATION, strdup("="), 2, $1, $3); + } + | expression '<' expression { + $$ = NODE(RELATION, strdup("<"), 2, $1, $3); + } + | expression '>' expression { + $$ = NODE(RELATION, strdup(">"), 2, $1, $3); + } + ; + +expression: + expression '|' expression { + $$ = NODE(EXPRESSION, strdup("|"), 2, $1, $3); + } + | expression '^' expression { + $$ = NODE(EXPRESSION, strdup("^"), 2, $1, $3); + } + | expression '&' expression { + $$ = NODE(EXPRESSION, strdup("&"), 2, $1, $3); + } + | expression '+' expression { + $$ = NODE(EXPRESSION, strdup("+"), 2, $1, $3); + } + | expression '-' expression { + $$ = NODE(EXPRESSION, strdup("-"), 2, $1, $3); + } + | expression '*' expression { + $$ = NODE(EXPRESSION, strdup("*"), 2, $1, $3); + } + | expression '/' expression { + $$ = NODE(EXPRESSION, strdup("/"), 2, $1, $3); + } + | '-' expression %prec UMINUS { + $$ = NODE(EXPRESSION, strdup("-"), 1, $2); + } + | '~' expression { + $$ = NODE(EXPRESSION, strdup("~"), 1, $2); + } + | '(' expression ')' { + $$ = NODE(EXPRESSION, /*NULL*/ strdup("group"), 1, $2); + } + | number { + $$ = NODE(EXPRESSION, /*NULL*/ strdup("number"), 1, $1); + } + | identifier { + $$ = NODE(EXPRESSION, /*NULL*/ strdup("identifier"), 1, $1); + } + | identifier '(' argument_list ')' { + $$ = NODE(EXPRESSION, /*NULL*/ strdup("function_call"), 2, $1, $3); + } + ; + +declaration: + VAR variable_list { + $$ = NODE(DECLARATION, NULL, 1, $2); + } + ; + +print_item: + expression { + $$ = NODE(PRINT_ITEM, NULL, 1, $1); + } + | string { + $$ = NODE(PRINT_ITEM, NULL, 1, $1); + } + ; + +identifier: + IDENTIFIER { + $$ = NODE(IDENTIFIER_DATA, strdup(yytext), 0); // Zero children + } + ; + +number: + NUMBER { + uint64_t* p_number = malloc(sizeof(uint64_t)); + *p_number = strtol(yytext, NULL, 10); + $$ = NODE(NUMBER_DATA, p_number, 0); // Zero children + } + ; + +string: + STRING { + $$ = NODE(STRING_DATA, strdup(yytext), 0); // Zero children + } + ; + %% int diff --git a/exercises/04/vslc/src/vslc.c b/exercises/04/vslc/src/vslc.c index 58e2f14..9ca271e 100644 --- a/exercises/04/vslc/src/vslc.c +++ b/exercises/04/vslc/src/vslc.c @@ -28,6 +28,7 @@ main ( int argc, char **argv ) options ( argc, argv ); yyparse(); // Generated from grammar/bison, constructs syntax tree + yylex_destroy(); // Free heap used by flex if ( print_full_tree ) print_syntax_tree (); diff --git a/exercises/04/vslc/vsl_programs/ps2-parser/if_else.ast b/exercises/04/vslc/vsl_programs/ps2-parser/if_else.ast deleted file mode 100644 index e69de29..0000000