%{ #include #include #include #include "ast.h" #define YYSTYPE struct ast * #include "y.tab.h" int yylex_debug = 1; int yylex(void); void yyerror(struct ast **result, const char *str) { ast_free(*result); fprintf(stderr, "error: %s\n", str); } int yywrap() { return 1; } %} //%define parse.error verbose %token ASSIGN BCLOSE BINAND BINOR BOOL BOPEN CCLOSE CHAR COMMA CONS COPEN %token DIVIDE ELSE IDENT IF INTEGER INVERSE MINUS MODULO NIL PLUS POWER RETURN %token SEMICOLON TIMES VAR WHILE %parse-param { struct ast **result } %right BINOR %right BINAND %nonassoc EQ NEQ LEQ LE GEQ GE %right CONS %left PLUS MINUS %left TIMES DIVIDE MODULO %right POWER %% start : decls { *result = ast_list($1); } ; decls : { $$ = NULL; } | decls vardecl SEMICOLON { $$ = ast_cons($2, $1); } | decls fundecl { $$ = ast_cons($2, $1); } ; vardecl : VAR IDENT ASSIGN expr { $$ = ast_vardecl($2, $4); } ; fundecl : IDENT BOPEN args BCLOSE COPEN body CCLOSE { $$ = ast_fundecl($1, ast_list($3), ast_list($6)); } ; args : { $$ = NULL; } | nargs ; nargs : nargs COMMA IDENT { $$ = ast_cons($3, $1); } | IDENT { $$ = ast_cons($1, NULL); } ; fargs : { $$ = NULL; } | fnargs ; fnargs : fnargs COMMA expr { $$ = ast_cons($3, $1); } | expr { $$ = ast_cons($1, NULL); } ; body : { $$ = NULL; } | body vardecl SEMICOLON { $$ = ast_cons($2, $1); } | body stmt { $$ = ast_cons($2, $1); } ; stmt : IF BOPEN expr BCLOSE COPEN body CCLOSE ELSE COPEN body CCLOSE { $$ = ast_if($3, ast_list($6), ast_list($10)); } | WHILE BOPEN expr BCLOSE COPEN body CCLOSE { $$ = ast_while($3, ast_list($6)); } | expr SEMICOLON { $$ = ast_stmt_expr($1); } | IDENT ASSIGN expr SEMICOLON { $$ = ast_assign($1, $3); } | RETURN expr SEMICOLON { $$ = ast_return($2); } | RETURN SEMICOLON { $$ = ast_return(NULL); } ; expr : expr BINOR expr { $$ = ast_binop($1, binor, $3); } | expr BINAND expr { $$ = ast_binop($1, binand, $3); } | expr EQ expr { $$ = ast_binop($1, eq, $3); } | expr NEQ expr { $$ = ast_binop($1, neq, $3); } | expr LEQ expr { $$ = ast_binop($1, leq, $3); } | expr LE expr { $$ = ast_binop($1, le, $3); } | expr GEQ expr { $$ = ast_binop($1, geq, $3); } | expr GE expr { $$ = ast_binop($1, ge, $3); } | expr CONS expr { $$ = ast_binop($1, cons, $3); } | expr PLUS expr { $$ = ast_binop($1, plus, $3); } | expr MINUS expr { $$ = ast_binop($1, minus, $3); } | expr TIMES expr { $$ = ast_binop($1, times, $3); } | expr DIVIDE expr { $$ = ast_binop($1, divide, $3); } | expr MODULO expr { $$ = ast_binop($1, modulo, $3); } | expr POWER expr { $$ = ast_binop($1, power, $3); } | MINUS expr { $$ = ast_unop(negate, $2); } | INVERSE expr { $$ = ast_unop(inverse, $2); } | BOPEN expr BCLOSE { $$ = $2; } | IDENT BOPEN fargs BCLOSE { $$ = ast_funcall($1, ast_list($3)); } | INTEGER | BOOL | CHAR | IDENT | NIL { $$ = ast_nil(); } ;