diff --git a/exercises/02/vslc/src/parser.y b/exercises/02/vslc/src/parser.y new file mode 100644 index 0000000..e567c41 --- /dev/null +++ b/exercises/02/vslc/src/parser.y @@ -0,0 +1,282 @@ +%{ +#include +%} + +%token FUNC PRINT RETURN CONTINUE IF THEN ELSE WHILE DO OPENBLOCK CLOSEBLOCK +%token VAR NUMBER IDENTIFIER STRING + +%% +program: + global_list { + node_init(root = malloc(sizeof(node_t)), PROGRAM, NULL, 1, $1); + } + ; + +global_list: + global { + node_init($$ = malloc(sizeof(node_t)), GLOBAL_LIST, NULL, 1, $1); + } + | global_list global { + node_init($$ = malloc(sizeof(node_t)), GLOBAL_LIST, NULL, 2, $1, $2); + } + ; + +global: + function { + node_init($$ = malloc(sizeof(node_t)), GLOBAL, NULL, 1, $1); + } + | declaration { + node_init($$ = malloc(sizeof(node_t)), GLOBAL, NULL, 1, $1); + } + ; + +statement_list: + statement { + node_init($$ = malloc(sizeof(node_t)), STATEMENT_LIST, NULL, 1, $1); + } + | statement_list statement { + node_init($$ = malloc(sizeof(node_t)), STATEMENT_LIST, NULL, 2, $1, $2); + } + ; + +print_list: + print_item { + node_init($$ = malloc(sizeof(node_t)), PRINT_LIST, NULL, 1, $1); + } + | print_list ',' print_item { + node_init($$ = malloc(sizeof(node_t)), PRINT_LIST, NULL, 2, $1, $3); + } + ; + +expression_list: + expression { + node_init($$ = malloc(sizeof(node_t)), EXPRESSION_LIST, NULL, 1, $1); + } + | expression_list ',' expression { + node_init($$ = malloc(sizeof(node_t)), EXPRESSION_LIST, NULL, 2, $1, $3); + } + ; + +variable_list: + identifier { + node_init($$ = malloc(sizeof(node_t)), VARIABLE_LIST, NULL, 1, $1); + } + | variable_list ',' identifier { + node_init($$ = malloc(sizeof(node_t)), VARIABLE_LIST, NULL, 2, $1, $3); + } + ; + +argument_list: + expression_list { + node_init($$ = malloc(sizeof(node_t)), ARGUMENT_LIST, NULL, 1, $1); + } + | /* epsilon */ { + node_init($$ = malloc(sizeof(node_t)), ARGUMENT_LIST, NULL, 0); + } + ; + +parameter_list: + variable_list { + node_init($$ = malloc(sizeof(node_t)), PARAMETER_LIST, NULL, 1, $1); + } + | /* epsilon */ { + node_init($$ = malloc(sizeof(node_t)), PARAMETER_LIST, NULL, 0); + } + ; + +declaration_list: + declaration { + node_init($$ = malloc(sizeof(node_t)), DECLARATION_LIST, NULL, 1, $1); + } + | declaration_list ',' declaration { + node_init($$ = malloc(sizeof(node_t)), DECLARATION_LIST, NULL, 2, $1, $3); + } + ; + +function: + FUNC identifier '(' parameter_list ')' statement { + node_init($$ = malloc(sizeof(node_t)), FUNCTION, NULL, 3, $2, $4, $6); + } + ; + +statement: + assignment_statement { + node_init($$ = malloc(sizeof(node_t)), STATEMENT, NULL, 1, $1); + } + | return_statement { + node_init($$ = malloc(sizeof(node_t)), STATEMENT, NULL, 1, $1); + } + | print_statement { + node_init($$ = malloc(sizeof(node_t)), STATEMENT, NULL, 1, $1); + } + | if_statement { + node_init($$ = malloc(sizeof(node_t)), STATEMENT, NULL, 1, $1); + } + | while_statement { + node_init($$ = malloc(sizeof(node_t)), STATEMENT, NULL, 1, $1); + } + | null_statement { + node_init($$ = malloc(sizeof(node_t)), STATEMENT, NULL, 1, $1); + } + | block { + node_init($$ = malloc(sizeof(node_t)), STATEMENT, NULL, 1, $1); + } + ; + +block: + OPENBLOCK declaration_list statement_list CLOSEBLOCK { + node_init($$ = malloc(sizeof(node_t)), BLOCK, NULL, 2, $2, $3); + } + | OPENBLOCK statement_list CLOSEBLOCK { + node_init($$ = malloc(sizeof(node_t)), BLOCK, NULL, 1, $2); + } + ; + +assignment_statement: + identifier ':' '=' expression { + node_init($$ = malloc(sizeof(node_t)), ASSIGNMENT_STATEMENT, NULL, 2, $1, $4); + } + | identifier '+' '=' expression { + node_init($$ = malloc(sizeof(node_t)), ADD_STATEMENT, NULL, 2, $1, $4); + } + | identifier '-' '=' expression { + node_init($$ = malloc(sizeof(node_t)), SUBTRACT_STATEMENT, NULL, 2, $1, $4); + } + | identifier '*' '=' expression { + node_init($$ = malloc(sizeof(node_t)), MULTIPLY_STATEMENT, NULL, 2, $1, $4); + } + | identifier '/' '=' expression { + node_init($$ = malloc(sizeof(node_t)), DIVIDE_STATEMENT, NULL, 2, $1, $4); + } + ; + +return_statement: + RETURN expression { + node_init($$ = malloc(sizeof(node_t)), RETURN_STATEMENT, NULL, 1, $2); + } + ; + +print_statement: + PRINT print_list { + node_init($$ = malloc(sizeof(node_t)), PRINT_STATEMENT, NULL, 1, $2); + } + ; + +null_statement: + CONTINUE { + node_init($$ = malloc(sizeof(node_t)), NULL_STATEMENT, NULL, 0); + } + ; + +if_statement: + IF relation THEN statement { + node_init($$ = malloc(sizeof(node_t)), IF_STATEMENT, NULL, 2, $2, $4); + } + | IF relation THEN statement ELSE statement { + node_init($$ = malloc(sizeof(node_t)), IF_STATEMENT, NULL, 3, $2, $4, $6); + } + ; + +while_statement: + WHILE relation DO statement { + node_init($$ = malloc(sizeof(node_t)), WHILE_STATEMENT, NULL, 2, $2, $4); + } + ; + +relation: + expression '=' expression { + node_init($$ = malloc(sizeof(node_t)), RELATION, strdup("="), 2, $1, $3); + } + | expression '<' expression { + node_init($$ = malloc(sizeof(node_t)), RELATION, strdup("<"), 2, $1, $3); + } + | expression '>' expression { + node_init($$ = malloc(sizeof(node_t)), RELATION, strdup(">"), 2, $1, $3); + } + ; + +expression: + expression '|' expression { + node_init($$ = malloc(sizeof(node_t)), EXPRESSION, strdup("|"), 2, $1, $3); + } + | expression '^' expression { + node_init($$ = malloc(sizeof(node_t)), EXPRESSION, strdup("^"), 2, $1, $3); + } + | expression '&' expression { + node_init($$ = malloc(sizeof(node_t)), EXPRESSION, strdup("&"), 2, $1, $3); + } + | expression '+' expression { + node_init($$ = malloc(sizeof(node_t)), EXPRESSION, strdup("+"), 2, $1, $3); + } + | expression '-' expression { + node_init($$ = malloc(sizeof(node_t)), EXPRESSION, strdup("-"), 2, $1, $3); + } + | expression '*' expression { + node_init($$ = malloc(sizeof(node_t)), EXPRESSION, strdup("*"), 2, $1, $3); + } + | expression '/' expression { + node_init($$ = malloc(sizeof(node_t)), EXPRESSION, strdup("/"), 2, $1, $3); + } + | '-' expression { + node_init($$ = malloc(sizeof(node_t)), EXPRESSION, strdup("-"), 1, $2); + } + | '~' expression { + node_init($$ = malloc(sizeof(node_t)), EXPRESSION, strdup("~"), 1, $2); + } + | '(' expression ')' { + $$ = $2; + } + | number { + node_init($$ = malloc(sizeof(node_t)), EXPRESSION, NULL, 1, $1); + } + | identifier { + node_init($$ = malloc(sizeof(node_t)), EXPRESSION, NULL, 1, $1); + } + | identifier '(' argument_list ')' { + node_init($$ = malloc(sizeof(node_t)), EXPRESSION, NULL, 2, $1, $3); + } + ; + +declaration: + VAR variable_list { + node_init($$ = malloc(sizeof(node_t)), DECLARATION, NULL, 1, $2); + } + ; + +print_item: + expression { + node_init($$ = malloc(sizeof(node_t)), PRINT_ITEM, NULL, 1, $1); + } + | string { + node_init($$ = malloc(sizeof(node_t)), PRINT_ITEM, NULL, 1, $1); + } + ; + +identifier: + IDENTIFIER { + node_init($$ = malloc(sizeof(node_t)), IDENTIFIER_DATA, strdup(yytext), 0); // Zero children + } + ; + +number: + NUMBER { + uint64_t* p_number = malloc(sizeof(uint64_t)); + *p_number = strtol(yytext, NULL, 10); + node_init($$ = malloc(sizeof(node_t)), NUMBER_DATA, p_number, 0); // Zero children + } + ; + +string: + STRING { + node_init($$ = malloc(sizeof(node_t)), STRING_DATA, strdup(yytext), 0); // Zero children + } + ; + +%% + +int +yyerror ( const char *error ) +{ + fprintf ( stderr, "%s on line %d\n", error, yylineno ); + exit ( EXIT_FAILURE ); +}