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}