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