-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathparser.mly
149 lines (123 loc) · 3 KB
/
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
%{
open Ast
let s2i_ht = Hashtbl.create 128
let i2s_ht = Hashtbl.create 128
let get_name s =
try Hashtbl.find s2i_ht s with
| Not_found ->
( let n = Hashtbl.length s2i_ht in
Hashtbl.replace s2i_ht s n;
Hashtbl.replace i2s_ht n s;
n
)
%}
%token EOF
%token OPAR CPAR
%token <string> NAME
%token <string> LABEL
%token <int> INT
%token BAR
%token ARROW
%token JUMP
%token EQUALS
%token LET
%token IN
%token WHERE
%token FUN
%token END
%token COMMA
%token TRUE
%token FALSE
%token PLUS
%token MINUS
%token EQUALS2
%token LESS
%token GREATER
%token LESSEQ
%token GREATEREQ
%left PLUS
%left MINUS
%left EQUALS2
%left LESS
%left GREATER
%left LESSEQ
%left GREATEREQ
%start program
%type <(Ast.decl list * (int,string) Hashtbl.t)> program
%%
program :
| decl_list EOF { ($1, i2s_ht) }
;
decl_list :
| list (decl) { $1 }
;
decl :
| LET pat EQUALS expr { DLet ($2, $4) }
;
pat :
| INT {PLit (LInt $1)}
| TRUE {PLit (LBool true)}
| FALSE {PLit (LBool false)}
| NAME {PName (get_name $1)}
| OPAR z = separated_list(COMMA, pat) CPAR
{ match z with
| [] -> PTuple []
| [x] -> x
| ls -> PTuple ls
}
;
expr :
| JUMP label WHERE dispatch END {EJumpIn ((Some $2, None), $4)}
| JUMP expr_x WHERE dispatch END {EJumpIn ((None, Some $2), $4)}
| JUMP label expr_x WHERE dispatch END {EJumpIn ((Some $2, Some $3), $5)}
| JUMP label {EJump (Some $2, None)}
| JUMP expr_x {EJump (None, Some $2)}
| JUMP label expr_x {EJump (Some $2, Some $3)}
| LET pat EQUALS expr IN expr {ELetIn ($2, $4, $6)}
| FUN pat ARROW expr {EFun ($2, $4)}
| expr_a { $1 }
;
expr_a :
| expr_a PLUS expr_a {EBinOp(BinOpPlus, $1, $3)}
| expr_a MINUS expr_a {EBinOp(BinOpMinus, $1, $3)}
| expr_a EQUALS2 expr_a {EBinOp(BinOpEquals, $1, $3)}
| expr_a LESS expr_a {EBinOp(BinOpLess, $1, $3)}
| expr_a GREATER expr_a {EBinOp(BinOpGreater, $1, $3)}
| expr_a LESSEQ expr_a {EBinOp(BinOpLessEq, $1, $3)}
| expr_a GREATEREQ expr_a {EBinOp(BinOpGreaterEq, $1, $3)}
| ls = nonempty_list(expr_x)
{ match ls with
| [hd] -> hd
| hd :: tl -> List.fold_left (fun acc next -> EApp (acc, next)) hd tl
| [] -> failwith "impossible: empty list parsed"
}
expr_x :
| ename {$1}
| elit {$1}
| OPAR z = separated_list(COMMA, expr) CPAR
{ match z with
| [] -> ETuple []
| [x] -> x
| ls -> ETuple ls
}
;
label :
| LABEL {get_name $1}
ename :
| NAME {EName (get_name $1)}
;
elit :
| INT {ELit (LInt $1)}
| TRUE {ELit (LBool true)}
| FALSE {ELit (LBool false)}
;
dispatch :
| nonempty_list (branch) {$1}
| OPAR dispatch CPAR {$2}
;
branch :
| BAR label pat ARROW expr {(Some $2, Some $3, $5)}
| BAR label ARROW expr {(Some $2, None, $4)}
| BAR pat ARROW expr {(None, Some $2, $4)}
;
%%