pest_meta/
parser.rs

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
12use 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/// Note: `include!` adds here a code generated from build.rs file.
24/// In case feature `not-bootstrap-in-src` is:
25/// * OFF  -> include generated `grammar.rs` file from meta/src
26/// * ON   -> include generated `__pest_grammar.rs` file from target/build/...
27#[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
36/// Import included grammar (`PestParser` class globally for current module).
37pub use self::grammar::*;
38
39/// A helper that will parse using the pest grammar
40#[allow(clippy::perf)]
41pub fn parse(rule: Rule, data: &str) -> Result<Pairs<'_, Rule>, Error<Rule>> {
42    PestParser::parse(rule, data)
43}
44
45/// The pest grammar rule
46#[derive(Clone, Debug, Eq, PartialEq)]
47pub struct ParserRule<'i> {
48    /// The rule's name
49    pub name: String,
50    /// The rule's span
51    pub span: Span<'i>,
52    /// The rule's type
53    pub ty: RuleType,
54    /// The rule's parser node
55    pub node: ParserNode<'i>,
56}
57
58/// The pest grammar node
59#[derive(Clone, Debug, Eq, PartialEq)]
60pub struct ParserNode<'i> {
61    /// The node's expression
62    pub expr: ParserExpr<'i>,
63    /// The node's span
64    pub span: Span<'i>,
65}
66
67impl<'i> ParserNode<'i> {
68    /// will remove nodes that do not match `f`
69    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/// All possible parser expressions
133#[derive(Clone, Debug, Eq, PartialEq)]
134pub enum ParserExpr<'i> {
135    /// Matches an exact string, e.g. `"a"`
136    Str(String),
137    /// Matches an exact string, case insensitively (ASCII only), e.g. `^"a"`
138    Insens(String),
139    /// Matches one character in the range, e.g. `'a'..'z'`
140    Range(String, String),
141    /// Matches the rule with the given name, e.g. `a`
142    Ident(String),
143    /// Matches a custom part of the stack, e.g. `PEEK[..]`
144    PeekSlice(i32, Option<i32>),
145    /// Positive lookahead; matches expression without making progress, e.g. `&e`
146    PosPred(Box<ParserNode<'i>>),
147    /// Negative lookahead; matches if expression doesn't match, without making progress, e.g. `!e`
148    NegPred(Box<ParserNode<'i>>),
149    /// Matches a sequence of two expressions, e.g. `e1 ~ e2`
150    Seq(Box<ParserNode<'i>>, Box<ParserNode<'i>>),
151    /// Matches either of two expressions, e.g. `e1 | e2`
152    Choice(Box<ParserNode<'i>>, Box<ParserNode<'i>>),
153    /// Optionally matches an expression, e.g. `e?`
154    Opt(Box<ParserNode<'i>>),
155    /// Matches an expression zero or more times, e.g. `e*`
156    Rep(Box<ParserNode<'i>>),
157    /// Matches an expression one or more times, e.g. `e+`
158    RepOnce(Box<ParserNode<'i>>),
159    /// Matches an expression an exact number of times, e.g. `e{n}`
160    RepExact(Box<ParserNode<'i>>, u32),
161    /// Matches an expression at least a number of times, e.g. `e{n,}`
162    RepMin(Box<ParserNode<'i>>, u32),
163    /// Matches an expression at most a number of times, e.g. `e{,n}`
164    RepMax(Box<ParserNode<'i>>, u32),
165    /// Matches an expression a number of times within a range, e.g. `e{m, n}`
166    RepMinMax(Box<ParserNode<'i>>, u32, u32),
167    /// Matches an expression and pushes it to the stack, e.g. `push(e)`
168    Push(Box<ParserNode<'i>>),
169    /// Pushes a literal string to the stack, e.g. `push_literal("a")`
170    #[cfg(feature = "grammar-extras")]
171    PushLiteral(String),
172    /// Matches an expression and assigns a label to it, e.g. #label = exp
173    #[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
217/// Converts a parser's result (`Pairs`) to an AST
218pub 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/// A helper function to rename verbose rules
229/// for the sake of better error messages
230#[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            // To ignore `grammar_rule > line_doc` pairs
276            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(); // assignment_operator
288
289            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(); // opening_brace
302
303            // skip initial infix operators
304            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(); // opening_paren
392                        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(); // opening_paren
406                        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(); // opening_brack
426                        let pair_start = pairs.next().unwrap(); // .. or integer
427                        let start: i32 = match pair_start.as_rule() {
428                            Rule::range_operator => 0,
429                            Rule::integer => {
430                                pairs.next().unwrap(); // ..
431                                pair_start.as_str().parse().unwrap()
432                            }
433                            _ => unreachable!("peek start"),
434                        };
435                        let pair_end = pairs.next().unwrap(); // integer or }
436                        let end: Option<i32> = match pair_end.as_rule() {
437                            Rule::closing_brack => None,
438                            Rule::integer => {
439                                pairs.next().unwrap(); // }
440                                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(); // opening_brace
515
516                            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(); // opening_brace
549
550                            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(); // opening_brace
572                            inner.next().unwrap(); // comma
573
574                            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(); // opening_brace
607
608                            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(); // comma
621
622                            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}