-
Notifications
You must be signed in to change notification settings - Fork 5
/
surface_parser.mly
116 lines (100 loc) · 2.71 KB
/
surface_parser.mly
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
%token <string> NAME
%token <int> NUMBER
%token KEYWORD_ELSE "else"
%token KEYWORD_FUN "fun"
%token KEYWORD_FALSE "false"
%token KEYWORD_IF "if"
%token KEYWORD_LET "let"
%token KEYWORD_THEN "then"
%token KEYWORD_TRUE "true"
%token ADD "+"
%token AMP_AMP "&&"
%token ASTERISK "*"
%token BANG "!"
%token COLON ":"
%token COLON_EQUALS ":="
%token EQUALS "="
%token EQUALS_GREATER "=>"
%token HYPHEN "-"
%token HYPHEN_GREATER "->"
%token PIPE_PIPE "||"
%token SEMICOLON ";"
%token OPEN_PAREN "("
%token CLOSE_PAREN ")"
%token END
%start <Surface.expr> main
%%
let main :=
| expr = located(expr); END;
{ expr }
let located(X) :=
| data = X;
{ Surface.{ loc = $loc; data } }
let binder :=
| located(NAME)
let param :=
| n = binder;
{ n, None }
| "("; n = binder; ":"; ty = located(ty); ")";
{ n, Some ty }
let ty :=
| ty1 = located(atomic_ty); "->"; ty2 = located(ty);
{ Surface.Fun_ty (ty1, ty2) }
| atomic_ty
let atomic_ty :=
| "("; ty = ty; ")";
{ ty }
| n = NAME;
{ Surface.Name n }
let expr :=
| "let"; n = binder; ps = list(param); ty = option(":"; ty = located(ty); { ty }); ":=";
expr0 = located(expr); ";"; expr1 = located(expr);
{ Surface.Let (n, ps, ty, expr0, expr1) }
| "fun"; ps = nonempty_list(param); "=>"; t = located(expr);
{ Surface.Fun_lit (ps, t) }
| "if"; expr0 = located(or_expr); "then"; expr1 = located(expr); "else"; expr2 = located(expr);
{ Surface.If_then_else (expr0, expr1, expr2) }
| expr = located(or_expr); ":"; ty = located(ty);
{ Surface.Ann (expr, ty) }
| or_expr
let or_expr :=
| expr0 = located(add_expr); "||"; expr1 = located(or_expr);
{ Surface.Op2 (`Or, expr0, expr1) }
| and_expr
let and_expr :=
| expr0 = located(add_expr); "&&"; expr1 = located(and_expr);
{ Surface.Op2 (`And, expr0, expr1) }
| eq_expr
let eq_expr :=
| expr0 = located(add_expr); "="; expr1 = located(eq_expr);
{ Surface.Op2 (`Eq, expr0, expr1) }
| add_expr
let add_expr :=
| expr0 = located(mul_expr); "+"; expr1 = located(add_expr);
{ Surface.Op2 (`Add, expr0, expr1) }
| expr0 = located(mul_expr); "-"; expr1 = located(add_expr);
{ Surface.Op2 (`Sub, expr0, expr1) }
| mul_expr
let mul_expr :=
| expr0 = located(app_expr); "*"; expr1 = located(mul_expr);
{ Surface.Op2 (`Mul, expr0, expr1) }
| app_expr
let app_expr :=
| expr0 = located(app_expr); expr1 = located(atomic_expr);
{ Surface.App (expr0, expr1) }
| "-"; expr = located(atomic_expr);
{ Surface.Op1 (`Neg, expr) }
| "!"; expr = located(atomic_expr);
{ Surface.Op1 (`Not, expr) }
| atomic_expr
let atomic_expr :=
| "("; expr = expr; ")";
{ expr }
| n = NAME;
{ Surface.Name n }
| "true";
{ Surface.Bool_lit true }
| "false";
{ Surface.Bool_lit false }
| i = NUMBER;
{ Surface.Int_lit i }