8 type query_tree_desc = Binop of op * query_tree * query_tree
9 | Axis of Xpath.Ast.axis * query_tree
12 | Tag of QNameSet.t * Tree.NodeKind.t
14 and op = Union | Inter | Diff
17 mutable desc : query_tree_desc;
27 (q1.id == q2.id && q1.id != -1) ||
28 match q1.desc, q2.desc with
29 | Binop(op1,qt1,qt2),Binop(op2,qt3,qt4)-> op1==op2&& (equal qt1 qt3 && equal qt2 qt4)
31 | Axis(a1,qt1),Axis(a2,qt2) -> compare_axis a1 a2 && equal qt1 qt2
32 | Tag(t1,k1),Tag(t2,k2) -> t1==t2&& k1==k2
33 | Dom,Dom | Start,Start -> true
35 and compare_axis a1 a2 =
37 Self ,Self | Attribute, Attribute | Child , Child | Parent , Parent
38 | FollowingSibling , FollowingSibling
39 | PrecedingSibling , PrecedingSibling
40 | Preceding , Preceding | Following , Following -> true
41 | Descendant b1, Descendant b2 -> b1==b2
42 | Ancestor b1, Ancestor b2 -> b1==b2
46 if q.hash != -1 then q.hash
47 else match q.desc with
50 | Tag(s,_) -> 5 + 17*QNameSet.hash s
51 | Axis(a,q) -> 7 + 17 * Hashtbl.hash a + 23* hash q
52 | Binop(op,q1,q2) -> 11 + 17* Hashtbl.hash op + 23* hash q1 + 27* hash q2
57 module QTreeHash = Hashtbl.Make(QTree)
59 let compare_node tree a b =
60 compare (Naive_tree.preorder tree a ) (Naive_tree.preorder tree b )
65 | Noeud of 'a tas * 'a * 'a tas
67 let comp_node tree a b = (Naive_tree.preorder tree a )< (Naive_tree.preorder tree b )
72 | Noeud (t1,racine,t2) -> 1+ size t1 + size t2
77 | Noeud (t1,racine,t2) -> 1 + max (height t1) (height t2)
83 | Noeud (t1,racine,t2) -> 1 + min (aux t1) (aux t2)
85 let max_h = height t in
87 if max_h- min_h >1 then false
91 if not (equilibre t) then false
96 | Noeud (Vide,racine,Vide) -> racine >= n
97 | Noeud (t1,racine, t2) -> (aux racine t1) && (aux racine t2)
103 Vide -> failwith "Tas vide"
104 | Noeud (t1, racine, t2) -> begin
108 | Noeud (t3,r1,t4),Noeud (t5,r2,t6) -> if comp_node tree r1 r2 then Noeud (pop tree t1, r1,t2)
109 else Noeud (pop tree t2, r2, t1)
112 let rec push tree t a =
114 Vide -> Noeud(Vide,a,Vide)
115 | Noeud (t1,r,t2) -> if comp_node tree a r then Noeud (t2,a,push tree t1 r)
116 else Noeud(t2,r, push tree t1 a)
118 let tas_of_list tree l =
119 List.fold_left (push tree) Vide l
121 let is_empty t = (size t )== 0
123 let rec list_of_tas tree t =
126 | Noeud(t1,r,t2) -> r::(list_of_tas tree (pop tree t))
128 let sort_of_list tree l =
129 let t = tas_of_list tree l in
135 parametres : tree l'arbre xml
138 retour :un noeud qui correspond ॆ la relation r
141 let print_node_list tree l =
142 List.iter (fun node ->
143 Naive_tree.print_xml stdout tree node;
147 let rec print_query_tree fmt q =
149 Dom -> Format.fprintf fmt "Dom"
150 | Start -> Format.fprintf fmt "Start"
151 | Tag (t,k) -> Format.fprintf fmt "Tag(%a, %a)" QNameSet.print t Tree.NodeKind.print k
153 Format.fprintf fmt "%a(%a)" Xpath.Ast.print_axis a print_query_tree q
154 | Binop (op,q1,q2) ->
155 Format.fprintf fmt "%a(%a, %a)"
160 and print_binop fmt o =
162 | Union -> Format.fprintf fmt "Union"
163 | Inter -> Format.fprintf fmt "Inter"
164 | Diff -> Format.fprintf fmt "Diff"
166 let rec eval_relation tree m n =
169 | Firstchild -> Naive_tree.first_child tree n
170 | Nextsibling -> Naive_tree.next_sibling tree n
171 | Revfirstchild -> Naive_tree.parent_of_first tree n
172 | Prevsibling -> Naive_tree.prev_sibling tree n
175 parametres : tree l'arbre xml
176 ls l'ensemble de noeuds
178 retour : l'ensemble de noeuds qui correspondent ॆ la relation r
184 let rec eval_move tree ls m =
187 | r -> List.filter (fun n -> n != Naive_tree.nil)
188 (List.map (eval_relation tree r) ls)
192 parametres : tree l'arbre xml
193 ls l'ensemble de noeuds
195 retour : l'ensemble de noeuds qui correspondent ॆ des relations lr
198 and eval_star tree ls lr =
199 let h = Hashtbl.create 17 in
200 let q = Queue.create () in
201 List.iter ( fun e -> Queue.add e q ) ls;
202 while not (Queue.is_empty q ) do
203 let n = Queue.pop q in
204 if not (Hashtbl.mem h n) then begin
206 List.iter ( fun r -> let m = eval_relation tree r n in
207 if m != Naive_tree.nil && not (Hashtbl.mem h m ) then begin
213 let l = Hashtbl.fold (fun k _ acc -> k::acc) h [] in
216 Tas.sort_of_list tree l
217 List.sort (compare_node tree) l*)
221 let rec eval_axis tree ls a =
222 let open Xpath.Ast in
227 | Attribute -> let lfc = eval_move tree ls Firstchild in
228 let lc = eval_star tree lfc [Nextsibling] in
231 | Child -> let lfc = eval_move tree ls Firstchild in
232 let lc = eval_star tree lfc [Nextsibling] in
235 | Descendant c -> let lfc = eval_move tree ls Firstchild in
236 let ls2 = eval_star tree lfc [Firstchild;Nextsibling] in
239 else List.merge (compare_node tree) ls2 ls
243 | FollowingSibling -> let lnexts = eval_move tree ls Nextsibling in
244 let lfs = eval_star tree lnexts [Nextsibling] in
247 | Parent -> let lprevs = eval_star tree ls [Prevsibling] in
248 let lp = eval_move tree lprevs Revfirstchild in
251 | Ancestor b -> let ls2 = eval_star tree ls [Revfirstchild;Prevsibling] in
252 let ls3 = eval_move tree ls2 Revfirstchild in
255 else List.merge (compare_node tree ) ls3 ls
259 | PrecedingSibling -> let ls2 = eval_star tree ls [Prevsibling] in
260 let lps = eval_move tree ls2 Prevsibling in
263 | Preceding -> let ls2 = eval_axis tree ls (Ancestor true) in
264 let ls3 = eval_axis tree ls2 PrecedingSibling in
265 let lp = eval_axis tree ls3 (Descendant true) in
268 | Following -> let ls2 = eval_axis tree ls (Ancestor true) in
269 let ls3 = eval_axis tree ls2 FollowingSibling in
270 let lf = eval_axis tree ls3 (Descendant true) in
273 List.sort (compare_node tree) res