···11+module type INPUT = sig
22+ type t
33+ type token
44+ val peek : t -> token option
55+ val advance : t -> t
66+ val position : t -> int
77+ val show_token : token -> string
88+end
99+1010+type error = {
1111+ pos : int;
1212+ expected : string list;
1313+}
1414+1515+let merge_errors e1 e2 =
1616+ if e1.pos > e2.pos then e1
1717+ else if e2.pos > e1.pos then e2
1818+ else { pos = e1.pos; expected = e1.expected @ e2.expected }
1919+2020+let pure x _input = Ok (x, _input)
2121+2222+let fail msg _input = Error { pos = 0; expected = [msg] }
2323+2424+module Char_input : sig
2525+ include INPUT with type token = char
2626+ val of_string : string -> t
2727+end = struct
2828+ type token = char
2929+ type t = { data : string; pos : int }
3030+3131+ let of_string s = { data = s; pos = 0 }
3232+3333+ let peek { data; pos } =
3434+ if pos >= String.length data then None
3535+ else Some (String.get data pos)
3636+3737+ let advance t = { t with pos = t.pos + 1 }
3838+ let position t = t.pos
3939+ let show_token c = Printf.sprintf "'%c'" c
4040+end
4141+4242+let parse_string parser s =
4343+ let input = Char_input.of_string s in
4444+ parser (module Char_input : INPUT with type t = Char_input.t and type token = char) input
4545+4646+let format_error ?(input = "") e =
4747+ let context =
4848+ if String.length input > 0 && e.pos < String.length input then
4949+ let start = max 0 (e.pos - 10) in
5050+ let len = min 20 (String.length input - start) in
5151+ Printf.sprintf " near '%s'" (String.sub input start len)
5252+ else ""
5353+ in
5454+ Printf.sprintf "parse error at position %d%s: expected %s"
5555+ e.pos context (String.concat " or " e.expected)
···11+open Ppxlib
22+open Ast_builder.Default
33+open Ir
44+55+let fresh =
66+ let counter = ref 0 in
77+ fun prefix ->
88+ incr counter;
99+ Printf.sprintf "%s_%d" prefix !counter
1010+1111+let error_expr ~loc expected =
1212+ [%expr Error { Combin.pos = I.position input; expected = [%e expected] }]
1313+1414+let expected_list ~loc strs =
1515+ elist ~loc (List.map (estring ~loc) strs)
1616+1717+let ok_expr ~loc value input_e =
1818+ [%expr Ok ([%e value], [%e input_e])]
1919+2020+let merge_errors_expr ~loc e1 e2 =
2121+ [%expr Combin.merge_errors [%e e1] [%e e2]]
2222+2323+let pvar_s ~loc s = ppat_var ~loc { txt = s; loc }
2424+let evar_s ~loc s = evar ~loc s
2525+2626+let mk_let_rec ~loc name params body rest =
2727+ let param_pats = List.map (pvar_s ~loc) params in
2828+ let func = List.fold_right (fun p e -> pexp_fun ~loc Nolabel None p e) param_pats body in
2929+ let vb = value_binding ~loc ~pat:(pvar_s ~loc name) ~expr:func in
3030+ pexp_let ~loc Recursive [vb] rest
3131+3232+let rec compile ~loc env expr =
3333+ match expr with
3434+ | Pure { value; _ } ->
3535+ [%expr Ok ([%e value], input)]
3636+3737+ | Fail { msg; _ } ->
3838+ error_expr ~loc (elist ~loc [estring ~loc msg])
3939+4040+ | Satisfy { pred; label; loc } ->
4141+ let expected = match label with
4242+ | Some l -> elist ~loc [estring ~loc l]
4343+ | None -> [%expr ["<satisfy>"]]
4444+ in
4545+ [%expr
4646+ match I.peek input with
4747+ | Some tok when [%e pred] tok -> Ok (tok, I.advance input)
4848+ | _ -> [%e error_expr ~loc expected]]
4949+5050+ | Any { loc } ->
5151+ [%expr
5252+ match I.peek input with
5353+ | Some tok -> Ok (tok, I.advance input)
5454+ | None -> [%e error_expr ~loc (elist ~loc [estring ~loc "<any>"])]]
5555+5656+ | Eof { loc } ->
5757+ [%expr
5858+ match I.peek input with
5959+ | None -> Ok ((), input)
6060+ | Some _ -> [%e error_expr ~loc (elist ~loc [estring ~loc "<eof>"])]]
6161+6262+ | Token { tok; loc } ->
6363+ [%expr
6464+ match I.peek input with
6565+ | Some t when t = [%e tok] -> Ok (t, I.advance input)
6666+ | _ -> [%e error_expr ~loc [%expr [I.show_token [%e tok]]]]]
6767+6868+ | Tokens { toks; loc } ->
6969+ [%expr
7070+ let rec loop toks_list inp =
7171+ match toks_list with
7272+ | [] -> Ok ([%e toks], inp)
7373+ | t :: rest ->
7474+ match I.peek inp with
7575+ | Some t' when t = t' -> loop rest (I.advance inp)
7676+ | _ -> [%e error_expr ~loc [%expr [String.concat "" (List.map I.show_token [%e toks])]]]
7777+ in
7878+ loop [%e toks] input]
7979+8080+ | OneOf { toks; loc } ->
8181+ [%expr
8282+ match I.peek input with
8383+ | Some t when List.mem t [%e toks] -> Ok (t, I.advance input)
8484+ | _ -> [%e error_expr ~loc [%expr List.map I.show_token [%e toks]]]]
8585+8686+ | NoneOf { toks; loc } ->
8787+ [%expr
8888+ match I.peek input with
8989+ | Some t when not (List.mem t [%e toks]) -> Ok (t, I.advance input)
9090+ | _ -> [%e error_expr ~loc (elist ~loc [estring ~loc "<none_of>"])]]
9191+9292+ | Bind { p; f; loc } ->
9393+ let p_code = compile ~loc env p in
9494+ [%expr
9595+ match [%e p_code] with
9696+ | Ok (x, inp) ->
9797+ let input = inp in
9898+ [%e f] x input
9999+ | Error e -> Error e]
100100+101101+ | Map { f; p; loc } ->
102102+ let p_code = compile ~loc env p in
103103+ [%expr
104104+ match [%e p_code] with
105105+ | Ok (x, inp) -> Ok ([%e f] x, inp)
106106+ | Error e -> Error e]
107107+108108+ | Apply { pf; px; loc } ->
109109+ let pf_code = compile ~loc env pf in
110110+ let px_code = compile ~loc env px in
111111+ [%expr
112112+ match [%e pf_code] with
113113+ | Ok (f, inp1) ->
114114+ let input = inp1 in
115115+ (match [%e px_code] with
116116+ | Ok (x, inp2) -> Ok (f x, inp2)
117117+ | Error e -> Error e)
118118+ | Error e -> Error e]
119119+120120+ | SeqLeft { p; q; loc } ->
121121+ let p_code = compile ~loc env p in
122122+ let q_code = compile ~loc env q in
123123+ [%expr
124124+ match [%e p_code] with
125125+ | Ok (x, inp1) ->
126126+ let input = inp1 in
127127+ (match [%e q_code] with
128128+ | Ok (_, inp2) -> Ok (x, inp2)
129129+ | Error e -> Error e)
130130+ | Error e -> Error e]
131131+132132+ | SeqRight { p; q; loc } ->
133133+ let p_code = compile ~loc env p in
134134+ let q_code = compile ~loc env q in
135135+ [%expr
136136+ match [%e p_code] with
137137+ | Ok (_, inp1) ->
138138+ let input = inp1 in
139139+ [%e q_code]
140140+ | Error e -> Error e]
141141+142142+ | Alt { p; q; loc } ->
143143+ let p_first = First_set.compute [] p in
144144+ let q_first = First_set.compute [] q in
145145+ if First_set.definitely_disjoint p_first q_first &&
146146+ First_set.all_static p_first && First_set.all_static q_first then
147147+ compile_committed_alt ~loc env p q p_first q_first
148148+ else
149149+ compile_backtrack_alt ~loc env p q
150150+151151+ | Attempt { p; loc } ->
152152+ let p_code = compile ~loc env p in
153153+ [%expr
154154+ let saved = input in
155155+ match [%e p_code] with
156156+ | Ok _ as r -> r
157157+ | Error e -> Error { e with Combin.pos = I.position saved }]
158158+159159+ | Cut { loc } ->
160160+ [%expr Ok ((), input)]
161161+162162+ | Lookahead { p; loc } ->
163163+ let p_code = compile ~loc env p in
164164+ [%expr
165165+ let saved = input in
166166+ match [%e p_code] with
167167+ | Ok (v, _) -> Ok (v, saved)
168168+ | Error e -> Error e]
169169+170170+ | NotFollowedBy { p; loc } ->
171171+ let p_code = compile ~loc env p in
172172+ [%expr
173173+ let saved = input in
174174+ match [%e p_code] with
175175+ | Ok _ -> [%e error_expr ~loc (elist ~loc [estring ~loc "<not_followed_by>"])]
176176+ | Error _ -> Ok ((), saved)]
177177+178178+ | Many { p; loc } ->
179179+ let p_code = compile ~loc env p in
180180+ [%expr
181181+ let rec loop acc input =
182182+ match [%e p_code] with
183183+ | Ok (x, inp) -> loop (x :: acc) inp
184184+ | Error _ -> Ok (List.rev acc, input)
185185+ in
186186+ loop [] input]
187187+188188+ | Some_ { p; loc } ->
189189+ let p_code = compile ~loc env p in
190190+ [%expr
191191+ match [%e p_code] with
192192+ | Ok (x, inp) ->
193193+ let rec loop acc input =
194194+ match [%e p_code] with
195195+ | Ok (y, inp2) -> loop (y :: acc) inp2
196196+ | Error _ -> Ok (List.rev acc, input)
197197+ in
198198+ loop [x] inp
199199+ | Error e -> Error e]
200200+201201+ | Optional { p; loc } ->
202202+ let p_code = compile ~loc env p in
203203+ [%expr
204204+ match [%e p_code] with
205205+ | Ok (x, inp) -> Ok (Some x, inp)
206206+ | Error _ -> Ok (None, input)]
207207+208208+ | Option { default; p; loc } ->
209209+ let p_code = compile ~loc env p in
210210+ [%expr
211211+ match [%e p_code] with
212212+ | Ok (x, inp) -> Ok (x, inp)
213213+ | Error _ -> Ok ([%e default], input)]
214214+215215+ | SepBy { p; sep; loc } ->
216216+ let sepby1 = compile ~loc env (SepBy1 { p; sep; loc }) in
217217+ [%expr
218218+ match [%e sepby1] with
219219+ | Ok _ as r -> r
220220+ | Error _ -> Ok ([], input)]
221221+222222+ | SepBy1 { p; sep; loc } ->
223223+ let p_code = compile ~loc env p in
224224+ let sep_code = compile ~loc env sep in
225225+ [%expr
226226+ match [%e p_code] with
227227+ | Ok (x, inp) ->
228228+ let rec loop acc input =
229229+ match [%e sep_code] with
230230+ | Ok (_, inp2) ->
231231+ let input = inp2 in
232232+ (match [%e p_code] with
233233+ | Ok (y, inp3) -> loop (y :: acc) inp3
234234+ | Error e -> Error e)
235235+ | Error _ -> Ok (List.rev acc, input)
236236+ in
237237+ loop [x] inp
238238+ | Error e -> Error e]
239239+240240+ | EndBy { p; sep; loc } ->
241241+ let endby1 = compile ~loc env (EndBy1 { p; sep; loc }) in
242242+ [%expr
243243+ match [%e endby1] with
244244+ | Ok _ as r -> r
245245+ | Error _ -> Ok ([], input)]
246246+247247+ | EndBy1 { p; sep; loc } ->
248248+ let p_code = compile ~loc env p in
249249+ let sep_code = compile ~loc env sep in
250250+ [%expr
251251+ match [%e p_code] with
252252+ | Ok (x, inp) ->
253253+ let input = inp in
254254+ (match [%e sep_code] with
255255+ | Ok (_, inp2) ->
256256+ let rec loop acc input =
257257+ match [%e p_code] with
258258+ | Ok (y, inp3) ->
259259+ let input = inp3 in
260260+ (match [%e sep_code] with
261261+ | Ok (_, inp4) -> loop (y :: acc) inp4
262262+ | Error e -> Error e)
263263+ | Error _ -> Ok (List.rev acc, input)
264264+ in
265265+ loop [x] inp2
266266+ | Error e -> Error e)
267267+ | Error e -> Error e]
268268+269269+ | ManyTill { p; end_; loc } ->
270270+ let p_code = compile ~loc env p in
271271+ let end_code = compile ~loc env end_ in
272272+ [%expr
273273+ let rec loop acc input =
274274+ match [%e end_code] with
275275+ | Ok (_, inp) -> Ok (List.rev acc, inp)
276276+ | Error _ ->
277277+ match [%e p_code] with
278278+ | Ok (x, inp) -> loop (x :: acc) inp
279279+ | Error e -> Error e
280280+ in
281281+ loop [] input]
282282+283283+ | Count { n; p; loc } ->
284284+ let p_code = compile ~loc env p in
285285+ [%expr
286286+ let rec loop n acc input =
287287+ if n <= 0 then Ok (List.rev acc, input)
288288+ else
289289+ match [%e p_code] with
290290+ | Ok (x, inp) -> loop (n - 1) (x :: acc) inp
291291+ | Error e -> Error e
292292+ in
293293+ loop [%e n] [] input]
294294+295295+ | Between { open_; close; p; loc } ->
296296+ compile ~loc env (SeqRight { loc; p = open_; q = SeqLeft { loc; p; q = close } })
297297+298298+ | ChainL { p; op; loc } ->
299299+ let chainl1 = compile ~loc env (ChainL1 { p; op; loc }) in
300300+ [%expr
301301+ match [%e chainl1] with
302302+ | Ok _ as r -> r
303303+ | Error _ -> Ok ([], input)]
304304+305305+ | ChainL1 { p; op; loc } ->
306306+ let p_code = compile ~loc env p in
307307+ let op_code = compile ~loc env op in
308308+ [%expr
309309+ match [%e p_code] with
310310+ | Ok (x, inp) ->
311311+ let rec loop acc input =
312312+ match [%e op_code] with
313313+ | Ok (f, inp2) ->
314314+ let input = inp2 in
315315+ (match [%e p_code] with
316316+ | Ok (y, inp3) -> loop (f acc y) inp3
317317+ | Error e -> Error e)
318318+ | Error _ -> Ok (acc, input)
319319+ in
320320+ loop x inp
321321+ | Error e -> Error e]
322322+323323+ | ChainR { p; op; loc } ->
324324+ let chainr1 = compile ~loc env (ChainR1 { p; op; loc }) in
325325+ [%expr
326326+ match [%e chainr1] with
327327+ | Ok _ as r -> r
328328+ | Error _ -> Ok ([], input)]
329329+330330+ | ChainR1 { p; op; loc } ->
331331+ let p_code = compile ~loc env p in
332332+ let op_code = compile ~loc env op in
333333+ [%expr
334334+ match [%e p_code] with
335335+ | Ok (x, inp) ->
336336+ let rec loop stack input =
337337+ match [%e op_code] with
338338+ | Ok (f, inp2) ->
339339+ let input = inp2 in
340340+ (match [%e p_code] with
341341+ | Ok (y, inp3) -> loop ((f, y) :: stack) inp3
342342+ | Error e -> Error e)
343343+ | Error _ ->
344344+ let rec fold v = function
345345+ | [] -> v
346346+ | (f, y) :: rest -> fold (f v y) rest
347347+ in
348348+ Ok (fold x (List.rev stack), input)
349349+ in
350350+ loop [] inp
351351+ | Error e -> Error e]
352352+353353+ | Choice { ps; label; loc } ->
354354+ let rec build_choice = function
355355+ | [] -> error_expr ~loc (match label with Some l -> elist ~loc [estring ~loc l] | None -> elist ~loc [estring ~loc "<choice>"])
356356+ | [p] -> compile ~loc env p
357357+ | p :: rest ->
358358+ let p_code = compile ~loc env p in
359359+ let rest_code = build_choice rest in
360360+ [%expr
361361+ let saved = input in
362362+ match [%e p_code] with
363363+ | Ok _ as r -> r
364364+ | Error e1 ->
365365+ let input = saved in
366366+ match [%e rest_code] with
367367+ | Ok _ as r -> r
368368+ | Error e2 -> Error (Combin.merge_errors e1 e2)]
369369+ in
370370+ build_choice ps
371371+372372+ | Label { p; label; loc } ->
373373+ let p_code = compile ~loc env p in
374374+ [%expr
375375+ match [%e p_code] with
376376+ | Ok _ as r -> r
377377+ | Error e -> Error { e with Combin.expected = [[%e estring ~loc label]] }]
378378+379379+ | Fix { body; _ } ->
380380+ [%expr
381381+ let rec parser_fix = [%e body] in
382382+ parser_fix input]
383383+384384+ | Var { name; loc } ->
385385+ [%expr [%e evar ~loc name] (module I) input]
386386+387387+and compile_committed_alt ~loc env p q p_first q_first =
388388+ let p_code = compile ~loc env p in
389389+ let q_code = compile ~loc env q in
390390+ let build_guard first =
391391+ match first.First_set.firsts with
392392+ | [First_set.Token tok] ->
393393+ [%expr match I.peek input with Some t when t = [%e tok] -> true | _ -> false]
394394+ | [First_set.OneOf toks] ->
395395+ [%expr match I.peek input with Some t when List.mem t [%e toks] -> true | _ -> false]
396396+ | _ -> [%expr true]
397397+ in
398398+ let p_guard = build_guard p_first in
399399+ let q_guard = build_guard q_first in
400400+ [%expr
401401+ if [%e p_guard] then [%e p_code]
402402+ else if [%e q_guard] then [%e q_code]
403403+ else [%e error_expr ~loc (elist ~loc [estring ~loc "<alt>"])]]
404404+405405+and compile_backtrack_alt ~loc env p q =
406406+ let p_code = compile ~loc env p in
407407+ let q_code = compile ~loc env q in
408408+ [%expr
409409+ let saved = input in
410410+ match [%e p_code] with
411411+ | Ok _ as r -> r
412412+ | Error e1 ->
413413+ let input = saved in
414414+ match [%e q_code] with
415415+ | Ok _ as r -> r
416416+ | Error e2 -> Error (Combin.merge_errors e1 e2)]
417417+418418+let compile_def env { name; expr; loc } =
419419+ let body = compile ~loc env expr in
420420+ let func = [%expr fun (type inp tok) (module I : Combin.INPUT with type t = inp and type token = tok) input -> [%e body]] in
421421+ value_binding ~loc ~pat:(pvar ~loc name) ~expr:func
422422+423423+let compile_mutual_def env { names; expr; loc } =
424424+ let body = compile ~loc env expr in
425425+ let func = [%expr fun (type inp tok) (module I : Combin.INPUT with type t = inp and type token = tok) input -> [%e body]] in
426426+ let pat = ppat_tuple ~loc (List.map (pvar ~loc) names) in
427427+ value_binding ~loc ~pat ~expr:func