Coverage Report

Created: 2025-08-26 06:21

/rust/registry/src/index.crates.io-6f17d22bba15001f/pest-2.8.1/src/parser_state.rs
Line
Count
Source (jump to first uncovered line)
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
//! The core functionality of parsing grammar.
11
//! State of parser during the process of rules handling.
12
13
use alloc::borrow::{Cow, ToOwned};
14
use alloc::boxed::Box;
15
use alloc::collections::BTreeSet;
16
use alloc::rc::Rc;
17
use alloc::string::String;
18
use alloc::sync::Arc;
19
use alloc::vec;
20
use alloc::vec::Vec;
21
use core::fmt::{Debug, Display, Formatter};
22
use core::num::NonZeroUsize;
23
use core::ops::Deref; // used in BorrowedOrRc.as_str
24
use core::ops::Range;
25
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
26
27
use crate::error::{Error, ErrorVariant};
28
use crate::iterators::pairs::new;
29
use crate::iterators::{pairs, QueueableToken};
30
use crate::position::Position;
31
use crate::span::Span;
32
use crate::stack::Stack;
33
use crate::RuleType;
34
35
/// The current lookahead status of a [`ParserState`].
36
///
37
/// [`ParserState`]: struct.ParserState.html
38
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
39
pub enum Lookahead {
40
    /// The positive predicate, written as an ampersand &,
41
    /// attempts to match its inner expression.
42
    /// If the inner expression succeeds, parsing continues,
43
    /// but at the same position as the predicate —
44
    /// &foo ~ bar is thus a kind of "AND" statement:
45
    /// "the input string must match foo AND bar".
46
    /// If the inner expression fails,
47
    /// the whole expression fails too.
48
    Positive,
49
    /// The negative predicate, written as an exclamation mark !,
50
    /// attempts to match its inner expression.
51
    /// If the inner expression fails, the predicate succeeds
52
    /// and parsing continues at the same position as the predicate.
53
    /// If the inner expression succeeds, the predicate fails —
54
    /// !foo ~ bar is thus a kind of "NOT" statement:
55
    /// "the input string must match bar but NOT foo".
56
    Negative,
57
    /// No lookahead (i.e. it will consume input).
58
    None,
59
}
60
61
/// The current atomicity of a [`ParserState`].
62
///
63
/// [`ParserState`]: struct.ParserState.html
64
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
65
pub enum Atomicity {
66
    /// prevents implicit whitespace: inside an atomic rule,
67
    /// the tilde ~ means "immediately followed by",
68
    /// and repetition operators (asterisk * and plus sign +)
69
    /// have no implicit separation. In addition, all other rules
70
    /// called from an atomic rule are also treated as atomic.
71
    /// (interior matching rules are silent)
72
    Atomic,
73
    /// The same as atomic, but inner tokens are produced as normal.
74
    CompoundAtomic,
75
    /// implicit whitespace is enabled
76
    NonAtomic,
77
}
78
79
/// Type alias to simplify specifying the return value of chained closures.
80
pub type ParseResult<S> = Result<S, S>;
81
82
/// Match direction for the stack. Used in `PEEK[a..b]`/`stack_match_peek_slice`.
83
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
84
pub enum MatchDir {
85
    /// from the bottom to the top of the stack
86
    BottomToTop,
87
    /// from the top to the bottom of the stack
88
    TopToBottom,
89
}
90
91
static CALL_LIMIT: AtomicUsize = AtomicUsize::new(0);
92
93
/// Sets the maximum call limit for the parser state
94
/// to prevent stack overflows or excessive execution times
95
/// in some grammars.
96
/// If set, the calls are tracked as a running total
97
/// over all non-terminal rules that can nest closures
98
/// (which are passed to transform the parser state).
99
///
100
/// # Arguments
101
///
102
/// * `limit` - The maximum number of calls. If None,
103
///             the number of calls is unlimited.
104
0
pub fn set_call_limit(limit: Option<NonZeroUsize>) {
105
0
    CALL_LIMIT.store(limit.map(|f| f.get()).unwrap_or(0), Ordering::Relaxed);
106
0
}
107
108
static ERROR_DETAIL: AtomicBool = AtomicBool::new(false);
109
110
/// Sets whether information for more error details
111
/// should be collected. This is useful for debugging
112
/// parser errors (as it leads to more comprehensive
113
/// error messages), but it has a higher performance cost.
114
/// (hence, it's off by default)
115
///
116
/// # Arguments
117
///
118
/// * `enabled` - Whether to enable the collection for
119
///               more error details.
120
0
pub fn set_error_detail(enabled: bool) {
121
0
    ERROR_DETAIL.store(enabled, Ordering::Relaxed);
122
0
}
123
124
#[derive(Debug)]
125
struct CallLimitTracker {
126
    current_call_limit: Option<(usize, usize)>,
127
}
128
129
impl Default for CallLimitTracker {
130
0
    fn default() -> Self {
131
0
        let limit = CALL_LIMIT.load(Ordering::Relaxed);
132
0
        let current_call_limit = if limit > 0 { Some((0, limit)) } else { None };
133
0
        Self { current_call_limit }
134
0
    }
135
}
136
137
impl CallLimitTracker {
138
0
    fn limit_reached(&self) -> bool {
139
0
        self.current_call_limit
140
0
            .map_or(false, |(current, limit)| current >= limit)
141
0
    }
142
143
0
    fn increment_depth(&mut self) {
144
0
        if let Some((current, _)) = &mut self.current_call_limit {
145
0
            *current += 1;
146
0
        }
147
0
    }
148
}
149
150
/// Number of call stacks that may result from a sequence of rules parsing.
151
const CALL_STACK_INITIAL_CAPACITY: usize = 20;
152
/// Max (un)expected number of tokens that we may see on the parsing error position.
153
const EXPECTED_TOKENS_INITIAL_CAPACITY: usize = 30;
154
/// Max rule children number for which we'll extend calls stacks.
155
///
156
/// In case rule we're working with has too many children rules that failed in parsing,
157
/// we don't want to store long stacks for all of them. If rule has more than this number
158
/// of failed children, they all will be collapsed in a parent rule.
159
const CALL_STACK_CHILDREN_THRESHOLD: usize = 4;
160
161
/// Structure tracking errored parsing call (associated with specific `ParserState` function).
162
#[derive(Debug, Hash, PartialEq, Eq, Clone, PartialOrd, Ord)]
163
pub enum ParseAttempt<R> {
164
    /// Call of `rule` errored.
165
    Rule(R),
166
    /// Call of token element (e.g., `match_string` or `match_insensitive`) errored.
167
    /// Works as indicator of that leaf node is not a rule. In order to get the token value we
168
    /// can address `ParseAttempts` `(un)expected_tokens`.
169
    Token,
170
}
171
172
impl<R> ParseAttempt<R> {
173
0
    pub fn get_rule(&self) -> Option<&R> {
174
0
        match self {
175
0
            ParseAttempt::Rule(r) => Some(r),
176
0
            ParseAttempt::Token => None,
177
        }
178
0
    }
179
}
180
181
/// Rules call stack.
182
/// Contains sequence of rule calls that resulted in new parsing attempt.
183
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
184
pub struct RulesCallStack<R> {
185
    /// Deepest rule caused a parsing error (ParseAttempt::Token transformed into a rule).
186
    pub deepest: ParseAttempt<R>,
187
    /// Most top rule covering `deepest`.
188
    pub parent: Option<R>,
189
}
190
191
impl<R> RulesCallStack<R> {
192
0
    fn new(deepest: ParseAttempt<R>) -> RulesCallStack<R> {
193
0
        RulesCallStack {
194
0
            deepest,
195
0
            parent: None,
196
0
        }
197
0
    }
Unexecuted instantiation: <pest::parser_state::RulesCallStack<semver_parser::generated::Rule>>::new
Unexecuted instantiation: <pest::parser_state::RulesCallStack<_>>::new
198
}
199
200
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
201
pub enum ParsingToken {
202
    Sensitive { token: String },
203
    Insensitive { token: String },
204
    Range { start: char, end: char },
205
    BuiltInRule,
206
}
207
208
impl Display for ParsingToken {
209
0
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
210
0
        match self {
211
0
            ParsingToken::Sensitive { token } => write!(f, "{token}"),
212
0
            ParsingToken::Insensitive { token } => write!(f, "{}", token.to_uppercase()),
213
0
            ParsingToken::Range { start, end } => write!(f, "{start}..{end}"),
214
0
            ParsingToken::BuiltInRule => write!(f, "BUILTIN_RULE"),
215
        }
216
0
    }
