Skip to main content

mist_parser/parser/common/
statement.rs

1use crate::{
2    Rule,
3    ast::*,
4    ast_ensure, ast_expr,
5    error::{AstError, AstResult, ErrorCode, IntoErr, collect_recovered},
6    parser::listen_rule,
7};
8
9impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Block {
10    type Error = AstError<'a, Self>;
11
12    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
13        ast_ensure!(pair, Rule::block => {
14            ast_expr!(Block(collect_recovered(pair.into_inner())))
15        })
16    }
17}
18
19impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for StatementBranch {
20    type Error = AstError<'a, Self>;
21
22    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
23        let mut inner = pair.clone().into_inner();
24
25        ast_ensure!(pair, Rule::statement_branch => {
26            ast_expr!(StatementBranch {
27                condition: inner.next().unwrap().try_into(),
28                body: inner.next().unwrap().try_into().map(Box::new),
29            })
30        })
31    }
32}
33
34impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Statement {
35    type Error = AstError<'a, Self>;
36
37    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
38        let rule = pair.as_rule();
39        let mut inner = pair.clone().into_inner();
40
41        match rule {
42            Rule::statement => Statement::try_from(inner.next().unwrap()),
43
44            Rule::expr_stmt => {
45                ast_expr!(Statement::Expression(inner.next().unwrap().try_into()))
46            }
47
48            Rule::block => ast_expr!(Statement::Block(pair.try_into())),
49
50            Rule::var_decl_statement => ast_expr!(Statement::VarDecl(pair.try_into())),
51
52            Rule::return_stmt => {
53                ast_expr!(Statement::Return(
54                    inner.next().map(Expression::try_from).transpose()
55                ))
56            }
57
58            Rule::break_stmt => Ok(Statement::Break),
59
60            Rule::continue_stmt => Ok(Statement::Continue),
61
62            Rule::if_stmt => {
63                ast_expr!(Statement::If {
64                    initial: inner.next().unwrap().try_into(),
65                    else_if: collect_recovered(inner.next().unwrap().into_inner()),
66                    else_branch: inner
67                        .next()
68                        .map(Statement::try_from)
69                        .transpose()
70                        .map(|v| v.map(Box::new))
71                        .get_map(|v| { Some(Box::new(v)) }),
72                })
73            }
74
75            Rule::while_stmt => ast_expr!(Statement::While(inner.next().unwrap().try_into())),
76
77            Rule::c_for_stmt => ast_expr!(Statement::CStyleFor {
78                init: inner.next().unwrap().try_into().map(Box::new),
79                condition: inner.next().unwrap().try_into(),
80                update: inner.next().unwrap().try_into().map(Box::new),
81                body: inner.next().unwrap().try_into().map(Box::new),
82            }),
83
84            Rule::for_stmt => ast_expr!(Statement::For {
85                mutable: Ok(listen_rule(&mut inner, Rule::mutable)) as AstResult<'_, bool>,
86                pattern: inner.next().unwrap().try_into(),
87                iterator: inner.next().unwrap().try_into(),
88                body: inner.next().unwrap().try_into().map(Box::new),
89            }),
90
91            Rule::assign_statement => ast_expr!(VarAssignStmt {
92                target: inner.next().unwrap().try_into(),
93                value: inner.next().unwrap().try_into(),
94            })
95            .map(Statement::VarAssign)
96            .get_map(Statement::VarAssign),
97
98            Rule::match_stmt => ast_expr!(Statement::Match(
99                inner.next().unwrap().try_into(),
100                inner
101                    .map(|match_itms| {
102                        let mut match_inner = match_itms.into_inner();
103                        Ok((
104                            Pattern::try_from(match_inner.next().unwrap()).get()?,
105                            Block::try_from(match_inner.next().unwrap()).get()?,
106                        ))
107                    })
108                    .collect::<AstResult<'a, Vec<_>>>(),
109            )),
110
111            Rule::unexpected_statement => {
112                return Err(AstError {
113                    span: pair.as_span(),
114                    error_code: ErrorCode::InvalidStatement,
115                    error_message: "Invalid Statement".to_string(),
116                    recovered: None,
117                });
118            }
119
120            _ => AstError::bug_unimplemented(pair),
121        }
122    }
123}