diff options
Diffstat (limited to 'src/parser.y')
-rw-r--r-- | src/parser.y | 239 |
1 files changed, 152 insertions, 87 deletions
diff --git a/src/parser.y b/src/parser.y index 3b69b06..7aacd39 100644 --- a/src/parser.y +++ b/src/parser.y @@ -7,6 +7,7 @@ #include <posthaste/parser.h> #include <posthaste/date.h> +#include <posthaste/ast.h> #define FOREACH_TOKEN(M) \ M(LPAREN) \ @@ -57,7 +58,7 @@ %parse-param {void *scanner} {struct parser* parser} %union { - struct ast_node *node; + struct ast *node; ph_date_t num; int64_t snum; char *str; @@ -101,6 +102,44 @@ %token PRINT "print" %token END "end" +%nterm <node> program +%nterm <node> definition +%nterm <node> definitions +%nterm <node> opt_definitions +%nterm <node> variable_definition +%nterm <node> variable_definitions +%nterm <node> opt_variable_definitions +%nterm <node> procedure_definition +%nterm <node> function_definition +%nterm <node> formal_arg +%nterm <node> formals +%nterm <node> lvalue +%nterm <node> rvalue +%nterm <node> print_item +%nterm <node> print_items +%nterm <node> opt_formals +%nterm <node> statement +%nterm <node> statement_list +%nterm <node> opt_arguments +%nterm <node> arguments +%nterm <node> print_statement +%nterm <node> unless_statement +%nterm <node> unless_expression +%nterm <node> until_statement +%nterm <node> assignment +%nterm <node> procedure_call +%nterm <node> function_call +%nterm <node> simple_expr +%nterm <node> atom +%nterm <node> term +%nterm <node> factor +%nterm <node> expression +%nterm <node> ident + +/* special case */ +%nterm <str> return +%nterm <str> opt_return + %{ /** Modifies the signature of yylex to fit our parser better. */ @@ -145,11 +184,11 @@ static void yyerror(YYLTYPE *yylloc, void *lexer, %% statement_list - : statement "," statement_list + : statement "," statement_list { $$ = $1; $$->n = $3; } | statement definitions - : definition definitions + : definition definitions { $$ = $1; $$->n = $2; } | definition definition @@ -158,74 +197,102 @@ definition | variable_definition variable_definition - : "var" IDENT "=" expression + : "var" IDENT "=" expression { + $$ = gen_var_def($[IDENT], $[expression], src_loc(@$)); + } variable_definitions - : variable_definition variable_definitions + : variable_definition variable_definitions { $$ = $1; $$->n = $2; } | variable_definition opt_variable_definitions : variable_definitions - | + | { $$ = NULL; } return - : "return" IDENT + : "return" IDENT { $$ = $2; } opt_return : return - | + | { $$ = NULL; } function_definition : "function" FUNC_IDENT "{" opt_formals "}" - return opt_variable_definitions "is" rvalue "end" "function" + return opt_variable_definitions "is" rvalue "end" "function" { + struct ast *ret = gen_return($[rvalue], $[rvalue]->loc); + $$ = gen_func_def($[FUNC_IDENT], + $[return], + $[opt_formals], + $[opt_variable_definitions], + ret, + src_loc(@$)); + } procedure_definition : "procedure" PROC_IDENT "{" opt_formals "}" opt_return opt_variable_definitions "is" statement_list - "end" "procedure" + "end" "procedure" { + $$ = gen_proc_def($[PROC_IDENT], + $[opt_return], + $[opt_formals], + $[opt_variable_definitions], + $[statement_list], + src_loc(@$)); + } formals - : formal_arg "," formal_arg + : formal_arg "," formals { $$ = $1; $$->n = $3; } | formal_arg opt_formals : formals - | + | { $$ = NULL; } formal_arg - : IDENT "[" IDENT "]" + : IDENT "[" IDENT "]" { + $$ = gen_formal_def($1, $3, src_loc(@$)); + } procedure_call - : PROC_IDENT "(" opt_arguments ")" + : PROC_IDENT "(" opt_arguments ")" { + $$ = gen_proc_call($[PROC_IDENT], $[opt_arguments], src_loc(@$)); + } arguments - : expression "," arguments + : expression "," arguments { $$ = $1; $$->n = $3; } | expression opt_arguments : arguments - | + | { $$ = NULL; } assignment - : lvalue "=" rvalue + : lvalue "=" rvalue { + $$ = gen_assign($[lvalue], $[rvalue], src_loc(@$)); + } + +ident + : IDENT { + $$ = gen_id($[IDENT], src_loc(@$)); + } lvalue - : IDENT - | IDENT "." IDENT + : ident + | ident "." IDENT { $$ = gen_dot($1, $3, src_loc(@$)); } rvalue : expression | unless_expression print_statement - : "print" print_items + : "print" print_items { $$ = gen_print($[print_items], src_loc(@$)); } print_items - : print_item "&" print_items + : print_item "&" print_items { $$ = $1; $$->n = $3; } | print_item print_item - : STRING + : STRING { $$ = gen_const_string($[STRING], src_loc(@$)); } | expression statement @@ -234,56 +301,98 @@ statement | print_statement | until_statement | unless_statement - | "return" expression + | "return" expression { $$ = gen_return($[expression], src_loc(@$)); } until_statement - : "do" statement_list "until" expression + : "do" statement_list "until" expression { + $$ = gen_until($[statement_list], $[expression], src_loc(@$)); + } unless_statement - : "do" statement_list "unless" expression "done" - | "do" statement_list "unless" expression "otherwise" statement_list "done" + : "do" statement_list "unless" expression "done" { + $$ = gen_unless($[statement_list], $[expression], NULL, src_loc(@$)); + } + | "do" statement_list "unless" expression "otherwise" statement_list "done" { + $$ = gen_unless($2, $[expression], $6, src_loc(@$)); + } expression : simple_expr - | expression "=" simple_expr - | expression "<" simple_expr + | expression "=" simple_expr { + $$ = gen_eq($1, $[simple_expr], src_loc(@$)); + } + | expression "<" simple_expr { + $$ = gen_lt($1, $[simple_expr], src_loc(@$)); + } simple_expr : term - | simple_expr "+" term - | simple_expr "-" term + | simple_expr "+" term { + $$ = gen_add($1, $[term], src_loc(@$)); + } + | simple_expr "-" term { + $$ = gen_sub($1, $[term], src_loc(@$)); + } term : factor - | term "*" factor - | term "/" factor + | term "*" factor { + $$ = gen_mul($1, $[factor], src_loc(@$)); + } + | term "/" factor { + $$ = gen_div($1, $[factor], src_loc(@$)); + } factor - : "+" atom - | "-" atom + : "+" atom { + $$ = gen_pos($[atom], src_loc(@$)); + } + | "-" atom { + $$ = gen_neg($[atom], src_loc(@$)); + } | atom atom - : IDENT - | IDENT "'" IDENT - | INT_LITERAL - | DATE_LITERAL + : ident + | ident "'" IDENT { + $$ = gen_attr($[ident], $[IDENT], src_loc(@$)); + } + | INT_LITERAL { + $$ = gen_const_int($[INT_LITERAL], src_loc(@$)); + } + | DATE_LITERAL { + $$ = gen_const_date($[DATE_LITERAL], src_loc(@$)); + } | function_call | procedure_call - | "(" expression ")" + | "(" expression ")" { $$ = $2; } function_call - : FUNC_IDENT "(" opt_arguments ")" + : FUNC_IDENT "(" opt_arguments ")" { + $$ = gen_func_call($[FUNC_IDENT], $[opt_arguments], src_loc(@$)); + } unless_expression - : "do" expression "unless" expression "otherwise" expression "done" + : "do" expression "unless" expression "otherwise" expression "done" { + $$ = gen_unless_expr($2, $4, $6, src_loc(@$)); + } opt_definitions : definitions - | {} + | { $$ = NULL; } program - : opt_definitions statement_list + : opt_definitions statement_list { + if ($1) { + ast_last($1)->n = $2; + $$ = $1; + } + else { + $$ = $2; + } + + parser->tree = $$; + } | error { /* make sure to catch parse errors */ parser->failed = true; @@ -293,44 +402,6 @@ program #include "gen_lexer.inc" -static void dump_yychar(struct parser *p, int yychar, YYSTYPE yylval, YYLTYPE yylloc) -{ - struct src_loc loc = src_loc(yylloc); - printf("%s:%d:%d: ", p->fname, loc.first_line, loc.first_col); - -#define PRINT_NAME(token) case token: printf(#token " "); break; - switch (yychar) { - FOREACH_TOKEN(PRINT_NAME); - default: printf("Unknown yychar\n"); return; - } - - char date_str[11] = {0}; - switch (yychar) { - case INT_LITERAL: printf("(%lld)", (long long int)yylval.snum); break; - case IDENT: printf("(%s)", yylval.str); break; - case FUNC_IDENT: printf("(%s)", yylval.str); break; - case PROC_IDENT: printf("(%s)", yylval.str); break; - case DATE_LITERAL: - date_to_string(date_str, yylval.num); - printf("(%s)", date_str); - break; - } - - printf("\n"); -} - -static void dump_lex(struct parser *p) -{ - int yychar; - YYSTYPE yylval; - YYLTYPE yylloc = {1, 1, 1, 1}; - - /* run lexer until we reach the end of the file */ - while ((yychar = yylex(&yylval, &yylloc, p->lexer, p)) != YYEOF) { - dump_yychar(p, yychar, yylval, yylloc); - } -} - static struct src_loc src_loc(YYLTYPE yylloc) { struct src_loc loc; @@ -377,11 +448,5 @@ void parse(struct parser *p, const char *fname, const char *buf) yylex_init(&p->lexer); yy_scan_string(buf, p->lexer); - - // debugging, remember to reset yy_scan_string once the actual parser - // runs - dump_lex(p); - - yy_scan_string(buf, p->lexer); yyparse(p->lexer, p); } |