Coverage Report

Created: 2026-04-12 06:48

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