Coverage Report

Created: 2025-09-27 06:52

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
/// 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)]
28
mod 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).
37
pub use self::grammar::*;
38
39
/// A helper that will parse using the pest grammar
40
#[allow(clippy::perf)]
41
5.00k
pub fn parse(rule: Rule, data: &str) -> Result<Pairs<'_, Rule>, Error<Rule>> {
42
5.00k
    PestParser::parse(rule, data)
43
5.00k
}
44
45
/// The pest grammar rule
46
#[derive(Clone, Debug, Eq, PartialEq)]
47
pub 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)]
60
pub 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
67
impl<'i> ParserNode<'i> {
68
    /// will remove nodes that do not match `f`
69
0
    pub fn filter_map_top_down<F, T>(self, mut f: F) -> Vec<T>
70
0
    where
71
0
        F: FnMut(ParserNode<'i>) -> Option<T>,
72
    {
73
0
        pub fn filter_internal<'i, F, T>(node: ParserNode<'i>, f: &mut F, result: &mut Vec<T>)
74
0
        where
75
0
            F: FnMut(ParserNode<'i>) -> Option<T>,
76
        {
77
0
            if let Some(value) = f(node.clone()) {
78
0
                result.push(value);
79
0
            }
80
81
0
            match node.expr {
82
0
                ParserExpr::PosPred(node) => {
83
0
                    filter_internal(*node, f, result);
84
0
                }
85
0
                ParserExpr::NegPred(node) => {
86
0
                    filter_internal(*node, f, result);
87
0
                }
88
0
                ParserExpr::Seq(lhs, rhs) => {
89
0
                    filter_internal(*lhs, f, result);
90
0
                    filter_internal(*rhs, f, result);
91
0
                }
92
0
                ParserExpr::Choice(lhs, rhs) => {
93
0
                    filter_internal(*lhs, f, result);
94
0
                    filter_internal(*rhs, f, result);
95
0
                }
96
0
                ParserExpr::Rep(node) => {
97
0
                    filter_internal(*node, f, result);
98
0
                }
99
0
                ParserExpr::RepOnce(node) => {
100
0
                    filter_internal(*node, f, result);
101
0
                }
102
0
                ParserExpr::RepExact(node, _) => {
103
0
                    filter_internal(*node, f, result);
104
0
                }
105
0
                ParserExpr::RepMin(node, _) => {
106
0
                    filter_internal(*node, f, result);
107
0
                }
108
0
                ParserExpr::RepMax(node, _) => {
109
0
                    filter_internal(*node, f, result);
110
0
                }
111
0
                ParserExpr::RepMinMax(node, ..) => {
112
0
                    filter_internal(*node, f, result);
113
0
                }
114
0
                ParserExpr::Opt(node) => {
115
0
                    filter_internal(*node, f, result);
116
0
                }
117
0
                ParserExpr::Push(node) => {
118
0
                    filter_internal(*node, f, result);
119
0
                }
120
0
                _ => (),
121
            }
122
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>>
123
124
0
        let mut result = vec![];
125
126
0
        filter_internal(self, &mut f, &mut result);
127
128
0
        result
129
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>>
130
}
131
132
/// All possible parser expressions
133
#[derive(Clone, Debug, Eq, PartialEq)]
134
pub 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
177
0
fn convert_rule(rule: ParserRule<'_>) -> AstRule {
178
0
    let ParserRule { name, ty, node, .. } = rule;
179
0
    let expr = convert_node(node);
180
0
    AstRule { name, ty, expr }
181
0
}
182
183
0
fn convert_node(node: ParserNode<'_>) -> Expr {
184
0
    match node.expr {
185
0
        ParserExpr::Str(string) => Expr::Str(string),
186
0
        ParserExpr::Insens(string) => Expr::Insens(string),
187
0
        ParserExpr::Range(start, end) => Expr::Range(start, end),
188
0
        ParserExpr::Ident(ident) => Expr::Ident(ident),
189
0
        ParserExpr::PeekSlice(start, end) => Expr::PeekSlice(start, end),
190
0
        ParserExpr::PosPred(node) => Expr::PosPred(Box::new(convert_node(*node))),
191
0
        ParserExpr::NegPred(node) => Expr::NegPred(Box::new(convert_node(*node))),
192
0
        ParserExpr::Seq(node1, node2) => Expr::Seq(
193
0
            Box::new(convert_node(*node1)),
194
0
            Box::new(convert_node(*node2)),
195
0
        ),
196
0
        ParserExpr::Choice(node1, node2) => Expr::Choice(
197
0
            Box::new(convert_node(*node1)),
198
0
            Box::new(convert_node(*node2)),
199
0
        ),
200
0
        ParserExpr::Opt(node) => Expr::Opt(Box::new(convert_node(*node))),
201
0
        ParserExpr::Rep(node) => Expr::Rep(Box::new(convert_node(*node))),
202
0
        ParserExpr::RepOnce(node) => Expr::RepOnce(Box::new(convert_node(*node))),
203
0
        ParserExpr::RepExact(node, num) => Expr::RepExact(Box::new(convert_node(*node)), num),
204
0
        ParserExpr::RepMin(node, max) => Expr::RepMin(Box::new(convert_node(*node)), max),
205
0
        ParserExpr::RepMax(node, max) => Expr::RepMax(Box::new(convert_node(*node)), max),
206
0
        ParserExpr::RepMinMax(node, min, max) => {
207
0
            Expr::RepMinMax(Box::new(convert_node(*node)), min, max)
208
        }
209
0
        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
0
}
216
217
/// Converts a parser's result (`Pairs`) to an AST
218
0
pub fn consume_rules(pairs: Pairs<'_, Rule>) -> Result<Vec<AstRule>, Vec<Error<Rule>>> {
219
0
    let rules = consume_rules_with_spans(pairs)?;
220
0
    let errors = validator::validate_ast(&rules);
221
0
    if errors.is_empty() {
222
0
        Ok(rules.into_iter().map(convert_rule).collect())
223
    } else {
224
0
        Err(errors)
225
    }
226
0
}
227
228
/// A helper function to rename verbose rules
229
/// for the sake of better error messages
230
#[inline]
231
pub 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
265
0
fn consume_rules_with_spans(
266
0
    pairs: Pairs<'_, Rule>,
267
0
) -> Result<Vec<ParserRule<'_>>, Vec<Error<Rule>>> {
268
0
    let pratt = PrattParser::new()
269
0
        .op(Op::infix(Rule::choice_operator, Assoc::Left))
270
0
        .op(Op::infix(Rule::sequence_operator, Assoc::Left));
271
272
0
    pairs
273
0
        .filter(|pair| pair.as_rule() == Rule::grammar_rule)
274
0
        .filter(|pair| {
275
            // To ignore `grammar_rule > line_doc` pairs
276
0
            let mut pairs = pair.clone().into_inner();
277
0
            let pair = pairs.next().unwrap();
278
279
0
            pair.as_rule() != Rule::line_doc
280
0
        })
281
0
        .map(|pair| {
282
0
            let mut pairs = pair.into_inner().peekable();
283
284
0
            let span = pairs.next().unwrap().as_span();
285
0
            let name = span.as_str().to_owned();
286
287
0
            pairs.next().unwrap(); // assignment_operator
288
289
0
            let ty = if pairs.peek().unwrap().as_rule() != Rule::opening_brace {
290
0
                match pairs.next().unwrap().as_rule() {
291
0
                    Rule::silent_modifier => RuleType::Silent,
292
0
                    Rule::atomic_modifier => RuleType::Atomic,
293
0
                    Rule::compound_atomic_modifier => RuleType::CompoundAtomic,
294
0
                    Rule::non_atomic_modifier => RuleType::NonAtomic,
295
0
                    _ => unreachable!(),
296
                }
297
            } else {
298
0
                RuleType::Normal
299
            };
300
301
0
            pairs.next().unwrap(); // opening_brace
302
303
            // skip initial infix operators
304
0
            let mut inner_nodes = pairs.next().unwrap().into_inner().peekable();
305
0
            if inner_nodes.peek().unwrap().as_rule() == Rule::choice_operator {
306
0
                inner_nodes.next().unwrap();
307
0
            }
308
309
0
            let node = consume_expr(inner_nodes, &pratt)?;
310
311
0
            Ok(ParserRule {
312
0
                name,
313
0
                span,
314
0
                ty,
315
0
                node,
316
0
            })
317
0
        })
318
0
        .collect()
319
0
}
320
321
0
fn get_node_tag<'i>(
322
0
    pairs: &mut Peekable<Pairs<'i, Rule>>,
323
0
) -> (Pair<'i, Rule>, Option<(String, Position<'i>)>) {
324
0
    let pair_or_tag = pairs.next().unwrap();
325
0
    if let Some(next_pair) = pairs.peek() {
326
0
        if next_pair.as_rule() == Rule::assignment_operator {
327
0
            pairs.next().unwrap();
328
0
            let pair = pairs.next().unwrap();
329
0
            (
330
0
                pair,
331
0
                Some((
332
0
                    pair_or_tag.as_str()[1..].to_string(),
333
0
                    pair_or_tag.as_span().start_pos(),
334
0
                )),
335
0
            )
336
        } else {
337
0
            (pair_or_tag, None)
338
        }
339
    } else {
340
0
        (pair_or_tag, None)
341
    }
342
0
}
343
344
0
fn consume_expr<'i>(
345
0
    pairs: Peekable<Pairs<'i, Rule>>,
346
0
    pratt: &PrattParser<Rule>,
347
0
) -> Result<ParserNode<'i>, Vec<Error<Rule>>> {
348
0
    fn unaries<'i>(
