spice/lib/syntax/parser.mly

77 lines
1.7 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:
| "nil" { Literal Nil }
| "true" { Literal True }
| "false" { Literal False }
| 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 }