%{ #include %} %token FUNC PRINT RETURN CONTINUE IF THEN ELSE WHILE DO OPENBLOCK CLOSEBLOCK %token VAR NUMBER IDENTIFIER STRING %left '|' '&' '^' %left '+' '-' %left '*' '/' %nonassoc UMINUS %right '~' %nonassoc IF THEN %nonassoc ELSE %% 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, $2); } ; 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 %prec UMINUS { 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*/ strdup("number"), 1, $1); } | identifier { node_init($$ = malloc(sizeof(node_t)), EXPRESSION, /*NULL*/ strdup("identifier"), 1, $1); } | identifier '(' argument_list ')' { node_init($$ = malloc(sizeof(node_t)), EXPRESSION, /*NULL*/ strdup("function_call"), 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 ); }