349
0
        mut pairs: Peekable<Pairs<'i, Rule>>,
350
0
        pratt: &PrattParser<Rule>,
351
0
    ) -> 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
0
        let (pair, _tag_start) = get_node_tag(&mut pairs);
356
357
0
        let node = match pair.as_rule() {
358
            Rule::opening_paren => {
359
0
                let node = unaries(pairs, pratt)?;
360
0
                let end = node.span.end_pos();
361
362
0
                ParserNode {
363
0
                    expr: node.expr,
364
0
                    span: pair.as_span().start_pos().span(&end),
365
0
                }
366
            }
367
            Rule::positive_predicate_operator => {
368
0
                let node = unaries(pairs, pratt)?;
369
0
                let end = node.span.end_pos();
370
371
0
                ParserNode {
372
0
                    expr: ParserExpr::PosPred(Box::new(node)),
373
0
                    span: pair.as_span().start_pos().span(&end),
374
0
                }
375
            }
376
            Rule::negative_predicate_operator => {
377
0
                let node = unaries(pairs, pratt)?;
378
0
                let end = node.span.end_pos();
379
380
0
                ParserNode {
381
0
                    expr: ParserExpr::NegPred(Box::new(node)),
382
0
                    span: pair.as_span().start_pos().span(&end),
383
0
                }
384
            }
385
0
            other_rule => {
386
0
                let node = match other_rule {
387
0
                    Rule::expression => consume_expr(pair.into_inner().peekable(), pratt)?,
388
                    Rule::_push => {
389
0
                        let start = pair.clone().as_span().start_pos();
390
0
                        let mut pairs = pair.into_inner();
391
0
                        pairs.next().unwrap(); // opening_paren
392
0
                        let pair = pairs.next().unwrap();
393
394
0
                        let node = consume_expr(pair.into_inner().peekable(), pratt)?;
395
0
                        let end = node.span.end_pos();
396
397
0
                        ParserNode {
398
0
                            expr: ParserExpr::Push(Box::new(node)),
399
0
                            span: start.span(&end),
400
0
                        }
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
0
                        return Err(vec![Error::new_from_span(
417
0
                            ErrorVariant::CustomError {
418
0
                                message: "PUSH_LITERAL requires feature grammar-extras".to_owned(),
419
0
                            },
420
0
                            pair.as_span(),
421
0
                        )]);
422
                    }
423
                    Rule::peek_slice => {
424
0
                        let mut pairs = pair.clone().into_inner();
425
0
                        pairs.next().unwrap(); // opening_brack
426
0
                        let pair_start = pairs.next().unwrap(); // .. or integer
427
0
                        let start: i32 = match pair_start.as_rule() {
428
0
                            Rule::range_operator => 0,
429
                            Rule::integer => {
430
0
                                pairs.next().unwrap(); // ..
431
0
                                pair_start.as_str().parse().unwrap()
432
                            }
433
0
                            _ => unreachable!("peek start"),
434
                        };
435
0
                        let pair_end = pairs.next().unwrap(); // integer or }
436
0
                        let end: Option<i32> = match pair_end.as_rule() {
437
0
                            Rule::closing_brack => None,
438
                            Rule::integer => {
439
0
                                pairs.next().unwrap(); // }
440
0
                                Some(pair_end.as_str().parse().unwrap())
441
                            }
442
0
                            _ => unreachable!("peek end"),
443
                        };
444
0
                        ParserNode {
445
0
                            expr: ParserExpr::PeekSlice(start, end),
446
0
                            span: pair.as_span(),
447
0
                        }
448
                    }
449
0
                    Rule::identifier => ParserNode {
450
0
                        expr: ParserExpr::Ident(pair.as_str().to_owned()),
451
0
                        span: pair.clone().as_span(),
452
0
                    },
453
                    Rule::string => {
454
0
                        let string = unescape(pair.as_str()).expect("incorrect string literal");
455
0
                        ParserNode {
456
0
                            expr: ParserExpr::Str(string[1..string.len() - 1].to_owned()),
457
0
                            span: pair.clone().as_span(),
458
0
                        }
459
                    }
460
                    Rule::insensitive_string => {
461
0
                        let string = unescape(pair.as_str()).expect("incorrect string literal");
462
0
                        ParserNode {
463
0
                            expr: ParserExpr::Insens(string[2..string.len() - 1].to_owned()),
464
0
                            span: pair.clone().as_span(),
465
0
                        }
466
                    }
467
                    Rule::range => {
468
0
                        let mut pairs = pair.into_inner();
469
0
                        let pair = pairs.next().unwrap();
470
0
                        let start = unescape(pair.as_str()).expect("incorrect char literal");
471
0
                        let start_pos = pair.clone().as_span().start_pos();
472
0
                        pairs.next();
473
0
                        let pair = pairs.next().unwrap();
474
0
                        let end = unescape(pair.as_str()).expect("incorrect char literal");
475
0
                        let end_pos = pair.clone().as_span().end_pos();
476
477
0
                        ParserNode {
478
0
                            expr: ParserExpr::Range(
479
0
                                start[1..start.len() - 1].to_owned(),
480
0
                                end[1..end.len() - 1].to_owned(),
481
0
                            ),
482
0
                            span: start_pos.span(&end_pos),
483
0
                        }
484
                    }
485
0
                    x => unreachable!("other rule: {:?}", x),
486
                };
487
488
0
                pairs.try_fold(node, |node: ParserNode<'i>, pair: Pair<'i, Rule>| {
489
0
                    let node = match pair.as_rule() {
490
                        Rule::optional_operator => {
491
0
                            let start = node.span.start_pos();
492
0
                            ParserNode {
493
0
                                expr: ParserExpr::Opt(Box::new(node)),
494
0
                                span: start.span(&pair.as_span().end_pos()),
495
0
                            }
496
                        }
497
                        Rule::repeat_operator => {
498
0
                            let start = node.span.start_pos();
499
0
                            ParserNode {
500
0
                                expr: ParserExpr::Rep(Box::new(node)),
501
0
                                span: start.span(&pair.as_span().end_pos()),
502
0
                            }
503
                        }
504
                        Rule::repeat_once_operator => {
505
0
                            let start = node.span.start_pos();
506
0
                            ParserNode {
507
0
                                expr: ParserExpr::RepOnce(Box::new(node)),
508
0
                                span: start.span(&pair.as_span().end_pos()),
509
0
                            }
510
                        }
511
                        Rule::repeat_exact => {
512
0
                            let mut inner = pair.clone().into_inner();
513
514
0
                            inner.next().unwrap(); // opening_brace
515
516
0
                            let number = inner.next().unwrap();
517
0
                            let num = if let Ok(num) = number.as_str().parse::<u32>() {
518
0
                                num
519
                            } else {
520
0
                                return Err(vec![Error::new_from_span(
521
0
                                    ErrorVariant::CustomError {
522
0
                                        message: "number cannot overflow u32".to_owned(),
523
0
                                    },
524
0
                                    number.as_span(),
525
0
                                )]);
526
                            };
527
528
0
                            if num == 0 {
529
0
                                let error: Error<Rule> = Error::new_from_span(
530
0
                                    ErrorVariant::CustomError {
531
0
                                        message: "cannot repeat 0 times".to_owned(),
532
0
                                    },
533
0
                                    number.as_span(),
534
                                );
535
536
0
                                return Err(vec![error]);
537
0
                            }
538
539
0
                            let start = node.span.start_pos();
540
0
                            ParserNode {
541
0
                                expr: ParserExpr::RepExact(Box::new(node), num),
542
0
                                span: start.span(&pair.as_span().end_pos()),
543
0
                            }
544
                        }
545
                        Rule::repeat_min => {
546
0
                            let mut inner = pair.clone().into_inner();
547
548
0
                            inner.next().unwrap(); // opening_brace
549
550
0
                            let min_number = inner.next().unwrap();
551
0
                            let min = if let Ok(min) = min_number.as_str().parse::<u32>() {
552
0
                                min
553
                            } else {
554
0
                                return Err(vec![Error::new_from_span(
555
0
                                    ErrorVariant::CustomError {
556
0
                                        message: "number cannot overflow u32".to_owned(),
557
0
                                    },
558
0
                                    min_number.as_span(),
559
0
                                )]);
560
                            };
561
562
0
                            let start = node.span.start_pos();
563
0
                            ParserNode {
564
0
                                expr: ParserExpr::RepMin(Box::new(node), min),
565
0
                                span: start.span(&pair.as_span().end_pos()),
566
0
                            }
567
                        }
568
                        Rule::repeat_max => {
569
0
                            let mut inner = pair.clone().into_inner();
570
571
0
                            inner.next().unwrap(); // opening_brace
572
0
                            inner.next().unwrap(); // comma
573
574
0
                            let max_number = inner.next().unwrap();
575
0
                            let max = if let Ok(max) = max_number.as_str().parse::<u32>() {
576
0
                                max
577
                            } else {
578
0
                                return Err(vec![Error::new_from_span(
579
0
                                    ErrorVariant::CustomError {
580
0
                                        message: "number cannot overflow u32".to_owned(),
581
0
                                    },
582
0
                                    max_number.as_span(),
583
0
                                )]);
584
                            };
585
586
0
                            if max == 0 {
587
0
                                let error: Error<Rule> = Error::new_from_span(
588
0
                                    ErrorVariant::CustomError {
589
0
                                        message: "cannot repeat 0 times".to_owned(),
590
0
                                    },
591
0
                                    max_number.as_span(),
592
                                );
593
594
0
                                return Err(vec![error]);
595
0
                            }
596
597
0
                            let start = node.span.start_pos();
598
0
                            ParserNode {
599
0
                                expr: ParserExpr::RepMax(Box::new(node), max),
600
0
                                span: start.span(&pair.as_span().end_pos()),
601
0
                            }
602
                        }
603
                        Rule::repeat_min_max => {
604
0
                            let mut inner = pair.clone().into_inner();
605
606
0
                            inner.next().unwrap(); // opening_brace
607
608
0
                            let min_number = inner.next().unwrap();
609
0
                            let min = if let Ok(min) = min_number.as_str().parse::<u32>() {
610
0
                                min
611
                            } else {
612
0
                                return Err(vec![Error::new_from_span(
613
0
                                    ErrorVariant::CustomError {
614
0
                                        message: "number cannot overflow u32".to_owned(),
615
0
                                    },
616
0
                                    min_number.as_span(),
617
0
                                )]);
618
                            };
619
620
0
                            inner.next().unwrap(); // comma
621
622
0
                            let max_number = inner.next().unwrap();
623
0
                            let max = if let Ok(max) = max_number.as_str().parse::<u32>() {
624
0
                                max
625
                            } else {
626
0
                                return Err(vec![Error::new_from_span(
627
0
                                    ErrorVariant::CustomError {
628
0
                                        message: "number cannot overflow u32".to_owned(),
629
0
                                    },
630
0
                                    max_number.as_span(),
631
0
                                )]);
632
                            };
633
634
0
                            if max == 0 {
635
0
                                let error: Error<Rule> = Error::new_from_span(
636
0
                                    ErrorVariant::CustomError {
637
0
                                        message: "cannot repeat 0 times".to_owned(),
638
0
                                    },
639
0
                                    max_number.as_span(),
640
                                );
641
642
0
                                return Err(vec![error]);
643
0
                            }
644
645
0
                            let start = node.span.start_pos();
646
0
                            ParserNode {
647
0
                                expr: ParserExpr::RepMinMax(Box::new(node), min, max),
648
0
                                span: start.span(&pair.as_span().end_pos()),
649
0
                            }
650
                        }
651
                        Rule::closing_paren => {
652
0
                            let start = node.span.start_pos();
653
654
0
                            ParserNode {
655
0
                                expr: node.expr,
656
0
                                span: start.span(&pair.as_span().end_pos()),
657
0
                            }
658
                        }
659
0
                        rule => unreachable!("node: {:?}", rule),
660
                    };
661
662
0
                    Ok(node)
663
0
                })?
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
0
        Ok(node)
678
0
    }
679
680
0
    let term = |pair: Pair<'i, Rule>| unaries(pair.into_inner().peekable(), pratt);
681
0
    let infix = |lhs: Result<ParserNode<'i>, Vec<Error<Rule>>>,
682
                 op: Pair<'i, Rule>,
683
0
                 rhs: Result<ParserNode<'i>, Vec<Error<Rule>>>| match op.as_rule() {
684
        Rule::sequence_operator => {
685
0
            let lhs = lhs?;
686
0
            let rhs = rhs?;
687
688
0
            let start = lhs.span.start_pos();
689
0
            let end = rhs.span.end_pos();
690
691
0
            Ok(ParserNode {
692
0
                expr: ParserExpr::Seq(Box::new(lhs), Box::new(rhs)),
693
0
                span: start.span(&end),
694
0
            })
695
        }
696
        Rule::choice_operator => {
697
0
            let lhs = lhs?;
698
0
            let rhs = rhs?;
699
700
0
            let start = lhs.span.start_pos();
701
0
            let end = rhs.span.end_pos();
702
703
0
            Ok(ParserNode {
704
0
                expr: ParserExpr::Choice(Box::new(lhs), Box::new(rhs)),
705
0
                span: start.span(&end),
706
0
            })
707
        }
708
0
        _ => unreachable!("infix"),
709
0
    };
