#include <stdio.h>
#include "ast.h"
-#include "y.tab.h"
+#include "list.h"
+#include "parse.h"
int yylex(void);
extern YYLTYPE yylloc;
void yyerror(struct ast **result, const char *str)
{
- fprintf(stderr, "%d-%d: %s\n", yylloc.first_line, yylloc.last_column, str);
(void)result;
+ fprintf(stderr, "%d-%d: %s\n", yylloc.first_line, yylloc.last_column, str);
}
int yywrap()
%}
+%define parse.lac full
+%define parse.error verbose
+
%union {
struct expr *expr;
struct stmt *stmt;
struct list *list;
struct vardecl *vardecl;
- struct decl *decl;
+ struct fundecl *fundecl;
struct type *type;
char *ident;
}
%locations
%token <ident> IDENT
-%token <expr> BOOL CHAR INTEGER
+%token <expr> BOOL CHAR INTEGER STRING
%token ARROW ASSIGN BCLOSE BINAND BINOR BOPEN CCLOSE COMMA CONS COPEN DIVIDE
%token DOT ELSE ERROR IF INVERSE MINUS MODULO NIL PLUS POWER RETURN SEMICOLON
%token SCLOSE SOPEN TIMES TBOOL TCHAR TINT TVOID VAR WHILE
%right POWER
%type <ast> start
-%type <decl> fundecl
%type <expr> expr
-%type <list> args body decls fargs field fnargs nargs funtype vardecls
+%type <list> args body decls fargs field fnargs nargs funtype bbody
%type <stmt> stmt
-%type <type> type
+%type <type> type ftype
%type <vardecl> vardecl
+%type <fundecl> fundecl
%%
decls
: /* empty */ { $$ = NULL; }
| decls vardecl { $$ = list_cons(decl_var($2), $1); }
- | decls fundecl { $$ = list_cons($2, $1); }
+ | decls fundecl { $$ = list_cons(decl_fun($2), $1); }
;
vardecl
: VAR IDENT ASSIGN expr SEMICOLON { $$ = vardecl(NULL, $2, $4); }
+ | type IDENT ASSIGN expr SEMICOLON { $$ = vardecl($1, $2, $4); }
;
fundecl
- : IDENT BOPEN args BCLOSE CONS CONS funtype ARROW type COPEN vardecls body CCLOSE
- { $$ = decl_fun($1, $3, $7, $9, $11, $12); }
- | IDENT BOPEN args BCLOSE COPEN vardecls body CCLOSE
- { $$ = decl_fun($1, $3, NULL, NULL, $6, $7); }
- ;
-vardecls
- : /* empty */ { $$ = NULL; }
- | vardecls vardecl { $$ = list_cons($2, $1); }
+ : IDENT BOPEN args BCLOSE COPEN body CCLOSE
+ { $$ = fundecl($1, $3, NULL, NULL, $6); }
+ | IDENT BOPEN args BCLOSE CONS CONS funtype ARROW ftype COPEN body CCLOSE
+ { $$ = fundecl($1, $3, $7, $9, $11); }
;
funtype
: /* empty */ { $$ = NULL; }
- | funtype type { $$ = list_cons($2, $1); }
- | funtype IDENT { $$ = list_cons(type_var($2), $1); }
+ | funtype ftype { $$ = list_cons($2, $1); }
;
+/* don't allow vardecls to be fully polymorph, this complicates parsing a lot */
type
- : BOPEN type COMMA type BCLOSE { $$ = type_tuple($2, $4); }
- | SOPEN type SCLOSE { $$ = type_list($2); }
+ : BOPEN ftype COMMA ftype BCLOSE { $$ = type_tuple($2, $4); }
+ | SOPEN ftype SCLOSE { $$ = type_list($2); }
| TBOOL { $$ = type_basic(btbool); }
| TCHAR { $$ = type_basic(btchar); }
| TINT { $$ = type_basic(btint); }
| TVOID { $$ = type_basic(btvoid); }
;
+ftype
+ : type
+ | IDENT { $$ = type_var($1); }
+ ;
args
: /* empty */ { $$ = NULL; }
| nargs
: /* empty */ { $$ = NULL; }
| body stmt { $$ = list_cons($2, $1); }
;
+field
+ : /* empty */ { $$ = NULL; }
+ | field DOT IDENT { $$ = list_cons($3, $1); }
+ ;
+bbody
+ : COPEN body CCLOSE { $$ = $2; }
+ | stmt { $$ = list_cons($1, NULL); }
+ ;
stmt
- : IF BOPEN expr BCLOSE COPEN body CCLOSE ELSE COPEN body CCLOSE
- { $$ = stmt_if($3, $6, $10); }
- | WHILE BOPEN expr BCLOSE COPEN body CCLOSE
- { $$ = stmt_while($3, $6); }
- | IDENT ASSIGN expr SEMICOLON { $$ = stmt_assign($1, $3); }
+ : IF BOPEN expr BCLOSE bbody { $$ = stmt_if($3, $5, NULL); }
+ | IF BOPEN expr BCLOSE bbody ELSE bbody { $$ = stmt_if($3, $5, $7); }
+ | WHILE BOPEN expr BCLOSE bbody { $$ = stmt_while($3, $5); }
+ | IDENT field ASSIGN expr SEMICOLON { $$ = stmt_assign($1, $2, $4); }
| RETURN expr SEMICOLON { $$ = stmt_return($2); }
| RETURN SEMICOLON { $$ = stmt_return(NULL); }
+ | vardecl { $$ = stmt_vardecl($1); }
| expr SEMICOLON { $$ = stmt_expr($1); }
;
-field
- : /* empty */ { $$ = NULL; }
- | field DOT IDENT { $$ = list_cons($3, $1); }
expr
: expr BINOR expr { $$ = expr_binop($1, binor, $3); }
| expr BINAND expr { $$ = expr_binop($1, binand, $3); }
| expr POWER expr { $$ = expr_binop($1, power, $3); }
| MINUS expr %prec TIMES { $$ = expr_unop(negate, $2); }
| INVERSE expr %prec TIMES { $$ = expr_unop(inverse, $2); }
- | IDENT BOPEN fargs BCLOSE { $$ = expr_funcall($1, $3); }
+ | IDENT BOPEN fargs BCLOSE field { $$ = expr_funcall($1, $3, $5); }
| BOPEN expr COMMA expr BCLOSE { $$ = expr_tuple($2, $4); }
| BOPEN expr BCLOSE { $$ = $2; }
| INTEGER
| BOOL
| CHAR
+ | STRING
| IDENT field { $$ = expr_ident($1, $2); }
| NIL { $$ = expr_nil(); }
;