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