aboutsummaryrefslogtreecommitdiff
path: root/src/parser.y
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.y')
-rw-r--r--src/parser.y239
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);
}