Peekers

Hidden in the Parse definition in the previous chapter is the peek method. It's definition is almost exactly the same as parse, but instead of returning Result<Self>, it returns bool. It's supposed to be a faster method of determining whether a given input could be parsed. A lot of the built in parsers utilise [peek] under the hood to resolve branches.


#![allow(unused)]
fn main() {
pub trait Parse<T>: Sized {
    fn parse(input: &mut impl Buffer<T>) -> eyre::Result<Self>;
    
    fn peek(input: &mut impl Buffer<T>) -> bool {
        // Default impl - override for better performance
        Self::parse(input).is_ok()
    }
}
}

Example

This is the same example from the Parsers section, but instead implementing peek. It follows a very similar implementation, but avoids a lot of the heavy work, such as dealing with errors and saving the chars to the string buffer


#![allow(unused)]
fn main() {
/// StringParser parses a code representation of a string
struct StringParser(String);
impl Parse<char> for StringParser {
    fn parse(input: &mut impl Buffer<char>) -> Result<Self> {
        unimplemented!()
    }
    
    fn peek(input: &mut impl Buffer<char>) -> bool {
        // ensure the first character is a quote mark
        if input.next() != Some('\"') {
            return false;
        }

        let mut escaped = false;

        // read from the input until the ending quote is found
        for c in input {
            match (c, escaped) {
                ('\"', true) => { escaped = false }
                ('n', true) => { escaped = false }
                ('r', true) => { escaped = false }
                ('t', true) => { escaped = false }
                ('\\', true) => { escaped = false }
                (c, true) => return false,
                ('\"', false) => return true,
                ('\\', false) => { escaped = true; }
                _ => {},
            }
        }

        false
    }
}
}