Skip to main content

mist_parser/parser/common/
mod.rs

1pub mod decl;
2pub mod expr;
3pub mod statement;
4pub mod types;
5
6use crate::{
7    Rule,
8    ast::*,
9    ast_ensure, ast_expr,
10    error::{AstError, AstResult, IntoErr, collect_recovered, collect_recovered_map},
11    parser::{consume_rule, listen_rule},
12};
13
14impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Identifier {
15    type Error = AstError<'a, Self>;
16
17    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
18        ast_ensure!(pair, Rule::identifier => {
19            Ok(Identifier(pair.as_str().to_string()))
20        })
21    }
22}
23
24impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Path {
25    type Error = AstError<'a, Self>;
26
27    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
28        match pair.as_rule() {
29            Rule::static_path => Ok(Path(collect_recovered(pair.into_inner()).get()?)),
30            _ => AstError::bug_unimplemented(pair),
31        }
32    }
33}
34
35impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Literal {
36    type Error = AstError<'a, Self>;
37
38    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
39        let rule = pair.as_rule();
40        let mut inner = pair.clone().into_inner();
41
42        Ok(match rule {
43            Rule::primary => Self::try_from(inner.next().unwrap())?,
44            Rule::literal => Self::try_from(inner.next().unwrap())?,
45            Rule::integer => Literal::Int(pair.as_str().parse::<i64>().unwrap()),
46            Rule::float => Literal::Float(pair.as_str().parse::<f64>().unwrap()),
47            Rule::boolean => Literal::Bool(pair.as_str().parse::<bool>().unwrap()),
48            Rule::string_lit => Literal::String(inner.as_str().to_string()),
49            Rule::tuple => Literal::Tuple(collect_recovered(inner).get()?),
50            _ => return AstError::bug_unimplemented(pair),
51        })
52    }
53}
54
55impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Pattern {
56    type Error = AstError<'a, Self>;
57
58    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
59        let rule = pair.as_rule();
60        let mut inner = pair.clone().into_inner();
61
62        match rule {
63            Rule::tuple_pattern => ast_expr!(Pattern::Tuple(collect_recovered_map(inner, |v| {
64                Self::try_from(v).map(Box::new)
65            }))),
66
67            Rule::named_tuple_pattern => ast_expr!(Pattern::NamedTuple(
68                Path::try_from(inner.next().unwrap()),
69                collect_recovered_map(inner, |v| Self::try_from(v).map(Box::new)),
70            )),
71
72            Rule::struct_pattern => ast_expr!(Pattern::Struct(
73                Path::try_from(inner.next().unwrap()),
74                collect_recovered_map(inner, |v| {
75                    if v.as_rule() == Rule::etc_pattern {
76                        return Ok(None);
77                    }
78
79                    let mut inner = v.into_inner();
80                    Some(ast_expr!((
81                        Identifier::try_from(inner.next().unwrap()),
82                        inner
83                            .next()
84                            .map(|v| Self::try_from(v).map(Box::new).get_map(Box::new))
85                            .transpose()
86                    )))
87                    .transpose()
88                }),
89            )),
90
91            Rule::literal => ast_expr!(Pattern::Literal(pair.try_into())),
92
93            Rule::path_pattern => ast_expr!(Pattern::Path(
94                Ok(listen_rule(&mut inner, Rule::mutable)) as AstResult<'_, bool>,
95                inner.next().unwrap().try_into()
96            )),
97
98            Rule::etc_pattern => Ok(Pattern::Etc),
99
100            _ => AstError::bug_unimplemented(pair),
101        }
102    }
103}
104
105impl<'a> TryFrom<&mut pest::iterators::Pairs<'a, Rule>> for Visibility {
106    type Error = AstError<'a, Self>;
107
108    fn try_from(pairs: &mut pest::iterators::Pairs<'a, Rule>) -> Result<Self, Self::Error> {
109        Ok(consume_rule(pairs, Rule::visibility)
110            .map(|pair| -> Result<Visibility, AstError<'a, Self>> {
111                if let Some(path) = pair.into_inner().next() {
112                    ast_expr!(Visibility::PublicTarget(Path::try_from(path)))
113                } else {
114                    Ok(Visibility::Public)
115                }
116            })
117            .transpose()?
118            .unwrap_or_else(|| Visibility::Private))
119    }
120}