Skip to main content

mist_parser/parser/common/
expr.rs

1use crate::{
2    Rule,
3    ast::*,
4    ast_expr,
5    error::{AstError, GetLength, IntoErr, collect_recovered, collect_recovered_map},
6};
7
8impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Expression {
9    type Error = AstError<'a, Self>;
10
11    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
12        let rule = pair.as_rule();
13        let mut inner = pair.clone().into_inner();
14
15        match rule {
16            Rule::expr => {
17                let prefixes = inner
18                    .next()
19                    .map(|p| collect_recovered::<Prefix, Prefix>(p.into_inner()))
20                    .unwrap_or_else(|| Ok(Vec::new()));
21
22                let exp = Expression::try_from(inner.next().unwrap());
23
24                if inner.len() > 0 || prefixes.len() > 0 {
25                    ast_expr!(Expression::Fix {
26                        initial: exp.map(Box::new),
27                        prefixes: prefixes,
28                        postfixes: collect_recovered(inner),
29                    })
30                } else {
31                    exp
32                }
33            }
34
35            Rule::primary => inner.next().unwrap().try_into(),
36            Rule::static_path => ast_expr!(Expression::Path(pair.try_into())),
37            Rule::literal => ast_expr!(Expression::Literal(pair.try_into())),
38
39            _ => AstError::bug_unimplemented(pair),
40        }
41    }
42}
43
44impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Prefix {
45    type Error = AstError<'a, Self>;
46
47    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
48        Ok(match pair.as_rule() {
49            Rule::prefix => Self::try_from(pair.into_inner().next().unwrap())?,
50            Rule::deref_px => Self::Deref,
51            Rule::mut_ref_px => Self::RefMut,
52            Rule::ref_px => Self::Ref,
53            Rule::new_px => Self::New,
54            Rule::not_px => Self::Not,
55
56            _ => return AstError::bug_unimplemented(pair),
57        })
58    }
59}
60
61impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Postfix {
62    type Error = AstError<'a, Self>;
63
64    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
65        let rule = pair.as_rule();
66        let mut inner = pair.clone().into_inner();
67
68        match rule {
69            Rule::postfix => Postfix::try_from(inner.next().unwrap()),
70
71            Rule::field_px => {
72                ast_expr!(Postfix::FieldAccess(inner.next().unwrap().try_into()))
73            }
74
75            Rule::call_px => ast_expr!(Postfix::Call(collect_recovered(inner))),
76
77            Rule::struct_px => ast_expr!(Postfix::StructCall(collect_recovered_map(inner, |p| {
78                let mut pi = p.into_inner();
79                Ok((
80                    Identifier::try_from(pi.next().unwrap())?,
81                    Expression::try_from(pi.next().unwrap()).get()?,
82                ))
83            }))),
84
85            Rule::index_px => {
86                ast_expr!(Postfix::Index(Expression::try_from(inner.next().unwrap())))
87            }
88
89            Rule::binary_px => {
90                let op_pair = inner.next().unwrap();
91                let op = match op_pair.as_str() {
92                    "+" => BinaryOp::Plus,
93                    "-" => BinaryOp::Minus,
94                    "*" => BinaryOp::Multiply,
95                    "/" => BinaryOp::Divide,
96                    "%" => BinaryOp::Modulo,
97                    "==" => BinaryOp::Equal,
98                    "!=" => BinaryOp::NotEqual,
99                    "<" => BinaryOp::LessThan,
100                    ">" => BinaryOp::GreaterThan,
101                    "<=" => BinaryOp::LessThanOrEqual,
102                    ">=" => BinaryOp::GreaterThanOrEqual,
103                    "&&" => BinaryOp::And,
104                    "||" => BinaryOp::Or,
105
106                    _ => return AstError::bug_unimplemented(op_pair),
107                };
108
109                Ok(Postfix::Binary(op, inner.next().unwrap().try_into().get()?))
110            }
111
112            Rule::macro_call_px => Ok(Postfix::MacroCall(inner.as_str().to_string())),
113
114            _ => AstError::bug_unimplemented(pair),
115        }
116    }
117}