2
* Copyright (C) 2005 Vincent Balat
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU Lesser General Public License as published by
6
* the Free Software Foundation, with linking exception;
7
* either version 2.1 of the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
Parseur camlp4 pour XML sans antiquotations
22
Attention c'est juste un essai
23
Je ne colle peut-�tre pas � la syntaxe XML
24
par ex il faut revoir si un attribut peut �tre vide en xml
25
Si oui, il faut remplacer le "string" par "string option"
27
Le typage des attributs n'est pas evident donc pour l'instant ils sont tous string
28
exemple << <plop number="5" /> >> ----> `Number 5 (en fait `Number (int_of_string "5"))
29
<< <plop number=$n$ /> >> ----> `Number n o`u n est de type int ???
31
On pourrait decider d'ecrire << <plop number=$string_of_int n$ /> >>
32
Mais du coup cela fait int_of_string (string_of_int n)
33
et ensuite encore string_of_int au moment de l'affichage
35
Revoir aussi la gestion des commentaires ?
43
exception Xml_parser_error of string
46
(* Instead of using Pcaml.gram, we use a new grammar, using xmllexer *)
47
let g = Grammar.gcreate (Xmllexer.gmake ())
50
module ExprOrPatt = struct
52
let loc = (Lexing.dummy_pos, Lexing.dummy_pos)
60
| PLCons of 'a * 'a tlist
63
EPanyattr of tvarval * tvarval
64
| EPanytag of string * texprpatt tlist * texprpatt tlist
66
| EPwhitespace of string
69
let list_of_mlast_expr el =
71
(fun x l -> <:expr< [$x$ :: $l$] >>) el <:expr< [] >>
73
let list_of_mlast_patt pl =
75
(fun x l -> <:patt< [$x$ :: $l$] >>) pl <:patt< [] >>
77
let expr_valorval = function
78
EPVstr v -> <:expr< $str:v$ >>
79
| EPVvar v -> <:expr< $lid:v$ >>
81
let patt_valorval = function
82
EPVstr v -> <:patt< $str:v$ >>
83
| EPVvar v -> <:patt< $lid:v$ >>
85
let rec to_expr = function
87
EPanyattr (EPVstr aa, v) ->
88
let vv = expr_valorval v in
89
<:expr< (`$uid:String.capitalize aa$, $vv$) >>
91
| EPanyattr (EPVvar aa, v) ->
92
let vv = expr_valorval v in
93
<:expr< ($lid:aa$, $vv$) >>
95
| EPanytag (tag, attribute_list, child_list) ->
96
<:expr< `$uid:String.capitalize tag$
97
$to_expr_attlist attribute_list$
98
$to_expr_taglist child_list$
101
| EPpcdata dt -> <:expr< `PCData $str:dt$ >>
103
| EPwhitespace dt -> <:expr< `Whitespace $str:dt$ >>
105
| EPcomment c -> <:expr< `Comment $str:c$ >>
107
and to_expr_taglist = function
108
PLEmpty -> <:expr< [] >>
109
| PLCons (a,l) -> <:expr< [ $to_expr a$ :: $to_expr_taglist l$ ] >>
111
and to_expr_attlist = function
112
PLEmpty -> <:expr< [] >>
113
| PLCons (a,l) -> <:expr< [ $to_expr a$ :: $to_expr_attlist l$ ] >>
116
let rec to_patt = function
118
EPanyattr (EPVstr a, v) ->
119
let vv = patt_valorval v in
120
<:patt< ((`$uid:String.capitalize a$), $vv$) >>
122
| EPanyattr (EPVvar a, v) ->
123
let vv = patt_valorval v in
124
<:patt< ($lid:a$, $vv$) >>
126
| EPanytag (tag, attribute_list, child_list) ->
127
<:patt< `$uid:String.capitalize tag$
128
$to_patt_attlist attribute_list$
129
$to_patt_taglist child_list$
132
| EPpcdata dt -> <:patt< `PCData $str:dt$ >>
134
| EPwhitespace dt -> <:patt< `Whitespace $str:dt$ >>
136
| EPcomment c -> <:patt< `Comment $str:c$ >>
138
and to_patt_taglist = function
139
PLEmpty -> <:patt< [] >>
140
| PLCons (a,l) -> <:patt< [ $to_patt a$ :: $to_patt_taglist l$ ] >>
142
and to_patt_attlist = function
143
PLEmpty -> <:patt< [] >>
144
| PLCons (a,l) -> <:patt< [ $to_patt a$ :: $to_patt_attlist l$ ] >>
150
let exprpatt_xml = Grammar.Entry.create g "xml"
151
let exprpatt_any_tag = Grammar.Entry.create g "xml tag"
152
let exprpatt_any_tag_list = Grammar.Entry.create g "xml tag list"
153
let exprpatt_any_attribute_list = Grammar.Entry.create g "xml attribute list"
154
let exprpatt_attr_or_var = Grammar.Entry.create g "xml attribute or $var$"
155
let exprpatt_value_or_var = Grammar.Entry.create g "xml value or $var$"
162
declaration_list = LIST0 [ DECL | XMLDECL ];
164
root_tag = exprpatt_any_tag;
172
attribute_list = OPT exprpatt_any_attribute_list;
173
child_list = OPT exprpatt_any_tag_list;
175
let attlist = match attribute_list with
179
let taglist = match child_list with
186
| dt = WHITESPACE -> EPwhitespace dt
187
| dt = DATA -> EPpcdata dt
188
| c = COMMENT -> EPcomment c
191
exprpatt_any_attribute_list:
193
a = exprpatt_attr_or_var;
195
value = exprpatt_value_or_var;
196
suite = OPT exprpatt_any_attribute_list ->
197
let suite = match suite with
200
in PLCons (EPanyattr (a,value), suite)
203
exprpatt_any_tag_list:
205
anytag = exprpatt_any_tag;
206
suite = OPT exprpatt_any_tag_list ->
207
let suite = match suite with
210
in PLCons (anytag, suite)
213
exprpatt_value_or_var:
215
v = VALUE -> EPVstr v
218
exprpatt_attr_or_var:
225
let xml_exp s = to_expr (Grammar.Entry.parse exprpatt_xml (Stream.of_string s))
226
let xml_pat s = to_patt (Grammar.Entry.parse exprpatt_xml (Stream.of_string s))
229
| Element of (string * (string * string) list * xml list)
233
"Caml code not allowed in configuration file. Use $$ to escape $."
236
let rec to_xml_tag l = function
238
| EPcomment _ -> to_xml l
239
| EPpcdata s -> (PCData s)::(to_xml l)
240
| EPanytag (s, atts, tags) ->
241
(Element (s, (to_xml_atts atts), (to_xml tags)))::(to_xml l)
242
| _ -> raise (Xml_parser_error nocaml_msg)
243
and to_xml_att l = function
245
| EPcomment _ -> to_xml_atts l
246
| EPanyattr ((EPVstr n), (EPVstr v)) -> (n, v)::(to_xml_atts l)
247
| _ -> raise (Xml_parser_error nocaml_msg)
248
and to_xml_atts = function
250
| PLCons (a, l) -> to_xml_att l a
253
| PLCons (a, l) -> to_xml_tag l a
256
let print_location loc =
257
Printf.sprintf "%d-%d" (fst loc).Lexing.pos_cnum (snd loc).Lexing.pos_cnum
261
let chan = open_in s in
262
let tree = Grammar.Entry.parse exprpatt_any_tag_list (Stream.of_channel chan) in
266
| Stdpp.Exc_located (fl, exn) ->
269
("XML error at position: "^
270
(print_location fl)^". "^(Printexc.to_string exn)))
272
let xmlparser s = to_xml (rawxmlparser s)