74 lines
1.6 KiB
OCaml
74 lines
1.6 KiB
OCaml
%token <int64> Int
|
|
%token <Ast.name> Name
|
|
%token <Ast.binop> Binop
|
|
|
|
%token LP "(" RP ")"
|
|
%token LC "{" RC "}"
|
|
%token Eq "="
|
|
%token Dot "."
|
|
%token Com ","
|
|
|
|
%token Kw_true "true"
|
|
%token Kw_false "false"
|
|
%token Kw_nil "nil"
|
|
%token Kw_val "val"
|
|
%token Kw_fun "fun"
|
|
%token Kw_obj "obj"
|
|
%token Kw_if "if"
|
|
%token Kw_else "else"
|
|
|
|
%token EOF
|
|
%start <Ast.modl> modl
|
|
|
|
%{
|
|
open Ast
|
|
|
|
let infix_base e0 = (e0, [])
|
|
let infix_app (e0, ops) op e2 = (e0, (op, e2) :: ops)
|
|
|
|
let resolve_fixity (e0, ops) =
|
|
List.fold_right
|
|
(fun (op, e2) e1 -> Binop (op, e1, e2))
|
|
ops e0
|
|
%}
|
|
%%
|
|
|
|
modl:
|
|
| items = list(item); EOF { { items } }
|
|
|
|
item:
|
|
| e = exp { Item_exp e }
|
|
| "val"; n = Name; "="; e = exp { Item_val (n, e) }
|
|
| "fun"; n = Name; p = params; e = exp { Item_fun (n, p, e) }
|
|
| "obj"; n = Name; b = block { Item_obj (n, b) }
|
|
|
|
exp:
|
|
| e = infixexp { resolve_fixity e }
|
|
| "if"; "("; e1 = exp; ")"; e2 = exp; "else"; e3 = exp { If (e1, e2, e3) }
|
|
| "fun"; p = params; e = exp { Fun (p, e) }
|
|
| "obj"; b = block { Obj b }
|
|
| b = block { Scope b }
|
|
|
|
infixexp:
|
|
| e0 = singleexp { infix_base e0 }
|
|
| e1 = infixexp; op = Binop; e2 = singleexp { infix_app e1 op e2 }
|
|
|
|
singleexp:
|
|
| i = Int { Literal (Int i) }
|
|
| p = path { Path p }
|
|
| f = path; a = args { Call (f, a) }
|
|
| "("; e = exp; ")" { e }
|
|
|
|
path:
|
|
| x = Name { Var x }
|
|
| e = singleexp; "."; x = Name { Ele (e, x) }
|
|
|
|
params: "("; list = trailing_list(Name); ")" { list }
|
|
args: "("; list = trailing_list(exp); ")" { list }
|
|
block: "{"; list = list(item); "}" { list }
|
|
|
|
trailing_list(X):
|
|
| { [] }
|
|
| x = X { [x] }
|
|
| x = X; ","; xs = trailing_list(X) { x :: xs }
|