1use crate::xml::xpath::ast::*;
38use crate::xml::xpath::lexer::Token;
39
40#[derive(Debug, Clone, PartialEq)]
42pub struct ParseError {
43 pub message: String,
44 pub pos: usize,
45}
46
47impl std::fmt::Display for ParseError {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 write!(
50 f,
51 "XPath parse error at position {}: {}",
52 self.pos, self.message
53 )
54 }
55}
56
57pub struct Parser {
62 tokens: Vec<Token>,
63 pos: usize,
64}
65
66impl Parser {
67 pub fn new(tokens: Vec<Token>) -> Self {
68 Self { tokens, pos: 0 }
69 }
70
71 pub fn parse(&mut self) -> Result<Expr, ParseError> {
73 let expr = self.parse_or_expr()?;
74 if !self.is_eof() {
75 return Err(self.error(format!("Unexpected token: {}", self.current())))?;
76 }
77 Ok(expr)
78 }
79
80 fn current(&self) -> Token {
83 if self.pos < self.tokens.len() {
84 self.tokens[self.pos].clone()
85 } else {
86 Token::Eof
87 }
88 }
89
90 fn peek(&self) -> Token {
91 if self.pos + 1 < self.tokens.len() {
92 self.tokens[self.pos + 1].clone()
93 } else {
94 Token::Eof
95 }
96 }
97
98 fn advance(&mut self) {
99 if self.pos < self.tokens.len() {
100 self.pos += 1;
101 }
102 }
103
104 fn is_eof(&self) -> bool {
105 matches!(self.current(), Token::Eof)
106 }
107
108 fn error(&self, msg: String) -> ParseError {
109 ParseError {
110 message: msg,
111 pos: self.pos,
112 }
113 }
114
115 fn at(&self, token: &Token) -> bool {
117 std::mem::discriminant(&self.current()) == std::mem::discriminant(token)
118 }
119
120 fn expect(&mut self, expected: &Token) -> Result<(), ParseError> {
122 if self.at(expected) {
123 self.advance();
124 Ok(())
125 } else {
126 Err(self.error(format!("Expected {}, got {}", expected, self.current())))
127 }
128 }
129
130 fn parse_or_expr(&mut self) -> Result<Expr, ParseError> {
134 let mut left = self.parse_and_expr()?;
135 while matches!(self.current(), Token::Or) {
136 self.advance();
137 let right = self.parse_and_expr()?;
138 left = Expr::BinaryOp {
139 op: BinaryOp::Or,
140 left: Box::new(left),
141 right: Box::new(right),
142 };
143 }
144 Ok(left)
145 }
146
147 fn parse_and_expr(&mut self) -> Result<Expr, ParseError> {
149 let mut left = self.parse_equality_expr()?;
150 while matches!(self.current(), Token::And) {
151 self.advance();
152 let right = self.parse_equality_expr()?;
153 left = Expr::BinaryOp {
154 op: BinaryOp::And,
155 left: Box::new(left),
156 right: Box::new(right),
157 };
158 }
159 Ok(left)
160 }
161
162 fn parse_equality_expr(&mut self) -> Result<Expr, ParseError> {
164 let mut left = self.parse_relational_expr()?;
165 loop {
166 let op = match self.current() {
167 Token::Eq => BinaryOp::Eq,
168 Token::Ne => BinaryOp::Ne,
169 _ => break,
170 };
171 self.advance();
172 let right = self.parse_relational_expr()?;
173 left = Expr::BinaryOp {
174 op,
175 left: Box::new(left),
176 right: Box::new(right),
177 };
178 }
179 Ok(left)
180 }
181
182 fn parse_relational_expr(&mut self) -> Result<Expr, ParseError> {
184 let mut left = self.parse_additive_expr()?;
185 loop {
186 let op = match self.current() {
187 Token::Lt => BinaryOp::Lt,
188 Token::Gt => BinaryOp::Gt,
189 Token::Le => BinaryOp::Le,
190 Token::Ge => BinaryOp::Ge,
191 _ => break,
192 };
193 self.advance();
194 let right = self.parse_additive_expr()?;
195 left = Expr::BinaryOp {
196 op,
197 left: Box::new(left),
198 right: Box::new(right),
199 };
200 }
201 Ok(left)
202 }
203
204 fn parse_additive_expr(&mut self) -> Result<Expr, ParseError> {
206 let mut left = self.parse_multiplicative_expr()?;
207 loop {
208 let op = match self.current() {
209 Token::Plus => BinaryOp::Add,
210 Token::Minus => BinaryOp::Sub,
211 _ => break,
212 };
213 self.advance();
214 let right = self.parse_multiplicative_expr()?;
215 left = Expr::BinaryOp {
216 op,
217 left: Box::new(left),
218 right: Box::new(right),
219 };
220 }
221 Ok(left)
222 }
223
224 fn parse_multiplicative_expr(&mut self) -> Result<Expr, ParseError> {
226 let mut left = self.parse_unary_expr()?;
227 loop {
228 let op = match self.current() {
229 Token::Star => BinaryOp::Mul,
231 Token::Div => BinaryOp::Div,
232 Token::Mod => BinaryOp::Mod,
233 _ => break,
234 };
235 self.advance();
236 let right = self.parse_unary_expr()?;
237 left = Expr::BinaryOp {
238 op,
239 left: Box::new(left),
240 right: Box::new(right),
241 };
242 }
243 Ok(left)
244 }
245
246 fn parse_unary_expr(&mut self) -> Result<Expr, ParseError> {
248 let mut minus_count = 0;
249 while matches!(self.current(), Token::Minus) {
250 self.advance();
251 minus_count += 1;
252 }
253 let mut expr = self.parse_union_expr()?;
254 if minus_count % 2 == 1 {
255 expr = Expr::UnaryMinus(Box::new(expr));
256 }
257 Ok(expr)
258 }
259
260 fn parse_union_expr(&mut self) -> Result<Expr, ParseError> {
262 let mut left = self.parse_path_expr()?;
263 while matches!(self.current(), Token::Pipe) {
264 self.advance();
265 let right = self.parse_path_expr()?;
266 left = Expr::Union(Box::new(left), Box::new(right));
267 }
268 Ok(left)
269 }
270
271 fn parse_path_expr(&mut self) -> Result<Expr, ParseError> {
273 if self.is_location_path_start() {
275 return self.parse_location_path();
276 }
277
278 let mut expr = self.parse_filter_expr()?;
280
281 loop {
283 match self.current() {
284 Token::Slash => {
285 self.advance();
286 let step = self.parse_relative_location_path()?;
287 expr = Expr::RelativePath(Box::new(expr), Box::new(step));
288 }
289 Token::DoubleSlash => {
290 self.advance();
291 let step = self.parse_relative_location_path()?;
292 let descendant = Expr::Step(Step {
294 axis: Axis::DescendantOrSelf,
295 node_test: NodeTest::Node,
296 predicates: vec![],
297 });
298 let path = Expr::RelativePath(Box::new(descendant), Box::new(step));
299 expr = Expr::RelativePath(Box::new(expr), Box::new(path));
300 }
301 _ => break,
302 }
303 }
304
305 Ok(expr)
306 }
307
308 fn is_location_path_start(&self) -> bool {
310 match self.current() {
311 Token::Slash | Token::DoubleSlash => true,
312 Token::Dot | Token::DotDot => true,
313 Token::At => true,
314 Token::Star => true,
315 Token::Name(_) => {
317 let next = self.peek();
319 !matches!(next, Token::LParen)
320 }
321 Token::Child
323 | Token::Descendant
324 | Token::DescendantOrSelf
325 | Token::Ancestor
326 | Token::AncestorOrSelf
327 | Token::Attribute
328 | Token::Following
329 | Token::FollowingSibling
330 | Token::Namespace
331 | Token::Parent
332 | Token::Preceding
333 | Token::PrecedingSibling
334 | Token::Self_ => true,
335 _ => false,
336 }
337 }
338
339 fn parse_location_path(&mut self) -> Result<Expr, ParseError> {
341 match self.current() {
342 Token::Slash => {
343 self.advance();
344 if self.is_location_path_start() {
345 let path = self.parse_relative_location_path()?;
346 Ok(Expr::AbsolutePath(Box::new(path)))
347 } else {
348 Ok(Expr::Step(Step {
350 axis: Axis::Self_,
351 node_test: NodeTest::Node,
352 predicates: vec![],
353 }))
354 }
355 }
356 Token::DoubleSlash => {
357 self.advance();
358 let path = self.parse_relative_location_path()?;
359 let descendant = Expr::Step(Step {
360 axis: Axis::DescendantOrSelf,
361 node_test: NodeTest::Node,
362 predicates: vec![],
363 });
364 Ok(Expr::AbsolutePath(Box::new(Expr::RelativePath(
365 Box::new(descendant),
366 Box::new(path),
367 ))))
368 }
369 _ => self.parse_relative_location_path(),
370 }
371 }
372
373 fn parse_relative_location_path(&mut self) -> Result<Expr, ParseError> {
375 let mut expr = self.parse_step()?;
376 loop {
377 match self.current() {
378 Token::Slash => {
379 self.advance();
380 let step = self.parse_step()?;
381 expr = Expr::RelativePath(Box::new(expr), Box::new(step));
382 }
383 Token::DoubleSlash => {
384 self.advance();
385 let step = self.parse_step()?;
386 let descendant = Expr::Step(Step {
387 axis: Axis::DescendantOrSelf,
388 node_test: NodeTest::Node,
389 predicates: vec![],
390 });
391 let path = Expr::RelativePath(Box::new(descendant), Box::new(step));
392 expr = Expr::RelativePath(Box::new(expr), Box::new(path));
393 }
394 _ => break,
395 }
396 }
397 Ok(expr)
398 }
399
400 fn parse_step(&mut self) -> Result<Expr, ParseError> {
403 match self.current() {
405 Token::Dot => {
406 self.advance();
407 return Ok(Expr::Step(Step {
408 axis: Axis::Self_,
409 node_test: NodeTest::Node,
410 predicates: vec![],
411 }));
412 }
413 Token::DotDot => {
414 self.advance();
415 return Ok(Expr::Step(Step {
416 axis: Axis::Parent,
417 node_test: NodeTest::Node,
418 predicates: vec![],
419 }));
420 }
421 _ => {}
422 }
423
424 let axis = self.parse_axis_specifier();
426
427 let node_test = self.parse_node_test()?;
429
430 let mut predicates = Vec::new();
432 while matches!(self.current(), Token::LBracket) {
433 self.advance(); let pred = self.parse_or_expr()?;
435 self.expect(&Token::RBracket)?;
436 predicates.push(pred);
437 }
438
439 Ok(Expr::Step(Step {
440 axis,
441 node_test,
442 predicates,
443 }))
444 }
445
446 fn parse_axis_specifier(&mut self) -> Axis {
448 if matches!(self.current(), Token::At) {
450 self.advance();
451 return Axis::Attribute;
452 }
453
454 let is_axis = match self.current() {
458 Token::Ancestor
459 | Token::AncestorOrSelf
460 | Token::Attribute
461 | Token::Child
462 | Token::Descendant
463 | Token::DescendantOrSelf
464 | Token::Following
465 | Token::FollowingSibling
466 | Token::Namespace
467 | Token::Parent
468 | Token::Preceding
469 | Token::PrecedingSibling
470 | Token::Self_ => matches!(self.peek(), Token::DoubleColon),
471 _ => false,
472 };
473
474 if is_axis {
475 let axis = match self.current() {
476 Token::Ancestor => Axis::Ancestor,
477 Token::AncestorOrSelf => Axis::AncestorOrSelf,
478 Token::Attribute => Axis::Attribute,
479 Token::Child => Axis::Child,
480 Token::Descendant => Axis::Descendant,
481 Token::DescendantOrSelf => Axis::DescendantOrSelf,
482 Token::Following => Axis::Following,
483 Token::FollowingSibling => Axis::FollowingSibling,
484 Token::Namespace => Axis::Namespace,
485 Token::Parent => Axis::Parent,
486 Token::Preceding => Axis::Preceding,
487 Token::PrecedingSibling => Axis::PrecedingSibling,
488 Token::Self_ => Axis::Self_,
489 _ => unreachable!(),
490 };
491 self.advance(); self.advance(); return axis;
494 }
495
496 Axis::Child
498 }
499
500 fn token_to_name(&self, token: &Token) -> Option<String> {
502 match token {
503 Token::Name(ref s) => Some(s.clone()),
504 Token::Div => Some("div".to_string()),
505 Token::Mod => Some("mod".to_string()),
506 Token::And => Some("and".to_string()),
507 Token::Or => Some("or".to_string()),
508 Token::Ancestor => Some("ancestor".to_string()),
509 Token::AncestorOrSelf => Some("ancestor-or-self".to_string()),
510 Token::Attribute => Some("attribute".to_string()),
511 Token::Child => Some("child".to_string()),
512 Token::Descendant => Some("descendant".to_string()),
513 Token::DescendantOrSelf => Some("descendant-or-self".to_string()),
514 Token::Following => Some("following".to_string()),
515 Token::FollowingSibling => Some("following-sibling".to_string()),
516 Token::Namespace => Some("namespace".to_string()),
517 Token::Parent => Some("parent".to_string()),
518 Token::Preceding => Some("preceding".to_string()),
519 Token::PrecedingSibling => Some("preceding-sibling".to_string()),
520 Token::Self_ => Some("self".to_string()),
521 _ => None,
522 }
523 }
524
525 fn parse_node_test(&mut self) -> Result<NodeTest, ParseError> {
528 let name_opt = self.token_to_name(&self.current());
530
531 match self.current() {
532 Token::Star => {
533 self.advance();
534 Ok(NodeTest::NameTest(NameTest::Any))
535 }
536 _ if name_opt.is_some() => {
537 let name = name_opt.unwrap();
538
539 if matches!(self.peek(), Token::LParen) {
541 match name.as_str() {
542 "node" => {
543 self.advance();
544 self.advance();
545 self.advance(); Ok(NodeTest::Node)
547 }
548 "text" => {
549 self.advance();
550 self.advance();
551 self.advance();
552 Ok(NodeTest::Text)
553 }
554 "comment" => {
555 self.advance();
556 self.advance();
557 self.advance();
558 Ok(NodeTest::Comment)
559 }
560 "processing-instruction" => {
561 self.advance(); self.advance(); let target = if matches!(self.current(), Token::StringLiteral(_)) {
565 if let Token::StringLiteral(s) = self.current() {
566 self.advance();
567 Some(s)
568 } else {
569 None
570 }
571 } else {
572 None
573 };
574 self.expect(&Token::RParen)?;
575 Ok(NodeTest::ProcessingInstruction(target))
576 }
577 _ => {
578 self.advance(); self.advance(); let mut args = Vec::new();
582 if !matches!(self.current(), Token::RParen) {
583 args.push(self.parse_or_expr()?);
584 while matches!(self.current(), Token::Comma) {
585 self.advance();
586 args.push(self.parse_or_expr()?);
587 }
588 }
589 self.expect(&Token::RParen)?;
590 return Ok(NodeTest::NameTest(NameTest::LocalName(name)));
592 }
593 }
594 } else {
595 self.advance();
596 if let Some(rest) = name.strip_suffix(":*") {
598 Ok(NodeTest::NsWildcard(rest.to_string()))
599 } else if let Some((prefix, local)) = name.split_once(':') {
600 Ok(NodeTest::NameTest(NameTest::QName {
601 prefix: prefix.to_string(),
602 local: local.to_string(),
603 }))
604 } else {
605 Ok(NodeTest::NameTest(NameTest::LocalName(name)))
606 }
607 }
608 }
609 _ => Err(self.error(format!("Expected node test, got {}", self.current()))),
610 }
611 }
612
613 fn parse_filter_expr(&mut self) -> Result<Expr, ParseError> {
615 let primary = self.parse_primary_expr()?;
616
617 let mut predicates = Vec::new();
619 while matches!(self.current(), Token::LBracket) {
620 self.advance(); let pred = self.parse_or_expr()?;
622 self.expect(&Token::RBracket)?;
623 predicates.push(pred);
624 }
625
626 if predicates.is_empty() {
627 Ok(primary)
628 } else {
629 Ok(Expr::Filter(Box::new(primary), predicates))
630 }
631 }
632
633 fn parse_primary_expr(&mut self) -> Result<Expr, ParseError> {
635 match self.current() {
636 Token::Dollar => {
637 self.advance();
638 if let Token::Name(name) = self.current() {
639 let name = name.clone();
640 self.advance();
641 Ok(Expr::Variable(name))
642 } else {
643 Err(self.error("Expected variable name after $".to_string()))
644 }
645 }
646 Token::LParen => {
647 self.advance();
648 let expr = self.parse_or_expr()?;
649 self.expect(&Token::RParen)?;
650 Ok(expr)
651 }
652 Token::StringLiteral(ref s) => {
653 let s = s.clone();
654 self.advance();
655 Ok(Expr::StringLiteral(s))
656 }
657 Token::NumberLiteral(n) => {
658 self.advance();
659 Ok(Expr::NumberLiteral(n))
660 }
661 Token::Name(ref name) => {
662 let name = name.clone();
663 if matches!(self.peek(), Token::LParen) {
664 self.advance(); self.advance(); let mut args = Vec::new();
668 if !matches!(self.current(), Token::RParen) {
669 args.push(self.parse_or_expr()?);
670 while matches!(self.current(), Token::Comma) {
671 self.advance();
672 args.push(self.parse_or_expr()?);
673 }
674 }
675 self.expect(&Token::RParen)?;
676 Ok(Expr::FunctionCall { name, args })
677 } else {
678 Err(self.error(format!("Unexpected name '{}' in primary expression", name)))
681 }
682 }
683 _ => Err(self.error(format!(
684 "Expected primary expression, got {}",
685 self.current()
686 ))),
687 }
688 }
689}
690
691pub fn parse_xpath(input: &str) -> Result<Expr, ParseError> {
697 let mut lexer = crate::xml::xpath::lexer::Lexer::new(input);
698 let mut tokens = Vec::new();
699 loop {
700 let tok = lexer.next_token();
701 let is_eof = matches!(tok, Token::Eof);
702 tokens.push(tok);
703 if is_eof {
704 break;
705 }
706 }
707 let mut parser = Parser::new(tokens);
708 parser.parse()
709}
710
711#[cfg(test)]
716mod tests {
717 use super::*;
718
719 #[test]
720 fn test_parse_simple_name() {
721 let expr = parse_xpath("para").unwrap();
722 assert!(matches!(expr, Expr::Step(_)));
723 }
724
725 #[test]
726 fn test_parse_absolute_path() {
727 let expr = parse_xpath("/child::para").unwrap();
728 assert!(matches!(expr, Expr::AbsolutePath(_)));
729 }
730
731 #[test]
732 fn test_parse_attribute() {
733 let expr = parse_xpath("@attr").unwrap();
734 assert!(matches!(expr, Expr::Step(_)));
735 }
736
737 #[test]
738 fn test_parse_predicate() {
739 let expr = parse_xpath("para[1]").unwrap();
740 assert!(matches!(expr, Expr::Step(_)));
741 }
742
743 #[test]
744 fn test_parse_function_call() {
745 let expr = parse_xpath("position()").unwrap();
746 assert!(matches!(expr, Expr::FunctionCall { .. }));
747 }
748
749 #[test]
750 fn test_parse_binary_op() {
751 let expr = parse_xpath("a = b").unwrap();
752 assert!(matches!(
753 expr,
754 Expr::BinaryOp {
755 op: BinaryOp::Eq,
756 ..
757 }
758 ));
759 }
760
761 #[test]
762 fn test_parse_union() {
763 let expr = parse_xpath("a | b").unwrap();
764 assert!(matches!(expr, Expr::Union(_, _)));
765 }
766
767 #[test]
768 fn test_parse_variable() {
769 let expr = parse_xpath("$var").unwrap();
770 assert!(matches!(expr, Expr::Variable(_)));
771 }
772
773 #[test]
774 fn test_parse_string_literal() {
775 let expr = parse_xpath("'hello'").unwrap();
776 assert_eq!(expr, Expr::StringLiteral("hello".to_string()));
777 }
778
779 #[test]
780 fn test_parse_number() {
781 let expr = parse_xpath("42").unwrap();
782 assert_eq!(expr, Expr::NumberLiteral(42.0));
783 }
784
785 #[test]
786 fn test_parse_nested_expression() {
787 let expr = parse_xpath("(1 + 2) * 3").unwrap();
788 assert!(matches!(
789 expr,
790 Expr::BinaryOp {
791 op: BinaryOp::Mul,
792 ..
793 }
794 ));
795 }
796
797 #[test]
798 fn test_parse_chained_path() {
799 let expr = parse_xpath("a/b/c").unwrap();
800 assert!(matches!(expr, Expr::RelativePath(_, _)));
801 }
802
803 #[test]
804 fn test_parse_double_slash() {
805 let expr = parse_xpath("//para").unwrap();
806 assert!(matches!(expr, Expr::AbsolutePath(_)));
807 }
808
809 #[test]
810 fn test_parse_dot() {
811 let expr = parse_xpath(".").unwrap();
812 assert!(matches!(expr, Expr::Step(_)));
813 }
814
815 #[test]
816 fn test_parse_dot_dot() {
817 let expr = parse_xpath("..").unwrap();
818 assert!(matches!(expr, Expr::Step(_)));
819 }
820
821 #[test]
822 fn test_parse_unary_minus() {
823 let expr = parse_xpath("-5").unwrap();
824 assert!(matches!(expr, Expr::UnaryMinus(_)));
825 }
826
827 #[test]
828 fn test_parse_double_unary_minus() {
829 let expr = parse_xpath("--5").unwrap();
830 assert!(!matches!(expr, Expr::UnaryMinus(_)));
832 }
833
834 #[test]
835 fn test_parse_complex_expression() {
836 let expr = parse_xpath("/html/body//div[@class='main']/p[1]").unwrap();
837 assert!(matches!(expr, Expr::AbsolutePath(_)));
838 }
839
840 #[test]
841 fn test_parse_error() {
842 let result = parse_xpath("(");
843 assert!(result.is_err());
844 }
845
846 #[test]
847 fn test_parse_empty() {
848 let result = parse_xpath("");
849 assert!(result.is_err());
850 }
851
852 #[test]
853 fn test_parse_and_or() {
854 let expr = parse_xpath("a = 1 and b = 2 or c = 3").unwrap();
855 assert!(matches!(expr, Expr::BinaryOp { .. }));
856 }
857
858 #[test]
859 fn test_parse_comparison_chain() {
860 let expr = parse_xpath("a < b <= c > d >= e").unwrap();
861 assert!(matches!(
863 expr,
864 Expr::BinaryOp {
865 op: BinaryOp::Ge,
866 ..
867 }
868 ));
869 }
870
871 #[test]
872 fn test_parse_arithmetic() {
873 let expr = parse_xpath("1 + 2 * 3").unwrap();
874 match expr {
876 Expr::BinaryOp {
877 op: BinaryOp::Add,
878 left,
879 right,
880 } => {
881 assert!(matches!(*left, Expr::NumberLiteral(1.0)));
882 assert!(matches!(
883 *right,
884 Expr::BinaryOp {
885 op: BinaryOp::Mul,
886 ..
887 }
888 ));
889 }
890 _ => panic!("Expected Add expression"),
891 }
892 }
893
894 #[test]
895 fn test_parse_filter_path() {
896 let expr = parse_xpath("//div/span").unwrap();
897 assert!(matches!(expr, Expr::AbsolutePath(_)));
898 }
899
900 #[test]
901 fn test_parse_node_test_functions() {
902 let expr = parse_xpath("child::node()").unwrap();
903 assert!(matches!(expr, Expr::Step(_)));
904 if let Expr::Step(step) = expr {
905 assert_eq!(step.node_test, NodeTest::Node);
906 }
907 }
908}