fuel_pest/iterators/
flat_pairs.rs

1// pest. The Elegant Parser
2// Copyright (c) 2018 DragoČ™ Tiselice
3//
4// Licensed under the Apache License, Version 2.0
5// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
6// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. All files in the project carrying such notice may not be copied,
8// modified, or distributed except according to those terms.
9
10use alloc::rc::Rc;
11use alloc::vec::Vec;
12use std::fmt;
13use std::sync::Arc;
14
15use super::pair::{self, Pair};
16use super::queueable_token::QueueableToken;
17use super::tokens::{self, Tokens};
18use RuleType;
19
20/// An iterator over [`Pair`]s. It is created by [`Pairs::flatten`].
21///
22/// [`Pair`]: struct.Pair.html
23/// [`Pairs::flatten`]: struct.Pairs.html#method.flatten
24pub struct FlatPairs<R> {
25    /// # Safety
26    ///
27    /// All `QueueableToken`s' `input_pos` must be valid character boundary indices into `input`.
28    queue: Rc<Vec<QueueableToken<R>>>,
29    input: Arc<str>,
30    start: usize,
31    end: usize,
32}
33
34/// # Safety
35///
36/// All `QueueableToken`s' `input_pos` must be valid character boundary indices into `input`.
37pub unsafe fn new<R: RuleType>(
38    queue: Rc<Vec<QueueableToken<R>>>,
39    input: Arc<str>,
40    start: usize,
41    end: usize,
42) -> FlatPairs<R> {
43    FlatPairs {
44        queue,
45        input,
46        start,
47        end,
48    }
49}
50
51impl<R: RuleType> FlatPairs<R> {
52    /// Returns the `Tokens` for these pairs.
53    ///
54    /// # Examples
55    ///
56    /// ```
57    /// # use std::rc::Rc;
58    /// # use pest;
59    /// # use std::sync::Arc;
60    /// # #[allow(non_camel_case_types)]
61    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
62    /// enum Rule {
63    ///     a
64    /// }
65    ///
66    /// let input: Arc<str> = Arc::from("");
67    /// let pairs = pest::state(input, |state| {
68    ///     // generating Token pair with Rule::a ...
69    /// #     state.rule(Rule::a, |s| Ok(s))
70    /// }).unwrap();
71    /// let tokens: Vec<_> = pairs.flatten().tokens().collect();
72    ///
73    /// assert_eq!(tokens.len(), 2);
74    /// ```
75    #[inline]
76    pub fn tokens(self) -> Tokens<R> {
77        tokens::new(self.queue, self.input, self.start, self.end)
78    }
79
80    fn next_start(&mut self) {
81        self.start += 1;
82
83        while self.start < self.end && !self.is_start(self.start) {
84            self.start += 1;
85        }
86    }
87
88    fn next_start_from_end(&mut self) {
89        self.end -= 1;
90
91        while self.end >= self.start && !self.is_start(self.end) {
92            self.end -= 1;
93        }
94    }
95
96    fn is_start(&self, index: usize) -> bool {
97        match self.queue[index] {
98            QueueableToken::Start { .. } => true,
99            QueueableToken::End { .. } => false,
100        }
101    }
102}
103
104impl<R: RuleType> Iterator for FlatPairs<R> {
105    type Item = Pair<R>;
106
107    fn next(&mut self) -> Option<Self::Item> {
108        if self.start >= self.end {
109            return None;
110        }
111
112        let pair = unsafe { pair::new(Rc::clone(&self.queue), self.input.clone(), self.start) };
113
114        self.next_start();
115
116        Some(pair)
117    }
118}
119
120impl<R: RuleType> DoubleEndedIterator for FlatPairs<R> {
121    fn next_back(&mut self) -> Option<Self::Item> {
122        if self.end <= self.start {
123            return None;
124        }
125
126        self.next_start_from_end();
127
128        let pair = unsafe { pair::new(Rc::clone(&self.queue), self.input.clone(), self.end) };
129
130        Some(pair)
131    }
132}
133
134impl<R: RuleType> fmt::Debug for FlatPairs<R> {
135    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
136        f.debug_struct("FlatPairs")
137            .field("pairs", &self.clone().collect::<Vec<_>>())
138            .finish()
139    }
140}
141
142impl<R: Clone> Clone for FlatPairs<R> {
143    fn clone(&self) -> FlatPairs<R> {
144        FlatPairs {
145            queue: Rc::clone(&self.queue),
146            input: self.input.clone(),
147            start: self.start,
148            end: self.end,
149        }
150    }
151}
152
153#[cfg(test)]
154mod tests {
155    use super::super::super::macros::tests::*;
156    use super::super::super::Parser;
157    use alloc::vec;
158    use alloc::vec::Vec;
159    use std::sync::Arc;
160
161    #[test]
162    fn iter_for_flat_pairs() {
163        let pairs = AbcParser::parse(Rule::a, Arc::from("abcde")).unwrap();
164
165        assert_eq!(
166            pairs.flatten().map(|p| p.as_rule()).collect::<Vec<Rule>>(),
167            vec![Rule::a, Rule::b, Rule::c]
168        );
169    }
170
171    #[test]
172    fn double_ended_iter_for_flat_pairs() {
173        let pairs = AbcParser::parse(Rule::a, Arc::from("abcde")).unwrap();
174        assert_eq!(
175            pairs
176                .flatten()
177                .rev()
178                .map(|p| p.as_rule())
179                .collect::<Vec<Rule>>(),
180            vec![Rule::c, Rule::b, Rule::a]
181        );
182    }
183}