mist_parser/parser/common/
statement.rs1use 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 StatementBranch {
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_branch => {
28 ast_expr!(StatementBranch {
29 condition: inner.next().unwrap().try_into(),
30 body: inner.next().unwrap().try_into().map(Box::new),
31 })
32 })
33 }
34}
35
36impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Statement {
37 type Error = AstError<'a, Self>;
38
39 fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
40 let rule = pair.as_rule();
41 let mut inner = pair.clone().into_inner();
42
43 match rule {
44 Rule::statement | Rule::basic_stmt | Rule::control_flow => {
45 Statement::try_from(inner.next().unwrap())
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(Expression::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::loop_stmt => ast_expr!(Statement::Loop(inner.next().unwrap().try_into())),
78
79 Rule::c_for_stmt => ast_expr!(Statement::CStyleFor {
80 init: inner.next().unwrap().try_into(),
81 condition: inner.next().unwrap().try_into(),
82 update: inner.next().unwrap().try_into(),
83 body: inner.next().unwrap().try_into(),
84 }),
85
86 Rule::for_stmt => ast_expr!(Statement::For {
87 mutable: Ok(listen_rule(&mut inner, Rule::mutable)) as AstResult<'_, bool>,
88 pattern: inner.next().unwrap().try_into(),
89 iterator: inner.next().unwrap().try_into(),
90 body: inner.next().unwrap().try_into().map(Box::new),
91 }),
92
93 Rule::match_stmt => ast_expr!(Statement::Match(
94 inner.next().unwrap().try_into(),
95 inner
96 .map(|match_itms| {
97 let mut match_inner = match_itms.into_inner();
98 Ok((
99 collect_recovered(match_inner.next().unwrap().into_inner()).get()?,
100 Expression::try_from(match_inner.next().unwrap()).get()?,
101 ))
102 })
103 .collect::<AstResult<'a, Vec<_>>>(),
104 )),
105
106 _ => AstError::bug_unimplemented(pair),
107 }
108 }
109}