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