work on type inference some more
[ccc.git] / parse.y
diff --git a/parse.y b/parse.y
index dcfbad6..29fa0ca 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -2,15 +2,16 @@
 #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()
@@ -20,19 +21,22 @@ 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
@@ -48,12 +52,12 @@ int yywrap()
 %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
 
 %%
 
@@ -61,34 +65,35 @@ start : decls { *result = ast($1); } ;
 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
@@ -109,19 +114,24 @@ body
        : /* 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); }
@@ -140,12 +150,13 @@ expr
        | 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(); }
        ;