9830e76c5a07fedb7dccb5c68422c14ccd828284
[tatoo.git] / src / xpath / xpath_internal_parser.mly
1 %{
2 (***********************************************************************)
3 (*                                                                     *)
4 (*                               TAToo                                 *)
5 (*                                                                     *)
6 (*                     Kim Nguyen, LRI UMR8623                         *)
7 (*                   Université Paris-Sud & CNRS                       *)
8 (*                                                                     *)
9 (*  Copyright 2010-2012 Université Paris-Sud and Centre National de la *)
10 (*  Recherche Scientifique. All rights reserved.  This file is         *)
11 (*  distributed under the terms of the GNU Lesser General Public       *)
12 (*  License, with the special exception on linking described in file   *)
13 (*  ../LICENSE.                                                        *)
14 (*                                                                     *)
15 (***********************************************************************)
16
17 (*
18   Time-stamp: <Last modified on 2013-03-13 14:21:53 CET by Kim Nguyen>
19 *)
20
21   open Ast
22   open Tree.Common
23 %}
24
25 %token <string> TAG
26 %token <string> PI
27 %token <string> ATTNAME
28 %token <string> STRING
29 %token <int>  INT
30 %token <float> FLOAT
31 %token <Ast.axis> AXIS
32 %token RB LB LP RP
33 %token SLASH SLASHSLASH COLONCOLON STAR PIPE DOT DOTDOT
34 %token EQ NEQ LT GT LTE GTE OR AND ADD SUB DIV MOD
35 %token NODE TEXT COMMENT
36 %token COMMA
37 %token EOF
38
39 %left OR
40 %left AND
41 %left EQ NEQ
42 %left LT GT LTE GTE
43 %left ADD SUB
44 %left MOD DIV STAR
45 %nonassoc uminus
46
47 %start xpath_query
48 %type <Ast.path> xpath_query
49
50
51 %%
52 xpath_query:
53 path EOF          { $1 }
54 ;
55
56 path:
57   path_rev { List.rev $1 }
58 ;
59
60 path_rev:
61   simple_path     { [ $1 ] }
62 | path_rev PIPE simple_path { $3 :: $1 }
63 ;
64
65
66 simple_path:
67    absolute_path  { Absolute  (List.rev $1) }
68 |  relative_path  { Relative  (List.rev $1) }
69 ;
70
71 absolute_path:
72   SLASH relative_path { $2 }
73 | SLASHSLASH relative_path { $2 @
74                                [(Descendant true,
75                                  (node, NodeKind.Node),
76                                  [])] }
77 ;
78
79 /*
80   step is always a small list, of size 1-3 so @ is
81   cheap
82 */
83 relative_path:
84   step { $1 }
85 | relative_path SLASH step { $3 @ $1 }
86 | relative_path SLASHSLASH step { $3 @
87                                     ((Descendant true,
88                                       (node, NodeKind.Node),
89                                       [])
90                                      :: $1) }
91 ;
92
93 step:
94   DOT                    { [ (Self, (node, NodeKind.Node), []) ] }
95 | DOTDOT                 { [ (Parent, (node, NodeKind.Node), []) ] }
96 | axis_test pred_list    {
97     match $1 with
98       (a,b) :: r -> (a,b,$2) :: (List.map (fun (a,b) -> (a,b,[])) r)
99     | [] -> assert false
100   }
101 ;
102
103 axis_test:
104   AXIS COLONCOLON test  { let a, (t,k) = $1, $3 in
105                           match a with
106                             Attribute when Utils.QNameSet.is_finite t ->
107                               [ a, ((Utils.QNameSet.fold
108                                        (fun t a ->
109                                          Utils.QNameSet.add
110                                            (Utils.QName.attribute t) a)
111                                        t Utils.QNameSet.empty), k) ]
112                           | Preceding|Following ->
113                               [ (Descendant true, (t,k));
114                                 if a == Preceding then
115                                   (PrecedingSibling, (node, NodeKind.Node))
116                                 else
117                                   (FollowingSibling, (node, NodeKind.Node));
118                                 (Ancestor true, (node, NodeKind.Node)) ]
119
120                           | _ -> [ a, (t,k) ]
121                         }
122 | test                  { [ Child, $1 ] }
123 | AXIS            {
124   let _ = Format.flush_str_formatter () in
125   let () = Format.fprintf Format.str_formatter "%a" Ast.print_axis $1 in
126   let a = Format.flush_str_formatter () in
127   [Child, (Utils.QNameSet.singleton (Utils.QName.of_string a),NodeKind.Element)]
128 }
129 | ATTNAME             {  [(Attribute,
130                            (Utils.QNameSet.singleton (Utils.QName.of_string $1),
131                             NodeKind.Attribute))] }
132 ;
133
134 test:
135   NODE                { node, NodeKind.Node }
136 | TEXT                { text, NodeKind.Text }
137 | STAR                { star, NodeKind.Element }
138 | COMMENT             { Utils.QNameSet.singleton(Utils.QName.comment),
139                         NodeKind.Comment
140                       }
141 | PI                  { (if $1 = "" then star
142                          else Utils.QNameSet.singleton(
143                            Utils.QName.processing_instruction (
144                              Utils.QName.of_string $1)
145                          )), NodeKind.ProcessingInstruction
146                       }
147 | TAG                 { Utils.QNameSet.singleton(Utils.QName.of_string $1),
148                         NodeKind.Element
149                       }
150 ;
151
152 pred_list:
153   pred_list_rev             { List.rev $1 }
154 ;
155
156 pred_list_rev:
157              { [] }
158 | pred_list LB expr RB   { $3 :: $1 }
159 ;
160
161 expr:
162   INT                       { Number(`Int($1)) }
163 | FLOAT                     { Number(`Float($1)) }
164 | STRING                    { String $1 }
165 | SUB expr     %prec uminus { Unop(Neg, $2) }
166 | expr AND expr             { Binop($1, And, $3) }
167 | expr OR expr              { Binop($1, Or, $3) }
168 | expr ADD expr             { Binop($1, Add, $3) }
169 | expr SUB expr             { Binop($1, Sub, $3) }
170 | expr STAR expr            { Binop($1, Mult, $3) }
171 | expr DIV expr             { Binop($1, Div, $3) }
172 | expr MOD expr             { Binop($1, Mod, $3) }
173 | expr EQ expr              { Binop($1, Eq, $3) }
174 | expr NEQ expr             { Binop($1, Neq, $3) }
175 | expr LT expr              { Binop($1, Lt, $3) }
176 | expr LTE expr             { Binop($1, Lte, $3) }
177 | expr GT expr              { Binop($1, Gt, $3) }
178 | expr GTE expr             { Binop($1, Gte, $3) }
179 | TAG LP arg_list RP        { Fun_call(Utils.QName.of_string $1, $3) }
180 | LP expr RP                { $2 }
181 | path                      { Path $1 }
182 ;
183
184 arg_list:
185                             { [] }
186 | arg_list1                 { List.rev $1 }
187 ;
188
189 arg_list1:
190   expr                     { [ $1 ] }
191 | arg_list1 COMMA expr     { $3 :: $1 }
192 ;