X-Git-Url: http://git.nguyen.vg/gitweb/?p=tatoo.git;a=blobdiff_plain;f=src%2Fxpath%2Fcompile.ml;h=20f06bec73480a9f74aa9e2e569b57c45d7af524;hp=c53057e6c5e2d69fabf102c43e4758c8c19baaed;hb=4f265eb7d78b740292b5543d94f9f0fa40d206d5;hpb=af9d790ca62e678e8e70ab8d8fa7f804985a75e0 diff --git a/src/xpath/compile.ml b/src/xpath/compile.ml index c53057e..20f06be 100644 --- a/src/xpath/compile.ml +++ b/src/xpath/compile.ml @@ -40,7 +40,7 @@ let root_set = QNameSet.singleton QName.document *) let compile_axis_test axis (test,kind) phi trans states = - let q = State.make () in + let q = State.next () in let phi = match kind with Tree.NodeKind.Node -> phi | _ -> phi %% F.is kind @@ -65,16 +65,15 @@ let compile_axis_test axis (test,kind) phi trans states = ]) :: trans, states) | Descendant true -> - let q' = State.make () in - (F.or_ (F.stay q) (F.first_child q'), - (q', [ test => phi; - QNameSet.any => F.first_child q' ++ F.next_sibling q'; - ]):: - (q, [ test => phi]):: trans, + let q' = State.next () in + (F.stay q ++ F.first_child q', + (q', [ QNameSet.any => F.stay q ++ F.first_child q' ++ F.next_sibling q'; + ]):: + (q, [ test => phi]):: trans, states) | Parent -> - let q' = State.make () in + let q' = State.next () in let move = F.parent q ++ F.previous_sibling q' in (move, (q, [ test => phi ]) @@ -82,13 +81,12 @@ let compile_axis_test axis (test,kind) phi trans states = (q' @: states)) | Ancestor self -> - let q' = State.make () in - let move = F.parent q ++ F.previous_sibling q' in - (if self then F.stay q else move), - (q, [ test => phi; - QNameSet.any => move ]) - :: (q', [ QNameSet.any => move ]) :: trans, - (q' @: states) + let q' = State.next () in + let move = F.parent q' ++ F.previous_sibling q' in + (if self then F.stay q ++ F.stay q' else F.stay q'), + (q', [ QNameSet.any => move ++ F.parent q]) + :: (q, [ test => phi ]) :: trans, + (q' @: states) | FollowingSibling | PrecedingSibling -> let move = @@ -210,26 +208,40 @@ let compile_top_level_step_list l trans states = in loop ll trans2 states2 phi2 in + let starting = State.next () in let phi0, trans0, states0 = compile_axis_test Self - (QNameSet.singleton QName.document, Tree.NodeKind.Node) - F.true_ + (QNameSet.any, Tree.NodeKind.Node) + (F.stay starting) trans states in - loop l trans0 states0 phi0 + let mstates, trans, states = loop l trans0 states0 phi0 in + starting, mstates, trans, states ;; let path p = - let mstates, trans, states = List.fold_left (fun (ams, atrs, asts) p -> - let ms, natrs, nasts = - match p with - | Absolute l | Relative l -> compile_top_level_step_list l atrs asts - in - (StateSet.add ms ams), natrs, nasts) (StateSet.empty, [], StateSet.empty) p + let sstates, mstates, trans, states = + List.fold_left (fun (ass, ams, atrs, asts) p -> + let ss, ms, natrs, nasts = + match p with + | Absolute l | Relative l -> compile_top_level_step_list l atrs asts + in + (StateSet.add ss ass), + (StateSet.add ms ams), + natrs, + nasts) (StateSet.empty, StateSet.empty, [], StateSet.empty) p in let builder = Ata.Builder.make () in + (** ensure that we have a single selecting state at the end *) + let phi_sel = StateSet.fold (fun q acc -> F.or_ (F.stay q) acc) mstates F.false_ in + let q_sel = State.next () in + let states = StateSet.add q_sel states in + let mstates = StateSet.singleton q_sel in + let trans = (q_sel, [QNameSet.any, phi_sel]) :: trans in + StateSet.iter + (Ata.Builder.add_state builder ~starting:true) sstates; StateSet.iter (Ata.Builder.add_state builder ~selecting:true) mstates; StateSet.iter