1 (***********************************************************************)
5 (* Kim Nguyen, LRI UMR8623 *)
6 (* Université Paris-Sud & CNRS *)
8 (* Copyright 2010-2013 Université Paris-Sud and Centre National de la *)
9 (* Recherche Scientifique. All rights reserved. This file is *)
10 (* distributed under the terms of the GNU Lesser General Public *)
11 (* License, with the special exception on linking described in file *)
14 (***********************************************************************)
17 Time-stamp: <Last modified on 2013-02-14 17:15:58 CET by Kim Nguyen>
25 Ata.SFormula.atom_ (Ata.Move.make (l,b,q))
27 let ( => ) a b = (a, b)
28 let ( ** ) l q = mk_atom l true q
29 let ( ++ ) a b = Ata.SFormula.or_ a b
30 let ( %% ) a b = Ata.SFormula.and_ a b
31 let ( @: ) a b = StateSet.add a b
33 (* [compile_axis_test axis test q phi trans states] Takes an xpath
34 [axis] and node [test], a formula [phi], a list of [trans]itions
35 and a set of [states] and returns a formula [phi'], a new set of
36 transitions, and a new set of states such that [phi'] holds iff
37 there exists a node reachable through [axis]::[test] where [phi]
41 let compile_axis_test axis test phi trans states =
42 let q = State.make () in
43 let phi, trans, states =
47 (q, [ test => phi ]) :: trans,
53 QNameSet.any => (`Right ** q) ]) :: trans,
57 (if self then (`Epsilon ** q) else (`Left ** q)),
59 QNameSet.any => (`Left ** q) %% (`Right ** q) ]) :: trans,
63 let q' = State.make () in
64 let move = (`Up1 ** q) ++ (`Up2 ** q') in
67 :: (q', [ QNameSet.any => move ]) :: trans,
71 let q' = State.make () in
72 let move = (`Up1 ** q) ++ (`Up2 ** q') in
73 (if self then (`Epsilon ** q) else move),
75 QNameSet.any => move ])
76 :: (q', [ QNameSet.any => move ]) :: trans,
79 | FollowingSibling | PrecedingSibling ->
81 if axis = PrecedingSibling then
87 QNameSet.any => move ]) :: trans,
91 let q' = State.make () in
92 let test = if QNameSet.is_finite test then
93 QNameSet.fold (fun tag acc -> QNameSet.add (QName.add_attribute_prefix tag) acc)
98 (q, [ QNameSet.singleton QName.attribute_map => (`Left ** q') ])
99 :: (q', [ test => phi;
100 QNameSet.any => (`Right ** q') ]) :: trans,
105 phi, trans, q @: states
107 let rec compile_expr e trans states =
109 | Binop (e1, (And|Or as op), e2) ->
110 let phi1, trans1, states1 = compile_expr e1 trans states in
111 let phi2, trans2, states2 = compile_expr e2 trans1 states1 in
112 (if op = Or then phi1 ++ phi2 else phi1 %% phi2),
115 | Fun_call (f, [ e0 ]) when (QName.to_string f) = "not" ->
116 let phi, trans0, states0 = compile_expr e0 trans states in
117 (Ata.SFormula.not_ phi),
120 | Path p -> compile_path p trans states
123 and compile_path paths trans states =
124 List.fold_left (fun (aphi, atrans, astates) p ->
125 let phi, ntrans, nstates = compile_single_path p atrans astates in
126 (Ata.SFormula.or_ phi aphi),
128 nstates) (Ata.SFormula.false_,trans,states) paths
130 and compile_single_path p trans states =
134 (Ancestor false, QNameSet.singleton QName.document, [])::steps
135 | Relative steps -> steps
137 compile_step_list steps trans states
138 and compile_step_list l trans states =
140 [] -> Ata.SFormula.true_, trans, states
141 | (axis, test, elist) :: ll ->
142 let phi0, trans0, states0 = compile_step_list ll trans states in
143 let phi1, trans1, states1 =
144 compile_axis_test axis test phi0 trans0 states0
146 List.fold_left (fun (aphi, atrans, astates) e ->
147 let ephi, etrans, estates = compile_expr e atrans astates in
148 aphi %% ephi, etrans, estates) (phi1, trans1, states1) elist