217
}
218
/// A helper that provides efficient string handling without unnecessary copying.
219
/// We use `Arc<String>` instead of `Cow<'i, str>` to avoid copying strings when cloning the `Owned` variant, since
220
/// `Arc::clone` only increments a reference count. [SpanOrLiteral] needs to be [Send] and [Sync]`, so we use [Arc]
221
/// instead of [Rc].
222
///
223
/// (We need to clone this struct to detach it from the `&self` borrow in [SpanOrLiteral::as_borrowed_or_rc], so that
224
/// we can then call `self.match_string` (a `mut self` method).
225
#[derive(Debug, Clone)]
226
enum BorrowedOrArc<'i> {
227
    Borrowed(&'i str),
228
    Owned(Arc<String>),
229
}
230
231
/// A holder for a literal string, for use in `push_literal`. This is typically a `&'static str`, but is an owned
232
/// `Rc<String>` for the pest vm.
233
impl<'i> BorrowedOrArc<'i> {
234
0
    fn as_str<'a: 'i>(&'a self) -> &'a str {
235
0
        match self {
236
0
            BorrowedOrArc::Borrowed(s) => s,
237
0
            BorrowedOrArc::Owned(s) => s.deref(),
238
        }
239
0
    }
240
}
241
242
impl From<Cow<'static, str>> for BorrowedOrArc<'_> {
243
0
    fn from(value: Cow<'static, str>) -> Self {
244
0
        match value {
245
0
            Cow::Borrowed(s) => Self::Borrowed(s),
246
0
            Cow::Owned(s) => Self::Owned(Arc::new(s)),
247
        }
248
0
    }
249
}
250
251
#[derive(Debug, Clone)]
252
enum SpanOrLiteral<'i> {
253
    Span(Span<'i>),
254
    Literal(BorrowedOrArc<'i>),
255
}
256
257
impl<'i> SpanOrLiteral<'i> {
258
    #[inline]
259
0
    fn as_borrowed_or_rc(&self) -> BorrowedOrArc<'i> {
260
0
        match self {
261
0
            Self::Span(s) => BorrowedOrArc::Borrowed(s.as_str()),
262
0
            Self::Literal(s) => s.clone(),
263
        }
264
0
    }
265
}
266
267
/// Structure that tracks all the parsing attempts made on the max position.
268
/// We want to give an error hint about parsing rules that succeeded
269
/// at the farthest input position.
270
/// The intuition is such rules will be most likely the query user initially wanted to write.
271
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
272
pub struct ParseAttempts<R> {
273
    /// Indicates whether the parsing attempts are tracked.
274
    enabled: bool,
275
    /// Vec of rule calls sequences awaiting tokens at the same `max_position`.
276
    /// If there are several stacks in vec, it means all those rule stacks are "equal"
277
    /// because their attempts occurred on the same position.
278
    pub call_stacks: Vec<RulesCallStack<R>>,
279
    /// Tokens that could be putted at `max_position`
280
    /// in order to get a valid grammar query.
281
    expected_tokens: Vec<ParsingToken>,
282
    /// Tokens that we've prohibited to be putted at `max_position`
283
    /// in order to get a valid grammar query.
284
    unexpected_tokens: Vec<ParsingToken>,
285
    /// Max position at which we were expecting to see one of `expected_tokens`.
286
    pub max_position: usize,
287
}
288
289
impl<R: RuleType> ParseAttempts<R> {
290
    /// Create new `ParseAttempts` instance with `call_stacks` and `expected_tokens`
291
    /// initialized with capacity.
292
0
    pub fn new() -> Self {
293
0
        Self {
294
0
            call_stacks: Vec::with_capacity(CALL_STACK_INITIAL_CAPACITY),
295
0
            expected_tokens: Vec::with_capacity(EXPECTED_TOKENS_INITIAL_CAPACITY),
296
0
            unexpected_tokens: Vec::with_capacity(EXPECTED_TOKENS_INITIAL_CAPACITY),
297
0
            max_position: 0,
298
0
            enabled: ERROR_DETAIL.load(Ordering::Relaxed),
299
0
        }
300
0
    }
Unexecuted instantiation: <pest::parser_state::ParseAttempts<semver_parser::generated::Rule>>::new
Unexecuted instantiation: <pest::parser_state::ParseAttempts<_>>::new
301
302
    /// Get number of currently present call stacks.
303
0
    fn call_stacks_number(&self) -> usize {
304
0
        self.call_stacks.len()
305
0
    }
Unexecuted instantiation: <pest::parser_state::ParseAttempts<semver_parser::generated::Rule>>::call_stacks_number
Unexecuted instantiation: <pest::parser_state::ParseAttempts<_>>::call_stacks_number
306
307
0
    pub fn expected_tokens(&self) -> Vec<ParsingToken> {
308
0
        self.expected_tokens
309
0
            .iter()
310
0
            .cloned()
311
0
            .collect::<BTreeSet<_>>()
312
0
            .into_iter()
313
0
            .collect()
314
0
    }
315
316
0
    pub fn unexpected_tokens(&self) -> Vec<ParsingToken> {
317
0
        self.unexpected_tokens
318
0
            .iter()
319
0
            .cloned()
320
0
            .collect::<BTreeSet<_>>()
321
0
            .into_iter()
322
0
            .collect()
323
0
    }
324
325
    /// Retrieve call stacks.
326
0
    pub fn call_stacks(&self) -> Vec<RulesCallStack<R>> {
327
0
        self.call_stacks
328
0
            .iter()
329
0
            .cloned()
330
0
            .collect::<BTreeSet<_>>()
331
0
            .into_iter()
332
0
            .collect()
333
0
    }
334
335
    /// In case we've tried to parse a rule, which start position is bigger than previous
336
    /// `max_position` it means that we've advanced in our parsing and found better candidate.
337
    ///
338
    /// `start_index` is:
339
    /// * Number of call stacks present in state at the moment current `rule` was called. The idea
340
    ///   is that we'd like to update only those stacks that originated from the current `rule` and
341
    ///   not from those that were called previously.
342
    /// * 0 in case we've successfully parsed some token since the moment `rule` was called.
343
0
    fn try_add_new_stack_rule(&mut self, rule: R, start_index: usize) {
344
0
        let mut non_token_call_stacks = Vec::new();
345
0
        let mut token_call_stack_met = false;
346
0
        for call_stack in self.call_stacks.iter().skip(start_index) {
347
0
            if matches!(call_stack.deepest, ParseAttempt::Token) {
348
0
                token_call_stack_met = true;
349
0
            } else {
350
0
                non_token_call_stacks.push(call_stack.clone())
351
            }
352
        }
353
0
        if token_call_stack_met && non_token_call_stacks.is_empty() {
354
0
            // If `non_token_call_stacks` is not empty we wouldn't like to add a new standalone
355
0
            // `RulesCallStack::new(ParseAttempt::Token)` (that will later be transformed into a
356
0
            // rule) as soon as it doesn't give us any useful additional info.
357
0
            non_token_call_stacks.push(RulesCallStack::new(ParseAttempt::Token));
358
0
        }
359
0
        self.call_stacks
360
0
            .splice(start_index.., non_token_call_stacks);
361
0
362
0
        let children_number_over_threshold =
363
0
            self.call_stacks_number() - start_index >= CALL_STACK_CHILDREN_THRESHOLD;
364
0
        if children_number_over_threshold {
365
0
            self.call_stacks.truncate(start_index);
366
0
            self.call_stacks
367
0
                .push(RulesCallStack::new(ParseAttempt::Rule(rule)));
368
0
        } else {
369
0
            for call_stack in self.call_stacks.iter_mut().skip(start_index) {
370
0
                if matches!(call_stack.deepest, ParseAttempt::Token) {
371
0
                    call_stack.deepest = ParseAttempt::Rule(rule);
372
0
                } else {
373
0
                    call_stack.parent = Some(rule);
374
0
                }
375
            }
376
        }
377
0
    }
Unexecuted instantiation: <pest::parser_state::ParseAttempts<semver_parser::generated::Rule>>::try_add_new_stack_rule
Unexecuted instantiation: <pest::parser_state::ParseAttempts<_>>::try_add_new_stack_rule
378
379
    /// If `expected` flag is set to false, it means we've successfully parsed token being in the
380
    /// state of negative lookahead and want to track `token` in the `unexpected_tokens`. Otherwise,
381
    /// we want to track it the `expected_tokens`. Let's call chosen vec a `target_vec`.
382
    ///
383
    /// In case `position` is:
384
    /// * Equal to `max_position`, add `token` to `target_vec`,
385
    /// * Bigger than `max_position`, set `token` as the only new element of `target_vec`.
386
    #[allow(clippy::comparison_chain)]
387
0
    fn try_add_new_token(
388
0
        &mut self,
389
0
        token: ParsingToken,
390
0
        start_position: usize,
391
0
        position: usize,
392
0
        negative_lookahead: bool,
393
0
    ) {
394
0
        let target_vec_push_token = |attempts: &mut ParseAttempts<R>| {
395
0
            let target_vec = if negative_lookahead {
396
0
                &mut attempts.unexpected_tokens
397
            } else {
398
0
                &mut attempts.expected_tokens
399
            };
400
0
            target_vec.push(token);
401
0
        };
Unexecuted instantiation: <pest::parser_state::ParseAttempts<semver_parser::generated::Rule>>::try_add_new_token::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParseAttempts<_>>::try_add_new_token::{closure#0}
402
403
0
        if position > self.max_position {
404
0
            if negative_lookahead && start_position > self.max_position {
405
                // We encountered a sequence under negative lookahead.
406
                // We would like to track only first failed token in this sequence (which
407
                // `start_position` should be equal to `self.max_position`).
408
0
                return;
409
0
            }
410
0
            target_vec_push_token(self);
411
0
412
0
            if negative_lookahead {
413
                // In case of successful parsing of token under negative lookahead the only
414
                // thing we'd like to do is to track the token in the `unexpected_tokens`.
415
0
                return;
416
0
            }
417
0
            self.max_position = position;
418
0
            self.expected_tokens.clear();
419
0
            self.unexpected_tokens.clear();
420
0
            self.call_stacks.clear();
421
0
            self.call_stacks
422
0
                .push(RulesCallStack::new(ParseAttempt::Token));
423
0
        } else if position == self.max_position {
424
0
            target_vec_push_token(self);
425
0
            self.call_stacks
426
0
                .push(RulesCallStack::new(ParseAttempt::Token));
427
0
        }
428
0
    }
Unexecuted instantiation: <pest::parser_state::ParseAttempts<semver_parser::generated::Rule>>::try_add_new_token
Unexecuted instantiation: <pest::parser_state::ParseAttempts<_>>::try_add_new_token
429
430
    /// Reset state in case we've successfully parsed some token in
431
    /// `match_string` or `match_insensetive`.
432
0
    fn nullify_expected_tokens(&mut self, new_max_position: usize) {
433
0
        self.call_stacks.clear();
434
0
        self.expected_tokens.clear();
435
0
        self.unexpected_tokens.clear();
436
0
        self.max_position = new_max_position;
437
0
    }
Unexecuted instantiation: <pest::parser_state::ParseAttempts<semver_parser::generated::Rule>>::nullify_expected_tokens
Unexecuted instantiation: <pest::parser_state::ParseAttempts<_>>::nullify_expected_tokens
438
}
439
440
impl<R: RuleType> Default for ParseAttempts<R> {
441
0
    fn default() -> Self {
442
0
        Self::new()
443
0
    }
444
}
445
446
/// The complete state of a [`Parser`].
447
///
448
/// [`Parser`]: trait.Parser.html
449
#[derive(Debug)]
450
pub struct ParserState<'i, R: RuleType> {
451
    /// Current position from which we try to apply some parser function.
452
    /// Initially is 0.
453
    /// E.g., we are parsing `create user 'Bobby'` query, we parsed "create" via `match_insensitive`
454
    /// and switched our `position` from 0 to the length of "create".
455
    ///
456
    /// E.g., see `match_string` -> `self.position.match_string(string)` which updates `self.pos`.
457
    position: Position<'i>,
458
    /// Queue representing rules partially (`QueueableToken::Start`) and
459
    /// totally (`QueueableToken::End`) parsed. When entering rule we put it in the queue in a state
460
    /// of `Start` and after all its sublogic (subrules or strings) are parsed, we change it to
461
    /// `End` state.
462
    queue: Vec<QueueableToken<'i, R>>,
463
    /// Status set in case specific lookahead logic is used in grammar.
464
    /// See `Lookahead` for more information.
465
    lookahead: Lookahead,
466
    /// Rules that we HAVE expected, tried to parse, but failed.
467
    pos_attempts: Vec<R>,
468
    /// Rules that we have NOT expected, tried to parse, but failed.
469
    neg_attempts: Vec<R>,
470
    /// Max position in the query from which we've tried to parse some rule but failed.
471
    attempt_pos: usize,
472
    /// Current atomicity status. For more information see `Atomicity`.
473
    atomicity: Atomicity,
474
    /// Helper structure tracking `Stack` status (used in case grammar contains stack PUSH/POP
475
    /// invocations).
476
    stack: Stack<SpanOrLiteral<'i>>,
477
    /// Used for setting max parser calls limit.
478
    call_tracker: CallLimitTracker,
479
    /// Together with tracking of `pos_attempts` and `attempt_pos`
480
    /// as a pair of (list of rules that we've tried to parse but failed, max parsed position)
481
    /// we track those rules (which we've tried to parse at the same max pos) at this helper struct.
482
    ///
483
    /// Note, that we may try to parse several rules on different positions. We want to track only
484
    /// those rules, which attempt position is bigger, because we consider that it's nearer to the
485
    /// query that user really wanted to pass.
486
    ///
487
    /// E.g. we have a query `create user "Bobby"` and two root rules:
488
    /// * CreateUser  = { "create" ~ "user"  ~ Name }
489
    /// * CreateTable = { "create" ~ "table" ~ Name }
490
    /// * Name = { SOME_DEFINITION }
491
    ///
492
    /// While parsing the query we'll update tracker position to the start of "Bobby", because we'd
493
    /// successfully parse "create" + "user" (and not "table").
494
    parse_attempts: ParseAttempts<R>,
495
}
496
497
/// Creates a `ParserState` from a `&str`, supplying it to a closure `f`.
498
///
499
/// # Examples
500
///
501
/// ```
502
/// # use pest;
503
/// let input = "";
504
/// pest::state::<(), _>(input, |s| Ok(s)).unwrap();
505
/// ```
506
#[allow(clippy::perf)]
507
0
pub fn state<'i, R: RuleType, F>(input: &'i str, f: F) -> Result<pairs::Pairs<'i, R>, Error<R>>
508
0
where
509
0
    F: FnOnce(Box<ParserState<'i, R>>) -> ParseResult<Box<ParserState<'i, R>>>,
510
0
{
511
0
    let state = ParserState::new(input);
512
0
513
0
    match f(state) {
514
0
        Ok(state) => {
515
0
            let len = state.queue.len();
516
0
            Ok(new(Rc::new(state.queue), input, None, 0, len))
517
        }
518
0
        Err(mut state) => {
519
0
            let variant = if state.reached_call_limit() {
520
0
                ErrorVariant::CustomError {
521
0
                    message: "call limit reached".to_owned(),
522
0
                }
523
            } else {
524
0
                state.pos_attempts.sort();
525
0
                state.pos_attempts.dedup();
526
0
                state.neg_attempts.sort();
527
0
                state.neg_attempts.dedup();
528
0
                ErrorVariant::ParsingError {
529
0
                    positives: state.pos_attempts.clone(),
530
0
                    negatives: state.neg_attempts.clone(),
531
0
                }
532
            };
533
534
0
            if state.parse_attempts.enabled {
535
0
                Err(Error::new_from_pos_with_parsing_attempts(
536
0
                    variant,
537
0
                    Position::new_internal(input, state.attempt_pos),
538
0
                    state.parse_attempts.clone(),
539
0
                ))
540
            } else {
541
0
                Err(Error::new_from_pos(
542
0
                    variant,
543
0
                    Position::new_internal(input, state.attempt_pos),
544
0
                ))
545
            }
546
        }
547
    }
548
0
}
Unexecuted instantiation: pest::parser_state::state::<semver_parser::generated::Rule, <semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::{closure#0}>
Unexecuted instantiation: pest::parser_state::state::<_, _>
549
550
impl<'i, R: RuleType> ParserState<'i, R> {
551
    /// Allocates a fresh `ParserState` object to the heap and returns the owned `Box`. This `Box`
552
    /// will be passed from closure to closure based on the needs of the specified `Parser`.
553
    ///
554
    /// # Examples
555
    ///
556
    /// ```
557
    /// # use pest;
558
    /// let input = "";
559
    /// let state: Box<pest::ParserState<&str>> = pest::ParserState::new(input);
560
    /// ```
561
0
    pub fn new(input: &'i str) -> Box<Self> {
562
0
        Box::new(ParserState {
563
0
            position: Position::from_start(input),
564
0
            queue: vec![],
565
0
            lookahead: Lookahead::None,
566
0
            pos_attempts: vec![],
567
0
            neg_attempts: vec![],
568
0
            attempt_pos: 0,
569
0
            atomicity: Atomicity::NonAtomic,
570
0
            stack: Stack::new(),
571
0
            call_tracker: Default::default(),
572
0
            parse_attempts: ParseAttempts::new(),
573
0
        })
574
0
    }
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::new
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::new
575
576
    /// Get all parse attempts after process of parsing is finished.
577
0
    pub fn get_parse_attempts(&self) -> &ParseAttempts<R> {
578
0
        &self.parse_attempts
579
0
    }
580
581
    /// Returns a reference to the current `Position` of the `ParserState`.
582
    ///
583
    /// # Examples
584
    ///
585
    /// ```
586
    /// # use pest;
587
    /// # #[allow(non_camel_case_types)]
588
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
589
    /// enum Rule {
590
    ///     ab
591
    /// }
592
    ///
593
    /// let input = "ab";
594
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
595
    /// let position = state.position();
596
    /// assert_eq!(position.pos(), 0);
597
    /// ```
598
0
    pub fn position(&self) -> &Position<'i> {
599
0
        &self.position
600
0
    }
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::position
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::position
601
602
    /// Returns the current atomicity of the `ParserState`.
603
    ///
604
    /// # Examples
605
    ///
606
    /// ```
607
    /// # use pest;
608
    /// # use pest::Atomicity;
609
    /// # #[allow(non_camel_case_types)]
610
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
611
    /// enum Rule {
612
    ///     ab
613
    /// }
614
    ///
615
    /// let input = "ab";
616
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
617
    /// let atomicity = state.atomicity();
618
    /// assert_eq!(atomicity, Atomicity::NonAtomic);
619
    /// ```
620
0
    pub fn atomicity(&self) -> Atomicity {
621
0
        self.atomicity
622
0
    }
623
624
    #[inline]
625
0
    fn inc_call_check_limit(mut self: Box<Self>) -> ParseResult<Box<Self>> {
626
0
        if self.call_tracker.limit_reached() {
627
0
            return Err(self);
628
0
        }
629
0
        self.call_tracker.increment_depth();
630
0
        Ok(self)
631
0
    }
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::inc_call_check_limit
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::inc_call_check_limit
632
633
    #[inline]
634
0
    fn reached_call_limit(&self) -> bool {
635
0
        self.call_tracker.limit_reached()
636
0
    }
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::reached_call_limit
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::reached_call_limit
637
638
    /// Wrapper needed to generate tokens. This will associate the `R` type rule to the closure
639
    /// meant to match the rule.
640
    ///
641
    /// # Examples
642
    ///
643
    /// ```
644
    /// # use pest;
645
    /// # #[allow(non_camel_case_types)]
646
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
647
    /// enum Rule {
648
    ///     a
649
    /// }
650
    ///
651
    /// let input = "a";
652
    /// let pairs: Vec<_> = pest::state(input, |state| {
653
    ///     state.rule(Rule::a, |s| Ok(s))
654
    /// }).unwrap().collect();
655
    ///
656
    /// assert_eq!(pairs.len(), 1);
657
    /// ```
658
    #[inline]
659
0
    pub fn rule<F>(mut self: Box<Self>, rule: R, f: F) -> ParseResult<Box<Self>>
660
0
    where
661
0
        F: FnOnce(Box<Self>) -> ParseResult<Box<Self>>,
662
0
    {
663
0
        self = self.inc_call_check_limit()?;
664
        // Position from which this `rule` starts parsing.
665
0
        let actual_pos = self.position.pos();
666
0
        // Remember index of the `self.queue` element that will be associated with this `rule`.
667
0
        let index = self.queue.len();
668
669
0
        let (pos_attempts_index, neg_attempts_index) = if actual_pos == self.attempt_pos {
670
0
            (self.pos_attempts.len(), self.neg_attempts.len())
671
        } else {
672
            // Attempts have not been cleared yet since the attempt_pos is older.
673
0
            (0, 0)
674
        };
675
676
0
        if self.lookahead == Lookahead::None && self.atomicity != Atomicity::Atomic {
677
0
            // Pair's position will only be known after running the closure.
678
0
            self.queue.push(QueueableToken::Start {
679
0
                end_token_index: 0,
680
0
                input_pos: actual_pos,
681
0
            });
682
0
        }
683
684
        // Remember attempts number before `f` call.
685
        // In `track` using this variable we can say, how many attempts were added
686
        // during children rules traversal.
687
0
        let attempts = self.attempts_at(actual_pos);
688
0
        // Number of call stacks present in `self.parse_attempts` before `f` call.
689
0
        // We need to remember this number only in case there wasn't found any farther attempt.
690
0
        // E.g. we are handling rule, on start position of which may be tested two
691
0
        // children rules. At the moment we'll return from `f` call below,
692
0
        // there will be two more children rules in `self.parse_attempts` that we'll
693
0
        // consider to be the children of current `rule`.
694
0
        let mut remember_call_stacks_number = self.parse_attempts.call_stacks_number();
695
0
        // Max parsing attempt position at the moment of `rule` handling.
696
0
        // It case it's raised during children rules handling, it means
697
0
        // we've made a parsing progress.
698
0
        let remember_max_position = self.parse_attempts.max_position;
699
0
700
0
        let result = f(self);
701
0
702
0
        let mut try_add_rule_to_stack = |new_state: &mut Box<ParserState<'_, R>>| {
703
0
            if new_state.parse_attempts.max_position > remember_max_position {
704
0
                // It means that one of `match_string` or e.g. `match_insensetive` function calls
705
0
                // have already erased `self.parse_attempts.call_stacks` and that previously
706
0
                // remembered values are not valid anymore.
707
0
                remember_call_stacks_number = 0;
708
0
            }
709
0
            if !matches!(new_state.atomicity, Atomicity::Atomic) {
710
0
                new_state
711
0
                    .parse_attempts
712
0
                    .try_add_new_stack_rule(rule, remember_call_stacks_number);
713
0
            }
714
0
        };
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::logical_or::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::primitive_op::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::nr::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::xr::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::EOI::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::part::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::caret::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::empty::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::parts::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::tilde::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::xr_op::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::hyphen::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::simple::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::partial::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::primitive::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::qualifier::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}>::{closure#0}
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::rule::<_>::{closure#0}
715
716
0
        match result {
717
0
            Ok(mut new_state) => {
718
0
                if new_state.lookahead == Lookahead::Negative {
719
0
                    new_state.track(
720
0
                        rule,
721
0
                        actual_pos,
722
0
                        pos_attempts_index,
723
0
                        neg_attempts_index,
724
0
                        attempts,
725
0
                    );
726
0
                }
727
728
0
                if new_state.lookahead == Lookahead::None
729
0
                    && new_state.atomicity != Atomicity::Atomic
730
                {
731
                    // Index of `QueueableToken::End` token added below
732
                    // that corresponds to previously added `QueueableToken::Start` token.
733
0
                    let new_index = new_state.queue.len();
734
0
                    match new_state.queue[index] {
735
                        QueueableToken::Start {
736
0
                            ref mut end_token_index,
737
0
                            ..
738
0
                        } => *end_token_index = new_index,
739
0
                        _ => unreachable!(),
740
                    };
741
742
0
                    let new_pos = new_state.position.pos();
743
0
744
0
                    new_state.queue.push(QueueableToken::End {
745
0
                        start_token_index: index,
746
0
                        rule,
747
0
                        tag: None,
748
0
                        input_pos: new_pos,
749
0
                    });
750
0
                }
751
752
                // Note, that we need to count positive parsing results too, because we can fail in
753
                // optional rule call inside which may lie the farthest
754
                // parsed token.
755
0
                if new_state.parse_attempts.enabled {
756
0
                    try_add_rule_to_stack(&mut new_state);
757
0
                }
758
0
                Ok(new_state)
759
            }
760
0
            Err(mut new_state) => {
761
0
                if new_state.lookahead != Lookahead::Negative {
762
0
                    new_state.track(
763
0
                        rule,
764
0
                        actual_pos,
765
0
                        pos_attempts_index,
766
0
                        neg_attempts_index,
767
0
                        attempts,
768
0
                    );
769
0
                    if new_state.parse_attempts.enabled {
770
0
                        try_add_rule_to_stack(&mut new_state);
771
0
                    }
772
0
                }
773
774
0
                if new_state.lookahead == Lookahead::None
775
0
                    && new_state.atomicity != Atomicity::Atomic
776
0
                {
777
0
                    new_state.queue.truncate(index);
778
0
                }
779
780
0
                Err(new_state)
781
            }
782
        }
783
0
    }
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::logical_or::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::primitive_op::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::nr::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::xr::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::EOI::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::part::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::caret::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::empty::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::parts::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::tilde::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::xr_op::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::hyphen::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::simple::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::partial::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::primitive::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::qualifier::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::rule::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::rule::<_>
784
785
    /// Tag current node
786
    ///
787
    /// # Examples
788
    ///
789
    /// Try to recognize the one specified in a set of characters
790
    ///
791
    /// ```
792
    /// use pest::{state, ParseResult, ParserState, iterators::Pair};
793
    /// #[allow(non_camel_case_types)]
794
    /// #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
795
    /// enum Rule {
796
    ///     character,
797
    /// }
798
    /// fn mark_c(state: Box<ParserState<Rule>>) -> ParseResult<Box<ParserState<Rule>>> {
799
    ///     state.sequence(|state| {
800
    ///         character(state)
801
    ///             .and_then(|state| character(state))
802
    ///             .and_then(|state| character(state))
803
    ///             .and_then(|state| state.tag_node("c"))
804
    ///             .and_then(|state| character(state))
805
    ///     })
806
    /// }
807
    /// fn character(state: Box<ParserState<Rule>>) -> ParseResult<Box<ParserState<Rule>>> {
808
    ///     state.rule(Rule::character, |state| state.match_range('a'..'z'))
809
    /// }
810
    ///
811
    /// let input = "abcd";
812
    /// let pairs = state(input, mark_c).unwrap();
813
    /// // find all node tag as `c`
814
    /// let find: Vec<Pair<Rule>> = pairs.filter(|s| s.as_node_tag() == Some("c")).collect();
815
    /// assert_eq!(find[0].as_str(), "c")
816
    /// ```
817
    #[inline]
818
0
    pub fn tag_node(mut self: Box<Self>, tag: &'i str) -> ParseResult<Box<Self>> {
819
0
        if let Some(QueueableToken::End { tag: old, .. }) = self.queue.last_mut() {
820
0
            *old = Some(tag)
821
0
        }
822
0
        Ok(self)
823
0
    }
824
825
    /// Get number of allowed rules attempts + prohibited rules attempts.
826
0
    fn attempts_at(&self, pos: usize) -> usize {
827
0
        if self.attempt_pos == pos {
828
0
            self.pos_attempts.len() + self.neg_attempts.len()
829
        } else {
830
0
            0
831
        }
832
0
    }
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::attempts_at
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::attempts_at
833
834
0
    fn track(
835
0
        &mut self,
836
0
        rule: R,
837
0
        pos: usize,
838
0
        pos_attempts_index: usize,
839
0
        neg_attempts_index: usize,
840
0
        prev_attempts: usize,
841
0
    ) {
842
0
        if self.atomicity == Atomicity::Atomic {
843
0
            return;
844
0
        }
845
0
846
0
        // If nested rules made no progress, there is no use to report them; it's only useful to
847
0
        // track the current rule, the exception being when only one attempt has been made during
848
0
        // the children rules.
849
0
        let curr_attempts = self.attempts_at(pos);
850
0
        if curr_attempts > prev_attempts && curr_attempts - prev_attempts == 1 {
851
0
            return;
852
0
        }
853
0
854
0
        if pos == self.attempt_pos {
855
0
            self.pos_attempts.truncate(pos_attempts_index);
856
0
            self.neg_attempts.truncate(neg_attempts_index);
857
0
        }
858
859
0
        if pos > self.attempt_pos {
860
0
            self.pos_attempts.clear();
861
0
            self.neg_attempts.clear();
862
0
            self.attempt_pos = pos;
863
0
        }
864
865
0
        let attempts = if self.lookahead != Lookahead::Negative {
866
0
            &mut self.pos_attempts
867
        } else {
868
0
            &mut self.neg_attempts
869
        };
870
871
0
        if pos == self.attempt_pos {
872
0
            attempts.push(rule);
873
0
        }
874
0
    }
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::track
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::track
875
876
    /// Starts a sequence of transformations provided by `f` from the `Box<ParserState>`. Returns
877
    /// the same `Result` returned by `f` in the case of an `Ok`, or `Err` with the current
878
    /// `Box<ParserState>` otherwise.
879
    ///
880
    /// This method is useful to parse sequences that only match together which usually come in the
881
    /// form of chained `Result`s with
882
    /// [`Result::and_then`](https://doc.rust-lang.org/std/result/enum.Result.html#method.and_then).
883
    ///
884
    ///
885
    /// # Examples
886
    ///
887
    /// ```
888
    /// # use pest;
889
    /// # #[allow(non_camel_case_types)]
890
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
891
    /// enum Rule {
892
    ///     a
893
    /// }
894
    ///
895
    /// let input = "a";
896
    /// let pairs: Vec<_> = pest::state(input, |state| {
897
    ///     state.sequence(|s| {
898
    ///         s.rule(Rule::a, |s| Ok(s)).and_then(|s| {
899
    ///             s.match_string("b")
900
    ///         })
901
    ///     }).or_else(|s| {
902
    ///         Ok(s)
903
    ///     })
904
    /// }).unwrap().collect();
905
    ///
906
    /// assert_eq!(pairs.len(), 0);
907
    /// ```
908
    #[inline]
909
0
    pub fn sequence<F>(mut self: Box<Self>, f: F) -> ParseResult<Box<Self>>
910
0
    where
911
0
        F: FnOnce(Box<Self>) -> ParseResult<Box<Self>>,
912
0
    {
913
0
        self = self.inc_call_check_limit()?;
914
0
        let token_index = self.queue.len();
915
0
        let initial_pos = self.position;
916
0
917
0
        let result = f(self);
918
0
919
0
        match result {
920
0
            Ok(new_state) => Ok(new_state),
921
0
            Err(mut new_state) => {
922
0
                // Restore the initial position and truncate the token queue.
923
0
                new_state.position = initial_pos;
924
0
                new_state.queue.truncate(token_index);
925
0
                Err(new_state)
926
            }
927
        }
928
0
    }
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#2}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#2}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#2}::{closure#0}::{closure#1}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#2}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#2}::{closure#0}::{closure#1}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::parts::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::hyphen::{closure#0}::{closure#0}::{closure#5}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::hyphen::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}::{closure#0}::{closure#5}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::nr::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::part::{closure#0}::{closure#0}::{closure#0}::{closure#4}::{closure#0}::{closure#0}::{closure#3}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#2}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::logical_or::{closure#0}::{closure#0}::{closure#4}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::caret::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::parts::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::tilde::{closure#0}::{closure#0}::{closure#2}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::partial::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#3}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::primitive::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}::{closure#0}::{closure#5}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}::{closure#0}::{closure#7}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::logical_or::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::parts::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::hyphen::{closure#0}::{closure#0}::{closure#5}::{closure#0}::{closure#1}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::hyphen::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#1}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}::{closure#0}::{closure#5}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::nr::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::part::{closure#0}::{closure#0}::{closure#0}::{closure#4}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::partial::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::logical_or::{closure#0}::{closure#0}::{closure#4}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::caret::{closure#0}::{closure#0}::{closure#1}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::parts::{closure#0}::{closure#0}::{closure#1}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::tilde::{closure#0}::{closure#0}::{closure#2}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::hyphen::{closure#0}::{closure#0}::{closure#5}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::hyphen::{closure#0}::{closure#0}::{closure#1}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::primitive::{closure#0}::{closure#0}::{closure#1}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}::{closure#0}::{closure#5}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}::{closure#0}::{closure#7}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}::{closure#0}::{closure#1}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::logical_or::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::nr::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::part::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::logical_or::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::caret::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::parts::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::tilde::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::hyphen::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::partial::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::primitive::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::qualifier::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::sequence::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::sequence::<_>
929
930
    /// Repeatedly applies the transformation provided by `f` from the `Box<ParserState>`. Returns
931
    /// `Ok` with the updated `Box<ParserState>` returned by `f` wrapped up in an `Err`.
932
    ///
933
    /// # Examples
934
    ///
935
    /// ```
936
    /// # use pest;
937
    /// # #[allow(non_camel_case_types)]
938
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
939
    /// enum Rule {
940
    ///     ab
941
    /// }
942
    ///
943
    /// let input = "aab";
944
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
945
    /// let mut result = state.repeat(|s| {
946
    ///     s.match_string("a")
947
    /// });
948
    /// assert!(result.is_ok());
949
    /// assert_eq!(result.unwrap().position().pos(), 2);
950
    ///
951
    /// state = pest::ParserState::new(input);
952
    /// result = state.repeat(|s| {
953
    ///     s.match_string("b")
954
    /// });
955
    /// assert!(result.is_ok());
956
    /// assert_eq!(result.unwrap().position().pos(), 0);
957
    /// ```
958
    #[inline]
959
0
    pub fn repeat<F>(mut self: Box<Self>, mut f: F) -> ParseResult<Box<Self>>
960
0
    where
961
0
        F: FnMut(Box<Self>) -> ParseResult<Box<Self>>,
962
0
    {
963
0
        self = self.inc_call_check_limit()?;
964
0
        let mut result = f(self);
965
966
        loop {
967
0
            match result {
968
0
                Ok(state) => result = f(state),
969
0
                Err(state) => return Ok(state),
970
            };
971
        }
972
0
    }
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#2}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#2}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::hyphen::{closure#0}::{closure#0}::{closure#5}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::hyphen::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::nr::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::part::{closure#0}::{closure#0}::{closure#0}::{closure#4}::{closure#0}::{closure#0}::{closure#3}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#1}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::logical_or::{closure#0}::{closure#0}::{closure#4}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::caret::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::parts::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#1}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::tilde::{closure#0}::{closure#0}::{closure#2}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::primitive::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}::{closure#0}::{closure#5}::{closure#0}::{closure#0}::{closure#1}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}::{closure#0}::{closure#7}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::repeat::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::logical_or::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::repeat::<_>
973
974
    /// Optionally applies the transformation provided by `f` from the `Box<ParserState>`. Returns
975
    /// `Ok` with the updated `Box<ParserState>` returned by `f` regardless of the `Result`.
976
    ///
977
    /// # Examples
978
    ///
979
    /// ```
980
    /// # use pest;
981
    /// # #[allow(non_camel_case_types)]
982
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
983
    /// enum Rule {
984
    ///     ab
985
    /// }
986
    ///
987
    /// let input = "ab";
988
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
989
    /// let result = state.optional(|s| {
990
    ///     s.match_string("ab")
991
    /// });
992
    /// assert!(result.is_ok());
993
    ///
994
    /// state = pest::ParserState::new(input);
995
    /// let result = state.optional(|s| {
996
    ///     s.match_string("ac")
997
    /// });
998
    /// assert!(result.is_ok());
999
    /// ```
1000
    #[inline]
1001
0
    pub fn optional<F>(mut self: Box<Self>, f: F) -> ParseResult<Box<Self>>
1002
0
    where
1003
0
        F: FnOnce(Box<Self>) -> ParseResult<Box<Self>>,
1004
0
    {
1005
0
        self = self.inc_call_check_limit()?;
1006
0
        match f(self) {
1007
0
            Ok(state) | Err(state) => Ok(state),
1008
        }
1009
0
    }
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#2}::{closure#0}::{closure#1}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#2}::{closure#0}::{closure#1}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::partial::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#3}::{closure#0}::{closure#0}::{closure#3}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::hyphen::{closure#0}::{closure#0}::{closure#5}::{closure#0}::{closure#1}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::hyphen::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#1}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::partial::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}::{closure#3}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::nr::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::part::{closure#0}::{closure#0}::{closure#0}::{closure#4}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range::{closure#0}::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::logical_or::{closure#0}::{closure#0}::{closure#4}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::caret::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::parts::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::tilde::{closure#0}::{closure#0}::{closure#2}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::primitive::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}::{closure#0}::{closure#5}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}::{closure#0}::{closure#7}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::range_set::{closure#0}::{closure#0}::{closure#1}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::logical_or::{closure#0}::{closure#0}::{closure#0}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::optional::<<semver_parser::SemverParser as pest::parser::Parser<semver_parser::generated::Rule>>::parse::rules::visible::partial::{closure#0}::{closure#0}::{closure#1}::{closure#0}>
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::optional::<_>
1010
1011
    /// Generic function to handle result of char/string/range parsing
1012
    /// in order to track (un)expected tokens.
1013
0
    fn handle_token_parse_result(
1014
0
        &mut self,
1015
0
        start_position: usize,
1016
0
        token: ParsingToken,
1017
0
        parse_succeeded: bool,
1018
0
    ) {
1019
0
        // New position after tracked parsed element for case of `parse_succeded` is true.
1020
0
        // Position of parsing failure otherwise.
1021
0
        let current_pos = self.position.pos();
1022
0
1023
0
        if parse_succeeded {
1024
0
            if self.lookahead == Lookahead::Negative {
1025
0
                self.parse_attempts
1026
0
                    .try_add_new_token(token, start_position, current_pos, true);
1027
0
            } else if current_pos > self.parse_attempts.max_position {
1028
0
                self.parse_attempts.nullify_expected_tokens(current_pos);
1029
0
            }
1030
0
        } else if self.lookahead != Lookahead::Negative {
1031
0
            self.parse_attempts
1032
0
                .try_add_new_token(token, start_position, current_pos, false);
1033
0
        }
1034
0
    }
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::handle_token_parse_result
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::handle_token_parse_result
1035
1036
    /// Attempts to match a single character based on a filter function. Returns `Ok` with the
1037
    /// updated `Box<ParserState>` if successful, or `Err` with the updated `Box<ParserState>`
1038
    /// otherwise.
1039
    ///
1040
    /// # Examples
1041
    ///
1042
    /// ```
1043
    /// # use pest;
1044
    /// # #[allow(non_camel_case_types)]
1045
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1046
    /// enum Rule {}
1047
    ///
1048
    /// let input = "ab";
1049
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1050
    /// let result = state.match_char_by(|c| c.is_ascii());
1051
    /// assert!(result.is_ok());
1052
    /// assert_eq!(result.unwrap().position().pos(), 1);
1053
    ///
1054
    /// let input = "❤";
1055
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1056
    /// let result = state.match_char_by(|c| c.is_ascii());
1057
    /// assert!(result.is_err());
1058
    /// assert_eq!(result.unwrap_err().position().pos(), 0);
1059
    /// ```
1060
    #[inline]
1061
0
    pub fn match_char_by<F>(mut self: Box<Self>, f: F) -> ParseResult<Box<Self>>
1062
0
    where
1063
0
        F: FnOnce(char) -> bool,
1064
0
    {
1065
0
        let start_position = self.position.pos();
1066
0
        let succeeded = self.position.match_char_by(f);
1067
0
        if self.parse_attempts.enabled {
1068
0
            let token = ParsingToken::BuiltInRule;
1069
0
            self.handle_token_parse_result(start_position, token, succeeded);
1070
0
        }
1071
0
        if succeeded {
1072
0
            Ok(self)
1073
        } else {
1074
0
            Err(self)
1075
        }
1076
0
    }
1077
1078
    /// Attempts to match the given string. Returns `Ok` with the updated `Box<ParserState>` if
1079
    /// successful, or `Err` with the updated `Box<ParserState>` otherwise.
1080
    ///
1081
    /// # Examples
1082
    ///
1083
    /// ```
1084
    /// # use pest;
1085
    /// # #[allow(non_camel_case_types)]
1086
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1087
    /// enum Rule {}
1088
    ///
1089
    /// let input = "ab";
1090
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1091
    /// let mut result = state.match_string("ab");
1092
    /// assert!(result.is_ok());
1093
    /// assert_eq!(result.unwrap().position().pos(), 2);
1094
    ///
1095
    /// state = pest::ParserState::new(input);
1096
    /// result = state.match_string("ac");
1097
    /// assert!(result.is_err());
1098
    /// assert_eq!(result.unwrap_err().position().pos(), 0);
1099
    /// ```
1100
    #[inline]
1101
0
    pub fn match_string(mut self: Box<Self>, string: &str) -> ParseResult<Box<Self>> {
1102
0
        let start_position = self.position.pos();
1103
0
        let succeeded = self.position.match_string(string);
1104
0
        if self.parse_attempts.enabled {
1105
0
            let token = ParsingToken::Sensitive {
1106
0
                token: String::from(string),
1107
0
            };
1108
0
            self.handle_token_parse_result(start_position, token, succeeded);
1109
0
        }
1110
0
        if succeeded {
1111
0
            Ok(self)
1112
        } else {
1113
0
            Err(self)
1114
        }
1115
0
    }
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::match_string
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::match_string
1116
1117
    /// Pushes the given literal to the stack, and always returns `Ok(Box<ParserState>)`.
1118
    ///
1119
    /// # Examples
1120
    ///
1121
    /// ```
1122
    /// # use pest;
1123
    /// # #[allow(non_camel_case_types)]
1124
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1125
    /// enum Rule {}
1126
    ///
1127
    /// let input = "ab";
1128
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1129
    ///
1130
    /// let mut result = state.stack_push_literal("a");
1131
    /// assert!(result.is_ok());
1132
    /// assert_eq!(result.as_ref().unwrap().position().pos(), 0);
1133
    ///
1134
    /// let mut result = result.unwrap().stack_pop();
1135
    /// assert!(result.is_ok());
1136
    /// assert_eq!(result.unwrap().position().pos(), 1);
1137
    /// ```
1138
    #[inline]
1139
0
    pub fn stack_push_literal(
1140
0
        mut self: Box<Self>,
1141
0
        string: impl Into<Cow<'static, str>>,
1142
0
    ) -> ParseResult<Box<Self>> {
1143
0
        // convert string into a Literal, and then into a BorrowedOrRc
1144
0
        self.stack
1145
0
            .push(SpanOrLiteral::Literal(string.into().into()));
1146
0
        Ok(self)
1147
0
    }
1148
1149
    /// Attempts to case-insensitively match the given string. Returns `Ok` with the updated
1150
    /// `Box<ParserState>` if successful, or `Err` with the updated `Box<ParserState>` otherwise.
1151
    ///
1152
    /// # Examples
1153
    ///
1154
    /// ```
1155
    /// # use pest;
1156
    /// # #[allow(non_camel_case_types)]
1157
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1158
    /// enum Rule {}
1159
    ///
1160
    /// let input = "ab";
1161
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1162
    /// let mut result = state.match_insensitive("AB");
1163
    /// assert!(result.is_ok());
1164
    /// assert_eq!(result.unwrap().position().pos(), 2);
1165
    ///
1166
    /// state = pest::ParserState::new(input);
1167
    /// result = state.match_insensitive("AC");
1168
    /// assert!(result.is_err());
1169
    /// assert_eq!(result.unwrap_err().position().pos(), 0);
1170
    /// ```
1171
    #[inline]
1172
0
    pub fn match_insensitive(mut self: Box<Self>, string: &str) -> ParseResult<Box<Self>> {
1173
0
        let start_position: usize = self.position().pos();
1174
0
        let succeeded = self.position.match_insensitive(string);
1175
0
        if self.parse_attempts.enabled {
1176
0
            let token = ParsingToken::Insensitive {
1177
0
                token: String::from(string),
1178
0
            };
1179
0
            self.handle_token_parse_result(start_position, token, succeeded);
1180
0
        }
1181
0
        if succeeded {
1182
0
            Ok(self)
1183
        } else {
1184
0
            Err(self)
1185
        }
1186
0
    }
1187
1188
    /// Attempts to match a single character from the given range. Returns `Ok` with the updated
1189
    /// `Box<ParserState>` if successful, or `Err` with the updated `Box<ParserState>` otherwise.
1190
    ///
1191
    /// # Caution
1192
    /// The provided `range` is interpreted as inclusive.
1193
    ///
1194
    /// # Examples
1195
    ///
1196
    /// ```
1197
    /// # use pest;
1198
    /// # #[allow(non_camel_case_types)]
1199
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1200
    /// enum Rule {}
1201
    ///
1202
    /// let input = "ab";
1203
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1204
    /// let mut result = state.match_range('a'..'z');
1205
    /// assert!(result.is_ok());
1206
    /// assert_eq!(result.unwrap().position().pos(), 1);
1207
    ///
1208
    /// state = pest::ParserState::new(input);
1209
    /// result = state.match_range('A'..'Z');
1210
    /// assert!(result.is_err());
1211
    /// assert_eq!(result.unwrap_err().position().pos(), 0);
1212
    /// ```
1213
    #[inline]
1214
0
    pub fn match_range(mut self: Box<Self>, range: Range<char>) -> ParseResult<Box<Self>> {
1215
0
        let start_position = self.position().pos();
1216
0
        let token = ParsingToken::Range {
1217
0
            start: range.start,
1218
0
            end: range.end,
1219
0
        };
1220
0
        let succeeded = self.position.match_range(range);
1221
0
        if self.parse_attempts.enabled {
1222
0
            self.handle_token_parse_result(start_position, token, succeeded);
1223
0
        }
1224
0
        if succeeded {
1225
0
            Ok(self)
1226
        } else {
1227
0
            Err(self)
1228
        }
1229
0
    }
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::match_range
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::match_range
1230
1231
    /// Attempts to skip `n` characters forward. Returns `Ok` with the updated `Box<ParserState>`
1232
    /// if successful, or `Err` with the updated `Box<ParserState>` otherwise.
1233
    ///
1234
    /// # Examples
1235
    ///
1236
    /// ```
1237
    /// # use pest;
1238
    /// # #[allow(non_camel_case_types)]
1239
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1240
    /// enum Rule {}
1241
    ///
1242
    /// let input = "ab";
1243
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1244
    /// let mut result = state.skip(1);
1245
    /// assert!(result.is_ok());
1246
    /// assert_eq!(result.unwrap().position().pos(), 1);
1247
    ///
1248
    /// state = pest::ParserState::new(input);
1249
    /// result = state.skip(3);
1250
    /// assert!(result.is_err());
1251
    /// assert_eq!(result.unwrap_err().position().pos(), 0);
1252
    /// ```
1253
    #[inline]
1254
0
    pub fn skip(mut self: Box<Self>, n: usize) -> ParseResult<Box<Self>> {
1255
0
        if self.position.skip(n) {
1256
0
            Ok(self)
1257
        } else {
1258
0
            Err(self)
1259
        }
1260
0
    }
1261
1262
    /// Attempts to skip forward until one of the given strings is found. Returns `Ok` with the
1263
    /// updated `Box<ParserState>` whether or not one of the strings is found.
1264
    ///
1265
    /// # Examples
1266
    ///
1267
    /// ```
1268
    /// # use pest;
1269
    /// # #[allow(non_camel_case_types)]
1270
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1271
    /// enum Rule {}
1272
    ///
1273
    /// let input = "abcd";
1274
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1275
    /// let mut result = state.skip_until(&["c", "d"]);
1276
    /// assert!(result.is_ok());
1277
    /// assert_eq!(result.unwrap().position().pos(), 2);
1278
    /// ```
1279
    #[inline]
1280
0
    pub fn skip_until(mut self: Box<Self>, strings: &[&str]) -> ParseResult<Box<Self>> {
1281
0
        self.position.skip_until(strings);
1282
0
        Ok(self)
1283
0
    }
1284
1285
    /// Attempts to match the start of the input. Returns `Ok` with the current `Box<ParserState>`
1286
    /// if the parser has not yet advanced, or `Err` with the current `Box<ParserState>` otherwise.
1287
    ///
1288
    /// # Examples
1289
    ///
1290
    /// ```
1291
    /// # use pest;
1292
    /// # #[allow(non_camel_case_types)]
1293
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1294
    /// enum Rule {}
1295
    ///
1296
    /// let input = "ab";
1297
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1298
    /// let mut result = state.start_of_input();
1299
    /// assert!(result.is_ok());
1300
    ///
1301
    /// state = pest::ParserState::new(input);
1302
    /// state = state.match_string("ab").unwrap();
1303
    /// result = state.start_of_input();
1304
    /// assert!(result.is_err());
1305
    /// ```
1306
    #[inline]
1307
0
    pub fn start_of_input(self: Box<Self>) -> ParseResult<Box<Self>> {
1308
0
        if self.position.at_start() {
1309
0
            Ok(self)
1310
        } else {
1311
0
            Err(self)
1312
        }
1313
0
    }
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::start_of_input
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::start_of_input
1314
1315
    /// Attempts to match the end of the input. Returns `Ok` with the current `Box<ParserState>` if
1316
    /// there is no input remaining, or `Err` with the current `Box<ParserState>` otherwise.
1317
    ///
1318
    /// # Examples
1319
    ///
1320
    /// ```
1321
    /// # use pest;
1322
    /// # #[allow(non_camel_case_types)]
1323
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1324
    /// enum Rule {}
1325
    ///
1326
    /// let input = "ab";
1327
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1328
    /// let mut result = state.end_of_input();
1329
    /// assert!(result.is_err());
1330
    ///
1331
    /// state = pest::ParserState::new(input);
1332
    /// state = state.match_string("ab").unwrap();
1333
    /// result = state.end_of_input();
1334
    /// assert!(result.is_ok());
1335
    /// ```
1336
    #[inline]
1337
0
    pub fn end_of_input(self: Box<Self>) -> ParseResult<Box<Self>> {
1338
0
        if self.position.at_end() {
1339
0
            Ok(self)
1340
        } else {
1341
0
            Err(self)
1342
        }
1343
0
    }
Unexecuted instantiation: <pest::parser_state::ParserState<semver_parser::generated::Rule>>::end_of_input
Unexecuted instantiation: <pest::parser_state::ParserState<_>>::end_of_input
1344
1345
    /// Starts a lookahead transformation provided by `f` from the `Box<ParserState>`. It returns
1346
    /// `Ok` with the current `Box<ParserState>` if `f` also returns an `Ok`, or `Err` with the current
1347
    /// `Box<ParserState>` otherwise. If `is_positive` is `false`, it swaps the `Ok` and `Err`
1348
    /// together, negating the `Result`.
1349
    ///
1350
    /// # Examples
1351
    ///
1352
    /// ```
1353
    /// # use pest;
1354
    /// # #[allow(non_camel_case_types)]
1355
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1356
    /// enum Rule {
1357
    ///     a
1358
    /// }
1359
    ///
1360
    /// let input = "a";
1361
    /// let pairs: Vec<_> = pest::state(input, |state| {
1362
    ///     state.lookahead(true, |state| {
1363
    ///         state.rule(Rule::a, |s| Ok(s))
1364
    ///     })
1365
    /// }).unwrap().collect();
1366
    ///
1367
    /// assert_eq!(pairs.len(), 0);
1368
    /// ```
1369
    #[inline]
1370
0
    pub fn lookahead<F>(mut self: Box<Self>, is_positive: bool, f: F) -> ParseResult<Box<Self>>
1371
0
    where
1372
0
        F: FnOnce(Box<Self>) -> ParseResult<Box<Self>>,
1373
0
    {
1374
0
        self = self.inc_call_check_limit()?;
1375
0
        let initial_lookahead = self.lookahead;
1376
0
1377
0
        self.lookahead = if is_positive {
1378
0
            match initial_lookahead {
1379
0
                Lookahead::None | Lookahead::Positive => Lookahead::Positive,
1380
0
                Lookahead::Negative => Lookahead::Negative,
1381
            }
1382
        } else {
1383
0
            match initial_lookahead {
1384
0
                Lookahead::None | Lookahead::Positive => Lookahead::Negative,
1385
0
                Lookahead::Negative => Lookahead::Positive,
1386
            }
1387
        };
1388
1389
0
        let initial_pos = self.position;
1390
0
1391
0
        let result = f(self.checkpoint());
1392
1393
0
        let result_state = match result {
1394
0
            Ok(mut new_state) => {
1395
0
                new_state.position = initial_pos;
1396
0
                new_state.lookahead = initial_lookahead;
1397
0
                Ok(new_state.restore())
1398
            }
1399
0
            Err(mut new_state) => {
1400
0
                new_state.position = initial_pos;
1401
0
                new_state.lookahead = initial_lookahead;
1402
0
                Err(new_state.restore())
1403
            }
1404
        };
1405
1406
0
        if is_positive {
1407
0
            result_state
1408
        } else {
1409
0
            match result_state {
1410
0
                Ok(state) => Err(state),
1411
0
                Err(state) => Ok(state),
1412
            }
1413
        }
1414
0
    }
1415
1416
    /// Transformation which stops `Token`s from being generated according to `is_atomic`.
1417
    /// Used as wrapper over `rule` (or even another `atomic`) call.
1418
    ///
1419
    /// # Examples
1420
    ///
1421
    /// ```
1422
    /// # use pest::{self, Atomicity};
1423
    /// # #[allow(non_camel_case_types)]
1424
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1425
    /// enum Rule {
1426
    ///     a
1427
    /// }
1428
    ///
1429
    /// let input = "a";
1430
    /// let pairs: Vec<_> = pest::state(input, |state| {
1431
    ///     state.atomic(Atomicity::Atomic, |s| {
1432
    ///         s.rule(Rule::a, |s| Ok(s))
1433
    ///     })
1434
    /// }).unwrap().collect();
1435
    ///
1436
    /// assert_eq!(pairs.len(), 0);
1437
    /// ```
1438
    #[inline]
1439
0
    pub fn atomic<F>(mut self: Box<Self>, atomicity: Atomicity, f: F) -> ParseResult<Box<Self>>
1440
0
    where
1441
0
        F: FnOnce(Box<Self>) -> ParseResult<Box<Self>>,
1442
0
    {
1443
0
        self = self.inc_call_check_limit()?;
1444
        // In case child parsing call is another `atomic` it will have its own atomicity status.
1445
0
        let initial_atomicity = self.atomicity;
1446
0
        // In case child atomicity is the same as we've demanded, we shouldn't do nothing.
1447
0
        // E.g. we have the following rules:
1448
0
        // * RootRule = @{ InnerRule }
1449
0
        // * InnerRule = @{ ... }
1450
0
        let should_toggle = self.atomicity != atomicity;
1451
0
1452
0
        // Note that we take atomicity of the top rule and not of the leaf (inner).
1453
0
        if should_toggle {
1454
0
            self.atomicity = atomicity;
1455
0
        }
1456
1457
0
        let result = f(self);
1458
0
1459
0
        match result {
1460
0
            Ok(mut new_state) => {
1461
0
                if should_toggle {
1462
0
                    new_state.atomicity = initial_atomicity;
1463
0
                }
1464
0
                Ok(new_state)
1465
            }
1466
0
            Err(mut new_state) => {
1467
0
                if should_toggle {
1468
0
                    new_state.atomicity = initial_atomicity;
1469
0
                }
1470
0
                Err(new_state)
1471
            }
1472
        }
1473
0
    }
1474
1475
    /// Evaluates the result of closure `f` and pushes the span of the input consumed from before
1476
    /// `f` is called to after `f` is called to the stack. Returns `Ok(Box<ParserState>)` if `f` is
1477
    /// called successfully, or `Err(Box<ParserState>)` otherwise.
1478
    ///
1479
    /// # Examples
1480
    ///
1481
    /// ```
1482
    /// # use pest;
1483
    /// # #[allow(non_camel_case_types)]
1484
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1485
    /// enum Rule {}
1486
    ///
1487
    /// let input = "ab";
1488
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1489
    /// let mut result = state.stack_push(|state| state.match_string("a"));
1490
    /// assert!(result.is_ok());
1491
    /// assert_eq!(result.unwrap().position().pos(), 1);
1492
    /// ```
1493
    #[inline]
1494
0
    pub fn stack_push<F>(mut self: Box<Self>, f: F) -> ParseResult<Box<Self>>
1495
0
    where
1496
0
        F: FnOnce(Box<Self>) -> ParseResult<Box<Self>>,
1497
0
    {
1498
0
        self = self.inc_call_check_limit()?;
1499
0
        let start = self.position;
1500
0
1501
0
        let result = f(self);
1502
0
1503
0
        match result {
1504
0
            Ok(mut state) => {
1505
0
                let end = state.position;
1506
0
                state.stack.push(SpanOrLiteral::Span(start.span(&end)));
1507
0
                Ok(state)
1508
            }
1509
0
            Err(state) => Err(state),
1510
        }
1511
0
    }
1512
1513
    /// Peeks the top of the stack and attempts to match the string. Returns `Ok(Box<ParserState>)`
1514
    /// if the string is matched successfully, or `Err(Box<ParserState>)` otherwise.
1515
    ///
1516
    /// # Examples
1517
    ///
1518
    /// ```
1519
    /// # use pest;
1520
    /// # #[allow(non_camel_case_types)]
1521
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1522
    /// enum Rule {}
1523
    ///
1524
    /// let input = "aa";
1525
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1526
    /// let mut result = state.stack_push(|state| state.match_string("a")).and_then(
1527
    ///     |state| state.stack_peek()
1528
    /// );
1529
    /// assert!(result.is_ok());
1530
    /// assert_eq!(result.unwrap().position().pos(), 2);
1531
    /// ```
1532
    #[inline]
1533
0
    pub fn stack_peek(self: Box<Self>) -> ParseResult<Box<Self>> {
1534
0
        let string = self
1535
0
            .stack
1536
0
            .peek()
1537
0
            .expect("peek was called on empty stack")
1538
0
            .as_borrowed_or_rc();
1539
0
        self.match_string(string.as_str())
1540
0
    }
1541
1542
    /// Pops the top of the stack and attempts to match the string. Returns `Ok(Box<ParserState>)`
1543
    /// if the string is matched successfully, or `Err(Box<ParserState>)` otherwise.
1544
    ///
1545
    /// # Examples
1546
    ///
1547
    /// ```
1548
    /// # use pest;
1549
    /// # #[allow(non_camel_case_types)]
1550
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1551
    /// enum Rule {}
1552
    ///
1553
    /// let input = "aa";
1554
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1555
    /// let mut result = state.stack_push(|state| state.match_string("a")).and_then(
1556
    ///     |state| state.stack_pop()
1557
    /// );
1558
    /// assert!(result.is_ok());
1559
    /// assert_eq!(result.unwrap().position().pos(), 2);
1560
    /// ```
1561
    #[inline]
1562
0
    pub fn stack_pop(mut self: Box<Self>) -> ParseResult<Box<Self>> {
1563
0
        let string = self
1564
0
            .stack
1565
0
            .pop()
1566
0
            .expect("pop was called on empty stack")
1567
0
            .as_borrowed_or_rc();
1568
0
        self.match_string(string.as_str())
1569
0
    }
1570
1571
    /// Matches part of the state of the stack.
1572
    ///
1573
    /// # Examples
1574
    ///
1575
    /// ```
1576
    /// # use pest::{self, MatchDir};
1577
    /// # #[allow(non_camel_case_types)]
1578
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1579
    /// enum Rule {}
1580
    ///
1581
    /// let input = "abcd cd cb";
1582
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1583
    /// let mut result = state
1584
    ///     .stack_push(|state| state.match_string("a"))
1585
    ///     .and_then(|state| state.stack_push(|state| state.match_string("b")))
1586
    ///     .and_then(|state| state.stack_push(|state| state.match_string("c")))
1587
    ///     .and_then(|state| state.stack_push(|state| state.match_string("d")))
1588
    ///     .and_then(|state| state.match_string(" "))
1589
    ///     .and_then(|state| state.stack_match_peek_slice(2, None, MatchDir::BottomToTop))
1590
    ///     .and_then(|state| state.match_string(" "))
1591
    ///     .and_then(|state| state.stack_match_peek_slice(1, Some(-1), MatchDir::TopToBottom));
1592
    /// assert!(result.is_ok());
1593
    /// assert_eq!(result.unwrap().position().pos(), 10);
1594
    /// ```
1595
    #[inline]
1596
0
    pub fn stack_match_peek_slice(
1597
0
        mut self: Box<Self>,
1598
0
        start: i32,
1599
0
        end: Option<i32>,
1600
0
        match_dir: MatchDir,
1601
0
    ) -> ParseResult<Box<Self>> {
1602
0
        let range = match constrain_idxs(start, end, self.stack.len()) {
1603
0
            Some(r) => r,
1604
0
            None => return Err(self),
1605
        };
1606
        // return true if an empty sequence is requested
1607
0
        if range.end <= range.start {
1608
0
            return Ok(self);
1609
0
        }
1610
0
1611
0
        let mut position = self.position;
1612
0
        let result = {
1613
0
            let mut iter_b2t = self.stack[range].iter();
1614
0
            let matcher =
1615
0
                |span: &SpanOrLiteral<'_>| position.match_string(span.as_borrowed_or_rc().as_str());
1616
0
            match match_dir {
1617
0
                MatchDir::BottomToTop => iter_b2t.all(matcher),
1618
0
                MatchDir::TopToBottom => iter_b2t.rev().all(matcher),
1619
            }
1620
        };
1621
0
        if result {
1622
0
            self.position = position;
1623
0
            Ok(self)
1624
        } else {
1625
0
            Err(self)
1626
        }
1627
0
    }
1628
1629
    /// Matches the full state of the stack.
1630
    ///
1631
    /// # Examples
1632
    ///
1633
    /// ```
1634
    /// # use pest;
1635
    /// # #[allow(non_camel_case_types)]
1636
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1637
    /// enum Rule {}
1638
    ///
1639
    /// let input = "abba";
1640
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1641
    /// let mut result = state
1642
    ///     .stack_push(|state| state.match_string("a"))
1643
    ///     .and_then(|state| { state.stack_push(|state| state.match_string("b")) })
1644
    ///     .and_then(|state| state.stack_match_peek());
1645
    /// assert!(result.is_ok());
1646
    /// assert_eq!(result.unwrap().position().pos(), 4);
1647
    /// ```
1648
    #[inline]
1649
0
    pub fn stack_match_peek(self: Box<Self>) -> ParseResult<Box<Self>> {
1650
0
        self.stack_match_peek_slice(0, None, MatchDir::TopToBottom)
1651
0
    }
1652
1653
    /// Matches the full state of the stack. This method will clear the stack as it evaluates.
1654
    ///
1655
    /// # Examples
1656
    ///
1657
    /// ```
1658
    /// /// # use pest;
1659
    /// # #[allow(non_camel_case_types)]
1660
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1661
    /// enum Rule {}
1662
    ///
1663
    /// let input = "aaaa";
1664
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1665
    /// let mut result = state.stack_push(|state| state.match_string("a")).and_then(|state| {
1666
    ///     state.stack_push(|state| state.match_string("a"))
1667
    /// }).and_then(|state| state.stack_match_peek());
1668
    /// assert!(result.is_ok());
1669
    /// assert_eq!(result.unwrap().position().pos(), 4);
1670
    /// ```
1671
    #[inline]
1672
0
    pub fn stack_match_pop(mut self: Box<Self>) -> ParseResult<Box<Self>> {
1673
0
        let mut position = self.position;
1674
0
        let mut result = true;
1675
0
        while let Some(span) = self.stack.pop() {
1676
0
            result = position.match_string(span.as_borrowed_or_rc().as_str());
1677
0
            if !result {
1678
0
                break;
1679
0
            }
1680
        }
1681
1682
0
        if result {
1683
0
            self.position = position;
1684
0
            Ok(self)
1685
        } else {
1686
0
            Err(self)
1687
        }
1688
0
    }
1689
1690
    /// Drops the top of the stack. Returns `Ok(Box<ParserState>)` if there was a value to drop, or
1691
    /// `Err(Box<ParserState>)` otherwise.
1692
    ///
1693
    /// # Examples
1694
    ///
1695
    /// ```
1696
    /// # use pest;
1697
    /// # #[allow(non_camel_case_types)]
1698
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1699
    /// enum Rule {}
1700
    ///
1701
    /// let input = "aa";
1702
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1703
    /// let mut result = state.stack_push(|state| state.match_string("a")).and_then(
1704
    ///     |state| state.stack_drop()
1705
    /// );
1706
    /// assert!(result.is_ok());
1707
    /// assert_eq!(result.unwrap().position().pos(), 1);
1708
    /// ```
1709
    #[inline]
1710
0
    pub fn stack_drop(mut self: Box<Self>) -> ParseResult<Box<Self>> {
1711
0
        match self.stack.pop() {
1712
0
            Some(_) => Ok(self),
1713
0
            None => Err(self),
1714
        }
1715
0
    }
1716
1717
    /// Restores the original state of the `ParserState` when `f` returns an `Err`. Currently,
1718
    /// this method only restores the stack.
1719
    ///
1720
    /// # Examples
1721
    ///
1722
    /// ```
1723
    /// # use pest;
1724
    /// # #[allow(non_camel_case_types)]
1725
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1726
    /// enum Rule {}
1727
    ///
1728
    /// let input = "ab";
1729
    /// let mut state: Box<pest::ParserState<'_, Rule>> = pest::ParserState::new(input);
1730
    /// let mut result = state.restore_on_err(|state| state.stack_push(|state|
1731
    ///     state.match_string("a")).and_then(|state| state.match_string("a"))
1732
    /// );
1733
    ///
1734
    /// assert!(result.is_err());
1735
    ///
1736
    /// // Since the the rule doesn't match, the "a" pushed to the stack will be removed.
1737
    /// let catch_panic = std::panic::catch_unwind(|| result.unwrap_err().stack_pop());
1738
    /// assert!(catch_panic.is_err());
1739
    /// ```
1740
    #[inline]
1741
0
    pub fn restore_on_err<F>(self: Box<Self>, f: F) -> ParseResult<Box<Self>>
1742
0
    where
1743
0
        F: FnOnce(Box<Self>) -> ParseResult<Box<Self>>,
1744
0
    {
1745
0
        match f(self.checkpoint()) {
1746
0
            Ok(state) => Ok(state.checkpoint_ok()),
1747
0
            Err(state) => Err(state.restore()),
1748
        }
1749
0
    }
1750
1751
    // Mark the current state as a checkpoint and return the `Box`.
1752
    #[inline]
1753
0
    pub(crate) fn checkpoint(mut self: Box<Self>) -> Box<Self> {
1754
0
        self.stack.snapshot();
1755
0
        self
1756
0
    }
1757
1758
    // The checkpoint was cleared successfully
1759
    // so remove it without touching other stack state.
1760
    #[inline]
1761
0
    pub(crate) fn checkpoint_ok(mut self: Box<Self>) -> Box<Self> {
1762
0
        self.stack.clear_snapshot();
1763
0
        self
1764
0
    }
1765
1766
    // Restore the current state to the most recent checkpoint.
1767
    #[inline]
1768
0
    pub(crate) fn restore(mut self: Box<Self>) -> Box<Self> {
1769
0
        self.stack.restore();
1770
0
        self
1771
0
    }
1772
}
1773
1774
/// Helper function used only in case stack operations (PUSH/POP) are used in grammar.
1775
0
fn constrain_idxs(start: i32, end: Option<i32>, len: usize) -> Option<Range<usize>> {
1776
0
    let start_norm = normalize_index(start, len)?;
1777
0
    let end_norm = end.map_or(Some(len), |e| normalize_index(e, len))?;
1778
0
    Some(start_norm..end_norm)
1779
0
}
1780
1781
/// `constrain_idxs` helper function.
1782
/// Normalizes the index using its sequence’s length.
1783
/// Returns `None` if the normalized index is OOB.
1784
0
fn normalize_index(i: i32, len: usize) -> Option<usize> {
1785
0
    if i > len as i32 {
1786
0
        None
1787
0
    } else if i >= 0 {
1788
0
        Some(i as usize)
1789
    } else {
1790
0
        let real_i = len as i32 + i;
1791
0
        if real_i >= 0 {
1792
0
            Some(real_i as usize)
1793
        } else {
1794
0
            None
1795
        }
1796
    }
1797
0
}
1798
1799
#[cfg(test)]
1800
mod test {
1801
    use super::*;
1802
1803
    #[test]
1804
    fn normalize_index_pos() {
1805
        assert_eq!(normalize_index(4, 6), Some(4));
1806
        assert_eq!(normalize_index(5, 5), Some(5));
1807
        assert_eq!(normalize_index(6, 3), None);
1808
    }
1809
1810
    #[test]
1811
    fn normalize_index_neg() {
1812
        assert_eq!(normalize_index(-4, 6), Some(2));
1813
        assert_eq!(normalize_index(-5, 5), Some(0));
1814
        assert_eq!(normalize_index(-6, 3), None);
1815
    }
1816
}