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 starts = lexer.token_starts();
766 let mut parser = Parser::new(tokens);
767 parser.parse().map_err(|e| {
768 let byte_off = starts
774 .get(e.pos)
775 .copied()
776 .unwrap_or(input.len())
777 .min(input.len());
778 ParseError {
779 message: e.message,
780 pos: byte_off,
781 }
782 })
783}
784
785#[cfg(test)]
790mod tests {
791 use super::*;
792
793 #[test]
794 fn test_parse_simple_name() {
795 let expr = parse_xpath("para").unwrap();
796 assert!(matches!(expr, Expr::Step(_)));
797 }
798
799 #[test]
800 fn test_parse_absolute_path() {
801 let expr = parse_xpath("/child::para").unwrap();
802 assert!(matches!(expr, Expr::AbsolutePath(_)));
803 }
804
805 #[test]
806 fn test_parse_attribute() {
807 let expr = parse_xpath("@attr").unwrap();
808 assert!(matches!(expr, Expr::Step(_)));
809 }
810
811 #[test]
812 fn test_parse_predicate() {
813 let expr = parse_xpath("para[1]").unwrap();
814 assert!(matches!(expr, Expr::Step(_)));
815 }
816
817 #[test]
818 fn test_parse_function_call() {
819 let expr = parse_xpath("position()").unwrap();
820 assert!(matches!(expr, Expr::FunctionCall { .. }));
821 }
822
823 #[test]
824 fn test_parse_binary_op() {
825 let expr = parse_xpath("a = b").unwrap();
826 assert!(matches!(
827 expr,
828 Expr::BinaryOp {
829 op: BinaryOp::Eq,
830 ..
831 }
832 ));
833 }
834
835 #[test]
836 fn test_parse_union() {
837 let expr = parse_xpath("a | b").unwrap();
838 assert!(matches!(expr, Expr::Union(_, _)));
839 }
840
841 #[test]
842 fn test_parse_variable() {
843 let expr = parse_xpath("$var").unwrap();
844 assert!(matches!(expr, Expr::Variable(_)));
845 }
846
847 #[test]
848 fn test_parse_string_literal() {
849 let expr = parse_xpath("'hello'").unwrap();
850 assert_eq!(expr, Expr::StringLiteral("hello".to_string()));
851 }
852
853 #[test]
854 fn test_parse_number() {
855 let expr = parse_xpath("42").unwrap();
856 assert_eq!(expr, Expr::NumberLiteral(42.0));
857 }
858
859 #[test]
860 fn test_parse_nested_expression() {
861 let expr = parse_xpath("(1 + 2) * 3").unwrap();
862 assert!(matches!(
863 expr,
864 Expr::BinaryOp {
865 op: BinaryOp::Mul,
866 ..
867 }
868 ));
869 }
870
871 #[test]
872 fn test_parse_chained_path() {
873 let expr = parse_xpath("a/b/c").unwrap();
874 assert!(matches!(expr, Expr::RelativePath(_, _)));
875 }
876
877 #[test]
878 fn test_parse_double_slash() {
879 let expr = parse_xpath("//para").unwrap();
880 assert!(matches!(expr, Expr::AbsolutePath(_)));
881 }
882
883 #[test]
884 fn test_parse_dot() {
885 let expr = parse_xpath(".").unwrap();
886 assert!(matches!(expr, Expr::Step(_)));
887 }
888
889 #[test]
890 fn test_parse_dot_dot() {
891 let expr = parse_xpath("..").unwrap();
892 assert!(matches!(expr, Expr::Step(_)));
893 }
894
895 #[test]
896 fn test_parse_unary_minus() {
897 let expr = parse_xpath("-5").unwrap();
898 assert!(matches!(expr, Expr::UnaryMinus(_)));
899 }
900
901 #[test]
902 fn test_parse_double_unary_minus() {
903 let expr = parse_xpath("--5").unwrap();
904 assert!(!matches!(expr, Expr::UnaryMinus(_)));
906 }
907
908 #[test]
909 fn test_parse_complex_expression() {
910 let expr = parse_xpath("/html/body//div[@class='main']/p[1]").unwrap();
911 assert!(matches!(expr, Expr::AbsolutePath(_)));
912 }
913
914 #[test]
915 fn test_parse_error() {
916 let result = parse_xpath("(");
917 assert!(result.is_err());
918 }
919
920 #[test]
921 fn test_parse_empty() {
922 let result = parse_xpath("");
923 assert!(result.is_err());
924 }
925
926 #[test]
927 fn test_parse_and_or() {
928 let expr = parse_xpath("a = 1 and b = 2 or c = 3").unwrap();
929 assert!(matches!(expr, Expr::BinaryOp { .. }));
930 }
931
932 #[test]
933 fn test_parse_comparison_chain() {
934 let expr = parse_xpath("a < b <= c > d >= e").unwrap();
935 assert!(matches!(
937 expr,
938 Expr::BinaryOp {
939 op: BinaryOp::Ge,
940 ..
941 }
942 ));
943 }
944
945 #[test]
946 fn test_parse_arithmetic() {
947 let expr = parse_xpath("1 + 2 * 3").unwrap();
948 match expr {
950 Expr::BinaryOp {
951 op: BinaryOp::Add,
952 left,
953 right,
954 } => {
955 assert!(matches!(*left, Expr::NumberLiteral(1.0)));
956 assert!(matches!(
957 *right,
958 Expr::BinaryOp {
959 op: BinaryOp::Mul,
960 ..
961 }
962 ));
963 }
964 _ => panic!("Expected Add expression"),
965 }
966 }
967
968 #[test]
969 fn test_parse_filter_path() {
970 let expr = parse_xpath("//div/span").unwrap();
971 assert!(matches!(expr, Expr::AbsolutePath(_)));
972 }
973
974 #[test]
975 fn test_parse_node_test_functions() {
976 let expr = parse_xpath("child::node()").unwrap();
977 assert!(matches!(expr, Expr::Step(_)));
978 if let Expr::Step(step) = expr {
979 assert_eq!(step.node_test, NodeTest::Node);
980 }
981 }
982}