1use crate::error::ParserError;
2use crate::expression::Expression;
3use lexgen::lexer;
4use pomelo::pomelo;
5
6pomelo! {
7 %include {
8 use crate::expression::*;
9 }
10
11 %type input Option<Expression>;
12 %type expr Expression;
13 %type Constant f32;
14 %type Literal String;
15
16 %left Plus;
17 %left Minus;
18 %left Prod;
19 %left Div;
20
21 input ::= expr?(E) { E };
22 expr ::= Constant(N) { Expression::constant(N) }
23 expr ::= Literal(V) { Expression::variable(V.as_str()) }
24 expr ::= LPar expr(E) RPar { E }
25 expr ::= expr(E1) Plus expr(E2) { Expression::addition(E1, E2) }
26 expr ::= expr(E1) Minus expr(E2) { Expression::subtraction(E1, E2) }
27 expr ::= expr(E1) Prod expr(E2) { Expression::product(E1, E2) }
28 expr ::= expr(E1) Div expr(E2) { Expression::division(E1, E2) }
29}
30
31use parser::Token;
32
33lexer! {
34 ExprLexer -> Token;
35
36 let number = ['0'-'9']+ '.' ['0'-'9']*;
37 let var = ['a'-'z''A'-'Z''_']*;
38
39 rule Init {
40 [' ''\t' '\n' '\r']+,
41 '+' => |lex| lex.return_(Token::Plus),
42 '-' => |lex| lex.return_(Token::Minus),
43 '*' => |lex| lex.return_(Token::Prod),
44 '/' => |lex| lex.return_(Token::Div),
45 '(' => |lex| lex.return_(Token::LPar),
46 ')' => |lex| lex.return_(Token::RPar),
47 $number => |lex| lex.return_(Token::Constant(
48 lex.match_()[..].to_owned().parse::<f32>().unwrap()
49 )),
50 $var => |lex| lex.return_(Token::Literal(
51 lex.match_()[..].to_string()
52 )),
53 }
54}
55
56pub fn parse_expression(input: &str) -> Result<Expression, ParserError> {
77 use parser::Parser;
78
79 let mut p = Parser::new();
80 let lexer = ExprLexer::new(input);
81
82 for tok in lexer {
83 match tok {
84 Ok((_, tok, _)) => {
85 if p.parse(tok).is_err() {
86 return Err(ParserError::ParserError);
87 }
88 }
89 Err(_) => return Err(ParserError::LexerError),
90 }
91 }
92
93 match p.end_of_input() {
94 Ok(Some(e)) => Ok(e),
95 Ok(None) => Err(ParserError::NoExpressionFound),
96 Err(_) => Err(ParserError::ParserError),
97 }
98}