simple_parser/
parser.rs

1use std::str::FromStr;
2use simple_lexer_bootstrap::{
3    Token,
4    Lexer,
5};
6use simple_parser_bootstrap::Parser as ParserBootstrap;
7use crate::{
8    grammar::{
9        LEXER_PRODUCTIONS,
10        PARSER_PRODUCTIONS,
11        Nonterminal,
12        as_productions
13    },
14    ParseTree,
15};
16
17type Result<T> = std::result::Result<T, &'static str>;
18
19pub struct Parser<N, T> {
20    parser: ParserBootstrap<N, T>,
21}
22
23impl<N: FromStr + Ord, T: FromStr> Parser<N, T> {
24    pub fn new(productions: &str, root: N) -> Result<Parser<N, T>> {
25        let lexer = Lexer::new(LEXER_PRODUCTIONS.clone());
26        let parser = ParserBootstrap::new(PARSER_PRODUCTIONS.clone(), Nonterminal::Root);
27        let tokens = lexer.lex(productions)?;
28        let parse_tree = parser.parse(&tokens)?;
29        let productions = as_productions(&parse_tree)?;
30        Ok(Parser { parser: ParserBootstrap::new(productions, root) })
31    }
32}
33
34impl<N: Clone + Ord, T: Clone + PartialEq> Parser<N, T> {
35    pub fn parse(&self, tokens: &[Token<T>]) -> Result<ParseTree<N, T>> {
36        self.parser.parse(tokens)
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use std::str::FromStr;
43    use simple_lexer_bootstrap::Token;
44    use crate::{
45        Parser,
46        ParseTree,
47    };
48    use super::Result;
49
50    #[allow(non_camel_case_types)]
51    #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
52    enum TokenKind {
53        PLUS_SIGN,
54        HYPHEN,
55        ASTERISK,
56        SLASH,
57        NUMBER,
58        LEFT_PARENTHESIS,
59        RIGHT_PARENTHESIS,
60    }
61
62    impl FromStr for TokenKind {
63        type Err = &'static str;
64
65        fn from_str(text: &str) -> Result<Self> {
66            use TokenKind::*;
67            match text {
68                "PLUS_SIGN" => Ok(PLUS_SIGN),
69                "HYPHEN" => Ok(HYPHEN),
70                "ASTERISK" => Ok(ASTERISK),
71                "SLASH" => Ok(SLASH),
72                "NUMBER" => Ok(NUMBER),
73                "LEFT_PARENTHESIS" => Ok(LEFT_PARENTHESIS),
74                "RIGHT_PARENTHESIS" => Ok(RIGHT_PARENTHESIS),
75                _ => Err("not token kind"),
76            }
77        }
78    }
79
80    #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
81    enum Nonterminal {
82        Addition,
83        Multiplication,
84        Atom,
85        Number,
86    }
87
88    impl FromStr for Nonterminal {
89        type Err = &'static str;
90
91        fn from_str(text: &str) -> Result<Self> {
92            use Nonterminal::*;
93            match text {
94                "Addition" => Ok(Addition),
95                "Multiplication" => Ok(Multiplication),
96                "Atom" => Ok(Atom),
97                "Number" => Ok(Number),
98                _ => Err("not nonterminal")
99            }
100        }
101    }
102
103    #[test]
104    fn test_expression() -> Result<()> {
105        use TokenKind::*;
106        use Nonterminal::*;
107        let expected = ParseTree::Nonterminal {
108            nonterminal: Addition,
109            tokens: vec![
110                Token::new(NUMBER, "1"),
111                Token::new(SLASH, "/"),
112                Token::new(LEFT_PARENTHESIS, "("),
113                Token::new(NUMBER, "2"),
114                Token::new(PLUS_SIGN, "+"),
115                Token::new(HYPHEN, "-"),
116                Token::new(NUMBER, "3"),
117                Token::new(RIGHT_PARENTHESIS, ")")
118            ],
119            children: vec![
120                ParseTree::Nonterminal {
121                    nonterminal: Multiplication,
122                    tokens: vec![
123                        Token::new(NUMBER, "1"),
124                        Token::new(SLASH, "/"),
125                        Token::new(LEFT_PARENTHESIS, "("),
126                        Token::new(NUMBER, "2"),
127                        Token::new(PLUS_SIGN, "+"),
128                        Token::new(HYPHEN, "-"),
129                        Token::new(NUMBER, "3"),
130                        Token::new(RIGHT_PARENTHESIS, ")")
131                    ],
132                    children: vec![
133                        ParseTree::Nonterminal {
134                            nonterminal: Atom,
135                            tokens: vec![Token::new(NUMBER, "1")],
136                            children: vec![
137                                ParseTree::Nonterminal {
138                                    nonterminal: Number,
139                                    tokens: vec![Token::new(NUMBER, "1")],
140                                    children: vec![
141                                        ParseTree::Token { token: Token::new(NUMBER, "1") }
142                                    ],
143                                },
144                            ],
145                        },
146                        ParseTree::Token { token: Token::new(SLASH, "/") },
147                        ParseTree::Nonterminal {
148                            nonterminal: Atom,
149                            tokens: vec![
150                                Token::new(LEFT_PARENTHESIS, "("),
151                                Token::new(NUMBER, "2"),
152                                Token::new(PLUS_SIGN, "+"),
153                                Token::new(HYPHEN, "-"),
154                                Token::new(NUMBER, "3"),
155                                Token::new(RIGHT_PARENTHESIS, ")")
156                            ],
157                            children: vec![
158                                ParseTree::Token { token: Token::new(LEFT_PARENTHESIS, "(") },
159                                ParseTree::Nonterminal {
160                                    nonterminal: Addition,
161                                    tokens: vec![
162                                        Token::new(NUMBER, "2"),
163                                        Token::new(PLUS_SIGN, "+"),
164                                        Token::new(HYPHEN, "-"),
165                                        Token::new(NUMBER, "3"),
166                                    ],
167                                    children: vec![
168                                        ParseTree::Nonterminal {
169                                            nonterminal: Multiplication,
170                                            tokens: vec![Token::new(NUMBER, "2")],
171                                            children: vec![
172                                                ParseTree::Nonterminal {
173                                                    nonterminal: Atom,
174                                                    tokens: vec![Token::new(NUMBER, "2")],
175                                                    children: vec![
176                                                        ParseTree::Nonterminal {
177                                                            nonterminal: Number,
178                                                            tokens: vec![Token::new(NUMBER, "2")],
179                                                            children: vec![
180                                                                ParseTree::Token { token: Token::new(NUMBER, "2") }
181                                                            ],
182                                                        }
183                                                    ]
184                                                },
185                                            ]
186                                        },
187                                        ParseTree::Token { token: Token::new(PLUS_SIGN, "+") },
188                                        ParseTree::Nonterminal {
189                                            nonterminal: Multiplication,
190                                            tokens: vec![
191                                                Token::new(HYPHEN, "-"),
192                                                Token::new(NUMBER, "3")
193                                            ],
194                                            children: vec![
195                                                ParseTree::Nonterminal {
196                                                    nonterminal: Atom,
197                                                    tokens: vec![
198                                                        Token::new(HYPHEN, "-"),
199                                                        Token::new(NUMBER, "3")
200                                                    ],
201                                                    children: vec![
202                                                        ParseTree::Nonterminal {
203                                                            nonterminal: Number,
204                                                            tokens: vec![
205                                                                Token::new(HYPHEN, "-"),
206                                                                Token::new(NUMBER, "3")
207                                                            ],
208                                                            children: vec![
209                                                                ParseTree::Token { token: Token::new(HYPHEN, "-") },
210                                                                ParseTree::Token { token: Token::new(NUMBER, "3") },
211                                                            ],
212                                                        }
213                                                    ]
214                                                },
215                                            ]
216                                        },
217                                    ]
218                                },
219                                ParseTree::Token { token: Token::new(RIGHT_PARENTHESIS, ")") },
220                            ]
221                        }
222                    ],
223                }
224            ]
225        };
226        let parser = Parser::new(r#"
227            Addition ::= Multiplication ((PLUS_SIGN | HYPHEN) Multiplication)*;
228            Multiplication ::= Atom ((ASTERISK | SLASH) Atom)*;
229            Atom ::= Number | LEFT_PARENTHESIS Addition RIGHT_PARENTHESIS;
230            Number ::= (PLUS_SIGN | HYPHEN)? NUMBER;
231        "#, Addition)?;
232        // 1 / (2 + -3)
233        let actual = parser.parse(&[
234            Token::new(NUMBER, "1"),
235            Token::new(SLASH, "/"),
236            Token::new(LEFT_PARENTHESIS, "("),
237            Token::new(NUMBER, "2"),
238            Token::new(PLUS_SIGN, "+"),
239            Token::new(HYPHEN, "-"),
240            Token::new(NUMBER, "3"), 
241            Token::new(RIGHT_PARENTHESIS, ")")
242        ])?;
243        assert_eq!(expected, actual);
244        Ok(())
245    }
246}