Skip to main content

mist_parser/parser/common/
statement.rs

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