summaryrefslogtreecommitdiff
path: root/chewed/src/parse.rs
blob: f6bbd66653e10ae0d91f2ef53b767b1c43dd3e0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use std::iter::Peekable;

use super::error::{ParseError, TakeError};

pub trait Parser: Iterator<Item = char> {
    fn peek(&mut self) -> Option<char>;

    fn take<P: Parse>(&mut self) -> Result<P, TakeError> {
        P::take(self)
    }

    fn parse<P: Parse>(self) -> Result<P, ParseError>
    where
        Self: Sized,
    {
        P::parse(self)
    }

    fn take_str(&mut self, s: &'static str) -> Result<(), TakeError> {
        let mut count = 0;

        for exp in s.chars() {
            if let Some(got) = self.peek() {
                if got == exp {
                    self.next();
                    count += 1
                } else {
                    let mut out = String::from(&s[..count]);
                    out.push(got);

                    return Err(TakeError::BadString(out, s));
                }
            } else {
                return Err(TakeError::EndOfStream);
            }
        }

        Ok(())
    }
}

impl<I: Iterator<Item = char>> Parser for Peekable<I> {
    fn peek(&mut self) -> Option<char> {
        Peekable::peek(self).copied()
    }
}

pub trait Parse: Sized {
    fn take<P: Parser + ?Sized>(input: &mut P) -> Result<Self, TakeError>;

    fn parse<P: Parser>(mut input: P) -> Result<Self, ParseError> {
        let res = Self::take(&mut input)?;

        if input.peek().is_some() {
            Err(ParseError::InputContinues)
        } else {
            Ok(res)
        }
    }
}

impl Parse for () {
    fn take<P: Parser + ?Sized>(_: &mut P) -> Result<Self, TakeError> {
        Ok(())
    }
}

impl<A: Parse, B: Parse> Parse for (A, B) {
    fn take<P: Parser + ?Sized>(input: &mut P) -> Result<Self, TakeError> {
        let a = input.take()?;
        let b = input.take()?;
        Ok((a, b))
    }

    fn parse<P: Parser>(mut input: P) -> Result<Self, ParseError> {
        let a = A::take(&mut input)?;
        let b = B::parse(input)?;
        Ok((a, b))
    }
}

impl<T: Parse + Sized> Parse for Box<T> {
    fn take<P: Parser + ?Sized>(input: &mut P) -> Result<Self, TakeError> {
        Ok(Box::new(input.take()?))
    }

    fn parse<P: Parser>(input: P) -> Result<Self, ParseError> {
        Ok(Box::new(input.parse()?))
    }
}