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