1use std::convert::TryFrom;
70use std::fmt;
71use std::fmt::{Debug, Formatter};
72use std::rc::Rc;
73use url::Url;
74
75use crate::item::{Item, Node, NodeType, Sequence, SequenceTrait};
76use crate::parser::combinators::whitespace::xpwhitespace;
77use crate::parser::xpath::literals::literal;
78use crate::parser::xpath::nodetests::{nodetest, qualname_test};
79use crate::parser::xpath::predicates::predicate_list;
80use crate::parser::xpath::variables::variable_reference;
81use crate::transform::context::{Context, ContextBuilder, StaticContext};
82use crate::transform::{Axis, KindTest, NameTest, NodeTest, Transform};
83use crate::value::Value;
84use crate::xdmerror::{Error, ErrorKind};
85
86use crate::parser::combinators::alt::{alt2, alt4, alt6};
87use crate::parser::combinators::list::{separated_list0, separated_list1};
89use crate::parser::combinators::many::many0;
90use crate::parser::combinators::map::map;
91use crate::parser::combinators::opt::opt;
92use crate::parser::combinators::pair::pair;
93use crate::parser::combinators::tag::tag;
94use crate::parser::combinators::tuple::{tuple2, tuple3};
95use crate::parser::{
96 ParseError, ParseInput, ParserState, ParserStateBuilder, StaticState, StaticStateBuilder,
97};
98use qualname::{NamespacePrefix, NamespaceUri, NcName, QName};
99
100#[derive(Clone)]
107pub enum Pattern<N: Node> {
108 Predicate(Transform<N>),
109 Selection(Path),
110 Error(Error),
111}
112
113impl<N: Node> Pattern<N> {
114 pub fn is_err(&self) -> bool {
116 if let Pattern::Selection(s) = self {
117 s.is_err()
118 } else {
119 matches!(self, Pattern::Error(_))
120 }
121 }
122 pub fn get_err(&self) -> Option<Error> {
123 if let Pattern::Selection(s) = self {
124 s.get_err()
125 } else if let Pattern::Error(e) = self {
126 Some(e.clone())
127 } else {
128 None
129 }
130 }
131 pub fn matches<
134 F: FnMut(&str) -> Result<(), Error>,
135 G: FnMut(&str) -> Result<N, Error>,
136 H: FnMut(&Url) -> Result<String, Error>,
137 >(
138 &self,
139 ctxt: &Context<N>,
140 stctxt: &mut StaticContext<N, F, G, H>,
141 i: &Item<N>,
142 ) -> bool {
143 match self {
144 Pattern::Predicate(t) => ContextBuilder::from(ctxt)
145 .context(vec![i.clone()])
146 .build()
147 .dispatch(stctxt, t)
148 .unwrap_or(vec![Item::Value(Rc::new(Value::from(false)))])
149 .to_bool(),
150 Pattern::Selection(p) => path_match(p, i),
151 _ => false, }
153 }
154 pub fn terminal_node_test(&self) -> (Axis, Axis, NodeTest) {
156 if let Pattern::Selection(sel) = self {
157 branch_terminal_node_test(sel)
158 } else {
159 (
160 Axis::SelfDocument,
161 Axis::SelfDocument,
162 NodeTest::Kind(KindTest::Document),
163 )
164 }
165 }
166}
167
168fn branch_terminal_node_test(b: &Branch) -> (Axis, Axis, NodeTest) {
169 match b {
170 Branch::SingleStep(t) => (t.terminal, t.non_terminal, t.nt.clone()),
171 Branch::RelPath(r) => branch_terminal_node_test(&r[0]),
172 Branch::Union(u) => branch_terminal_node_test(&u[0]), Branch::Error(_) => (
174 Axis::SelfDocument,
175 Axis::SelfDocument,
176 NodeTest::Kind(KindTest::Document),
177 ),
178 }
179}
180
181fn path_match<N: Node>(p: &Path, i: &Item<N>) -> bool {
184 !branch_match(p, vec![i.clone()]).is_empty()
185}
186fn branch_match<N: Node>(p: &Path, s: Sequence<N>) -> Sequence<N> {
189 match p {
192 Branch::SingleStep(t) => s
193 .iter()
194 .filter(|i| is_match(&t.terminal, &t.nt, i))
195 .flat_map(|i| find_seq(&t.non_terminal, i))
196 .collect(),
197 Branch::RelPath(r) => {
198 r.iter().fold(s, |ctxt, b| {
201 let new_ctxt = ctxt
202 .iter()
203 .cloned()
204 .flat_map(|i| branch_match(b, vec![i]))
205 .collect();
206 new_ctxt
207 })
208 }
209 Branch::Union(u) => {
210 u.iter()
212 .flat_map(|b| {
213 s.iter()
214 .cloned()
215 .flat_map(|i| branch_match(b, vec![i]))
216 .collect::<Sequence<N>>()
217 })
218 .collect()
219 }
220 Branch::Error(_) => vec![],
221 }
222}
223
224fn find_seq<N: Node>(a: &Axis, i: &Item<N>) -> Sequence<N> {
225 match a {
226 Axis::SelfDocument => match i {
227 Item::Node(n) => {
228 if n.node_type() == NodeType::Document {
229 vec![i.clone()]
230 } else {
231 vec![]
232 }
233 }
234 _ => vec![],
235 },
236 Axis::SelfAxis => vec![i.clone()],
237 Axis::Parent => match i {
238 Item::Node(n) => n.parent().map_or(vec![], |p| vec![Item::Node(p)]),
239 _ => vec![],
240 },
241 _ => vec![], }
243}
244
245fn is_match<N: Node>(a: &Axis, nt: &NodeTest, i: &Item<N>) -> bool {
246 match a {
247 Axis::SelfDocument => {
248 match i {
250 Item::Node(n) => {
251 if n.node_type() == NodeType::Document {
252 nt.matches_item(i)
253 } else {
254 false
255 }
256 }
257 _ => false,
258 }
259 }
260 Axis::SelfAxis => {
261 nt.matches_item(i)
263 }
274 Axis::Parent => {
275 match i {
277 Item::Node(n) => n.parent().is_some_and(|p| nt.matches(&p)),
278 _ => false,
279 }
280 }
281 Axis::SelfAttribute => match i {
282 Item::Node(n) => {
283 if n.node_type() == NodeType::Attribute {
284 nt.matches(n)
285 } else {
286 false
287 }
288 }
289 _ => false,
290 },
291 _ => false, }
293}
294
295impl<N: Node> Debug for Pattern<N> {
296 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
297 match self {
298 Pattern::Predicate(t) => write!(f, "Pattern::Predicate t==\"{:?}\"", t),
299 Pattern::Selection(p) => write!(f, "Pattern::Selection path=\"{:?}\"", p),
300 Pattern::Error(e) => write!(f, "Pattern::Error error=\"{:?}\"", e),
301 }
302 }
303}
304
305pub type Path = Branch;
315#[derive(Clone, Debug)]
316pub enum Branch {
317 SingleStep(Step),
318 RelPath(Vec<Branch>),
319 Union(Vec<Branch>),
320 Error(Error),
321}
322
323impl Branch {
324 pub fn terminal_node_test(&self) -> (Axis, Axis, NodeTest) {
325 branch_terminal_node_test(self)
326 }
327 pub fn is_err(&self) -> bool {
329 match self {
330 Branch::Error(_) => true,
331 Branch::SingleStep(_) => false,
332 Branch::RelPath(r) => r.iter().any(|f| f.is_err()),
333 Branch::Union(u) => u.iter().any(|f| f.is_err()),
334 }
335 }
336 pub fn get_err(&self) -> Option<Error> {
338 match self {
339 Branch::Error(e) => Some(e.clone()),
340 Branch::SingleStep(_) => None,
341 Branch::RelPath(r) => r.iter().fold(None, |v, f| v.or_else(|| f.get_err())),
342 Branch::Union(u) => u.iter().fold(None, |v, f| v.or_else(|| f.get_err())),
343 }
344 }
345}
346
347#[derive(Clone, Debug)]
383pub struct Step {
384 terminal: Axis,
385 non_terminal: Axis,
386 nt: NodeTest,
387}
388
389impl Step {
390 pub fn new(terminal: Axis, non_terminal: Axis, nt: NodeTest) -> Self {
391 Step {
392 terminal,
393 non_terminal,
394 nt,
395 }
396 }
397 pub fn get_ref(&self) -> (&Axis, &Axis, &NodeTest) {
398 (&self.terminal, &self.non_terminal, &self.nt)
399 }
400}
401
402impl<N: Node> TryFrom<&str> for Pattern<N> {
404 type Error = Error;
405 fn try_from(e: &str) -> Result<Self, <crate::pattern::Pattern<N> as TryFrom<&str>>::Error> {
406 if e.is_empty() {
407 Err(Error::new(
408 ErrorKind::TypeError,
409 String::from("empty string is not allowed as an XPath pattern"),
410 ))
411 } else {
412 pattern_driver(e, None)
413 }
429 }
430}
431
432impl<N: Node> TryFrom<(&str, N)> for Pattern<N> {
434 type Error = Error;
435 fn try_from(
436 e: (&str, N),
437 ) -> Result<Self, <crate::pattern::Pattern<N> as TryFrom<&str>>::Error> {
438 if e.0.is_empty() {
439 Err(Error::new(
440 ErrorKind::TypeError,
441 String::from("empty string is not allowed as an XPath pattern"),
442 ))
443 } else {
444 pattern_driver(e.0, Some(e.1))
445 }
466 }
467}
468
469impl<'a, N: Node> TryFrom<String> for Pattern<N> {
470 type Error = Error;
471 fn try_from(e: String) -> Result<Self, <Pattern<N> as TryFrom<&'a str>>::Error> {
472 Pattern::try_from(e.as_str())
473 }
474}
475impl<'a, N: Node> TryFrom<(String, N)> for Pattern<N> {
476 type Error = Error;
477 fn try_from(e: (String, N)) -> Result<Self, <Pattern<N> as TryFrom<(&'a str, N)>>::Error> {
478 Pattern::try_from((e.0.as_str(), e.1))
479 }
480}
481
482fn pattern_driver<N: Node>(e: &str, n: Option<N>) -> Result<Pattern<N>, Error> {
483 let state = n.clone().map_or_else(
484 || ParserState::new(),
485 |m| ParserStateBuilder::new().doc(m).build(),
486 );
487 let mut static_state = StaticStateBuilder::new()
489 .namespace(|nsp| {
490 n.as_ref().map_or_else(
491 || Err(ParseError::MissingNameSpace),
492 |m| {
493 m.to_namespace_uri(&Some(nsp.clone()))
494 .map_err(|_| ParseError::MissingNameSpace)
495 },
496 )
497 })
498 .build();
499 match pattern((e, state), &mut static_state) {
500 Ok(((rem, _), f)) => {
501 if rem.is_empty() {
502 Ok(f)
503 } else {
504 Err(Error::new(
505 ErrorKind::Unknown,
506 format!("extra characters found: \"{:?}\"", rem),
507 ))
508 }
509 }
510 Err(err) => Err(Error::new(ErrorKind::Unknown, format!("{:?}", err))),
511 }
512}
513
514fn pattern<'a, N: Node + 'a, L>(
516 input: ParseInput<'a, N>,
517 static_state: &mut StaticState<L>,
518) -> Result<(ParseInput<'a, N>, Pattern<N>), ParseError>
519where
520 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
521{
522 alt2(predicate_pattern::<N, L>(), union_expr_pattern())(input, static_state)
523}
524
525fn predicate_pattern<'a, N: Node + 'a, L>() -> Box<
528 dyn Fn(
529 ParseInput<'a, N>,
530 &mut StaticState<L>,
531 ) -> Result<(ParseInput<'a, N>, Pattern<N>), ParseError>
532 + 'a,
533>
534where
535 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
536{
537 Box::new(map(
538 pair(
539 map(tuple3(xpwhitespace(), tag("."), xpwhitespace()), |_| ()),
540 predicate_list::<N, L>(),
541 ),
542 |(_, p)| Pattern::Predicate(p),
543 ))
544}
545
546fn union_expr_pattern<'a, N: Node + 'a, L>() -> Box<
549 dyn Fn(
550 ParseInput<'a, N>,
551 &mut StaticState<L>,
552 ) -> Result<(ParseInput<'a, N>, Pattern<N>), ParseError>
553 + 'a,
554>
555where
556 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
557{
558 Box::new(map(
559 separated_list1(
560 map(
561 tuple3(xpwhitespace(), alt2(tag("union"), tag("|")), xpwhitespace()),
562 |_| (),
563 ),
564 intersect_except_expr_pattern::<N, L>(),
565 ),
566 |v| {
567 Pattern::Selection(Branch::Union(v))
568 },
574 ))
575}
576
577fn union_expr_wrapper<'a, N: Node + 'a, L>(
579 b: bool,
580) -> Box<
581 dyn Fn(
582 ParseInput<'a, N>,
583 &mut StaticState<L>,
584 ) -> Result<(ParseInput<'a, N>, Pattern<N>), ParseError>,
585>
586where
587 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
588{
589 Box::new(move |input, ss| {
590 if b {
591 union_expr_pattern::<N, L>()(input, ss)
592 } else {
593 noop()(input, ss)
594 }
595 })
596}
597
598fn noop<'a, N: Node, L>() -> Box<
599 dyn Fn(
600 ParseInput<'a, N>,
601 &mut StaticState<L>,
602 ) -> Result<(ParseInput<'a, N>, Pattern<N>), ParseError>,
603>
604where
605 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
606{
607 Box::new(move |_, _| Err(ParseError::Combinator(String::from("noop - pattern"))))
608}
609
610fn intersect_except_expr_pattern<'a, N: Node + 'a, L>() -> Box<
613 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
614 + 'a,
615>
616where
617 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
618{
619 Box::new(map(
620 separated_list1(
621 map(
622 tuple3(
623 xpwhitespace(),
624 alt2(tag("intersect"), tag("except")),
625 xpwhitespace(),
626 ),
627 |_| (),
628 ),
629 path_expr_pattern::<N, L>(),
630 ),
631 |mut v| {
632 if v.len() == 1 {
633 v.pop().unwrap()
634 } else {
635 Branch::Error(Error::new(
637 ErrorKind::NotImplemented,
638 String::from("intersect or except in a pattern has not been implemented"),
639 ))
640 }
641 },
642 ))
643}
644
645fn path_expr_pattern<'a, N: Node + 'a, L>() -> Box<
647 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
648 + 'a,
649>
650where
651 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
652{
653 Box::new(alt4(
654 rooted_path_pattern::<N, L>(),
655 absolutedescendant_expr_pattern(),
656 absolutepath_expr_pattern(),
657 relativepath_expr_pattern::<N, L>(),
658 ))
659}
660
661fn rooted_path_pattern<'a, N: Node + 'a, L>() -> Box<
663 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
664 + 'a,
665>
666where
667 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
668{
669 Box::new(map(
670 tuple3(
671 alt2(
672 variable_reference_pattern::<N, L>(),
673 function_call_pattern(),
674 ),
675 predicate_list::<N, L>(),
676 alt2(
677 absolutedescendant_expr_pattern::<N, L>(),
678 absolutepath_expr_pattern(),
679 ),
680 ),
681 |(_a, _b, _c)| {
682 Branch::Error(Error::new(
683 ErrorKind::NotImplemented,
684 String::from("rooted path in a pattern has not been implemented"),
685 ))
686 },
687 ))
688}
689
690fn variable_reference_pattern<'a, N: Node + 'a, L>() -> Box<
692 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
693 + 'a,
694>
695where
696 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
697{
698 Box::new(map(variable_reference::<N, L>(), |_| {
699 Branch::Error(Error::new(
700 ErrorKind::NotImplemented,
701 "variable reference not yet supported",
702 ))
703 }))
704}
705
706fn absolutedescendant_expr_pattern<'a, N: Node + 'a, L>() -> Box<
708 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
709 + 'a,
710>
711where
712 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
713{
714 Box::new(map(
715 pair(tag("//"), relativepath_expr_pattern::<N, L>()),
716 |(_, _r)| {
717 Branch::Error(Error::new(
718 ErrorKind::NotImplemented,
719 String::from("absolute descendant path in a pattern has not been implemented"),
720 ))
721 },
722 ))
723}
724
725fn absolutepath_expr_pattern<'a, N: Node + 'a, L>() -> Box<
727 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
728 + 'a,
729>
730where
731 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
732{
733 Box::new(map(
734 pair(
735 map(tag("/"), |_| "/"),
736 opt(relativepath_expr_pattern::<N, L>()),
737 ),
738 |(d, r)| match (d, r.clone()) {
739 ("/", None) => {
740 Branch::SingleStep(Step::new(
742 Axis::SelfDocument,
743 Axis::SelfDocument,
744 NodeTest::Kind(KindTest::Document),
745 ))
746 }
747 ("/", Some(Branch::SingleStep(s))) => Branch::RelPath(vec![
748 Branch::SingleStep(s),
749 Branch::SingleStep(Step::new(
750 Axis::SelfDocument,
751 Axis::SelfDocument,
752 NodeTest::Kind(KindTest::Document),
753 )),
754 ]),
755 ("/", Some(Branch::RelPath(mut a))) => {
756 a.push(Branch::SingleStep(Step::new(
765 Axis::SelfDocument,
766 Axis::SelfDocument,
767 NodeTest::Kind(KindTest::Document),
768 )));
769 Branch::RelPath(a)
770 }
771 ("/", Some(Branch::Union(u))) => Branch::RelPath(vec![
772 Branch::Union(u),
773 Branch::SingleStep(Step::new(
774 Axis::SelfDocument,
775 Axis::SelfDocument,
776 NodeTest::Kind(KindTest::Document),
777 )),
778 ]),
779 _ => Branch::Error(Error::new(
780 ErrorKind::Unknown,
781 String::from("unable to parse pattern"),
782 )),
783 },
784 ))
785}
786
787fn relativepath_expr_pattern<'a, N: Node + 'a, L>() -> Box<
789 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
790 + 'a,
791>
792where
793 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
794{
795 Box::new(map(
796 pair(
797 step_expr_pattern::<N, L>(),
798 many0(tuple2(
799 alt2(
800 map(tuple3(xpwhitespace(), tag("//"), xpwhitespace()), |_| "//"),
801 map(tuple3(xpwhitespace(), tag("/"), xpwhitespace()), |_| "/"),
802 ),
803 step_expr_pattern::<N, L>(),
804 )),
805 ),
806 |(a, b)| {
807 if b.is_empty() {
808 a
810 } else {
811 let mut result = vec![a];
813 for (_c, d) in b {
814 result.insert(0, d);
815 }
816 Branch::RelPath(result)
817 }
818 },
819 ))
820}
821
822fn step_expr_pattern<'a, N: Node + 'a, L>() -> Box<
824 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
825 + 'a,
826>
827where
828 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
829{
830 Box::new(alt2(
831 postfix_expr_pattern::<N, L>(),
832 axis_step_pattern::<N, L>(),
833 ))
834}
835
836fn postfix_expr_pattern<'a, N: Node + 'a, L>() -> Box<
839 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
840 + 'a,
841>
842where
843 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
844{
845 Box::new(map(
846 tuple2(paren_expr_pattern(), predicate_list::<N, L>()),
847 |(p, _)| p,
848 ))
849}
850
851fn paren_expr_pattern<'a, N: Node + 'a, L>() -> Box<
853 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
854 + 'a,
855>
856where
857 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
858{
859 Box::new(map(
860 tuple3(
861 tuple3(xpwhitespace(), tag("("), xpwhitespace()),
862 union_expr_wrapper(true),
863 tuple3(xpwhitespace(), tag(")"), xpwhitespace()),
864 ),
865 |(_, u, _)| {
866 if let Pattern::Selection(sel) = u {
867 sel
868 } else {
869 Branch::Error(Error::new(
870 ErrorKind::TypeError,
871 "expression must be a selection",
872 ))
873 }
874 },
875 ))
876}
877
878fn axis_step_pattern<'a, N: Node + 'a, L>() -> Box<
881 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
882 + 'a,
883>
884where
885 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
886{
887 Box::new(map(
888 tuple2(forward_step_pattern(), predicate_list::<N, L>()),
889 |(f, _p)| f, ))
891}
892
893fn forward_step_pattern<'a, N: Node + 'a, L>() -> Box<
896 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
897 + 'a,
898>
899where
900 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
901{
902 Box::new(map(
903 alt2(
904 tuple2(forward_axis_pattern(), nodetest()),
905 abbrev_forward_step(),
906 ),
907 |((a, c), nt)| Branch::SingleStep(Step::new(a, c, nt)),
908 ))
909}
910
911fn abbrev_forward_step<'a, N: Node + 'a, L>() -> Box<
913 dyn Fn(
914 ParseInput<'a, N>,
915 &mut StaticState<L>,
916 ) -> Result<(ParseInput<'a, N>, ((Axis, Axis), NodeTest)), ParseError>
917 + 'a,
918>
919where
920 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
921{
922 Box::new(map(tuple2(opt(tag("@")), nodetest()), |(a, nt)| {
923 a.map_or_else(
924 || {
925 ((Axis::SelfAxis, Axis::Parent), nt.clone())
927 },
928 |_| {
929 ((Axis::SelfAttribute, Axis::Parent), nt.clone())
931 },
932 )
933 }))
934}
935
936fn forward_axis_pattern<'a, N: Node + 'a, L>() -> Box<
939 dyn Fn(
940 ParseInput<'a, N>,
941 &mut StaticState<L>,
942 ) -> Result<(ParseInput<'a, N>, (Axis, Axis)), ParseError>
943 + 'a,
944>
945where
946 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
947{
948 Box::new(map(
949 tuple2(
950 alt6(
951 map(tag("child"), |_| (Axis::SelfAxis, Axis::Parent)),
952 map(tag("descendant"), |_| (Axis::SelfAxis, Axis::Ancestor)),
953 map(tag("attribute"), |_| (Axis::SelfAttribute, Axis::Parent)),
954 map(tag("self"), |_| (Axis::SelfAxis, Axis::SelfAxis)),
955 map(tag("descendant-or-self"), |_| {
956 (Axis::SelfAxis, Axis::Ancestor)
957 }),
958 map(tag("namespace"), |_| (Axis::SelfNamespace, Axis::Parent)),
959 ),
960 tag("::"),
961 ),
962 |(a, _)| a,
963 ))
964}
965
966fn function_call_pattern<'a, N: Node + 'a, L>() -> Box<
968 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
969 + 'a,
970>
971where
972 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
973{
974 Box::new(map(
975 tuple2(outer_function_name(), argument_list_pattern::<N, L>()),
976 |(_n, _a)| {
977 Branch::Error(Error::new(
979 ErrorKind::NotImplemented,
980 String::from("function call in a pattern has not been implemented"),
981 ))
982 },
983 ))
984}
985
986fn argument_list_pattern<'a, N: Node + 'a, L>() -> Box<
988 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
989 + 'a,
990>
991where
992 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
993{
994 Box::new(map(
995 tuple3(
996 map(tuple3(xpwhitespace(), tag("("), xpwhitespace()), |_| ()),
997 separated_list0(
998 map(tuple3(xpwhitespace(), tag(","), xpwhitespace()), |_| ()),
999 argument_pattern::<N, L>(),
1000 ),
1001 map(tuple3(xpwhitespace(), tag(")"), xpwhitespace()), |_| ()),
1002 ),
1003 |(_, _a, _)| {
1004 Branch::Error(Error::new(
1006 ErrorKind::NotImplemented,
1007 String::from("argument list in a pattern has not been implemented"),
1008 ))
1009 },
1010 ))
1011}
1012
1013fn argument_pattern<'a, N: Node + 'a, L>() -> Box<
1015 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
1016 + 'a,
1017>
1018where
1019 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
1020{
1021 Box::new(alt2(
1022 variable_reference_pattern::<N, L>(),
1023 literal_pattern::<N, L>(),
1024 ))
1025}
1026
1027fn literal_pattern<'a, N: Node + 'a, L>() -> Box<
1029 dyn Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, Path), ParseError>
1030 + 'a,
1031>
1032where
1033 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
1034{
1035 Box::new(map(literal::<N, L>(), |_| {
1036 Branch::Error(Error::new(ErrorKind::NotImplemented, "not yet implemented"))
1037 }))
1038}
1039
1040fn outer_function_name<'a, N: Node + 'a, L>() -> Box<
1042 dyn Fn(
1043 ParseInput<'a, N>,
1044 &mut StaticState<L>,
1045 ) -> Result<(ParseInput<'a, N>, NodeTest), ParseError>
1046 + 'a,
1047>
1048where
1049 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError> + 'a,
1050{
1051 Box::new(alt6(
1052 map(tag("doc"), |_| {
1053 NodeTest::Name(NameTest::Name(QName::from_local_name(
1055 NcName::try_from("doc").unwrap(),
1056 )))
1057 }),
1058 map(tag("id"), |_| {
1059 NodeTest::Name(NameTest::Name(QName::from_local_name(
1060 NcName::try_from("id").unwrap(),
1061 )))
1062 }),
1063 map(tag("element-with-id"), |_| {
1064 NodeTest::Name(NameTest::Name(QName::from_local_name(
1065 NcName::try_from("element-with-id").unwrap(),
1066 )))
1067 }),
1068 map(tag("key"), |_| {
1069 NodeTest::Name(NameTest::Name(QName::from_local_name(
1070 NcName::try_from("key").unwrap(),
1071 )))
1072 }),
1073 map(tag("root"), |_| {
1074 NodeTest::Name(NameTest::Name(QName::from_local_name(
1075 NcName::try_from("root").unwrap(),
1076 )))
1077 }),
1078 map(qualname_test(), |q| q),
1079 ))
1080}