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 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}