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