fuel_pest/iterators/
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::format;
11use alloc::rc::Rc;
12use alloc::string::String;
13use alloc::vec::Vec;
14use std::fmt;
15use std::hash::{Hash, Hasher};
16use std::str;
17use std::sync::Arc;
18
19#[cfg(feature = "pretty-print")]
20use serde::ser::SerializeStruct;
21
22use super::flat_pairs::{self, FlatPairs};
23use super::pair::{self, Pair};
24use super::queueable_token::QueueableToken;
25use super::tokens::{self, Tokens};
26use RuleType;
27
28/// An iterator over [`Pair`]s. It is created by [`pest::state`] and [`Pair::into_inner`].
29///
30/// [`Pair`]: struct.Pair.html
31/// [`pest::state`]: ../fn.state.html
32/// [`Pair::into_inner`]: struct.Pair.html#method.into_inner
33#[derive(Clone)]
34pub struct Pairs<R> {
35    queue: Rc<Vec<QueueableToken<R>>>,
36    input: Arc<str>,
37    start: usize,
38    end: usize,
39}
40
41pub fn new<R: RuleType>(
42    queue: Rc<Vec<QueueableToken<R>>>,
43    input: Arc<str>,
44    start: usize,
45    end: usize,
46) -> Pairs<R> {
47    Pairs {
48        queue,
49        input,
50        start,
51        end,
52    }
53}
54
55impl<R: RuleType> Pairs<R> {
56    /// Captures a slice from the `&str` defined by the starting position of the first token `Pair`
57    /// and the ending position of the last token `Pair` of the `Pairs`. This also captures
58    /// the input between those two token `Pair`s.
59    ///
60    /// # Examples
61    ///
62    /// ```
63    /// # use std::rc::Rc;
64    /// # use pest;
65    /// # use std::sync::Arc;
66    /// # #[allow(non_camel_case_types)]
67    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
68    /// enum Rule {
69    ///     a,
70    ///     b
71    /// }
72    ///
73    /// let input: Arc<str> = Arc::from("a b");
74    /// let pairs = pest::state(input, |state| {
75    ///     // generating Token pairs with Rule::a and Rule::b ...
76    /// #     state.rule(Rule::a, |s| s.match_string("a")).and_then(|s| s.skip(1))
77    /// #         .and_then(|s| s.rule(Rule::b, |s| s.match_string("b")))
78    /// }).unwrap();
79    ///
80    /// assert_eq!(pairs.as_str(), "a b");
81    /// ```
82    #[inline]
83    pub fn as_str(&self) -> &str {
84        if self.start < self.end {
85            let start = self.pos(self.start);
86            let end = self.pos(self.end - 1);
87            // Generated positions always come from Positions and are UTF-8 borders.
88            &self.input[start..end]
89        } else {
90            ""
91        }
92    }
93
94    /// Captures inner token `Pair`s and concatenates resulting `&str`s. This does not capture
95    /// the input between token `Pair`s.
96    ///
97    /// # Examples
98    ///
99    /// ```
100    /// # use std::rc::Rc;
101    /// # use pest;
102    /// # use std::sync::Arc;
103    /// # #[allow(non_camel_case_types)]
104    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
105    /// enum Rule {
106    ///     a,
107    ///     b
108    /// }
109    ///
110    /// let input: Arc<str> = Arc::from("a b");
111    /// let pairs = pest::state(input, |state| {
112    ///     // generating Token pairs with Rule::a and Rule::b ...
113    /// #     state.rule(Rule::a, |s| s.match_string("a")).and_then(|s| s.skip(1))
114    /// #         .and_then(|s| s.rule(Rule::b, |s| s.match_string("b")))
115    /// }).unwrap();
116    ///
117    /// assert_eq!(pairs.concat(), "ab");
118    /// ```
119    #[inline]
120    pub fn concat(&self) -> String {
121        self.clone()
122            .fold(String::new(), |string, pair| string + pair.as_str())
123    }
124
125    /// Flattens the `Pairs`.
126    ///
127    /// # Examples
128    ///
129    /// ```
130    /// # use std::rc::Rc;
131    /// # use pest;
132    /// # use std::sync::Arc;
133    /// # #[allow(non_camel_case_types)]
134    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
135    /// enum Rule {
136    ///     a,
137    ///     b
138    /// }
139    ///
140    /// let input: Arc<str> = Arc::from("");
141    /// let pairs = pest::state(input, |state| {
142    ///     // generating nested Token pair with Rule::b inside Rule::a
143    /// #     state.rule(Rule::a, |state| {
144    /// #         state.rule(Rule::b, |s| Ok(s))
145    /// #     })
146    /// }).unwrap();
147    /// let tokens: Vec<_> = pairs.flatten().tokens().collect();
148    ///
149    /// assert_eq!(tokens.len(), 4);
150    /// ```
151    #[inline]
152    pub fn flatten(self) -> FlatPairs<R> {
153        unsafe { flat_pairs::new(self.queue, self.input, self.start, self.end) }
154    }
155
156    /// Returns the `Tokens` for the `Pairs`.
157    ///
158    /// # Examples
159    ///
160    /// ```
161    /// # use std::rc::Rc;
162    /// # use pest;
163    /// # use std::sync::Arc;
164    /// # #[allow(non_camel_case_types)]
165    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
166    /// enum Rule {
167    ///     a
168    /// }
169    ///
170    /// let input: Arc<str> = Arc::from("");
171    /// let pairs = pest::state(input, |state| {
172    ///     // generating Token pair with Rule::a ...
173    /// #     state.rule(Rule::a, |s| Ok(s))
174    /// }).unwrap();
175    /// let tokens: Vec<_> = pairs.tokens().collect();
176    ///
177    /// assert_eq!(tokens.len(), 2);
178    /// ```
179    #[inline]
180    pub fn tokens(self) -> Tokens<R> {
181        tokens::new(self.queue, self.input, self.start, self.end)
182    }
183
184    /// Peek at the first inner `Pair` without changing the position of this iterator.
185    #[inline]
186    pub fn peek(&self) -> Option<Pair<R>> {
187        if self.start < self.end {
188            Some(unsafe { pair::new(Rc::clone(&self.queue), self.input.clone(), self.start) })
189        } else {
190            None
191        }
192    }
193
194    /// Generates a string that stores the lexical information of `self` in
195    /// a pretty-printed JSON format.
196    #[cfg(feature = "pretty-print")]
197    pub fn to_json(&self) -> String {
198        ::serde_json::to_string_pretty(self).expect("Failed to pretty-print Pairs to json.")
199    }
200
201    fn pair(&self) -> usize {
202        match self.queue[self.start] {
203            QueueableToken::Start {
204                end_token_index, ..
205            } => end_token_index,
206            _ => unreachable!(),
207        }
208    }
209
210    fn pair_from_end(&self) -> usize {
211        match self.queue[self.end - 1] {
212            QueueableToken::End {
213                start_token_index, ..
214            } => start_token_index,
215            _ => unreachable!(),
216        }
217    }
218
219    fn pos(&self, index: usize) -> usize {
220        match self.queue[index] {
221            QueueableToken::Start { input_pos, .. } | QueueableToken::End { input_pos, .. } => {
222                input_pos
223            }
224        }
225    }
226}
227
228impl<R: RuleType> Iterator for Pairs<R> {
229    type Item = Pair<R>;
230
231    fn next(&mut self) -> Option<Self::Item> {
232        let pair = self.peek()?;
233        self.start = self.pair() + 1;
234        Some(pair)
235    }
236}
237
238impl<R: RuleType> DoubleEndedIterator for Pairs<R> {
239    fn next_back(&mut self) -> Option<Self::Item> {
240        if self.end <= self.start {
241            return None;
242        }
243
244        self.end = self.pair_from_end();
245
246        let pair = unsafe { pair::new(Rc::clone(&self.queue), self.input.clone(), self.end) };
247
248        Some(pair)
249    }
250}
251
252impl<R: RuleType> fmt::Debug for Pairs<R> {
253    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
254        f.debug_list().entries(self.clone()).finish()
255    }
256}
257
258impl<R: RuleType> fmt::Display for Pairs<R> {
259    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
260        write!(
261            f,
262            "[{}]",
263            self.clone()
264                .map(|pair| format!("{}", pair))
265                .collect::<Vec<_>>()
266                .join(", ")
267        )
268    }
269}
270
271impl<R: PartialEq> PartialEq for Pairs<R> {
272    fn eq(&self, other: &Pairs<R>) -> bool {
273        Rc::ptr_eq(&self.queue, &other.queue)
274            && Arc::ptr_eq(&self.input, &other.input)
275            && self.start == other.start
276            && self.end == other.end
277    }
278}
279
280impl<R: Eq> Eq for Pairs<R> {}
281
282impl<R: Hash> Hash for Pairs<R> {
283    fn hash<H: Hasher>(&self, state: &mut H) {
284        (&*self.queue as *const Vec<QueueableToken<R>>).hash(state);
285        Arc::as_ptr(&self.input).hash(state);
286        self.start.hash(state);
287        self.end.hash(state);
288    }
289}
290
291#[cfg(feature = "pretty-print")]
292impl<R: RuleType> ::serde::Serialize for Pairs<R> {
293    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
294    where
295        S: ::serde::Serializer,
296    {
297        let start = self.pos(self.start);
298        let end = self.pos(self.end - 1);
299        let pairs = self.clone().collect::<Vec<_>>();
300
301        let mut ser = serializer.serialize_struct("Pairs", 2)?;
302        ser.serialize_field("pos", &(start, end))?;
303        ser.serialize_field("pairs", &pairs)?;
304        ser.end()
305    }
306}
307
308#[cfg(test)]
309mod tests {
310    use super::super::super::macros::tests::*;
311    use super::super::super::Parser;
312    use alloc::borrow::ToOwned;
313    use alloc::format;
314    use alloc::vec;
315    use alloc::vec::Vec;
316    use std::sync::Arc;
317
318    #[test]
319    #[cfg(feature = "pretty-print")]
320    fn test_pretty_print() {
321        let pairs = AbcParser::parse(Rule::a, Arc::from("abcde")).unwrap();
322
323        let expected = r#"{
324  "pos": [
325    0,
326    5
327  ],
328  "pairs": [
329    {
330      "pos": [
331        0,
332        3
333      ],
334      "rule": "a",
335      "inner": {
336        "pos": [
337          1,
338          2
339        ],
340        "pairs": [
341          {
342            "pos": [
343              1,
344              2
345            ],
346            "rule": "b",
347            "inner": "b"
348          }
349        ]
350      }
351    },
352    {
353      "pos": [
354        4,
355        5
356      ],
357      "rule": "c",
358      "inner": "e"
359    }
360  ]
361}"#;
362
363        assert_eq!(expected, pairs.to_json());
364    }
365
366    #[test]
367    fn as_str() {
368        let pairs = AbcParser::parse(Rule::a, Arc::from("abcde")).unwrap();
369
370        assert_eq!(pairs.as_str(), "abcde");
371    }
372
373    #[test]
374    fn as_str_empty() {
375        let mut pairs = AbcParser::parse(Rule::a, Arc::from("abcde")).unwrap();
376
377        assert_eq!(pairs.nth(1).unwrap().into_inner().as_str(), "");
378    }
379
380    #[test]
381    fn concat() {
382        let pairs = AbcParser::parse(Rule::a, Arc::from("abcde")).unwrap();
383
384        assert_eq!(pairs.concat(), "abce");
385    }
386
387    #[test]
388    fn pairs_debug() {
389        let pairs = AbcParser::parse(Rule::a, Arc::from("abcde")).unwrap();
390
391        #[rustfmt::skip]
392        assert_eq!(
393            format!("{:?}", pairs),
394            "[\
395                Pair { rule: a, span: Span { str: \"abc\", start: 0, end: 3 }, inner: [\
396                    Pair { rule: b, span: Span { str: \"b\", start: 1, end: 2 }, inner: [] }\
397                ] }, \
398                Pair { rule: c, span: Span { str: \"e\", start: 4, end: 5 }, inner: [] }\
399            ]"
400            .to_owned()
401        );
402    }
403
404    #[test]
405    fn pairs_display() {
406        let pairs = AbcParser::parse(Rule::a, Arc::from("abcde")).unwrap();
407
408        assert_eq!(
409            format!("{}", pairs),
410            "[a(0, 3, [b(1, 2)]), c(4, 5)]".to_owned()
411        );
412    }
413
414    #[test]
415    fn iter_for_pairs() {
416        let pairs = AbcParser::parse(Rule::a, Arc::from("abcde")).unwrap();
417        assert_eq!(
418            pairs.map(|p| p.as_rule()).collect::<Vec<Rule>>(),
419            vec![Rule::a, Rule::c]
420        );
421    }
422
423    #[test]
424    fn double_ended_iter_for_pairs() {
425        let pairs = AbcParser::parse(Rule::a, Arc::from("abcde")).unwrap();
426        assert_eq!(
427            pairs.rev().map(|p| p.as_rule()).collect::<Vec<Rule>>(),
428            vec![Rule::c, Rule::a]
429        );
430    }
431}