Source file lib_ast_fuzzy.ml
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
open Common
open Ast_fuzzy
module PI = Parse_info
type 'tok hooks = {
kind : 'tok -> Parse_info.token_kind;
tokf : 'tok -> Parse_info.t;
}
exception Unclosed of string * Parse_info.t
let char_of_token_kind = function
| PI.RAngle -> '>'
| PI.RBracket -> ']'
| PI.RBrace -> '}'
| _ -> raise Impossible
let mk_trees h xs =
let xs =
xs
|> Common.exclude (fun t ->
let kind = h.kind t in
match kind with
| PI.Esthet _
| PI.Eof ->
true
| _ -> false)
in
let rec consume x xs =
match x with
| tok when h.kind tok =*= PI.LBrace ->
let body, closing, rest = look_close PI.RBrace x [] xs in
(Ast_fuzzy.Braces (h.tokf x, body, h.tokf closing), rest)
| tok when h.kind tok =*= PI.LBracket ->
let body, closing, rest = look_close PI.RBracket x [] xs in
(Ast_fuzzy.Bracket (h.tokf x, body, h.tokf closing), rest)
| tok when h.kind tok =*= PI.LAngle ->
let body, closing, rest = look_close PI.RAngle x [] xs in
(Ast_fuzzy.Angle (h.tokf x, body, h.tokf closing), rest)
| tok when h.kind tok =*= PI.LPar ->
let body, closing, rest = look_close_paren x [] xs in
let body' = split_comma body in
(Ast_fuzzy.Parens (h.tokf x, body', h.tokf closing), rest)
| tok -> (Ast_fuzzy.Tok (PI.str_of_info (h.tokf tok), h.tokf x), xs)
and aux xs =
match xs with
| [] -> []
| x :: xs ->
let x', xs' = consume x xs in
x' :: aux xs'
and look_close close_kind tok_start accbody xs =
match xs with
| [] ->
raise
(Unclosed
( spf "look_close '%c'" (char_of_token_kind close_kind),
h.tokf tok_start ))
| x :: xs -> (
match x with
| tok when h.kind tok =*= close_kind -> (List.rev accbody, x, xs)
| _ ->
let x', xs' = consume x xs in
look_close close_kind tok_start (x' :: accbody) xs')
and look_close_paren tok_start accbody xs =
match xs with
| [] -> raise (Unclosed ("look_close_paren", h.tokf tok_start))
| x :: xs -> (
match x with
| tok when h.kind tok =*= PI.RPar -> (List.rev accbody, x, xs)
| _ ->
let x', xs' = consume x xs in
look_close_paren tok_start (x' :: accbody) xs')
and split_comma xs =
let rec aux acc xs =
match xs with
| [] -> if null acc then [] else [ Left (acc |> List.rev) ]
| x :: xs -> (
match x with
| Ast_fuzzy.Tok (",", info) ->
let before = acc |> List.rev in
if null before then aux [] xs
else Left before :: Right info :: aux [] xs
| _ -> aux (x :: acc) xs)
in
aux [] xs
in
aux xs
let mk_tokens hooks toks =
toks |> List.map (fun tok -> (hooks.kind tok, hooks.tokf tok))
type visitor_out = trees -> unit
type visitor_in = {
ktree : (tree -> unit) * visitor_out -> tree -> unit;
ktrees : (trees -> unit) * visitor_out -> trees -> unit;
ktok : (tok -> unit) * visitor_out -> tok -> unit;
}
let (default_visitor : visitor_in) =
{
ktree = (fun (k, _) x -> k x);
ktok = (fun (k, _) x -> k x);
ktrees = (fun (k, _) x -> k x);
}
let (mk_visitor : visitor_in -> visitor_out) =
fun vin ->
let rec v_tree x =
let k x =
match x with
| Braces (v1, v2, v3) ->
let _v1 = v_tok v1 and _v2 = v_trees v2 and _v3 = v_tok v3 in
()
| Parens (v1, v2, v3) ->
let _v1 = v_tok v1
and _v2 = OCaml.v_list (OCaml.v_either v_trees v_tok) v2
and _v3 = v_tok v3 in
()
| Angle (v1, v2, v3) ->
let _v1 = v_tok v1 and _v2 = v_trees v2 and _v3 = v_tok v3 in
()
| Bracket (v1, v2, v3) ->
let _v1 = v_tok v1 and _v2 = v_trees v2 and _v3 = v_tok v3 in
()
| Metavar v1 ->
let _v1 = v_wrap v1 in
()
| Dots v1 ->
let _v1 = v_tok v1 in
()
| Tok v1 ->
let _v1 = v_wrap v1 in
()
in
vin.ktree (k, all_functions) x
and v_trees a =
let k xs =
match xs with
| [] -> ()
| x :: xs ->
v_tree x;
v_trees xs
in
vin.ktrees (k, all_functions) a
and v_wrap (_s, x) = v_tok x
and v_tok x =
let k _x = () in
vin.ktok (k, all_functions) x
and all_functions x = v_trees x in
all_functions
type map_visitor = { mtok : (tok -> tok) -> tok -> tok }
let (mk_mapper : map_visitor -> trees -> trees) =
fun hook ->
let rec map_tree = function
| Braces (v1, v2, v3) ->
let v1 = map_tok v1 and v2 = map_trees v2 and v3 = map_tok v3 in
Braces (v1, v2, v3)
| Parens (v1, v2, v3) ->
let v1 = map_tok v1
and v2 = List.map (OCaml.map_of_either map_trees map_tok) v2
and v3 = map_tok v3 in
Parens (v1, v2, v3)
| Angle (v1, v2, v3) ->
let v1 = map_tok v1 and v2 = map_trees v2 and v3 = map_tok v3 in
Angle (v1, v2, v3)
| Bracket (v1, v2, v3) ->
let v1 = map_tok v1 and v2 = map_trees v2 and v3 = map_tok v3 in
Bracket (v1, v2, v3)
| Metavar v1 ->
let v1 = map_wrap v1 in
Metavar v1
| Dots v1 ->
let v1 = map_tok v1 in
Dots v1
| Tok v1 ->
let v1 = map_wrap v1 in
Tok v1
and map_trees v = List.map map_tree v
and map_tok v =
let k v = v in
hook.mtok k v
and map_wrap (s, t) = (s, map_tok t) in
map_trees
let (toks_of_trees : trees -> Parse_info.t list) =
fun trees ->
let globals = ref [] in
let hooks =
{ default_visitor with ktok = (fun (_k, _) i -> Common.push i globals) }
in
let vout = mk_visitor hooks in
vout trees;
List.rev !globals
let abstract_position_trees trees =
let hooks =
{ mtok = (fun _k i -> { i with Parse_info.token = Parse_info.Ab }) }
in
let mapper = mk_mapper hooks in
mapper trees