%{ #include #include #include #include #include "rust.h" #define YYSTYPE BSTNode int yyerror(char*); extern Frame* current_frame; extern Frame* main_frame; extern Functions* global_functions; %} %token NUMBER IDENT ASSIGN SPACE BLOCKSTART BLOCKEND DICE RETURN FUNCTION DROP %token PLUS MINUS MUL DIV POWER FLATMUL LESS LESSEQ EQ GREATEREQ GREATER %token LEFT RIGHT %token END ARGSEP %left LESS LESSEQ EQ GREATEREQ GREATER %left PLUS MINUS %left MUL DIV FLATMUL %left NEG %left BAR FACT %right POWER %start Input %% Input: /* empty input */ | Input Line ; Line: END // echo expressions to stdout | Expression END { if (current_frame == main_frame) print_node(main_frame, $1, global_functions); else insert_instruction(current_frame, evaluate($1)); } // assignment | IDENT ASSIGN Expression END { if (current_frame == main_frame) assign_node(main_frame, $1, $3, global_functions); else insert_instruction(current_frame, assign($1, $3)); } // return something | RETURN Expression END { if (current_frame == main_frame) fprintf(stderr, "cannot return from repl\n"); else insert_instruction(current_frame, return_value($2)); } // return nothing | RETURN END { if (current_frame == main_frame) fprintf(stderr, "cannot return from repl\n"); else insert_instruction(current_frame, return_nothing()); } // function definition | FUNCTION IDENT LEFT Arglist RIGHT BLOCKSTART END { current_frame = make_frame_from_declaration($2, $4); } // and function finish | BLOCKEND END { add_function(global_functions, current_frame); current_frame = main_frame; } // memory management | DROP IDENT END { drop_bst($2, current_frame); } ; Expression: // terminal nodes: a literal number and a variable NUMBER { $$ = yylval; } | IDENT { $$ = yylval; } | DICE { $$ = yylval; } // term separators | Expression PLUS Expression { $$ = bst_add($1, $3); } | Expression MINUS Expression { $$ = bst_sub($1, $3); } // there are a surprising number of ways to multiply | Expression MUL Expression { $$ = bst_mul($1, $3); } | LEFT Expression RIGHT LEFT Expression RIGHT { $$ = bst_mul($2, $5); } | Expression FLATMUL Expression { $$ = bst_flatmul($1, $3); } // division | Expression DIV Expression { $$ = bst_div($1, $3); } | Expression POWER Expression { $$ = bst_pow($1, $3); } | MINUS Expression %prec NEG { $$ = bst_neg($2); } // factorial, absolute value | Expression FACT { $$ = bst_fact($1); } | BAR Expression BAR { $$ = bst_abs($2); } // parenthesis | LEFT Expression RIGHT { $$ = $2; } // function call | IDENT LEFT Arglist RIGHT { $$ = call_function($1, $3); } // comparison operators | Expression LESS Expression { } | Expression LESSEQ Expression { } | Expression EQ Expression { } | Expression GREATEREQ Expression { } | Expression GREATER Expression { } ; Arglist: /* empty arg list */ { $$ = no_arg(); } | NonEmptyArglist { $$ = $1; } ; NonEmptyArglist: Expression { $$ = one_arg($1); } | NonEmptyArglist ARGSEP Expression { $$ = add_arg($1, $3); } ; %% int yyerror(char *s) { printf("%s\n", s); }