710
711
0
    pratt.map_primary(term).map_infix(infix).parse(pairs)
712
0
}
713
714
0
fn unescape(string: &str) -> Option<String> {
715
0
    let mut result = String::new();
716
0
    let mut chars = string.chars();
717
718
    loop {
719
0
        match chars.next() {
720
0
            Some('\\') => match chars.next()? {
721
0
                '"' => result.push('"'),
722
0
                '\\' => result.push('\\'),
723
0
                'r' => result.push('\r'),
724
0
                'n' => result.push('\n'),
725
0
                't' => result.push('\t'),
726
0
                '0' => result.push('\0'),
727
0
                '\'' => result.push('\''),
728
                'x' => {
729
0
                    let string: String = chars.clone().take(2).collect();
730
731
0
                    if string.len() != 2 {
732
0
                        return None;
733
0
                    }
734
735
0
                    for _ in 0..string.len() {
736
0
                        chars.next()?;
737
                    }
738
739
0
                    let value = u8::from_str_radix(&string, 16).ok()?;
740
741
0
                    result.push(char::from(value));
742
                }
743
                'u' => {
744
0
                    if chars.next()? != '{' {
745
0
                        return None;
746
0
                    }
747
748
0
                    let string: String = chars.clone().take_while(|c| *c != '}').collect();
749
750
0
                    if string.len() < 2 || 6 < string.len() {
751
0
                        return None;
752
0
                    }
753
754
0
                    for _ in 0..string.len() + 1 {
755
0
                        chars.next()?;
756
                    }
757
758
0
                    let value = u32::from_str_radix(&string, 16).ok()?;
759
760
0
                    result.push(char::from_u32(value)?);
761
                }
762
0
                _ => return None,
763
            },
764
0
            Some(c) => result.push(c),
765
0
            None => return Some(result),
766
        };
767
    }
768
0
}
769
770
#[cfg(test)]
771
mod 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
  |
1567
1 | 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
  |
1607
1 | 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
  |
1623
1 | 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
  |
1639
1 | 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
  |
1655
1 | 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
  |
1671
1 | 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
  |
1687
1 | 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
  |
1703
1 | 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
}