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, 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        let mut inner = pair.clone().into_inner();
14
15        ast_ensure!(pair, Rule::block => {
16            ast_expr!(Block(collect_recovered(inner.next().unwrap().into_inner()), inner.next().map(Spanned::try_from).transpose()))
17        })
18    }
19}
20
21impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for StatementBody {
22    type Error = AstError<'a, Self>;
23
24    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
25        let mut inner = pair.clone().into_inner();
26
27        ast_ensure!(pair, Rule::statement_body => {
28            let i = inner.next().unwrap();
29
30            match i.as_rule() {
31                Rule::expr => ast_expr!(StatementBody::Expression(i.try_into())),
32                Rule::statement_wrapper => ast_expr!(StatementBody::Statement(i.try_into())),
33                _ => AstError::bug_unimplemented(i),
34            }
35        })
36    }
37}
38
39impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for StatementBranch {
40    type Error = AstError<'a, Self>;
41
42    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
43        let mut inner = pair.clone().into_inner();
44
45        ast_ensure!(pair, Rule::statement_branch => {
46            ast_expr!(StatementBranch {
47                condition: inner.next().unwrap().try_into(),
48                body: inner.next().unwrap().try_into().map(Box::new),
49            })
50        })
51    }
52}
53
54impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Statement {
55    type Error = AstError<'a, Self>;
56
57    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
58        let rule = pair.as_rule();
59        let mut inner = pair.clone().into_inner();
60
61        match rule {
62            Rule::statement | Rule::basic_stmt | Rule::control_flow => {
63                Statement::try_from(inner.next().unwrap())
64            }
65
66            Rule::block => ast_expr!(Statement::Block(pair.try_into())),
67
68            Rule::var_decl_statement => ast_expr!(Statement::VarDecl(pair.try_into())),
69
70            Rule::return_stmt => {
71                ast_expr!(Statement::Return(
72                    inner.next().map(Expression::try_from).transpose()
73                ))
74            }
75
76            Rule::break_stmt => Ok(Statement::Break),
77
78            Rule::continue_stmt => Ok(Statement::Continue),
79
80            Rule::if_stmt => {
81                ast_expr!(Statement::If {
82                    initial: inner.next().unwrap().try_into(),
83                    else_if: collect_recovered(inner.next().unwrap().into_inner()),
84                    else_branch: inner.next().map(StatementBody::try_from).transpose(),
85                })
86            }
87
88            Rule::while_stmt => ast_expr!(Statement::While(inner.next().unwrap().try_into())),
89
90            Rule::loop_stmt => ast_expr!(Statement::Loop(inner.next().unwrap().try_into())),
91
92            Rule::c_for_stmt => ast_expr!(Statement::CStyleFor {
93                init: inner.next().unwrap().try_into(),
94                condition: inner.next().unwrap().try_into(),
95                update: inner.next().unwrap().try_into(),
96                body: inner.next().unwrap().try_into(),
97            }),
98
99            Rule::for_stmt => ast_expr!(Statement::For {
100                mutable: Ok(listen_rule(&mut inner, Rule::mutable)) as AstResult<'_, bool>,
101                pattern: inner.next().unwrap().try_into(),
102                iterator: inner.next().unwrap().try_into(),
103                body: inner.next().unwrap().try_into(),
104            }),
105
106            Rule::match_stmt => ast_expr!(Statement::Match(
107                inner.next().unwrap().try_into(),
108                inner
109                    .map(|match_itms| {
110                        let mut match_inner = match_itms.into_inner();
111                        Ok((
112                            collect_recovered(match_inner.next().unwrap().into_inner()).get()?,
113                            Expression::try_from(match_inner.next().unwrap()).get()?,
114                        ))
115                    })
116                    .collect::<AstResult<'a, Vec<_>>>(),
117            )),
118
119            _ => AstError::bug_unimplemented(pair),
120        }
121    }
122}