%{
#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
#include "ast.h"
-
#include "y.tab.h"
int yylex(void);
+extern YYLTYPE yylloc;
void yyerror(struct ast **result, const char *str)
{
- ast_free(*result);
- fprintf(stderr, "error: %s\n", str);
+ fprintf(stderr, "%d-%d: %s\n", yylloc.first_line, yylloc.last_column, str);
+ (void)result;
}
int yywrap()
%}
-%union
-{
+%union {
struct expr *expr;
struct stmt *stmt;
struct list *list;
- struct vardecl vardecl;
+ struct vardecl *vardecl;
struct decl *decl;
+ struct type *type;
char *ident;
}
-//%define parse.error verbose
+%locations
%token <ident> IDENT
%token <expr> BOOL CHAR INTEGER
-%token ASSIGN BCLOSE BINAND BINOR BOPEN CCLOSE COMMA CONS COPEN DIVIDE DOT ELSE
-%token IF INVERSE MINUS MODULO NIL PLUS POWER RETURN SEMICOLON TIMES VAR WHILE
+%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 VAR WHILE
%parse-param { struct ast **result }
+%right ARROW
%right BINOR
%right BINAND
%nonassoc EQ NEQ LEQ LE GEQ GE
%right POWER
%type <ast> start
-%type <expr> expr
-%type <list> args body decls fargs field fnargs nargs
%type <decl> fundecl
-%type <vardecl> vardecl
+%type <expr> expr
+%type <list> args body decls fargs field fnargs nargs funtype vardecls
%type <stmt> stmt
+%type <type> type
+%type <vardecl> vardecl
%%
start : decls { *result = ast($1); } ;
decls
: { $$ = NULL; }
- | decls vardecl SEMICOLON { $$ = list_cons(decl_var($2), $1); }
+ | decls vardecl { $$ = list_cons(decl_var($2), $1); }
| decls fundecl { $$ = list_cons($2, $1); }
;
vardecl
- : VAR IDENT ASSIGN expr { $$ = (struct vardecl) {.ident=$2, .expr=$4}; }
+ : VAR IDENT ASSIGN expr SEMICOLON { $$ = vardecl(NULL, $2, $4); }
+ | type IDENT ASSIGN expr SEMICOLON { $$ = vardecl($1, $2, $4); }
;
fundecl
- : IDENT BOPEN args BCLOSE COPEN body CCLOSE
- { $$ = decl_fun($1, $3, $6); }
+ : 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
+ : { $$ = NULL; }
+ | vardecls vardecl { $$ = list_cons($2, $1); }
+ ;
+funtype
+ : { $$ = NULL; }
+ | funtype type { $$ = list_cons($2, $1); }
+ ;
+type
+ : BOPEN type COMMA type BCLOSE { $$ = type_tuple($2, $4); }
+ | BOPEN type BCLOSE { $$ = $2; }
+ | SOPEN type SCLOSE { $$ = type_list($2); }
+ | IDENT { $$ = type_var($1); }
;
args
: { $$ = NULL; }
| IDENT ASSIGN expr SEMICOLON { $$ = stmt_assign($1, $3); }
| RETURN expr SEMICOLON { $$ = stmt_return($2); }
| RETURN SEMICOLON { $$ = stmt_return(NULL); }
- | vardecl SEMICOLON { $$ = stmt_vardecl($1); }
;
field
: { $$ = NULL; }
| expr DIVIDE expr { $$ = expr_binop($1, divide, $3); }
| expr MODULO expr { $$ = expr_binop($1, modulo, $3); }
| expr POWER expr { $$ = expr_binop($1, power, $3); }
- | MINUS expr { $$ = expr_unop(negate, $2); }
+ | MINUS expr %prec TIMES { $$ = expr_unop(negate, $2); }
| INVERSE expr %prec TIMES { $$ = expr_unop(inverse, $2); }
| BOPEN expr COMMA expr BCLOSE { $$ = expr_tuple($2, $4); }
| BOPEN expr BCLOSE { $$ = $2; }