rune/ast/
macro_utils.rs

1use super::prelude::*;
2use super::Eq;
3
4/// An `= ...` e.g. inside an attribute `#[doc = ...]`.
5///
6/// To get unparsed tokens use `EqValue<TokenStream>`.
7#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Parse, Spanned)]
8#[try_clone(bound = {T: TryClone})]
9pub struct EqValue<T> {
10    /// The `=` token.
11    pub eq: Eq,
12    /// The remainder.
13    pub value: T,
14}
15
16/// Parses `[{( ... )}]` ensuring that the delimiter is balanced.
17#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Spanned)]
18pub struct Group {
19    /// The opening delimiter.
20    pub open: ast::Token,
21    /// The content between the delimiters.
22    #[rune(iter)]
23    pub content: TokenStream,
24    /// The closing delimiter.
25    pub close: ast::Token,
26}
27
28impl Parse for Group {
29    fn parse(parser: &mut Parser<'_>) -> compile::Result<Self> {
30        let mut level = 1;
31        let open = parser.next()?;
32
33        let delim = match open.kind {
34            ast::Kind::Open(delim) => delim,
35            _ => {
36                return Err(compile::Error::expected(open, Expectation::OpenDelimiter));
37            }
38        };
39
40        let close;
41
42        let mut stream = Vec::new();
43
44        loop {
45            let token = parser.next()?;
46
47            match token.kind {
48                ast::Kind::Open(..) => level += 1,
49                ast::Kind::Close(actual) => {
50                    level -= 1;
51
52                    if level == 0 {
53                        if actual != delim {
54                            return Err(compile::Error::new(
55                                open,
56                                ErrorKind::ExpectedMacroCloseDelimiter {
57                                    actual: token.kind,
58                                    expected: ast::Kind::Close(delim),
59                                },
60                            ));
61                        }
62
63                        close = token;
64                        break;
65                    }
66                }
67                _ => (),
68            }
69
70            stream.try_push(token)?;
71        }
72
73        Ok(Self {
74            open,
75            content: TokenStream::from(stream),
76            close,
77        })
78    }
79}