1 open Camlp4; (* -*- camlp4r -*- *)
2 (****************************************************************************)
6 (* INRIA Rocquencourt *)
8 (* Copyright 1998-2006 Institut National de Recherche en Informatique et *)
9 (* en Automatique. All rights reserved. This file is distributed under *)
10 (* the terms of the GNU Library General Public License, with the special *)
11 (* exception on linking described in LICENSE at the top of the Objective *)
12 (* Caml source tree. *)
14 (****************************************************************************)
17 * - Daniel de Rauglaudre: initial version
18 * - Nicolas Pouillard: refactoring
22 module Id : Sig.Id = struct
23 value name = "Camlp4OCamlRevisedParserParser";
24 value version = Sys.ocaml_version;
27 module Make (Syntax : Sig.Camlp4Syntax) = struct
32 [ SpTrm of Loc.t and Ast.patt and option Ast.expr
33 | SpNtr of Loc.t and Ast.patt and Ast.expr
34 | SpStr of Loc.t and Ast.patt ]
37 [ SeTrm of Loc.t and Ast.expr | SeNtr of Loc.t and Ast.expr ]
40 value stream_expr = Gram.Entry.mk "stream_expr";
41 value stream_begin = Gram.Entry.mk "stream_begin";
42 value stream_end = Gram.Entry.mk "stream_end";
43 value stream_quot = Gram.Entry.mk "stream_quot";
44 value parser_case = Gram.Entry.mk "parser_case";
45 value parser_case_list = Gram.Entry.mk "parser_case_list";
47 value strm_n = "__strm";
48 value peek_fun _loc = <:expr< Stream.peek >>;
49 value junk_fun _loc = <:expr< Stream.junk >>;
52 (* In syntax generated, many cases are optimisations. *)
54 value rec pattern_eq_expression p e =
56 [ (<:patt< $lid:a$ >>, <:expr< $lid:b$ >>) -> a = b
57 | (<:patt< $uid:a$ >>, <:expr< $uid:b$ >>) -> a = b
58 | (<:patt< $p1$ $p2$ >>, <:expr< $e1$ $e2$ >>) ->
59 pattern_eq_expression p1 e1 && pattern_eq_expression p2 e2
65 [ <:expr< raise $_$ >> -> True
69 value is_raise_failure e =
71 [ <:expr< raise Stream.Failure >> -> True
75 value rec handle_failure e =
77 [ <:expr< try $_$ with [ Stream.Failure -> $e$] >> ->
79 | <:expr< match $me$ with [ $a$ ] >> ->
80 let rec match_case_handle_failure =
82 [ <:match_case< $a1$ | $a2$ >> ->
83 match_case_handle_failure a1 && match_case_handle_failure a2
84 | <:match_case< $pat:_$ -> $e$ >> -> handle_failure e
86 in handle_failure me && match_case_handle_failure a
87 | <:expr< let $bi$ in $e$ >> ->
88 let rec binding_handle_failure =
90 [ <:binding< $b1$ and $b2$ >> ->
91 binding_handle_failure b1 && binding_handle_failure b2
92 | <:binding< $_$ = $e$ >> -> handle_failure e
94 in binding_handle_failure bi && handle_failure e
95 | <:expr< $lid:_$ >> | <:expr< $int:_$ >> | <:expr< $str:_$ >> |
96 <:expr< $chr:_$ >> | <:expr< fun [ $_$ ] >> | <:expr< $uid:_$ >> ->
98 | <:expr< raise $e$ >> ->
100 [ <:expr< Stream.Failure >> -> False
102 | <:expr< $f$ $x$ >> ->
103 is_constr_apply f && handle_failure f && handle_failure x
105 and is_constr_apply =
107 [ <:expr< $uid:_$ >> -> True
108 | <:expr< $lid:_$ >> -> False
109 | <:expr< $x$ $_$ >> -> is_constr_apply x
113 value rec subst v e =
114 let _loc = Ast.loc_of_expr e in
116 [ <:expr< $lid:x$ >> ->
117 let x = if x = v then strm_n else x in
119 | <:expr< $uid:_$ >> -> e
120 | <:expr< $int:_$ >> -> e
121 | <:expr< $chr:_$ >> -> e
122 | <:expr< $str:_$ >> -> e
123 | <:expr< $_$ . $_$ >> -> e
124 | <:expr< let $rec:rf$ $bi$ in $e$ >> ->
125 <:expr< let $rec:rf$ $subst_binding v bi$ in $subst v e$ >>
126 | <:expr< $e1$ $e2$ >> -> <:expr< $subst v e1$ $subst v e2$ >>
127 | <:expr< ( $tup:e$ ) >> -> <:expr< ( $tup:subst v e$ ) >>
128 | <:expr< $e1$, $e2$ >> -> <:expr< $subst v e1$, $subst v e2$ >>
129 | _ -> raise Not_found ]
130 and subst_binding v =
132 [ <:binding@_loc< $b1$ and $b2$ >> ->
133 <:binding< $subst_binding v b1$ and $subst_binding v b2$ >>
134 | <:binding@_loc< $lid:v'$ = $e$ >> ->
135 <:binding< $lid:v'$ = $if v = v' then e else subst v e$ >>
136 | _ -> raise Not_found ];
138 value stream_pattern_component skont ckont =
140 [ SpTrm _loc p None ->
141 <:expr< match $peek_fun _loc$ $lid:strm_n$ with
143 do { $junk_fun _loc$ $lid:strm_n$; $skont$ }
145 | SpTrm _loc p (Some w) ->
146 <:expr< match $peek_fun _loc$ $lid:strm_n$ with
147 [ Some $p$ when $w$ ->
148 do { $junk_fun _loc$ $lid:strm_n$; $skont$ }
153 [ <:expr< fun [ ($lid:v$ : Stream.t _) -> $e$ ] >> when v = strm_n -> e
154 | _ -> <:expr< $e$ $lid:strm_n$ >> ]
156 if pattern_eq_expression p skont then
157 if is_raise_failure ckont then e
158 else if handle_failure e then e
159 else <:expr< try $e$ with [ Stream.Failure -> $ckont$ ] >>
160 else if is_raise_failure ckont then
161 <:expr< let $p$ = $e$ in $skont$ >>
162 else if pattern_eq_expression <:patt< Some $p$ >> skont then
163 <:expr< try Some $e$ with [ Stream.Failure -> $ckont$ ] >>
164 else if is_raise ckont then
166 if handle_failure e then e
167 else <:expr< try $e$ with [ Stream.Failure -> $ckont$ ] >>
169 <:expr< let $p$ = $tst$ in $skont$ >>
171 <:expr< match try Some $e$ with [ Stream.Failure -> None ] with
172 [ Some $p$ -> $skont$
177 [ <:patt< $lid:v$ >> -> subst v skont
178 | _ -> raise Not_found ]
180 [ Not_found -> <:expr< let $p$ = $lid:strm_n$ in $skont$ >> ] ]
183 value rec stream_pattern _loc epo e ekont =
187 [ Some ep -> <:expr< let $ep$ = Stream.count $lid:strm_n$ in $e$ >>
189 | [(spc, err) :: spcl] ->
195 | _ -> <:expr< "" >> ]
197 <:expr< raise (Stream.Error $str$) >>
199 stream_pattern _loc epo e ekont spcl
201 let ckont = ekont err in stream_pattern_component skont ckont spc ]
204 value stream_patterns_term _loc ekont tspel =
207 (fun (p, w, _loc, spcl, epo, e) acc ->
208 let p = <:patt< Some $p$ >> in
214 | _ -> <:expr< "" >> ]
216 <:expr< raise (Stream.Error $str$) >>
218 let skont = stream_pattern _loc epo e ekont spcl in
219 <:expr< do { $junk_fun _loc$ $lid:strm_n$; $skont$ } >>
222 [ Some w -> <:match_case< $pat:p$ when $w$ -> $e$ | $acc$ >>
223 | None -> <:match_case< $pat:p$ -> $e$ | $acc$ >> ])
224 tspel <:match_case<>>
226 <:expr< match $peek_fun _loc$ $lid:strm_n$ with [ $pel$ | _ -> $ekont ()$ ] >>
229 value rec group_terms =
231 [ [([(SpTrm _loc p w, None) :: spcl], epo, e) :: spel] ->
232 let (tspel, spel) = group_terms spel in
233 ([(p, w, _loc, spcl, epo, e) :: tspel], spel)
234 | spel -> ([], spel) ]
237 value rec parser_cases _loc =
239 [ [] -> <:expr< raise Stream.Failure >>
241 match group_terms spel with
242 [ ([], [(spcl, epo, e) :: spel]) ->
243 stream_pattern _loc epo e (fun _ -> parser_cases _loc spel) spcl
245 stream_patterns_term _loc (fun _ -> parser_cases _loc spel) tspel ] ]
248 value cparser _loc bpo pc =
249 let e = parser_cases _loc pc in
252 [ Some bp -> <:expr< let $bp$ = Stream.count $lid:strm_n$ in $e$ >>
255 let p = <:patt< ($lid:strm_n$ : Stream.t _) >> in
256 <:expr< fun $p$ -> $e$ >>
259 value cparser_match _loc me bpo pc =
260 let pc = parser_cases _loc pc in
263 [ Some bp -> <:expr< let $bp$ = Stream.count $lid:strm_n$ in $pc$ >>
268 [ <:expr@_loc< $_$; $_$ >> as e -> <:expr< do { $e$ } >>
272 [ <:expr< $lid:x$ >> when x = strm_n -> e
273 | _ -> <:expr< let ($lid:strm_n$ : Stream.t _) = $me$ in $e$ >> ]
278 value rec not_computing =
280 [ <:expr< $lid:_$ >> | <:expr< $uid:_$ >> | <:expr< $int:_$ >> |
281 <:expr< $flo:_$ >> | <:expr< $chr:_$ >> | <:expr< $str:_$ >> -> True
282 | <:expr< $x$ $y$ >> -> is_cons_apply_not_computing x && not_computing y
284 and is_cons_apply_not_computing =
286 [ <:expr< $uid:_$ >> -> True
287 | <:expr< $lid:_$ >> -> False
288 | <:expr< $x$ $y$ >> -> is_cons_apply_not_computing x && not_computing y
294 [ <:expr< $f$ () >> ->
296 [ <:expr< $lid:_$ >> -> f
297 | _ -> <:expr< fun _ -> $e$ >> ]
298 | _ -> <:expr< fun _ -> $e$ >> ]
301 value rec cstream gloc =
303 [ [] -> let _loc = gloc in <:expr< Stream.sempty >>
305 if not_computing e then <:expr< Stream.ising $e$ >>
306 else <:expr< Stream.lsing $slazy _loc e$ >>
307 | [SeTrm _loc e :: secl] ->
308 if not_computing e then <:expr< Stream.icons $e$ $cstream gloc secl$ >>
309 else <:expr< Stream.lcons $slazy _loc e$ $cstream gloc secl$ >>
311 if not_computing e then e else <:expr< Stream.slazy $slazy _loc e$ >>
312 | [SeNtr _loc e :: secl] ->
313 if not_computing e then <:expr< Stream.iapp $e$ $cstream gloc secl$ >>
314 else <:expr< Stream.lapp $slazy _loc e$ $cstream gloc secl$ >> ]
316 (* Syntax extensions in Revised Syntax grammar *)
319 GLOBAL: expr stream_expr stream_begin stream_end stream_quot
320 parser_case parser_case_list;
322 [ [ "parser"; po = OPT parser_ipatt; pcl = parser_case_list ->
323 <:expr< $cparser _loc po pcl$ >>
324 | "match"; e = sequence; "with"; "parser"; po = OPT parser_ipatt;
325 pcl = parser_case_list ->
326 <:expr< $cparser_match _loc e po pcl$ >>
330 [ [ "["; pcl = LIST0 parser_case SEP "|"; "]" -> pcl
331 | pc = parser_case -> [pc]
335 [ [ stream_begin; sp = stream_patt; stream_end; po = OPT parser_ipatt; "->"; e = expr ->
348 [ [ e = expr -> e ] ]
351 [ [ spc = stream_patt_comp -> [(spc, None)]
352 | spc = stream_patt_comp; ";"; sp = stream_patt_comp_err_list ->
356 stream_patt_comp_err:
357 [ [ spc = stream_patt_comp; eo = OPT [ "??"; e = stream_expr -> e ] ->
360 stream_patt_comp_err_list:
361 [ [ spc = stream_patt_comp_err -> [spc]
362 | spc = stream_patt_comp_err; ";" -> [spc]
363 | spc = stream_patt_comp_err; ";"; sp = stream_patt_comp_err_list ->
367 [ [ stream_quot; p = patt; eo = OPT [ "when"; e = stream_expr -> e ] -> SpTrm _loc p eo
368 | p = patt; "="; e = stream_expr -> SpNtr _loc p e
369 | p = patt -> SpStr _loc p ] ]
372 [ [ i = a_LIDENT -> <:patt< $lid:i$ >>
373 | "_" -> <:patt< _ >>
377 [ [ stream_begin; stream_end -> <:expr< $cstream _loc []$ >>
378 | stream_begin; sel = stream_expr_comp_list; stream_end ->
379 <:expr< $cstream _loc sel$ >> ] ]
381 stream_expr_comp_list:
382 [ [ se = stream_expr_comp; ";"; sel = stream_expr_comp_list -> [se :: sel]
383 | se = stream_expr_comp; ";" -> [se]
384 | se = stream_expr_comp -> [se] ] ]
387 [ [ stream_quot; e = stream_expr -> SeTrm _loc e
388 | e = stream_expr -> SeNtr _loc e ] ]
394 module M = Register.OCamlSyntaxExtension Id Make;