pear/
combinators.rs

1use crate::input::{Pear, Input, Rewind, Token, Result};
2use crate::macros::parser;
3use crate::parsers::*;
4
5pub trait Collection<A>: Default + Extend<A> {
6    #[inline(always)]
7    fn push(&mut self, item: A) {
8        self.extend(Some(item))
9    }
10}
11
12impl<A, T: Default + Extend<A>> Collection<A> for T {  }
13
14/// Parses `p`, returning `Some` if it succeeds and `None` if it fails. Discards
15/// the error message.
16pub fn ok<I, P, O>(input: &mut Pear<I>, p: P) -> Option<O>
17    where I: Input, P: FnOnce(&mut Pear<I>) -> Result<O, I>
18{
19    let save = input.emit_error;
20    input.emit_error = false;
21    let ok = p(input).ok();
22    input.emit_error = save;
23    ok
24}
25
26/// Parses `p`, returning `true` if it succeeds and `false` if it fails.
27/// Discards the error message.
28pub fn succeeds<I, P, O>(input: &mut Pear<I>, p: P) -> bool
29    where I: Input, P: FnOnce(&mut Pear<I>) -> Result<O, I>
30{
31    ok(input, p).is_some()
32}
33
34/// Parses `p` until `p` fails, returning the last successful `p`.
35#[parser(raw)]
36pub fn last_of_many<I, O, P>(input: &mut Pear<I>, mut p: P) -> Result<O, I>
37    where I: Input, P: FnMut(&mut Pear<I>) -> Result<O, I>
38{
39    loop {
40        let output = p()?;
41        if succeeds(input, eof) {
42            return Ok(output);
43        }
44    }
45}
46
47/// Skips all tokens that match `f` before and after a `p`, returning `p`.
48#[parser(raw)]
49pub fn surrounded<I, O, F, P>(input: &mut Pear<I>, mut p: P, mut f: F) -> Result<O, I>
50    where I: Input,
51          F: FnMut(&I::Token) -> bool,
52          P: FnMut(&mut Pear<I>) -> Result<O, I>
53{
54    skip_while(&mut f)?;
55    let output = p()?;
56    skip_while(&mut f)?;
57    Ok(output)
58}
59
60/// Parses as many `p` as possible until EOF is reached, collecting them into a
61/// `C`. Fails if `p` every fails. `C` may be empty.
62#[parser(raw)]
63pub fn collect<C, I, O, P>(input: &mut Pear<I>, mut p: P) -> Result<C, I>
64    where C: Collection<O>, I: Input, P: FnMut(&mut Pear<I>) -> Result<O, I>
65{
66    let mut collection = C::default();
67    loop {
68        if succeeds(input, eof) {
69            return Ok(collection);
70        }
71
72        collection.push(p()?);
73    }
74}
75
76/// Parses as many `p` as possible until EOF is reached, collecting them into a
77/// `C`. Fails if `p` ever fails. `C` is not allowed to be empty.
78#[parser(raw)]
79pub fn collect_some<C, I, O, P>(input: &mut Pear<I>, mut p: P) -> Result<C, I>
80    where C: Collection<O>, I: Input, P: FnMut(&mut Pear<I>) -> Result<O, I>
81{
82    let mut collection = C::default();
83    loop {
84        collection.push(p()?);
85        if succeeds(input, eof) {
86            return Ok(collection);
87        }
88    }
89}
90
91/// Parses as many `p` as possible until EOF is reached or `p` fails, collecting
92/// them into a `C`. `C` may be empty.
93#[parser(raw)]
94pub fn try_collect<C, I, O, P>(input: &mut Pear<I>, mut p: P) -> Result<C, I>
95    where C: Collection<O>, I: Input + Rewind, P: FnMut(&mut Pear<I>) -> Result<O, I>
96{
97    let mut collection = C::default();
98    loop {
99        if succeeds(input, eof) {
100            return Ok(collection);
101        }
102
103        // FIXME: We should be able to call `parse_marker!` here.
104        let start = input.mark(&crate::input::ParserInfo {
105            name: "try_collect",
106            raw: true
107        });
108
109        match ok(input, |i| p(i)) {
110            Some(val) => collection.push(val),
111            None => {
112                input.rewind_to(start);
113                break;
114            }
115        }
116    }
117
118    Ok(collection)
119}
120
121/// Parses many `separator` delimited `p`s, the entire collection of which must
122/// start with `start` and end with `end`. `item` Gramatically, this is:
123///
124/// START (item SEPERATOR)* END
125#[parser(raw)]
126pub fn delimited_collect<C, I, T, S, O, P>(
127    input: &mut Pear<I>,
128    start: T,
129    mut item: P,
130    separator: S,
131    end: T,
132) -> Result<C, I>
133    where C: Collection<O>,
134          I: Input,
135          T: Token<I> + Clone,
136          S: Into<Option<T>>,
137          P: FnMut(&mut Pear<I>) -> Result<O, I>,
138{
139    eat(start)?;
140
141    let seperator = separator.into();
142    let mut collection = C::default();
143    loop {
144        if succeeds(input, |i| eat(i, end.clone())) {
145            break;
146        }
147
148        collection.push(item()?);
149
150        if let Some(ref separator) = seperator {
151            if !succeeds(input, |i| eat(i, separator.clone())) {
152                eat(end.clone())?;
153                break;
154            }
155        }
156    }
157
158    Ok(collection)
159}
160
161/// Parses many `separator` delimited `p`s. Gramatically, this is:
162///
163/// item (SEPERATOR item)*
164#[parser(raw)]
165pub fn series<C, I, S, O, P>(
166    input: &mut Pear<I>,
167    mut item: P,
168    seperator: S,
169) -> Result<C, I>
170    where C: Collection<O>,
171          I: Input,
172          S: Token<I> + Clone,
173          P: FnMut(&mut Pear<I>) -> Result<O, I>,
174{
175    let mut collection = C::default();
176    loop {
177        collection.push(item()?);
178        if !succeeds(input, |i| eat(i, seperator.clone())) {
179            break;
180        }
181    }
182
183    Ok(collection)
184}
185
186/// Parses many `separator` delimited `p`s with an optional trailing separator.
187/// Gramatically, this is:
188///
189/// item (SEPERATOR item)* SEPERATOR?
190#[parser(raw)]
191pub fn trailing_series<C, I, S, O, P>(
192    input: &mut Pear<I>,
193    mut item: P,
194    seperator: S,
195) -> Result<C, I>
196    where C: Collection<O>,
197          I: Input,
198          S: Token<I> + Clone,
199          P: FnMut(&mut Pear<I>) -> Result<O, I>,
200{
201    let mut collection = C::default();
202    let mut have_some = false;
203    loop {
204        if have_some {
205            if let Some(item) = ok(input, |i| item(i)) {
206                collection.push(item);
207            } else {
208                break
209            }
210        } else {
211            collection.push(item()?);
212            have_some = true;
213        }
214
215        if !succeeds(input, |i| eat(i, seperator.clone())) {
216            break;
217        }
218    }
219
220    Ok(collection)
221}
222
223/// Parses many `separator` delimited `p`s that are collectively prefixed with
224/// `prefix`. Gramatically, this is:
225///
226/// PREFIX (item SEPERATOR)*
227#[parser(raw)]
228pub fn prefixed_series<C, I, T, O, P>(
229    input: &mut Pear<I>,
230    prefix: T,
231    item: P,
232    seperator: T,
233) -> Result<C, I>
234    where C: Collection<O>,
235          I: Input,
236          T: Token<I> + Clone,
237          P: FnMut(&mut Pear<I>) -> Result<O, I>,
238{
239    if !succeeds(input, |i| eat(i, prefix)) {
240        return Ok(C::default());
241    }
242
243    series(input, item, seperator)
244}