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