types and locations
[ccc.git] / parse.y
diff --git a/parse.y b/parse.y
index 33e9881..7cad6e5 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -1,18 +1,16 @@
 %{
 #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()
@@ -22,24 +20,26 @@ 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
@@ -49,26 +49,44 @@ int yywrap()
 %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; }
@@ -99,7 +117,6 @@ stmt
        | 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; }
@@ -120,7 +137,7 @@ expr
        | 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; }