pear/
parsers.rs

1use crate::error::Expected;
2use crate::input::{Input, Pear, Length, Token, Slice, Result, Rewind};
3use crate::combinators::succeeds;
4use crate::macros::parser;
5
6// TODO: provide more basic parsers in pear
7//   - [f32, f64, i8, i32, ..., bool, etc.]: one for all reasonable built-ins
8//   - quoted_string(allowed): '"' allowed* '"'
9//   - escaped string, with some way to configure escapes
10
11#[inline]
12fn expected_token<T, I>(
13    input: &mut Pear<I>,
14    token: Option<T>
15) -> Expected<I::Token, I::Slice>
16    where T: Token<I>, I: Input
17{
18    // TODO: Have some way to test this is being called minimally.
19    if input.emit_error {
20        Expected::token(token.as_ref(), input.token())
21    } else {
22        Expected::Elided
23    }
24}
25
26#[inline]
27fn expected_slice<S, I>(
28    input: &mut Pear<I>,
29    slice: S
30) -> Expected<I::Token, I::Slice>
31    where S: Slice<I>, I: Input
32{
33    // TODO: Have some way to test this is being called minimally.
34    if input.emit_error {
35        Expected::slice(Some(&slice), input.slice(slice.len()))
36    } else {
37        Expected::Elided
38    }
39}
40
41/// Eats the current token if it is `token`.
42#[parser(raw)]
43pub fn eat<I, T>(input: &mut Pear<I>, token: T) -> Result<I::Token, I>
44    where I: Input, T: Token<I>
45{
46    match input.eat(|t| &token == t) {
47        Some(token) => Ok(token),
48        None => return parse_error!(expected_token(input, Some(token)))
49    }
50}
51
52/// Eats the token `token` if `cond` holds on the current token.
53#[parser(raw)]
54pub fn eat_if<I, F>(input: &mut Pear<I>, cond: F) -> Result<I::Token, I>
55    where I: Input, F: FnMut(&I::Token) -> bool
56{
57    match input.eat(cond) {
58        Some(token) => Ok(token),
59        None => parse_error!(expected_token::<I::Token, _>(input, None))
60    }
61}
62
63/// Eats the current token unconditionally. Fails if there are no tokens.
64#[parser(raw)]
65pub fn eat_any<I: Input>(input: &mut Pear<I>) -> Result<I::Token, I> {
66    match input.eat(|_| true) {
67        Some(token) => Ok(token),
68        None => return parse_error!(Expected::Token(None, None))
69    }
70}
71
72/// Skips the current token unconditionally. Fails if there are no tokens.
73#[parser(raw)]
74pub fn skip_any<I: Input>(input: &mut Pear<I>) -> Result<(), I> {
75    let mut skipped = false;
76    input.skip(|_| {
77        if !skipped {
78            skipped = true;
79            true
80        } else {
81            false
82        }
83    });
84
85    match skipped {
86        true => Ok(()),
87        false => return parse_error!(Expected::Token(None, None)),
88    }
89}
90
91/// Eats the current slice if it is `slice`.
92#[parser(raw)]
93pub fn eat_slice<I, S>(input: &mut Pear<I>, slice: S) -> Result<I::Slice, I>
94    where I: Input, S: Slice<I>
95{
96    match input.eat_slice(slice.len(), |s| &slice == s) {
97        Some(slice) => Ok(slice),
98        None => return parse_error!(expected_slice(input, slice))
99    }
100}
101
102/// Succeeds if the current token is `token`.
103#[parser(raw)]
104pub fn peek<I, T>(input: &mut Pear<I>, token: T) -> Result<(), I>
105    where I: Input, T: Token<I>
106{
107    match input.peek(|t| &token == t) {
108        true => Ok(()),
109        false => return parse_error!(expected_token(input, Some(token)))
110    }
111}
112
113/// Succeeds if `cond` holds for the current token.
114#[parser(raw)]
115pub fn peek_if_copy<I, F>(input: &mut Pear<I>, cond: F) -> Result<I::Token, I>
116    where I: Input, F: FnMut(&I::Token) -> bool
117{
118    match input.peek(cond) {
119        true => Ok(input.token().unwrap()),
120        false => parse_error!(expected_token::<I::Token, _>(input, None))
121    }
122}
123
124/// Succeeds if `cond` holds for the current token.
125#[parser(raw)]
126pub fn peek_if<I, F>(input: &mut Pear<I>, cond: F) -> Result<(), I>
127    where I: Input, F: FnMut(&I::Token) -> bool
128{
129    match input.peek(cond) {
130        true => Ok(()),
131        false => parse_error!(expected_token::<I::Token, _>(input, None))
132    }
133}
134
135/// Succeeds if the current slice is `slice`.
136#[parser(raw)]
137pub fn peek_slice<I, S>(input: &mut Pear<I>, slice: S) -> Result<(), I>
138    where I: Input, S: Slice<I>
139{
140    match input.peek_slice(slice.len(), |s| &slice == s) {
141        true => Ok(()),
142        false => return parse_error!(expected_slice(input, slice)),
143    }
144}
145
146/// Succeeds if the current slice is `slice`.
147#[parser(raw)]
148pub fn peek_slice_if<I, F>(input: &mut Pear<I>, len: usize, cond: F) -> Result<(), I>
149    where I: Input, F: FnMut(&I::Slice) -> bool
150{
151    match input.peek_slice(len, cond) {
152        true => Ok(()),
153        false => return parse_error!(Expected::Slice(None, None)),
154    }
155}
156
157/// Returns the current token.
158#[parser(raw)]
159pub fn peek_any<I: Input>(input: &mut Pear<I>) -> Result<I::Token, I> {
160    match input.token() {
161        Some(peeked) => Ok(peeked),
162        None => return parse_error!(Expected::Token(None, None)),
163    }
164}
165
166/// Skips tokens while `cond` matches.
167#[parser(raw)]
168pub fn skip_while<I, F>(input: &mut Pear<I>, cond: F) -> Result<usize, I>
169    where I: Input, F: FnMut(&I::Token) -> bool
170{
171    Ok(input.skip(cond))
172}
173
174/// Consumes tokens while `cond` matches and returns them. Succeeds even if no
175/// tokens match.
176#[parser(raw)]
177pub fn take_while<I, F>(input: &mut Pear<I>, cond: F) -> Result<I::Many, I>
178    where I: Input, F: FnMut(&I::Token) -> bool
179{
180    Ok(input.take(cond))
181}
182
183/// Consumes no tokens. Always succeeds. Equivalent to `take_while(|_| false)`.
184#[parser(raw)]
185pub fn none<I: Input>(input: &mut Pear<I>) -> Result<I::Many, I> {
186    take_while(input, |_| false)
187}
188
189/// Consumes tokens while `cond` matches on a continously growing slice
190/// beginning at a length of `0` and ending when `cond` fails. Returns the slice
191/// between `0` and `cond` failing. Errors if no such slice exists.
192#[parser(raw)]
193pub fn take_while_slice<I, F>(input: &mut Pear<I>, mut f: F) -> Result<I::Slice, I>
194    where I: Input, F: FnMut(&I::Slice) -> bool
195{
196    let mut len = 0;
197    let mut last_good = None;
198    loop {
199        match input.slice(len) {
200            // There's a slice and it matches the condition, keep going!
201            Some(ref slice) if f(slice) => {
202                last_good = Some(len);
203                len += 1;
204            }
205            // There's no slice of length `n`, but there _might_ be a slice of
206            // length `n + 1`, so we  need to keep trying.
207            None if input.has(len + 1) => len += 1,
208            // There are no more slices or the match failed. We're done.
209            _ => break,
210        }
211    }
212
213    match last_good {
214        Some(len) => Ok(input.eat_slice(len, |_| true).expect("slice exists")),
215        None => return parse_error!(Expected::Slice(None, None)),
216    }
217}
218
219/// Consumes tokens while `cond` matches on a window of tokens of size `n` and
220/// returns all of the tokens prior to the first failure to match. For example,
221/// given a string of "aaab" and a size 2 window predicate of `window == "aa"`,
222/// the return value is `"aa"` as the first failure to match is at `"ab"`.
223///
224/// Always succeeds. If no tokens match, the result will be empty. If there are
225/// fewer than `n` tokens, takes all tokens and returns them.
226#[parser(raw)]
227pub fn take_while_window<I, F>(input: &mut Pear<I>, n: usize, mut f: F) -> Result<I::Many, I>
228    where I: Input + Rewind, F: FnMut(&I::Slice) -> bool
229{
230    if !input.has(n) {
231        return Ok(input.take(|_| true));
232    }
233
234    let start = parse_current_marker!();
235    let mut tokens = 0;
236    loop {
237        // See `take_while_slice` for  an explanation of these arms.
238        match input.slice(n) {
239            Some(ref slice) if f(slice) => {
240                if !succeeds(input, skip_any) { break; }
241                tokens += 1;
242            }
243            None if input.has(n + 1) => {
244                if !succeeds(input, skip_any) { break; }
245                tokens += 1;
246            }
247            _ => break,
248        }
249    }
250
251    input.rewind_to(start);
252    Ok(input.take(|_| match tokens > 0 {
253        true => { tokens -= 1; true },
254        false => false
255    }))
256}
257
258/// Consumes tokens while `cond` matches on a window of tokens of size `n` and
259/// returns them. Fails if there no tokens match, otherwise returns all of the
260/// tokens before the first failure.
261#[parser(raw)]
262pub fn take_some_while_window<I, F>(input: &mut Pear<I>, n: usize, f: F) -> Result<I::Many, I>
263    where I: Input + Rewind, F: FnMut(&I::Slice) -> bool
264{
265    let result = take_while_window(n, f)?;
266    if result.is_empty() {
267        return parse_error!(Expected::Slice(None, None));
268    }
269
270    Ok(result)
271}
272
273/// Consumes tokens while `cond` matches on a window of tokens of size `n` and
274/// returns them. Fails if there aren't at least `n` tokens, otherwise always
275/// otherwise always succeeds. If no tokens match, the result will be empty.
276#[parser(raw)]
277pub fn take_while_some_window<I, F>(input: &mut Pear<I>, n: usize, f: F) -> Result<I::Many, I>
278    where I: Input + Rewind, F: FnMut(&I::Slice) -> bool
279{
280    if !input.has(n) {
281        return parse_error!(Expected::Slice(None, None));
282    }
283
284    take_while_window(input, n, f)
285}
286
287/// Consumes tokens while `cond` matches on a window of tokens of size `n` and
288/// returns them. Fails if there aren't at least `n` tokens or if no tokens
289/// match, otherwise returns all of the tokens before the first failure.
290#[parser(raw)]
291pub fn take_some_while_some_window<I, F>(input: &mut Pear<I>, n: usize, f: F) -> Result<I::Many, I>
292    where I: Input + Rewind, F: FnMut(&I::Slice) -> bool
293{
294    if !input.has(n) {
295        return parse_error!(Expected::Slice(None, None));
296    }
297
298    take_some_while_window(input, n, f)
299}
300
301/// Consumes tokens while `cond` matches on a window of tokens of size `n` and
302/// returns them. Succeeds even if no tokens match.
303#[parser(raw)]
304pub fn take_until_slice<I, S>(input: &mut Pear<I>, slice: S) -> Result<I::Many, I>
305    where I: Input + Rewind, S: Slice<I>
306{
307    take_while_window(input, slice.len(), |s| &slice != s)
308}
309
310/// Consumes tokens while `cond` matches and returns them. Succeeds only if at
311/// least one token matched `cond`.
312#[parser(raw)]
313pub fn take_some_while<I, F>(input: &mut Pear<I>, cond: F) -> Result<I::Many, I>
314    where I: Input, F: FnMut(&I::Token) -> bool
315{
316    let value = input.take(cond);
317    if value.len() == 0 {
318        return parse_error!(Expected::Token(None, None));
319    }
320
321    Ok(value)
322}
323
324/// Consumes tokens while `cond` matches and the token is not `until`. Succeeds
325/// even if no tokens match.
326#[parser(raw)]
327pub fn take_while_until<I, T, F>(
328    input: &mut Pear<I>,
329    mut cond: F,
330    until: T,
331) -> Result<I::Many, I>
332    where I: Input,
333          T: Token<I>,
334          F: FnMut(&I::Token) -> bool
335{
336    take_while(input, |t| cond(t) && (&until != t))
337}
338
339/// Consumes tokens while `cond` matches and the token is not `until`. Succeeds
340/// only if at least one token matched `cond`.
341#[parser(raw)]
342pub fn take_some_while_until<I, T, F>(
343    input: &mut Pear<I>,
344    mut cond: F,
345    until: T,
346) -> Result<I::Many, I>
347    where I: Input,
348          T: Token<I>,
349          F: FnMut(&I::Token) -> bool
350{
351    take_some_while(input, |t| cond(t) && (&until != t))
352}
353
354/// Takes at most `n` tokens.
355#[parser(raw)]
356pub fn take_n<I: Input>(input: &mut Pear<I>, n: usize) -> Result<I::Many, I> {
357    let mut i = 0;
358    Ok(input.take(|_| { let c = i < n; i += 1; c }))
359}
360
361/// Takes at most `n` tokens as long as `cond` holds.
362#[parser(raw)]
363pub fn take_n_while<I, F>(input: &mut Pear<I>, n: usize, mut cond: F) -> Result<I::Many, I>
364    where I: Input, F: FnMut(&I::Token) -> bool
365{
366    let mut i = 0;
367    Ok(input.take(|c| { cond(c) && { let ok = i < n; i += 1; ok } }))
368}
369
370/// Take exactly `n` tokens, ensuring `cond` holds on all `n`.
371#[parser(raw)]
372pub fn take_n_if<I, F>(input: &mut Pear<I>, n: usize, mut cond: F) -> Result<I::Many, I>
373    where I: Input, F: FnMut(&I::Token) -> bool
374{
375    let mut i = 0;
376    let v = input.take(|c| { cond(c) && { let ok = i < n; i += 1; ok } });
377    if v.len() != n {
378        return parse_error!(Expected::Token(None, None));
379    }
380
381    Ok(v)
382}
383
384/// Parse a token stream that starts with `start` and ends with `end`, returning
385/// all of the tokens in between. The tokens in between must match `cond`.
386/// Succeeds even if there are no tokens between `start` and `end`.
387#[parser(raw)]
388pub fn delimited<I, T, F>(
389    input: &mut Pear<I>,
390    start: T,
391    mut cond: F,
392    end: T,
393) -> Result<I::Many, I>
394    where I: Input,
395          T: Token<I>,
396          F: FnMut(&I::Token) -> bool
397{
398    eat(start)?;
399    let output = input.take(|t| cond(t) && (&end != t));
400    eat(end)?;
401    Ok(output)
402}
403
404/// Parse a token stream that starts with `start` and ends with `end`, returning
405/// all of the tokens in between. The tokens in between must match `cond`. There
406/// must be at least one token between `start` and `end`.
407#[parser(raw)]
408pub fn delimited_some<I, T, F>(
409    input: &mut Pear<I>,
410    start: T,
411    mut cond: F,
412    end: T,
413) -> Result<I::Many, I>
414    where I: Input,
415          T: Token<I>,
416          F: FnMut(&I::Token) -> bool
417{
418    eat(start)?;
419    let output = take_some_while(|t| cond(t) && (&end != t))?;
420    eat(end)?;
421    Ok(output)
422}
423
424/// Succeeds only if the input has reached EOF.
425#[parser(raw)]
426pub fn eof<I: Input>(input: &mut Pear<I>) -> Result<(), I> {
427    Ok(if input.has(1) {
428        let next = input.token();
429        parse_error!(Expected::Eof(next))?
430    })
431}
432
433/// Like `delimited` but keeps the `start` and `end`.
434#[parser(raw)]
435pub fn enclosed<I, T, F>(
436    input: &mut Pear<I>,
437    start: T,
438    mut cond: F,
439    end: T,
440) -> Result<I::Many, I>
441    where I: Input,
442          T: Token<I>,
443          F: FnMut(&I::Token) -> bool
444{
445    enum State {
446        Start,
447        Inner,
448        End
449    }
450
451    let mut state = State::Start;
452    let value = input.take(|t| {
453        match state {
454            State::Start if &start == t => { state = State::Inner; true },
455            State::Start => false,
456            State::Inner if cond(t) => true,
457            State::Inner if &end == t => { state = State::End; true },
458            State::Inner => false,
459            State::End => false,
460        }
461    });
462
463    match state {
464        State::Start => parse_error!(expected_token(input, Some(start))),
465        State::Inner => parse_error!(expected_token(input, Some(end))),
466        State::End => Ok(value)
467    }
468}