rune/ast/
macro_call.rs
1use crate::ast::prelude::*;
2
3#[test]
4#[cfg(not(miri))]
5fn ast_parse() {
6 rt::<ast::MacroCall>("foo!()");
7 rt::<ast::MacroCall>("::bar::foo!(question to life)");
8}
9
10#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Spanned)]
14#[non_exhaustive]
15pub struct MacroCall {
16 #[rune(skip)]
19 pub(crate) id: Option<NonZeroId>,
20 #[rune(iter)]
22 pub attributes: Vec<ast::Attribute>,
23 pub path: ast::Path,
25 pub bang: T![!],
27 pub open: ast::Token,
29 #[rune(iter)]
31 pub input: TokenStream,
32 pub close: ast::Token,
34}
35
36impl MacroCall {
37 pub(crate) fn needs_semi(&self) -> bool {
39 !matches!(self.close.kind, K!['}'])
40 }
41
42 pub(crate) fn input_span(&self) -> Span {
44 if let Some(span) = self.input.option_span() {
45 span
46 } else {
47 self.open.span.tail()
48 }
49 }
50
51 pub(crate) fn parse_with_meta_path(
53 parser: &mut Parser,
54 attributes: Vec<ast::Attribute>,
55 path: ast::Path,
56 ) -> Result<Self> {
57 let bang = parser.parse()?;
58
59 let mut level = 1;
60 let open = parser.next()?;
61
62 let delim = match open.kind {
63 ast::Kind::Open(delim) => delim,
64 _ => {
65 return Err(compile::Error::expected(open, Expectation::OpenDelimiter));
66 }
67 };
68
69 let close;
70
71 let mut stream = Vec::new();
72
73 loop {
74 let token = parser.next()?;
75
76 match token.kind {
77 ast::Kind::Open(..) => level += 1,
78 ast::Kind::Close(actual) => {
79 level -= 1;
80
81 if level == 0 {
82 if actual != delim {
83 return Err(compile::Error::new(
84 open,
85 ErrorKind::ExpectedMacroCloseDelimiter {
86 actual: token.kind,
87 expected: ast::Kind::Close(delim),
88 },
89 ));
90 }
91
92 close = token;
93 break;
94 }
95 }
96 _ => (),
97 }
98
99 stream.try_push(token)?;
100 }
101
102 Ok(Self {
103 id: Default::default(),
104 attributes,
105 bang,
106 path,
107 open,
108 input: TokenStream::from(stream),
109 close,
110 })
111 }
112}
113
114impl Parse for MacroCall {
115 fn parse(parser: &mut Parser<'_>) -> Result<Self> {
116 let attributes = parser.parse()?;
117 let path = parser.parse()?;
118 Self::parse_with_meta_path(parser, attributes, path)
119 }
120}