2222open MoreLabels
2323include Mustache_types
2424
25- let dummy_loc = {
26- loc_start = Lexing. dummy_pos;
27- loc_end = Lexing. dummy_pos;
28- }
29-
3025module List = ListLabels
3126module String = StringLabels
3227
33- module Infix = struct
34- let (^) y x = Concat (dummy_loc, [x; y])
35- end
36-
3728module Json = struct
3829 type value =
3930 [ `Null
@@ -50,9 +41,6 @@ module Json = struct
5041 let value: t -> value = fun t -> (t :> value )
5142end
5243
53- let parse_lx = Mustache_parser. mustache Mustache_lexer. mustache
54- let of_string s = parse_lx (Lexing. from_string s)
55-
5644let escape_html s =
5745 let b = Buffer. create (String. length s) in
5846 String. iter ( function
@@ -65,73 +53,82 @@ let escape_html s =
6553 ) s ;
6654 Buffer. contents b
6755
68- let rec pp fmt = function
69-
70- | String (_ , s ) ->
56+ (* Utility functions that allow converting between the ast with locations and
57+ without locations. *)
58+
59+ let dummy_loc =
60+ { Locs. loc_start = Lexing. dummy_pos;
61+ Locs. loc_end = Lexing. dummy_pos }
62+
63+ let rec erase_locs { Locs. desc; _ } =
64+ erase_locs_desc desc
65+ and erase_locs_desc = function
66+ | Locs. String s -> No_locs. String s
67+ | Locs. Escaped s -> No_locs. Escaped s
68+ | Locs. Section s -> No_locs. Section (erase_locs_section s)
69+ | Locs. Unescaped s -> No_locs. Unescaped s
70+ | Locs. Partial s -> No_locs. Partial s
71+ | Locs. Inverted_section s -> No_locs. Inverted_section (erase_locs_section s)
72+ | Locs. Concat l -> No_locs. Concat (List. map erase_locs l)
73+ | Locs. Comment s -> No_locs. Comment s
74+ and erase_locs_section { Locs. name; Locs. contents } =
75+ { No_locs. name; No_locs. contents = erase_locs contents }
76+
77+ let rec add_dummy_locs t =
78+ { Locs. loc = dummy_loc;
79+ Locs. desc = add_dummy_locs_desc t }
80+ and add_dummy_locs_desc = function
81+ | No_locs. String s -> Locs. String s
82+ | No_locs. Escaped s -> Locs. Escaped s
83+ | No_locs. Section s -> Locs. Section (add_dummy_locs_section s)
84+ | No_locs. Unescaped s -> Locs. Unescaped s
85+ | No_locs. Partial s -> Locs. Partial s
86+ | No_locs. Inverted_section s ->
87+ Locs. Inverted_section (add_dummy_locs_section s)
88+ | No_locs. Concat l -> Locs. Concat (List. map add_dummy_locs l)
89+ | No_locs. Comment s -> Locs. Comment s
90+ and add_dummy_locs_section { No_locs. name; No_locs. contents } =
91+ { Locs. name; Locs. contents = add_dummy_locs contents }
92+
93+ (* Printing: defined on the ast without locations. *)
94+
95+ let rec pp fmt =
96+ let open No_locs in
97+ function
98+ | String s ->
7199 Format. pp_print_string fmt s
72100
73- | Escaped ( _ , s ) ->
101+ | Escaped s ->
74102 Format. fprintf fmt " {{ %s }}" s
75103
76- | Unescaped ( _ , s ) ->
104+ | Unescaped s ->
77105 Format. fprintf fmt " {{& %s }}" s
78106
79- | Inverted_section ( _ , s ) ->
107+ | Inverted_section s ->
80108 Format. fprintf fmt " {{^%s}}%a{{/%s}}"
81109 s.name pp s.contents s.name
82110
83- | Section ( _ , s ) ->
111+ | Section s ->
84112 Format. fprintf fmt " {{#%s}}%a{{/%s}}"
85113 s.name pp s.contents s.name
86114
87- | Partial ( _ , s ) ->
115+ | Partial s ->
88116 Format. fprintf fmt " {{> %s }}" s
89117
90- | Comment ( _ , s ) ->
118+ | Comment s ->
91119 Format. fprintf fmt " {{! %s }}" s
92120
93- | Concat ( _ , s ) ->
121+ | Concat s ->
94122 List. iter (pp fmt) s
95123
96- let to_formatter = pp
97-
98124let to_string x =
99125 let b = Buffer. create 0 in
100126 let fmt = Format. formatter_of_buffer b in
101127 pp fmt x ;
102128 Format. pp_print_flush fmt () ;
103129 Buffer. contents b
104130
105- let rec fold ~string ~section ~escaped ~unescaped ~partial ~comment ~concat t =
106- let go = fold ~string ~section ~escaped ~unescaped ~partial ~comment ~concat in
107- match t with
108- | String (_ , s ) -> string s
109- | Escaped (_ , s ) -> escaped s
110- | Unescaped (_ , s ) -> unescaped s
111- | Comment (_ , s ) -> comment s
112- | Section (_ , { name; contents } ) ->
113- section ~inverted: false name (go contents)
114- | Inverted_section (_ , { name; contents } ) ->
115- section ~inverted: true name (go contents)
116- | Concat (_ , ms ) ->
117- concat (List. map ms ~f: go)
118- | Partial (_ , p ) -> partial p
119-
120- let raw s = String (dummy_loc, s)
121- let escaped s = Escaped (dummy_loc, s)
122- let unescaped s = Unescaped (dummy_loc, s)
123- let section n c = Section (dummy_loc, { name = n ; contents = c })
124- let inverted_section n c = Inverted_section (dummy_loc, { name = n ; contents = c })
125- let partial s = Partial (dummy_loc, s)
126- let concat t = Concat (dummy_loc, t)
127- let comment s = Comment (dummy_loc, s)
128-
129- let rec expand_partials =
130- let section ~inverted =
131- if inverted then inverted_section else section
132- in
133- fun partial ->
134- fold ~string: raw ~section ~escaped ~unescaped ~partial ~comment ~concat
131+ (* Rendering: defined on the ast without locations. *)
135132
136133module Lookup = struct
137134 let scalar ?(strict =true ) = function
@@ -177,48 +174,170 @@ module Lookup = struct
177174
178175end
179176
180- let render_fmt ?(strict =true ) (fmt : Format.formatter ) (m : t ) (js : Json.t ) =
181-
177+ let render_fmt ?(strict =true ) (fmt : Format.formatter ) (m : No_locs. t ) (js : Json.t ) =
178+ let open No_locs in
182179 let rec render ' m (js : Json.value ) = match m with
183180
184- | String ( _ , s ) ->
181+ | String s ->
185182 Format. pp_print_string fmt s
186183
187- | Escaped ( _ , "." ) ->
184+ | Escaped "." ->
188185 Format. pp_print_string fmt (escape_html (Lookup. scalar js))
189- | Escaped ( _ , key ) ->
186+ | Escaped key ->
190187 Format. pp_print_string fmt (escape_html (Lookup. str ~strict ~key js))
191188
192- | Unescaped ( _ , "." ) ->
189+ | Unescaped "." ->
193190 Format. pp_print_string fmt (Lookup. scalar js)
194- | Unescaped ( _ , key ) ->
191+ | Unescaped key ->
195192 Format. pp_print_string fmt (Lookup. str ~strict ~key js)
196193
197- | Inverted_section ( loc , s ) ->
194+ | Inverted_section s ->
198195 if Lookup. inverted js s.name
199- then render' (Section (loc, s) ) js
196+ then render' (Section s ) js
200197
201- | Section ( _ , s ) ->
198+ | Section s ->
202199 begin match Lookup. section ~strict js ~key: s.name with
203200 | `Bool false -> ()
204201 | `Bool true -> render' s.contents js
205202 | `A contexts -> List. iter (render' s.contents) contexts
206203 | context -> render' s.contents context
207204 end
208205
209- | Partial ( _ , _ ) ->
206+ | Partial _ ->
210207 pp fmt m
211208
212- | Comment ( _ , c ) -> ()
209+ | Comment c -> ()
213210
214- | Concat ( _ , templates ) ->
211+ | Concat templates ->
215212 List. iter (fun x -> render' x js) templates
216213
217214 in render' m (Json. value js)
218215
219- let render ?(strict =true ) (m : t ) (js : Json.t ) =
216+ let render ?(strict =true ) (m : No_locs. t ) (js : Json.t ) =
220217 let b = Buffer. create 0 in
221218 let fmt = Format. formatter_of_buffer b in
222219 render_fmt ~strict fmt m js ;
223220 Format. pp_print_flush fmt () ;
224221 Buffer. contents b
222+
223+ (* Parsing: produces an ast with locations. *)
224+
225+ let parse_lx : Lexing.lexbuf -> Locs.t =
226+ Mustache_parser. mustache Mustache_lexer. mustache
227+
228+ let of_string s = parse_lx (Lexing. from_string s)
229+
230+ (* Packing up everything in two modules of similar signature:
231+ [With_locations] and [Without_locations].
232+ *)
233+
234+ module With_locations = struct
235+ include Locs
236+
237+ let dummy_loc = dummy_loc
238+ let parse_lx = parse_lx
239+ let of_string = of_string
240+
241+ let pp fmt x = pp fmt (erase_locs x)
242+ let to_formatter = pp
243+
244+ let to_string x = to_string (erase_locs x)
245+
246+ let render_fmt ?strict fmt m js =
247+ render_fmt ?strict fmt (erase_locs m) js
248+
249+ let render ?strict m js =
250+ render ?strict (erase_locs m) js
251+
252+ let rec fold ~string ~section ~escaped ~unescaped ~partial ~comment ~concat t =
253+ let go = fold ~string ~section ~escaped ~unescaped ~partial ~comment ~concat in
254+ let { desc; loc } = t in
255+ match desc with
256+ | String s -> string ~loc s
257+ | Escaped s -> escaped ~loc s
258+ | Unescaped s -> unescaped ~loc s
259+ | Comment s -> comment ~loc s
260+ | Section { name; contents } ->
261+ section ~loc ~inverted: false name (go contents)
262+ | Inverted_section { name; contents } ->
263+ section ~loc ~inverted: true name (go contents)
264+ | Concat ms ->
265+ concat ~loc (List. map ms ~f: go)
266+ | Partial p -> partial ~loc p
267+
268+ module Infix = struct
269+ let (^) t1 t2 = { desc = Concat [t1; t2]; loc = dummy_loc }
270+ end
271+
272+ let raw ~loc s = { desc = String s; loc }
273+ let escaped ~loc s = { desc = Escaped s; loc }
274+ let unescaped ~loc s = { desc = Unescaped s; loc }
275+ let section ~loc n c =
276+ { desc = Section { name = n; contents = c };
277+ loc }
278+ let inverted_section ~loc n c =
279+ { desc = Inverted_section { name = n; contents = c };
280+ loc }
281+ let partial ~loc s = { desc = Partial s; loc }
282+ let concat ~loc t = { desc = Concat t; loc }
283+ let comment ~loc s = { desc = Comment s; loc }
284+
285+ let rec expand_partials =
286+ let section ~loc ~inverted =
287+ if inverted then inverted_section ~loc else section ~loc
288+ in
289+ fun partial ->
290+ fold ~string: raw ~section ~escaped ~unescaped ~partial ~comment ~concat
291+ end
292+
293+ module Without_locations = struct
294+ include No_locs
295+
296+ let parse_lx lexbuf = erase_locs (parse_lx lexbuf)
297+ let of_string s = erase_locs (of_string s)
298+
299+ let pp = pp
300+ let to_formatter = pp
301+
302+ let to_string = to_string
303+
304+ let rec fold ~string ~section ~escaped ~unescaped ~partial ~comment ~concat t =
305+ let go = fold ~string ~section ~escaped ~unescaped ~partial ~comment ~concat in
306+ match t with
307+ | String s -> string s
308+ | Escaped s -> escaped s
309+ | Unescaped s -> unescaped s
310+ | Comment s -> comment s
311+ | Section { name; contents } ->
312+ section ~inverted: false name (go contents)
313+ | Inverted_section { name; contents } ->
314+ section ~inverted: true name (go contents)
315+ | Concat ms ->
316+ concat (List. map ms ~f: go)
317+ | Partial p -> partial p
318+
319+ module Infix = struct
320+ let (^) y x = Concat [x; y]
321+ end
322+
323+ let raw s = String s
324+ let escaped s = Escaped s
325+ let unescaped s = Unescaped s
326+ let section n c = Section { name = n ; contents = c }
327+ let inverted_section n c = Inverted_section { name = n ; contents = c }
328+ let partial s = Partial s
329+ let concat t = Concat t
330+ let comment s = Comment s
331+
332+ let rec expand_partials =
333+ let section ~inverted =
334+ if inverted then inverted_section else section
335+ in
336+ fun partial ->
337+ fold ~string: raw ~section ~escaped ~unescaped ~partial ~comment ~concat
338+ end
339+
340+ (* Include [Without_locations] at the toplevel, to preserve backwards
341+ compatibility of the API. *)
342+
343+ include Without_locations
0 commit comments