Commentaries
[tatoo.git] / src / compil.ml
1 (***********************************************************************)
2 (*                                                                     *)
3 (*                               TAToo                                 *)
4 (*                                                                     *)
5 (*                   Lucca Hirschi, LRI UMR8623                        *)
6 (*                   Université Paris-Sud & CNRS                       *)
7 (*                                                                     *)
8 (*  Copyright 2010-2012 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   *)
12 (*  ../LICENSE.                                                        *)
13 (*                                                                     *)
14 (***********************************************************************)
15
16 open XPath.Ast
17 open Formula.Infix
18
19 exception Not_core_XPath
20 (** Raised whenever the XPath query contains not implemented structures *)
21
22 let pr_er = Format.err_formatter
23
24 let trans query =
25   (* Buidling of the ASTA step by step with a special case for the last
26      step. Then add a top most state. Each function modifies asta. *)
27   let asta = Asta.empty in
28   (* builds asta from the bottom of the query *)
29   let rec trans = function
30     | [s] -> trans_last s
31     | s :: tl ->  trans tl; trans_step s
32     | [] -> ()
33  
34   (* Add THE top most state for top-level query (done in the end) *)
35   and trans_init () =
36     let top_st = Asta.new_state () in
37     let or_top = 
38  List.fold_left (fun acc x -> ((`Left *+ x) +| acc))
39         (Formula.false_) (Asta.top_states asta)
40     in
41     Asta.add_quer asta top_st;
42     Asta.init_top asta;
43     Asta.add_top asta top_st;
44     Asta.add_bot asta top_st;   (* for trees which are leaves *)
45     Asta.add_tr asta (top_st, Asta.any_label, or_top) true
46
47   (* A selecting state is needed *)
48   and trans_last (ax,test,pred) =
49     let fo_p = trans_pr pred in
50     let q,q' = Asta.new_state(), Asta.new_state() in
51     Asta.add_selec asta q';
52     Asta.add_quer asta q;
53     Asta.add_quer asta q';
54     Asta.add_top asta q;
55     Asta.add_top asta q';
56     Asta.add_bot asta q;                (* q' \notin B !! *)
57     let Simple lab = test in
58     let tr_selec = (q', lab, fo_p)
59     and tr_q = (q, Asta.any_label, form_propa_selec q q' ax) in
60     Asta.add_tr asta tr_selec true;
61     Asta.add_tr asta tr_q true
62  
63   (* Add a new state and its transitions for the step *)
64   and trans_step (ax,test,pred) =
65     let fo_p = trans_pr pred
66     and q = Asta.new_state() in
67     let Simple label = test
68     and form_next = (fo_p) *&                    (* (\/ top_next) /\ predicat *)
69       (List.fold_left (fun acc x -> (`Left *+ x ) +| acc)
70          Formula.false_ (Asta.top_states asta)) in
71     let tr_next = (q, label, form_next)
72     and tr_propa = (q, Asta.any_label, form_propa q ax) in
73     Asta.add_quer asta q;
74     Asta.add_top asta q;
75     Asta.add_bot asta q;
76     Asta.add_tr asta tr_next true;
77     Asta.add_tr asta tr_propa true;
78     Asta.init_top asta;
79     Asta.add_top asta q
80
81   (* Translating of predicates. Either we apply De Morgan rules
82      in xPath.parse or here *)
83   and trans_pr  = function
84     | Expr True -> Formula.true_
85     | Expr False -> Formula.false_
86     | Or (p_1,p_2) -> trans_pr(p_1) +| trans_pr(p_2)
87     | And (p_1,p_2) -> trans_pr(p_1) *& trans_pr(p_2)
88     | Not (Expr Path q) -> (trans_pr_path false q)
89     | Expr Path q -> (trans_pr_path true q)
90     | x -> print_predicate pr_er x; raise Not_core_XPath
91
92   (* Builds asta for predicate and gives the formula which must be satsified *)
93   and trans_pr_path posi = function
94     | Relative [] -> if posi then Formula.true_ else Formula.false_
95     | Relative steps -> List.fold_left
96       (fun acc x -> if posi then (`Left *+ x) +| acc else (`Left *- x) +| acc)
97       Formula.false_ (trans_pr_step_l steps)
98     | AbsoluteDoS steps as x -> print pr_er x; raise Not_core_XPath
99     | Absolute steps as x -> print pr_er x; raise Not_core_XPath
100
101   (* Builds asta for a predicate query and give the formula *)
102   and trans_pr_step_l = function
103     | [step] -> trans_pr_step [] step
104     | step :: tl -> let list_top = trans_pr_step_l tl in
105                     trans_pr_step list_top step
106     | [] -> failwith "Can not happened! 1"
107
108   (* Add a step on the top of a list of states in a predicate *)
109   and trans_pr_step list (ax,test,pred) =
110     let form_next =
111       if list = []
112       then trans_pr pred
113       else (trans_pr pred) *&
114         (List.fold_left (fun acc x -> (`Left *+ x) +| acc)
115            Formula.false_ list)
116     and q = Asta.new_state() 
117     and Simple label = test in
118     let tr_next = (q,label, form_next)
119     and tr_propa = (q, Asta.any_label, form_propa q ax) in
120     Asta.add_reco asta q;
121     Asta.add_tr asta tr_next false;
122     Asta.add_tr asta tr_propa false;
123     [q]                                 (* always one element here, but more with self
124                                            axis *)
125   (* Gives the propagation formula *)
126   and form_propa q = function
127     | Child -> `Right *+ q
128     | Descendant -> (`Left *+ q +| `Right *+ q)
129     | x -> print_axis pr_er x; raise Not_core_XPath 
130
131   (* The same with a selecting state *)
132   and form_propa_selec q q' = function
133     | Child -> `Right *+ q +| `Right *+ q'
134     | Descendant -> (`Left *+ q +| `Right *+ q) +| (`Left *+ q' +| `Right *+ q')
135     | x -> print_axis pr_er x; raise Not_core_XPath 
136       
137   in
138   (* Match the top-level query *)
139   match query with      
140     | Absolute steps -> trans steps; trans_init(); asta
141     | AbsoluteDoS steps as x -> print pr_er x; raise Not_core_XPath
142     | Relative steps as x -> print pr_er x; raise Not_core_XPath