1use std::char;
13use std::iter::Peekable;
14
15use pest::error::{Error, ErrorVariant};
16use pest::iterators::{Pair, Pairs};
17use pest::pratt_parser::{Assoc, Op, PrattParser};
18use pest::{Parser, Position, Span};
19
20use crate::ast::{Expr, Rule as AstRule, RuleType};
21use crate::validator;
22
23#[allow(missing_docs, unused_qualifications)]
28mod grammar {
29 #[cfg(not(feature = "not-bootstrap-in-src"))]
30 include!("grammar.rs");
31
32 #[cfg(feature = "not-bootstrap-in-src")]
33 include!(concat!(env!("OUT_DIR"), "/__pest_grammar.rs"));
34}
35
36pub use self::grammar::*;
38
39#[allow(clippy::perf)]
41pub fn parse(rule: Rule, data: &str) -> Result<Pairs<'_, Rule>, Error<Rule>> {
42 PestParser::parse(rule, data)
43}
44
45#[derive(Clone, Debug, Eq, PartialEq)]
47pub struct ParserRule<'i> {
48 pub name: String,
50 pub span: Span<'i>,
52 pub ty: RuleType,
54 pub node: ParserNode<'i>,
56}
57
58#[derive(Clone, Debug, Eq, PartialEq)]
60pub struct ParserNode<'i> {
61 pub expr: ParserExpr<'i>,
63 pub span: Span<'i>,
65}
66
67impl<'i> ParserNode<'i> {
68 pub fn filter_map_top_down<F, T>(self, mut f: F) -> Vec<T>
70 where
71 F: FnMut(ParserNode<'i>) -> Option<T>,
72 {
73 pub fn filter_internal<'i, F, T>(node: ParserNode<'i>, f: &mut F, result: &mut Vec<T>)
74 where
75 F: FnMut(ParserNode<'i>) -> Option<T>,
76 {
77 if let Some(value) = f(node.clone()) {
78 result.push(value);
79 }
80
81 match node.expr {
82 ParserExpr::PosPred(node) => {
83 filter_internal(*node, f, result);
84 }
85 ParserExpr::NegPred(node) => {
86 filter_internal(*node, f, result);
87 }
88 ParserExpr::Seq(lhs, rhs) => {
89 filter_internal(*lhs, f, result);
90 filter_internal(*rhs, f, result);
91 }
92 ParserExpr::Choice(lhs, rhs) => {
93 filter_internal(*lhs, f, result);
94 filter_internal(*rhs, f, result);
95 }
96 ParserExpr::Rep(node) => {
97 filter_internal(*node, f, result);
98 }
99 ParserExpr::RepOnce(node) => {
100 filter_internal(*node, f, result);
101 }
102 ParserExpr::RepExact(node, _) => {
103 filter_internal(*node, f, result);
104 }
105 ParserExpr::RepMin(node, _) => {
106 filter_internal(*node, f, result);
107 }
108 ParserExpr::RepMax(node, _) => {
109 filter_internal(*node, f, result);
110 }
111 ParserExpr::RepMinMax(node, ..) => {
112 filter_internal(*node, f, result);
113 }
114 ParserExpr::Opt(node) => {
115 filter_internal(*node, f, result);
116 }
117 ParserExpr::Push(node) => {
118 filter_internal(*node, f, result);
119 }
120 _ => (),
121 }
122 }
123
124 let mut result = vec![];
125
126 filter_internal(self, &mut f, &mut result);
127
128 result
129 }
130}
131
132#[derive(Clone, Debug, Eq, PartialEq)]
134pub enum ParserExpr<'i> {
135 Str(String),
137 Insens(String),
139 Range(String, String),
141 Ident(String),
143 PeekSlice(i32, Option<i32>),
145 PosPred(Box<ParserNode<'i>>),
147 NegPred(Box<ParserNode<'i>>),
149 Seq(Box<ParserNode<'i>>, Box<ParserNode<'i>>),
151 Choice(Box<ParserNode<'i>>, Box<ParserNode<'i>>),
153 Opt(Box<ParserNode<'i>>),
155 Rep(Box<ParserNode<'i>>),
157 RepOnce(Box<ParserNode<'i>>),
159 RepExact(Box<ParserNode<'i>>, u32),
161 RepMin(Box<ParserNode<'i>>, u32),
163 RepMax(Box<ParserNode<'i>>, u32),
165 RepMinMax(Box<ParserNode<'i>>, u32, u32),
167 Push(Box<ParserNode<'i>>),
169 #[cfg(feature = "grammar-extras")]
171 PushLiteral(String),
172 #[cfg(feature = "grammar-extras")]
174 NodeTag(Box<ParserNode<'i>>, String),
175}
176
177fn convert_rule(rule: ParserRule<'_>) -> AstRule {
178 let ParserRule { name, ty, node, .. } = rule;
179 let expr = convert_node(node);
180 AstRule { name, ty, expr }
181}
182
183fn convert_node(node: ParserNode<'_>) -> Expr {
184 match node.expr {
185 ParserExpr::Str(string) => Expr::Str(string),
186 ParserExpr::Insens(string) => Expr::Insens(string),
187 ParserExpr::Range(start, end) => Expr::Range(start, end),
188 ParserExpr::Ident(ident) => Expr::Ident(ident),
189 ParserExpr::PeekSlice(start, end) => Expr::PeekSlice(start, end),
190 ParserExpr::PosPred(node) => Expr::PosPred(Box::new(convert_node(*node))),
191 ParserExpr::NegPred(node) => Expr::NegPred(Box::new(convert_node(*node))),
192 ParserExpr::Seq(node1, node2) => Expr::Seq(
193 Box::new(convert_node(*node1)),
194 Box::new(convert_node(*node2)),
195 ),
196 ParserExpr::Choice(node1, node2) => Expr::Choice(
197 Box::new(convert_node(*node1)),
198 Box::new(convert_node(*node2)),
199 ),
200 ParserExpr::Opt(node) => Expr::Opt(Box::new(convert_node(*node))),
201 ParserExpr::Rep(node) => Expr::Rep(Box::new(convert_node(*node))),
202 ParserExpr::RepOnce(node) => Expr::RepOnce(Box::new(convert_node(*node))),
203 ParserExpr::RepExact(node, num) => Expr::RepExact(Box::new(convert_node(*node)), num),
204 ParserExpr::RepMin(node, max) => Expr::RepMin(Box::new(convert_node(*node)), max),
205 ParserExpr::RepMax(node, max) => Expr::RepMax(Box::new(convert_node(*node)), max),
206 ParserExpr::RepMinMax(node, min, max) => {
207 Expr::RepMinMax(Box::new(convert_node(*node)), min, max)
208 }
209 ParserExpr::Push(node) => Expr::Push(Box::new(convert_node(*node))),
210 #[cfg(feature = "grammar-extras")]
211 ParserExpr::PushLiteral(string) => Expr::PushLiteral(string),
212 #[cfg(feature = "grammar-extras")]
213 ParserExpr::NodeTag(node, tag) => Expr::NodeTag(Box::new(convert_node(*node)), tag),
214 }
215}
216
217pub fn consume_rules(pairs: Pairs<'_, Rule>) -> Result<Vec<AstRule>, Vec<Error<Rule>>> {
219 let rules = consume_rules_with_spans(pairs)?;
220 let errors = validator::validate_ast(&rules);
221 if errors.is_empty() {
222 Ok(rules.into_iter().map(convert_rule).collect())
223 } else {
224 Err(errors)
225 }
226}
227
228#[inline]
231pub fn rename_meta_rule(rule: &Rule) -> String {
232 match *rule {
233 Rule::grammar_rule => "rule".to_owned(),
234 Rule::_push => "PUSH".to_owned(),
235 Rule::_push_literal => "PUSH_LITERAL".to_owned(),
236 Rule::assignment_operator => "`=`".to_owned(),
237 Rule::silent_modifier => "`_`".to_owned(),
238 Rule::atomic_modifier => "`@`".to_owned(),
239 Rule::compound_atomic_modifier => "`$`".to_owned(),
240 Rule::non_atomic_modifier => "`!`".to_owned(),
241 Rule::opening_brace => "`{`".to_owned(),
242 Rule::closing_brace => "`}`".to_owned(),
243 Rule::opening_brack => "`[`".to_owned(),
244 Rule::closing_brack => "`]`".to_owned(),
245 Rule::opening_paren => "`(`".to_owned(),
246 Rule::positive_predicate_operator => "`&`".to_owned(),
247 Rule::negative_predicate_operator => "`!`".to_owned(),
248 Rule::sequence_operator => "`&`".to_owned(),
249 Rule::choice_operator => "`|`".to_owned(),
250 Rule::optional_operator => "`?`".to_owned(),
251 Rule::repeat_operator => "`*`".to_owned(),
252 Rule::repeat_once_operator => "`+`".to_owned(),
253 Rule::comma => "`,`".to_owned(),
254 Rule::closing_paren => "`)`".to_owned(),
255 Rule::quote => "`\"`".to_owned(),
256 Rule::insensitive_string => "`^`".to_owned(),
257 Rule::range_operator => "`..`".to_owned(),
258 Rule::single_quote => "`'`".to_owned(),
259 Rule::grammar_doc => "//!".to_owned(),
260 Rule::line_doc => "///".to_owned(),
261 other_rule => format!("{:?}", other_rule),
262 }
263}
264
265fn consume_rules_with_spans(
266 pairs: Pairs<'_, Rule>,
267) -> Result<Vec<ParserRule<'_>>, Vec<Error<Rule>>> {
268 let pratt = PrattParser::new()
269 .op(Op::infix(Rule::choice_operator, Assoc::Left))
270 .op(Op::infix(Rule::sequence_operator, Assoc::Left));
271
272 pairs
273 .filter(|pair| pair.as_rule() == Rule::grammar_rule)
274 .filter(|pair| {
275 let mut pairs = pair.clone().into_inner();
277 let pair = pairs.next().unwrap();
278
279 pair.as_rule() != Rule::line_doc
280 })
281 .map(|pair| {
282 let mut pairs = pair.into_inner().peekable();
283
284 let span = pairs.next().unwrap().as_span();
285 let name = span.as_str().to_owned();
286
287 pairs.next().unwrap(); let ty = if pairs.peek().unwrap().as_rule() != Rule::opening_brace {
290 match pairs.next().unwrap().as_rule() {
291 Rule::silent_modifier => RuleType::Silent,
292 Rule::atomic_modifier => RuleType::Atomic,
293 Rule::compound_atomic_modifier => RuleType::CompoundAtomic,
294 Rule::non_atomic_modifier => RuleType::NonAtomic,
295 _ => unreachable!(),
296 }
297 } else {
298 RuleType::Normal
299 };
300
301 pairs.next().unwrap(); let mut inner_nodes = pairs.next().unwrap().into_inner().peekable();
305 if inner_nodes.peek().unwrap().as_rule() == Rule::choice_operator {
306 inner_nodes.next().unwrap();
307 }
308
309 let node = consume_expr(inner_nodes, &pratt)?;
310
311 Ok(ParserRule {
312 name,
313 span,
314 ty,
315 node,
316 })
317 })
318 .collect()
319}
320
321fn get_node_tag<'i>(
322 pairs: &mut Peekable<Pairs<'i, Rule>>,
323) -> (Pair<'i, Rule>, Option<(String, Position<'i>)>) {
324 let pair_or_tag = pairs.next().unwrap();
325 if let Some(next_pair) = pairs.peek() {
326 if next_pair.as_rule() == Rule::assignment_operator {
327 pairs.next().unwrap();
328 let pair = pairs.next().unwrap();
329 (
330 pair,
331 Some((
332 pair_or_tag.as_str()[1..].to_string(),
333 pair_or_tag.as_span().start_pos(),
334 )),
335 )
336 } else {
337 (pair_or_tag, None)
338 }
339 } else {
340 (pair_or_tag, None)
341 }
342}
343
344fn consume_expr<'i>(
345 pairs: Peekable<Pairs<'i, Rule>>,
346 pratt: &PrattParser<Rule>,
347) -> Result<ParserNode<'i>, Vec<Error<Rule>>> {
348 fn unaries<'i>(
349 mut pairs: Peekable<Pairs<'i, Rule>>,
350 pratt: &PrattParser<Rule>,
351 ) -> Result<ParserNode<'i>, Vec<Error<Rule>>> {
352 #[cfg(feature = "grammar-extras")]
353 let (pair, tag_start) = get_node_tag(&mut pairs);
354 #[cfg(not(feature = "grammar-extras"))]
355 let (pair, _tag_start) = get_node_tag(&mut pairs);
356
357 let node = match pair.as_rule() {
358 Rule::opening_paren => {
359 let node = unaries(pairs, pratt)?;
360 let end = node.span.end_pos();
361
362 ParserNode {
363 expr: node.expr,
364 span: pair.as_span().start_pos().span(&end),
365 }
366 }
367 Rule::positive_predicate_operator => {
368 let node = unaries(pairs, pratt)?;
369 let end = node.span.end_pos();
370
371 ParserNode {
372 expr: ParserExpr::PosPred(Box::new(node)),
373 span: pair.as_span().start_pos().span(&end),
374 }
375 }
376 Rule::negative_predicate_operator => {
377 let node = unaries(pairs, pratt)?;
378 let end = node.span.end_pos();
379
380 ParserNode {
381 expr: ParserExpr::NegPred(Box::new(node)),
382 span: pair.as_span().start_pos().span(&end),
383 }
384 }
385 other_rule => {
386 let node = match other_rule {
387 Rule::expression => consume_expr(pair.into_inner().peekable(), pratt)?,
388 Rule::_push => {
389 let start = pair.clone().as_span().start_pos();
390 let mut pairs = pair.into_inner();
391 pairs.next().unwrap(); let pair = pairs.next().unwrap();
393
394 let node = consume_expr(pair.into_inner().peekable(), pratt)?;
395 let end = node.span.end_pos();
396
397 ParserNode {
398 expr: ParserExpr::Push(Box::new(node)),
399 span: start.span(&end),
400 }
401 }
402 #[cfg(feature = "grammar-extras")]
403 Rule::_push_literal => {
404 let mut pairs = pair.into_inner();
405 pairs.next().unwrap(); let contents_pair = pairs.next().unwrap();
407 let string =
408 unescape(contents_pair.as_str()).expect("incorrect string literal");
409 ParserNode {
410 expr: ParserExpr::PushLiteral(string[1..string.len() - 1].to_owned()),
411 span: contents_pair.clone().as_span(),
412 }
413 }
414 #[cfg(not(feature = "grammar-extras"))]
415 Rule::_push_literal => {
416 return Err(vec![Error::new_from_span(
417 ErrorVariant::CustomError {
418 message: "PUSH_LITERAL requires feature grammar-extras".to_owned(),
419 },
420 pair.as_span(),
421 )]);
422 }
423 Rule::peek_slice => {
424 let mut pairs = pair.clone().into_inner();
425 pairs.next().unwrap(); let pair_start = pairs.next().unwrap(); let start: i32 = match pair_start.as_rule() {
428 Rule::range_operator => 0,
429 Rule::integer => {
430 pairs.next().unwrap(); pair_start.as_str().parse().unwrap()
432 }
433 _ => unreachable!("peek start"),
434 };
435 let pair_end = pairs.next().unwrap(); let end: Option<i32> = match pair_end.as_rule() {
437 Rule::closing_brack => None,
438 Rule::integer => {
439 pairs.next().unwrap(); Some(pair_end.as_str().parse().unwrap())
441 }
442 _ => unreachable!("peek end"),
443 };
444 ParserNode {
445 expr: ParserExpr::PeekSlice(start, end),
446 span: pair.as_span(),
447 }
448 }
449 Rule::identifier => ParserNode {
450 expr: ParserExpr::Ident(pair.as_str().to_owned()),
451 span: pair.clone().as_span(),
452 },
453 Rule::string => {
454 let string = unescape(pair.as_str()).expect("incorrect string literal");
455 ParserNode {
456 expr: ParserExpr::Str(string[1..string.len() - 1].to_owned()),
457 span: pair.clone().as_span(),
458 }
459 }
460 Rule::insensitive_string => {
461 let string = unescape(pair.as_str()).expect("incorrect string literal");
462 ParserNode {
463 expr: ParserExpr::Insens(string[2..string.len() - 1].to_owned()),
464 span: pair.clone().as_span(),
465 }
466 }
467 Rule::range => {
468 let mut pairs = pair.into_inner();
469 let pair = pairs.next().unwrap();
470 let start = unescape(pair.as_str()).expect("incorrect char literal");
471 let start_pos = pair.clone().as_span().start_pos();
472 pairs.next();
473 let pair = pairs.next().unwrap();
474 let end = unescape(pair.as_str()).expect("incorrect char literal");
475 let end_pos = pair.clone().as_span().end_pos();
476
477 ParserNode {
478 expr: ParserExpr::Range(
479 start[1..start.len() - 1].to_owned(),
480 end[1..end.len() - 1].to_owned(),
481 ),
482 span: start_pos.span(&end_pos),
483 }
484 }
485 x => unreachable!("other rule: {:?}", x),
486 };
487
488 pairs.try_fold(node, |node: ParserNode<'i>, pair: Pair<'i, Rule>| {
489 let node = match pair.as_rule() {
490 Rule::optional_operator => {
491 let start = node.span.start_pos();
492 ParserNode {
493 expr: ParserExpr::Opt(Box::new(node)),
494 span: start.span(&pair.as_span().end_pos()),
495 }
496 }
497 Rule::repeat_operator => {
498 let start = node.span.start_pos();
499 ParserNode {
500 expr: ParserExpr::Rep(Box::new(node)),
501 span: start.span(&pair.as_span().end_pos()),
502 }
503 }
504 Rule::repeat_once_operator => {
505 let start = node.span.start_pos();
506 ParserNode {
507 expr: ParserExpr::RepOnce(Box::new(node)),
508 span: start.span(&pair.as_span().end_pos()),
509 }
510 }
511 Rule::repeat_exact => {
512 let mut inner = pair.clone().into_inner();
513
514 inner.next().unwrap(); let number = inner.next().unwrap();
517 let num = if let Ok(num) = number.as_str().parse::<u32>() {
518 num
519 } else {
520 return Err(vec![Error::new_from_span(
521 ErrorVariant::CustomError {
522 message: "number cannot overflow u32".to_owned(),
523 },
524 number.as_span(),
525 )]);
526 };
527
528 if num == 0 {
529 let error: Error<Rule> = Error::new_from_span(
530 ErrorVariant::CustomError {
531 message: "cannot repeat 0 times".to_owned(),
532 },
533 number.as_span(),
534 );
535
536 return Err(vec![error]);
537 }
538
539 let start = node.span.start_pos();
540 ParserNode {
541 expr: ParserExpr::RepExact(Box::new(node), num),
542 span: start.span(&pair.as_span().end_pos()),
543 }
544 }
545 Rule::repeat_min => {
546 let mut inner = pair.clone().into_inner();
547
548 inner.next().unwrap(); let min_number = inner.next().unwrap();
551 let min = if let Ok(min) = min_number.as_str().parse::<u32>() {
552 min
553 } else {
554 return Err(vec![Error::new_from_span(
555 ErrorVariant::CustomError {
556 message: "number cannot overflow u32".to_owned(),
557 },
558 min_number.as_span(),
559 )]);
560 };
561
562 let start = node.span.start_pos();
563 ParserNode {
564 expr: ParserExpr::RepMin(Box::new(node), min),
565 span: start.span(&pair.as_span().end_pos()),
566 }
567 }
568 Rule::repeat_max => {
569 let mut inner = pair.clone().into_inner();
570
571 inner.next().unwrap(); inner.next().unwrap(); let max_number = inner.next().unwrap();
575 let max = if let Ok(max) = max_number.as_str().parse::<u32>() {
576 max
577 } else {
578 return Err(vec![Error::new_from_span(
579 ErrorVariant::CustomError {
580 message: "number cannot overflow u32".to_owned(),
581 },
582 max_number.as_span(),
583 )]);
584 };
585
586 if max == 0 {
587 let error: Error<Rule> = Error::new_from_span(
588 ErrorVariant::CustomError {
589 message: "cannot repeat 0 times".to_owned(),
590 },
591 max_number.as_span(),
592 );
593
594 return Err(vec![error]);
595 }
596
597 let start = node.span.start_pos();
598 ParserNode {
599 expr: ParserExpr::RepMax(Box::new(node), max),
600 span: start.span(&pair.as_span().end_pos()),
601 }
602 }
603 Rule::repeat_min_max => {
604 let mut inner = pair.clone().into_inner();
605
606 inner.next().unwrap(); let min_number = inner.next().unwrap();
609 let min = if let Ok(min) = min_number.as_str().parse::<u32>() {
610 min
611 } else {
612 return Err(vec![Error::new_from_span(
613 ErrorVariant::CustomError {
614 message: "number cannot overflow u32".to_owned(),
615 },
616 min_number.as_span(),
617 )]);
618 };
619
620 inner.next().unwrap(); let max_number = inner.next().unwrap();
623 let max = if let Ok(max) = max_number.as_str().parse::<u32>() {
624 max
625 } else {
626 return Err(vec![Error::new_from_span(
627 ErrorVariant::CustomError {
628 message: "number cannot overflow u32".to_owned(),
629 },
630 max_number.as_span(),
631 )]);
632 };
633
634 if max == 0 {
635 let error: Error<Rule> = Error::new_from_span(
636 ErrorVariant::CustomError {
637 message: "cannot repeat 0 times".to_owned(),
638 },
639 max_number.as_span(),
640 );
641
642 return Err(vec![error]);
643 }
644
645 let start = node.span.start_pos();
646 ParserNode {
647 expr: ParserExpr::RepMinMax(Box::new(node), min, max),
648 span: start.span(&pair.as_span().end_pos()),
649 }
650 }
651 Rule::closing_paren => {
652 let start = node.span.start_pos();
653
654 ParserNode {
655 expr: node.expr,
656 span: start.span(&pair.as_span().end_pos()),
657 }
658 }
659 rule => unreachable!("node: {:?}", rule),
660 };
661
662 Ok(node)
663 })?
664 }
665 };
666 #[cfg(feature = "grammar-extras")]
667 if let Some((tag, start)) = tag_start {
668 let span = start.span(&node.span.end_pos());
669 Ok(ParserNode {
670 expr: ParserExpr::NodeTag(Box::new(node), tag),
671 span,
672 })
673 } else {
674 Ok(node)
675 }
676 #[cfg(not(feature = "grammar-extras"))]
677 Ok(node)
678 }
679
680 let term = |pair: Pair<'i, Rule>| unaries(pair.into_inner().peekable(), pratt);
681 let infix = |lhs: Result<ParserNode<'i>, Vec<Error<Rule>>>,
682 op: Pair<'i, Rule>,
683 rhs: Result<ParserNode<'i>, Vec<Error<Rule>>>| match op.as_rule() {
684 Rule::sequence_operator => {
685 let lhs = lhs?;
686 let rhs = rhs?;
687
688 let start = lhs.span.start_pos();
689 let end = rhs.span.end_pos();
690
691 Ok(ParserNode {
692 expr: ParserExpr::Seq(Box::new(lhs), Box::new(rhs)),
693 span: start.span(&end),
694 })
695 }
696 Rule::choice_operator => {
697 let lhs = lhs?;
698 let rhs = rhs?;
699
700 let start = lhs.span.start_pos();
701 let end = rhs.span.end_pos();
702
703 Ok(ParserNode {
704 expr: ParserExpr::Choice(Box::new(lhs), Box::new(rhs)),
705 span: start.span(&end),
706 })
707 }
708 _ => unreachable!("infix"),
709 };
710
711 pratt.map_primary(term).map_infix(infix).parse(pairs)
712}
713
714fn unescape(string: &str) -> Option<String> {
715 let mut result = String::new();
716 let mut chars = string.chars();
717
718 loop {
719 match chars.next() {
720 Some('\\') => match chars.next()? {
721 '"' => result.push('"'),
722 '\\' => result.push('\\'),
723 'r' => result.push('\r'),
724 'n' => result.push('\n'),
725 't' => result.push('\t'),
726 '0' => result.push('\0'),
727 '\'' => result.push('\''),
728 'x' => {
729 let string: String = chars.clone().take(2).collect();
730
731 if string.len() != 2 {
732 return None;
733 }
734
735 for _ in 0..string.len() {
736 chars.next()?;
737 }
738
739 let value = u8::from_str_radix(&string, 16).ok()?;
740
741 result.push(char::from(value));
742 }
743 'u' => {
744 if chars.next()? != '{' {
745 return None;
746 }
747
748 let string: String = chars.clone().take_while(|c| *c != '}').collect();
749
750 if string.len() < 2 || 6 < string.len() {
751 return None;
752 }
753
754 for _ in 0..string.len() + 1 {
755 chars.next()?;
756 }
757
758 let value = u32::from_str_radix(&string, 16).ok()?;
759
760 result.push(char::from_u32(value)?);
761 }
762 _ => return None,
763 },
764 Some(c) => result.push(c),
765 None => return Some(result),
766 };
767 }
768}
769
770#[cfg(test)]
771mod tests {
772 use std::convert::TryInto;
773
774 use super::super::unwrap_or_report;
775 use super::*;
776
777 #[test]
778 fn rules() {
779 parses_to! {
780 parser: PestParser,
781 input: "a = { b } c = { d }",
782 rule: Rule::grammar_rules,
783 tokens: [
784 grammar_rule(0, 9, [
785 identifier(0, 1),
786 assignment_operator(2, 3),
787 opening_brace(4, 5),
788 expression(6, 8, [
789 term(6, 8, [
790 identifier(6, 7)
791 ])
792 ]),
793 closing_brace(8, 9)
794 ]),
795 grammar_rule(10, 19, [
796 identifier(10, 11),
797 assignment_operator(12, 13),
798 opening_brace(14, 15),
799 expression(16, 18, [
800 term(16, 18, [
801 identifier(16, 17)
802 ])
803 ]),
804 closing_brace(18, 19)
805 ])
806 ]
807 };
808 }
809
810 #[test]
811 fn rule() {
812 parses_to! {
813 parser: PestParser,
814 input: "a = ! { b ~ c }",
815 rule: Rule::grammar_rule,
816 tokens: [
817 grammar_rule(0, 15, [
818 identifier(0, 1),
819 assignment_operator(2, 3),
820 non_atomic_modifier(4, 5),
821 opening_brace(6, 7),
822 expression(8, 14, [
823 term(8, 10, [
824 identifier(8, 9)
825 ]),
826 sequence_operator(10, 11),
827 term(12, 14, [
828 identifier(12, 13)
829 ])
830 ]),
831 closing_brace(14, 15)
832 ])
833 ]
834 };
835 }
836
837 #[test]
838 fn expression() {
839 parses_to! {
840 parser: PestParser,
841 input: "_a | 'a'..'b' ~ !^\"abc\" ~ (d | e)*?",
842 rule: Rule::expression,
843 tokens: [
844 expression(0, 35, [
845 term(0, 3, [
846 identifier(0, 2)
847 ]),
848 choice_operator(3, 4),
849 term(5, 14, [
850 range(5, 13, [
851 character(5, 8, [
852 single_quote(5, 6),
853 inner_chr(6, 7),
854 single_quote(7, 8)
855 ]),
856 range_operator(8, 10),
857 character(10, 13, [
858 single_quote(10, 11),
859 inner_chr(11, 12),
860 single_quote(12, 13)
861 ])
862 ])
863 ]),
864 sequence_operator(14, 15),
865 term(16, 24, [
866 negative_predicate_operator(16, 17),
867 insensitive_string(17, 23, [
868 string(18, 23, [
869 quote(18, 19),
870 inner_str(19, 22),
871 quote(22, 23)
872 ])
873 ])
874 ]),
875 sequence_operator(24, 25),
876 term(26, 35, [
877 opening_paren(26, 27),
878 expression(27, 32, [
879 term(27, 29, [
880 identifier(27, 28)
881 ]),
882 choice_operator(29, 30),
883 term(31, 32, [
884 identifier(31, 32)
885 ])
886 ]),
887 closing_paren(32, 33),
888 repeat_operator(33, 34),
889 optional_operator(34, 35)
890 ])
891 ])
892 ]
893 };
894 }
895
896 #[test]
897 fn repeat_exact() {
898 parses_to! {
899 parser: PestParser,
900 input: "{1}",
901 rule: Rule::repeat_exact,
902 tokens: [
903 repeat_exact(0, 3, [
904 opening_brace(0, 1),
905 number(1, 2),
906 closing_brace(2, 3)
907 ])
908 ]
909 };
910 }
911
912 #[test]
913 fn repeat_min() {
914 parses_to! {
915 parser: PestParser,
916 input: "{2,}",
917 rule: Rule::repeat_min,
918 tokens: [
919 repeat_min(0, 4, [
920 opening_brace(0,1),
921 number(1,2),
922 comma(2,3),
923 closing_brace(3,4)
924 ])
925 ]
926 }
927 }
928
929 #[test]
930 fn repeat_max() {
931 parses_to! {
932 parser: PestParser,
933 input: "{, 3}",
934 rule: Rule::repeat_max,
935 tokens: [
936 repeat_max(0, 5, [
937 opening_brace(0,1),
938 comma(1,2),
939 number(3,4),
940 closing_brace(4,5)
941 ])
942 ]
943 }
944 }
945
946 #[test]
947 fn repeat_min_max() {
948 parses_to! {
949 parser: PestParser,
950 input: "{1, 2}",
951 rule: Rule::repeat_min_max,
952 tokens: [
953 repeat_min_max(0, 6, [
954 opening_brace(0, 1),
955 number(1, 2),
956 comma(2, 3),
957 number(4, 5),
958 closing_brace(5, 6)
959 ])
960 ]
961 };
962 }
963
964 #[test]
965 fn push() {
966 parses_to! {
967 parser: PestParser,
968 input: "PUSH ( a )",
969 rule: Rule::_push,
970 tokens: [
971 _push(0, 10, [
972 opening_paren(5, 6),
973 expression(7, 9, [
974 term(7, 9, [
975 identifier(7, 8)
976 ])
977 ]),
978 closing_paren(9, 10)
979 ])
980 ]
981 };
982 }
983
984 #[test]
985 fn peek_slice_all() {
986 parses_to! {
987 parser: PestParser,
988 input: "PEEK[..]",
989 rule: Rule::peek_slice,
990 tokens: [
991 peek_slice(0, 8, [
992 opening_brack(4, 5),
993 range_operator(5, 7),
994 closing_brack(7, 8)
995 ])
996 ]
997 };
998 }
999
1000 #[test]
1001 fn peek_slice_start() {
1002 parses_to! {
1003 parser: PestParser,
1004 input: "PEEK[1..]",
1005 rule: Rule::peek_slice,
1006 tokens: [
1007 peek_slice(0, 9, [
1008 opening_brack(4, 5),
1009 integer(5, 6),
1010 range_operator(6, 8),
1011 closing_brack(8, 9)
1012 ])
1013 ]
1014 };
1015 }
1016
1017 #[test]
1018 fn peek_slice_end() {
1019 parses_to! {
1020 parser: PestParser,
1021 input: "PEEK[ ..-1]",
1022 rule: Rule::peek_slice,
1023 tokens: [
1024 peek_slice(0, 11, [
1025 opening_brack(4, 5),
1026 range_operator(6, 8),
1027 integer(8, 10),
1028 closing_brack(10, 11)
1029 ])
1030 ]
1031 };
1032 }
1033
1034 #[test]
1035 fn peek_slice_start_end() {
1036 parses_to! {
1037 parser: PestParser,
1038 input: "PEEK[-5..10]",
1039 rule: Rule::peek_slice,
1040 tokens: [
1041 peek_slice(0, 12, [
1042 opening_brack(4, 5),
1043 integer(5, 7),
1044 range_operator(7, 9),
1045 integer(9, 11),
1046 closing_brack(11, 12)
1047 ])
1048 ]
1049 };
1050 }
1051
1052 #[test]
1053 fn identifier() {
1054 parses_to! {
1055 parser: PestParser,
1056 input: "_a8943",
1057 rule: Rule::identifier,
1058 tokens: [
1059 identifier(0, 6)
1060 ]
1061 };
1062 }
1063
1064 #[test]
1065 fn string() {
1066 parses_to! {
1067 parser: PestParser,
1068 input: "\"aaaaa\\n\\r\\t\\\\\\0\\'\\\"\\x0F\\u{123abC}\\u{12}aaaaa\"",
1069 rule: Rule::string,
1070 tokens: [
1071 string(0, 46, [
1072 quote(0, 1),
1073 inner_str(1, 45),
1074 quote(45, 46)
1075 ])
1076 ]
1077 };
1078 }
1079
1080 #[test]
1081 fn insensitive_string() {
1082 parses_to! {
1083 parser: PestParser,
1084 input: "^ \"\\\"hi\"",
1085 rule: Rule::insensitive_string,
1086 tokens: [
1087 insensitive_string(0, 9, [
1088 string(3, 9, [
1089 quote(3, 4),
1090 inner_str(4, 8),
1091 quote(8, 9)
1092 ])
1093 ])
1094 ]
1095 };
1096 }
1097
1098 #[test]
1099 fn range() {
1100 parses_to! {
1101 parser: PestParser,
1102 input: "'\\n' .. '\\x1a'",
1103 rule: Rule::range,
1104 tokens: [
1105 range(0, 14, [
1106 character(0, 4, [
1107 single_quote(0, 1),
1108 inner_chr(1, 3),
1109 single_quote(3, 4)
1110 ]),
1111 range_operator(5, 7),
1112 character(8, 14, [
1113 single_quote(8, 9),
1114 inner_chr(9, 13),
1115 single_quote(13, 14)
1116 ])
1117 ])
1118 ]
1119 };
1120 }
1121
1122 #[test]
1123 fn character() {
1124 parses_to! {
1125 parser: PestParser,
1126 input: "'\\u{123abC}'",
1127 rule: Rule::character,
1128 tokens: [
1129 character(0, 12, [
1130 single_quote(0, 1),
1131 inner_chr(1, 11),
1132 single_quote(11, 12)
1133 ])
1134 ]
1135 };
1136 }
1137
1138 #[test]
1139 fn number() {
1140 parses_to! {
1141 parser: PestParser,
1142 input: "0123",
1143 rule: Rule::number,
1144 tokens: [
1145 number(0, 4)
1146 ]
1147 };
1148 }
1149
1150 #[test]
1151 fn comment() {
1152 parses_to! {
1153 parser: PestParser,
1154 input: "a ~ // asda\n b",
1155 rule: Rule::expression,
1156 tokens: [
1157 expression(0, 17, [
1158 term(0, 2, [
1159 identifier(0, 1)
1160 ]),
1161 sequence_operator(2, 3),
1162 term(16, 17, [
1163 identifier(16, 17)
1164 ])
1165 ])
1166 ]
1167 };
1168 }
1169
1170 #[test]
1171 fn grammar_doc_and_line_doc() {
1172 let input = "//! hello\n/// world\na = { \"a\" }";
1173 parses_to! {
1174 parser: PestParser,
1175 input: input,
1176 rule: Rule::grammar_rules,
1177 tokens: [
1178 grammar_doc(0, 9, [
1179 inner_doc(4, 9),
1180 ]),
1181 grammar_rule(10, 19, [
1182 line_doc(10, 19, [
1183 inner_doc(14, 19),
1184 ]),
1185 ]),
1186 grammar_rule(20, 31, [
1187 identifier(20, 21),
1188 assignment_operator(22, 23),
1189 opening_brace(24, 25),
1190 expression(26, 30, [
1191 term(26, 30, [
1192 string(26, 29, [
1193 quote(26, 27),
1194 inner_str(27, 28),
1195 quote(28, 29)
1196 ])
1197 ])
1198 ]),
1199 closing_brace(30, 31),
1200 ])
1201 ]
1202 };
1203 }
1204
1205 #[test]
1206 fn wrong_identifier() {
1207 fails_with! {
1208 parser: PestParser,
1209 input: "0",
1210 rule: Rule::grammar_rules,
1211 positives: vec![Rule::EOI, Rule::grammar_rule, Rule::grammar_doc],
1212 negatives: vec![],
1213 pos: 0
1214 };
1215 }
1216
1217 #[test]
1218 fn missing_assignment_operator() {
1219 fails_with! {
1220 parser: PestParser,
1221 input: "a {}",
1222 rule: Rule::grammar_rules,
1223 positives: vec![Rule::assignment_operator],
1224 negatives: vec![],
1225 pos: 2
1226 };
1227 }
1228
1229 #[test]
1230 fn wrong_modifier() {
1231 fails_with! {
1232 parser: PestParser,
1233 input: "a = *{}",
1234 rule: Rule::grammar_rules,
1235 positives: vec![
1236 Rule::opening_brace,
1237 Rule::silent_modifier,
1238 Rule::atomic_modifier,
1239 Rule::compound_atomic_modifier,
1240 Rule::non_atomic_modifier
1241 ],
1242 negatives: vec![],
1243 pos: 4
1244 };
1245 }
1246
1247 #[test]
1248 fn missing_opening_brace() {
1249 fails_with! {
1250 parser: PestParser,
1251 input: "a = _",
1252 rule: Rule::grammar_rules,
1253 positives: vec![Rule::opening_brace],
1254 negatives: vec![],
1255 pos: 5
1256 };
1257 }
1258
1259 #[test]
1260 fn empty_rule() {
1261 fails_with! {
1262 parser: PestParser,
1263 input: "a = {}",
1264 rule: Rule::grammar_rules,
1265 positives: vec![Rule::expression],
1266 negatives: vec![],
1267 pos: 5
1268 };
1269 }
1270
1271 #[test]
1272 fn missing_rhs() {
1273 fails_with! {
1274 parser: PestParser,
1275 input: "a = { b ~ }",
1276 rule: Rule::grammar_rules,
1277 positives: vec![Rule::term],
1278 negatives: vec![],
1279 pos: 10
1280 };
1281 }
1282
1283 #[test]
1284 fn incorrect_prefix() {
1285 fails_with! {
1286 parser: PestParser,
1287 input: "a = { ~ b}",
1288 rule: Rule::grammar_rules,
1289 positives: vec![Rule::expression],
1290 negatives: vec![],
1291 pos: 6
1292 };
1293 }
1294
1295 #[test]
1296 fn wrong_op() {
1297 fails_with! {
1298 parser: PestParser,
1299 input: "a = { b % }",
1300 rule: Rule::grammar_rules,
1301 positives: vec![
1302 Rule::opening_brace,
1303 Rule::closing_brace,
1304 Rule::sequence_operator,
1305 Rule::choice_operator,
1306 Rule::optional_operator,
1307 Rule::repeat_operator,
1308 Rule::repeat_once_operator
1309 ],
1310 negatives: vec![],
1311 pos: 8
1312 };
1313 }
1314
1315 #[test]
1316 fn missing_closing_paren() {
1317 fails_with! {
1318 parser: PestParser,
1319 input: "a = { (b }",
1320 rule: Rule::grammar_rules,
1321 positives: vec![
1322 Rule::opening_brace,
1323 Rule::closing_paren,
1324 Rule::sequence_operator,
1325 Rule::choice_operator,
1326 Rule::optional_operator,
1327 Rule::repeat_operator,
1328 Rule::repeat_once_operator
1329 ],
1330 negatives: vec![],
1331 pos: 9
1332 };
1333 }
1334
1335 #[test]
1336 fn missing_term() {
1337 fails_with! {
1338 parser: PestParser,
1339 input: "a = { ! }",
1340 rule: Rule::grammar_rules,
1341 positives: vec![
1342 Rule::opening_paren,
1343 Rule::positive_predicate_operator,
1344 Rule::negative_predicate_operator,
1345 Rule::_push,
1346 Rule::_push_literal,
1347 Rule::peek_slice,
1348 Rule::identifier,
1349 Rule::insensitive_string,
1350 Rule::quote,
1351 Rule::single_quote
1352 ],
1353 negatives: vec![],
1354 pos: 8
1355 };
1356 }
1357
1358 #[test]
1359 fn string_missing_ending_quote() {
1360 fails_with! {
1361 parser: PestParser,
1362 input: "a = { \" }",
1363 rule: Rule::grammar_rules,
1364 positives: vec![Rule::quote],
1365 negatives: vec![],
1366 pos: 9
1367 };
1368 }
1369
1370 #[test]
1371 fn insensitive_missing_string() {
1372 fails_with! {
1373 parser: PestParser,
1374 input: "a = { ^ }",
1375 rule: Rule::grammar_rules,
1376 positives: vec![Rule::quote],
1377 negatives: vec![],
1378 pos: 8
1379 };
1380 }
1381
1382 #[test]
1383 fn char_missing_ending_single_quote() {
1384 fails_with! {
1385 parser: PestParser,
1386 input: "a = { \' }",
1387 rule: Rule::grammar_rules,
1388 positives: vec![Rule::single_quote],
1389 negatives: vec![],
1390 pos: 8
1391 };
1392 }
1393
1394 #[test]
1395 fn range_missing_range_operator() {
1396 fails_with! {
1397 parser: PestParser,
1398 input: "a = { \'a\' }",
1399 rule: Rule::grammar_rules,
1400 positives: vec![Rule::range_operator],
1401 negatives: vec![],
1402 pos: 10
1403 };
1404 }
1405
1406 #[test]
1407 fn wrong_postfix() {
1408 fails_with! {
1409 parser: PestParser,
1410 input: "a = { a& }",
1411 rule: Rule::grammar_rules,
1412 positives: vec![
1413 Rule::opening_brace,
1414 Rule::closing_brace,
1415 Rule::sequence_operator,
1416 Rule::choice_operator,
1417 Rule::optional_operator,
1418 Rule::repeat_operator,
1419 Rule::repeat_once_operator
1420 ],
1421 negatives: vec![],
1422 pos: 7
1423 };
1424 }
1425
1426 #[test]
1427 fn node_tag() {
1428 parses_to! {
1429 parser: PestParser,
1430 input: "#a = a",
1431 rule: Rule::expression,
1432 tokens: [
1433 expression(0, 6, [
1434 term(0, 6, [
1435 tag_id(0, 2),
1436 assignment_operator(3, 4),
1437 identifier(5, 6)
1438 ])
1439 ])
1440 ]
1441 };
1442 }
1443
1444 #[test]
1445 fn incomplete_node_tag() {
1446 fails_with! {
1447 parser: PestParser,
1448 input: "a = { # }",
1449 rule: Rule::grammar_rules,
1450 positives: vec![
1451 Rule::expression
1452 ],
1453 negatives: vec![],
1454 pos: 6
1455 };
1456 }
1457
1458 #[test]
1459 fn incomplete_node_tag_assignment() {
1460 fails_with! {
1461 parser: PestParser,
1462 input: "a = { #a = }",
1463 rule: Rule::grammar_rules,
1464 positives: vec![
1465 Rule::opening_paren,
1466 Rule::positive_predicate_operator,
1467 Rule::negative_predicate_operator,
1468 Rule::_push,
1469 Rule::_push_literal,
1470 Rule::peek_slice,
1471 Rule::identifier,
1472 Rule::insensitive_string,
1473 Rule::quote,
1474 Rule::single_quote
1475 ],
1476 negatives: vec![],
1477 pos: 11
1478 };
1479 }
1480
1481 #[test]
1482 fn incomplete_node_tag_pound_key() {
1483 fails_with! {
1484 parser: PestParser,
1485 input: "a = { a = a }",
1486 rule: Rule::grammar_rules,
1487 positives: vec![
1488 Rule::opening_brace,
1489 Rule::closing_brace,
1490 Rule::sequence_operator,
1491 Rule::choice_operator,
1492 Rule::optional_operator,
1493 Rule::repeat_operator,
1494 Rule::repeat_once_operator
1495 ],
1496 negatives: vec![],
1497 pos: 8
1498 };
1499 }
1500
1501 #[test]
1502 fn ast() {
1503 let input = r#"
1504 /// This is line comment
1505 /// This is rule
1506 rule = _{ a{1} ~ "a"{3,} ~ b{, 2} ~ "b"{1, 2} | !(^"c" | PUSH('d'..'e'))?* }
1507 "#;
1508
1509 let pairs = PestParser::parse(Rule::grammar_rules, input).unwrap();
1510 let ast = consume_rules_with_spans(pairs).unwrap();
1511 let ast: Vec<_> = ast.into_iter().map(convert_rule).collect();
1512
1513 assert_eq!(
1514 ast,
1515 vec![AstRule {
1516 name: "rule".to_owned(),
1517 ty: RuleType::Silent,
1518 expr: Expr::Choice(
1519 Box::new(Expr::Seq(
1520 Box::new(Expr::Seq(
1521 Box::new(Expr::Seq(
1522 Box::new(Expr::RepExact(Box::new(Expr::Ident("a".to_owned())), 1)),
1523 Box::new(Expr::RepMin(Box::new(Expr::Str("a".to_owned())), 3))
1524 )),
1525 Box::new(Expr::RepMax(Box::new(Expr::Ident("b".to_owned())), 2))
1526 )),
1527 Box::new(Expr::RepMinMax(Box::new(Expr::Str("b".to_owned())), 1, 2))
1528 )),
1529 Box::new(Expr::NegPred(Box::new(Expr::Rep(Box::new(Expr::Opt(
1530 Box::new(Expr::Choice(
1531 Box::new(Expr::Insens("c".to_owned())),
1532 Box::new(Expr::Push(Box::new(Expr::Range(
1533 "d".to_owned(),
1534 "e".to_owned()
1535 ))))
1536 ))
1537 ))))))
1538 )
1539 },]
1540 );
1541 }
1542
1543 #[cfg(feature = "grammar-extras")]
1544 #[test]
1545 fn ast_push_literal() {
1546 let input = r#"rule = _{ PUSH_LITERAL("a") }"#;
1547
1548 let pairs = PestParser::parse(Rule::grammar_rules, input).unwrap();
1549 let ast = consume_rules_with_spans(pairs).unwrap();
1550 let ast: Vec<_> = ast.into_iter().map(convert_rule).collect();
1551
1552 assert_eq!(
1553 ast,
1554 vec![AstRule {
1555 name: "rule".to_owned(),
1556 ty: RuleType::Silent,
1557 expr: Expr::PushLiteral("a".to_string()),
1558 }],
1559 );
1560 }
1561
1562 #[test]
1563 #[should_panic(expected = "grammar error
1564
1565 --> 1:24
1566 |
15671 | rule = _{ PUSH_LITERAL(a) }
1568 | ^---
1569 |
1570 = expected quote")]
1571 fn ast_push_literal_bad_input() {
1572 let input = r#"rule = _{ PUSH_LITERAL(a) }"#;
1573
1574 let pairs_result = PestParser::parse(Rule::grammar_rules, input);
1575 match pairs_result {
1576 Ok(ok) => panic!("expected Err, but found {ok}"),
1577 Err(e) => panic!("grammar error\n\n{e}"),
1578 }
1579 }
1580
1581 #[test]
1582 fn ast_peek_slice() {
1583 let input = "rule = _{ PEEK[-04..] ~ PEEK[..3] }";
1584
1585 let pairs = PestParser::parse(Rule::grammar_rules, input).unwrap();
1586 let ast = consume_rules_with_spans(pairs).unwrap();
1587 let ast: Vec<_> = ast.into_iter().map(convert_rule).collect();
1588
1589 assert_eq!(
1590 ast,
1591 vec![AstRule {
1592 name: "rule".to_owned(),
1593 ty: RuleType::Silent,
1594 expr: Expr::Seq(
1595 Box::new(Expr::PeekSlice(-4, None)),
1596 Box::new(Expr::PeekSlice(0, Some(3))),
1597 ),
1598 }],
1599 );
1600 }
1601
1602 #[test]
1603 #[should_panic(expected = "grammar error
1604
1605 --> 1:13
1606 |
16071 | rule = { \"\"{4294967297} }
1608 | ^--------^
1609 |
1610 = number cannot overflow u32")]
1611 fn repeat_exact_overflow() {
1612 let input = "rule = { \"\"{4294967297} }";
1613
1614 let pairs = PestParser::parse(Rule::grammar_rules, input).unwrap();
1615 unwrap_or_report(consume_rules_with_spans(pairs));
1616 }
1617
1618 #[test]
1619 #[should_panic(expected = "grammar error
1620
1621 --> 1:13
1622 |
16231 | rule = { \"\"{0} }
1624 | ^
1625 |
1626 = cannot repeat 0 times")]
1627 fn repeat_exact_zero() {
1628 let input = "rule = { \"\"{0} }";
1629
1630 let pairs = PestParser::parse(Rule::grammar_rules, input).unwrap();
1631 unwrap_or_report(consume_rules_with_spans(pairs));
1632 }
1633
1634 #[test]
1635 #[should_panic(expected = "grammar error
1636
1637 --> 1:13
1638 |
16391 | rule = { \"\"{4294967297,} }
1640 | ^--------^
1641 |
1642 = number cannot overflow u32")]
1643 fn repeat_min_overflow() {
1644 let input = "rule = { \"\"{4294967297,} }";
1645
1646 let pairs = PestParser::parse(Rule::grammar_rules, input).unwrap();
1647 unwrap_or_report(consume_rules_with_spans(pairs));
1648 }
1649
1650 #[test]
1651 #[should_panic(expected = "grammar error
1652
1653 --> 1:14
1654 |
16551 | rule = { \"\"{,4294967297} }
1656 | ^--------^
1657 |
1658 = number cannot overflow u32")]
1659 fn repeat_max_overflow() {
1660 let input = "rule = { \"\"{,4294967297} }";
1661
1662 let pairs = PestParser::parse(Rule::grammar_rules, input).unwrap();
1663 unwrap_or_report(consume_rules_with_spans(pairs));
1664 }
1665
1666 #[test]
1667 #[should_panic(expected = "grammar error
1668
1669 --> 1:14
1670 |
16711 | rule = { \"\"{,0} }
1672 | ^
1673 |
1674 = cannot repeat 0 times")]
1675 fn repeat_max_zero() {
1676 let input = "rule = { \"\"{,0} }";
1677
1678 let pairs = PestParser::parse(Rule::grammar_rules, input).unwrap();
1679 unwrap_or_report(consume_rules_with_spans(pairs));
1680 }
1681
1682 #[test]
1683 #[should_panic(expected = "grammar error
1684
1685 --> 1:13
1686 |
16871 | rule = { \"\"{4294967297,4294967298} }
1688 | ^--------^
1689 |
1690 = number cannot overflow u32")]
1691 fn repeat_min_max_overflow() {
1692 let input = "rule = { \"\"{4294967297,4294967298} }";
1693
1694 let pairs = PestParser::parse(Rule::grammar_rules, input).unwrap();
1695 unwrap_or_report(consume_rules_with_spans(pairs));
1696 }
1697
1698 #[test]
1699 #[should_panic(expected = "grammar error
1700
1701 --> 1:15
1702 |
17031 | rule = { \"\"{0,0} }
1704 | ^
1705 |
1706 = cannot repeat 0 times")]
1707 fn repeat_min_max_zero() {
1708 let input = "rule = { \"\"{0,0} }";
1709
1710 let pairs = PestParser::parse(Rule::grammar_rules, input).unwrap();
1711 unwrap_or_report(consume_rules_with_spans(pairs));
1712 }
1713
1714 #[test]
1715 fn unescape_all() {
1716 let string = r"a\nb\x55c\u{111}d";
1717
1718 assert_eq!(unescape(string), Some("a\nb\x55c\u{111}d".to_owned()));
1719 }
1720
1721 #[test]
1722 fn unescape_empty_escape() {
1723 let string = r"\";
1724
1725 assert_eq!(unescape(string), None);
1726 }
1727
1728 #[test]
1729 fn unescape_wrong_escape() {
1730 let string = r"\w";
1731
1732 assert_eq!(unescape(string), None);
1733 }
1734
1735 #[test]
1736 fn unescape_backslash() {
1737 let string = "\\\\";
1738 assert_eq!(unescape(string), Some("\\".to_owned()));
1739 }
1740
1741 #[test]
1742 fn unescape_return() {
1743 let string = "\\r";
1744 assert_eq!(unescape(string), Some("\r".to_owned()));
1745 }
1746
1747 #[test]
1748 fn unescape_tab() {
1749 let string = "\\t";
1750 assert_eq!(unescape(string), Some("\t".to_owned()));
1751 }
1752
1753 #[test]
1754 fn unescape_null() {
1755 let string = "\\0";
1756 assert_eq!(unescape(string), Some("\0".to_owned()));
1757 }
1758
1759 #[test]
1760 fn unescape_single_quote() {
1761 let string = "\\'";
1762 assert_eq!(unescape(string), Some("\'".to_owned()));
1763 }
1764
1765 #[test]
1766 fn unescape_wrong_byte() {
1767 let string = r"\xfg";
1768
1769 assert_eq!(unescape(string), None);
1770 }
1771
1772 #[test]
1773 fn unescape_short_byte() {
1774 let string = r"\xf";
1775
1776 assert_eq!(unescape(string), None);
1777 }
1778
1779 #[test]
1780 fn unescape_no_open_brace_unicode() {
1781 let string = r"\u11";
1782
1783 assert_eq!(unescape(string), None);
1784 }
1785
1786 #[test]
1787 fn unescape_no_close_brace_unicode() {
1788 let string = r"\u{11";
1789
1790 assert_eq!(unescape(string), None);
1791 }
1792
1793 #[test]
1794 fn unescape_short_unicode() {
1795 let string = r"\u{1}";
1796
1797 assert_eq!(unescape(string), None);
1798 }
1799
1800 #[test]
1801 fn unescape_long_unicode() {
1802 let string = r"\u{1111111}";
1803
1804 assert_eq!(unescape(string), None);
1805 }
1806
1807 #[test]
1808 fn handles_deep_nesting() {
1809 let sample1 = include_str!(concat!(
1810 env!("CARGO_MANIFEST_DIR"),
1811 "/resources/test/fuzzsample1.grammar"
1812 ));
1813 let sample2 = include_str!(concat!(
1814 env!("CARGO_MANIFEST_DIR"),
1815 "/resources/test/fuzzsample2.grammar"
1816 ));
1817 let sample3 = include_str!(concat!(
1818 env!("CARGO_MANIFEST_DIR"),
1819 "/resources/test/fuzzsample3.grammar"
1820 ));
1821 let sample4 = include_str!(concat!(
1822 env!("CARGO_MANIFEST_DIR"),
1823 "/resources/test/fuzzsample4.grammar"
1824 ));
1825 let sample5 = include_str!(concat!(
1826 env!("CARGO_MANIFEST_DIR"),
1827 "/resources/test/fuzzsample5.grammar"
1828 ));
1829 const ERROR: &str = "call limit reached";
1830 pest::set_call_limit(Some(5_000usize.try_into().unwrap()));
1831 let s1 = parse(Rule::grammar_rules, sample1);
1832 assert!(s1.is_err());
1833 assert_eq!(s1.unwrap_err().variant.message(), ERROR);
1834 let s2 = parse(Rule::grammar_rules, sample2);
1835 assert!(s2.is_err());
1836 assert_eq!(s2.unwrap_err().variant.message(), ERROR);
1837 let s3 = parse(Rule::grammar_rules, sample3);
1838 assert!(s3.is_err());
1839 assert_eq!(s3.unwrap_err().variant.message(), ERROR);
1840 let s4 = parse(Rule::grammar_rules, sample4);
1841 assert!(s4.is_err());
1842 assert_eq!(s4.unwrap_err().variant.message(), ERROR);
1843 let s5 = parse(Rule::grammar_rules, sample5);
1844 assert!(s5.is_err());
1845 assert_eq!(s5.unwrap_err().variant.message(), ERROR);
1846 }
1847}