/* milly's Bison grammar */ %{ #include int yylex(); void yyerror(const char *); %} %token IDENT %token PARAM_IDENT %token INT STRING %token TRUE FALSE %token CASE LET IN MATCH OF DEF DATATYPE ALIAS TYPECHECK %token ARROW /* Function constructor is right associative */ %right ARROW %right ':' %start program %% program: decl | decl program /* Types syntax */ type: atomic_type | type ARROW type atomic_type: type_app | PARAM_IDENT | '(' type ')' | '(' tuple_types ')' type_app_atom: PARAM_IDENT | '(' type ')' | '(' tuple_types ')' | IDENT type_app: IDENT | type_app_atom type_app tuple_types: type ',' type | type ',' tuple_types /* Declaration syntax */ decl: datatype_decl | alias_decl | typecheck_decl | value_decl | func_decl datatype_decl: DATATYPE def_type_params IDENT '{' datatype_alts '}' /* type parameters of a definition */ def_type_params: %empty | PARAM_IDENT def_type_params datatype_alts: %empty | IDENT type ',' datatype_alts alias_decl: ALIAS def_type_params IDENT '=' type typecheck_decl: TYPECHECK IDENT ':' type value_decl: DEF IDENT '=' expr func_decl: DEF IDENT param_patterns '=' expr fun_alts param_patterns: pattern | pattern param_patterns fun_alts: %empty | '|' IDENT param_patterns '=' expr fun_alts /* Expressions */ atomic_expr: IDENT | INT | TRUE | FALSE | STRING | '[' list_elems ']' | '(' expr ',' list_elems ')' | '(' expr ')' list_elems: %empty | expr ',' list_elems fun_app_expr: atomic_expr | fun_app_expr atomic_expr infix_expr: fun_app_expr | infix_expr ':' infix_expr /* List cons */ /* TODO: | infix_expr IDENT infix_expr */ expr: infix_expr | MATCH expr '{' case_alts '}' | LET let_decls IN expr case_alts: %empty | CASE pattern ARROW expr case_alts let_decls: decl | decl let_decls /* Pattern language */ pattern: IDENT | INT | TRUE | FALSE | STRING | '<' IDENT param_patterns '>' | '(' pattern ',' pattern_list ')' | '[' pattern_list ']' pattern_list: %empty | pattern ',' pattern_list %% void yyerror(const char *err) { fprintf(stderr, "Error: %s", err); }