Skip to main content

welly_parser/
bracket.rs

1//! Welly's bracket matcher.
2
3use super::{Tree, EndOfFile, Location, Token, Stream};
4
5pub const MISSING_OPEN: &'static str = "Unmatched close bracket";
6pub const MISSING_CLOSE: &'static str = "Unmatched open bracket";
7
8// ----------------------------------------------------------------------------
9
10/// A sequence of [`Token`]s enclosed in round brackets.
11///
12/// The contents should be comma-separated [`Expr`]s, but we allow anything,
13/// including errors.
14///
15/// [`Expr`]: super::welly::Expr
16#[derive(Debug)]
17pub struct Round(pub Vec<Token>);
18
19impl Round {
20    pub fn new(contents: Vec<Token>) -> Box<Self> { Box::new(Self(contents)) }
21}
22
23impl Tree for Round {}
24
25/// A sequence of [`Token`]s enclosed in square brackets.
26///
27/// The contents should be comma-separated [`Expr`]s, but we allow anything,
28/// including errors.
29///
30/// [`Expr`]: super::welly::Expr
31#[derive(Debug)]
32pub struct Square(pub Vec<Token>);
33
34impl Square {
35    pub fn new(contents: Vec<Token>) -> Box<Self> { Box::new(Self(contents)) }
36}
37
38impl Tree for Square {}
39
40/// A sequence of [`Token`]s enclosed in curly brackets.
41///
42/// The contents should be [`Stmt`]s, but we allow anything, including errors.
43///
44/// [`Stmt`]: super::welly::Stmt
45#[derive(Debug)]
46pub struct Brace(pub Vec<Token>);
47
48impl Brace {
49    pub fn new(contents: Vec<Token>) -> Box<Self> { Box::new(Self(contents)) }
50}
51
52impl Tree for Brace {}
53
54// ----------------------------------------------------------------------------
55
56/// A [`Stream`] that matches nested brackets.
57///
58/// Note that this is not a [`Parse`] implementation, because it is recursive.
59///
60/// [`Parse`]: super::Parse
61pub struct Brackets<F, I> {
62    open: char,
63    close: char,
64    new_bracket: F,
65    input: I,
66    depth: usize
67}
68
69impl<
70    F: Fn(Vec<Token>) -> Box<dyn Tree>,
71    I: Stream,
72> Brackets<F, I> {
73    /// Construct a [`Brackets`].
74    /// - open - the [`char`] used to open a bracket.
75    /// - close - the [`char`] used to close a bracket.
76    /// - new_bracket - turns bracket contents into a bracket value.
77    ///   The bracket contents are read from `Self`.
78    /// - input - a [`Stream`] that contains [`char`]s.
79    pub fn new(open: char, close: char, new_bracket: F, input: I) -> Self {
80        Self {open, close, new_bracket, input, depth: 0}
81    }
82
83    /// Returns the bracket starting at `open`.
84    fn parse_bracket(&mut self, open_loc: Location) -> Token {
85        let mut contents: Vec<Token> = Vec::new();
86        loop {
87            let token = self.read();
88            if token.is_incomplete() { return token; }
89            if token == EndOfFile { return Token::new_err(MISSING_CLOSE, open_loc); }
90            if token == self.close {
91                let close_loc = token.location();
92                let bracket = (&self.new_bracket)(contents);
93                return Token::new(bracket, Location {start: open_loc.start, end: close_loc.end});
94            }
95            contents.push(token);
96        }
97    }
98}
99
100impl<
101    F: Fn(Vec<Token>) -> Box<dyn Tree>,
102    I: Stream,
103> Stream for Brackets<F, I> {
104    fn read(&mut self) -> Token {
105        let token = self.input.read();
106        if token == self.open {
107            self.depth += 1;
108            return self.parse_bracket(token.location());
109        }
110        if token == self.close {
111            if self.depth == 0 {
112                return Token::new_err(MISSING_OPEN, token.location());
113            }
114            self.depth -= 1;
115        }
116        token
117    }
118}
119
120// ----------------------------------------------------------------------------
121
122#[cfg(test)]
123mod tests {
124    use crate::{Characters};
125    use super::*;
126
127    #[test]
128    fn some_brackets() {
129        let mut parser = Brackets::new(
130            '(',
131            ')',
132            |contents| Box::new(Round(contents)),
133            Brackets::new(
134                '{',
135                '}',
136                |contents| Box::new(Brace(contents)),
137                Characters::new("(a{b}(cd)){}", true)
138            )
139        );
140        let mut contents1 = parser.read().unwrap::<Round>().0.into_iter();
141        assert_eq!(contents1.read(), 'a');
142        let mut contents2 = contents1.read().unwrap::<Brace>().0.into_iter();
143        assert_eq!(contents2.read(), 'b');
144        assert_eq!(contents2.read(), EndOfFile);
145        let mut contents2 = contents1.read().unwrap::<Round>().0.into_iter();
146        assert_eq!(contents2.read(), 'c');
147        assert_eq!(contents2.read(), 'd');
148        assert_eq!(contents2.read(), EndOfFile);
149        assert_eq!(contents1.read(), EndOfFile);
150        let mut contents1 = parser.read().unwrap::<Brace>().0.into_iter();
151        assert_eq!(contents1.read(), EndOfFile);
152        assert_eq!(parser.read(), EndOfFile);
153    }
154
155    #[test]
156    fn inside_out() {
157        /// Pretend this is a parser for a complicated grammar.
158        fn noop(parser: impl Stream) -> impl Stream { parser }
159
160        /// Wrap 'parser' in a [`Round`] parser.
161        fn round(parser: impl Stream) -> impl Stream {
162            noop(Brackets::new('(', ')', |contents| {
163                let contents = noop(contents.into_iter()).read_all();
164                Box::new(Round(contents))
165            }, parser))
166        }
167
168        /// Wrap 'parser' in a [`Square`] parser.
169        fn square(parser: impl Stream) -> impl Stream {
170            round(Brackets::new('[', ']', |contents| {
171                let contents = round(contents.into_iter()).read_all();
172                Box::new(Square(contents))
173            }, parser))
174        }
175
176        /// Wrap 'parser' in a [`Brace`] parser.
177        fn brace(parser: impl Stream) -> impl Stream {
178            square(Brackets::new('{', '}', |contents| {
179                let contents = square(contents.into_iter()).read_all();
180                Box::new(Brace(contents))
181            }, parser))
182        }
183
184        let mut parser = brace(Characters::new("a{b[c(d(e[f{g}]))]}", true));
185        assert_eq!(parser.read(), 'a');
186        let mut contents1 = parser.read().unwrap::<Brace>().0.into_iter();
187        assert_eq!(contents1.read(), 'b');
188        let mut contents2 = contents1.read().unwrap::<Square>().0.into_iter();
189        assert_eq!(contents2.read(), 'c');
190        let mut contents3 = contents2.read().unwrap::<Round>().0.into_iter();
191        assert_eq!(contents3.read(), 'd');
192        let mut contents4 = contents3.read().unwrap::<Round>().0.into_iter();
193        assert_eq!(contents4.read(), 'e');
194        let mut contents5 = contents4.read().unwrap::<Square>().0.into_iter();
195        assert_eq!(contents5.read(), 'f');
196        let mut contents6 = contents5.read().unwrap::<Brace>().0.into_iter();
197        assert_eq!(contents6.read(), 'g');
198        assert_eq!(contents6.read(), EndOfFile);
199        assert_eq!(contents5.read(), EndOfFile);
200        assert_eq!(contents4.read(), EndOfFile);
201        assert_eq!(contents3.read(), EndOfFile);
202        assert_eq!(contents2.read(), EndOfFile);
203        assert_eq!(contents1.read(), EndOfFile);
204        assert_eq!(parser.read(), EndOfFile);
205    }
206}