Skip to main content

mist_parser/parser/items/
attribute.rs

1use crate::{
2    Rule,
3    ast::*,
4    error::{AstError, IntoErr, collect_recovered},
5};
6
7impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Attribute {
8    type Error = AstError<'a, Self>;
9
10    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
11        match pair.as_rule() {
12            Rule::attribute => {
13                // unwrap #[ ... ]
14                Attribute::try_from(pair.into_inner().next().unwrap())
15            }
16
17            Rule::meta => {
18                let mut inner = pair.into_inner();
19
20                // first item is always the path
21                let path = inner.next().unwrap().try_into().get()?;
22
23                // check what comes next
24                match inner.next() {
25                    None => {
26                        // #[path]
27                        Ok(Attribute::Path(path))
28                    }
29
30                    Some(next) => match next.as_rule() {
31                        Rule::literal => {
32                            // #[path = literal]
33                            Ok(Attribute::NameValue {
34                                path,
35                                value: next.try_into().get()?,
36                            })
37                        }
38
39                        Rule::meta_list => {
40                            // #[path(...)]
41                            Ok(Attribute::List {
42                                path,
43                                items: collect_recovered(next.into_inner()).get()?,
44                            })
45                        }
46
47                        _ => unreachable!("unexpected rule in meta: {:?}", next.as_rule()),
48                    },
49                }
50            }
51
52            Rule::meta_list => {
53                // This case usually won't be hit directly,
54                // but it's nice to keep it safe if reused
55                let items = pair
56                    .into_inner()
57                    .map(Attribute::try_from)
58                    .collect::<Vec<_>>();
59
60                // NOTE: this shouldn't normally construct an Attribute alone
61                // but you can panic or wrap depending on your design
62                panic!("meta_list should be handled inside meta: {:?}", items);
63            }
64
65            _ => unreachable!("unexpected rule: {:?}", pair.as_rule()),
66        }
67    }
68}