Skip to main content

moxy_token/
group.rs

1use crate::lex::{Cursor, LexError, Scan};
2use crate::span::DelimSpan;
3use crate::{Delim, Span, TokenStream, TokenTree};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct Group {
7    pub(crate) delim: Delim,
8    pub(crate) span: DelimSpan,
9    pub(crate) tokens: TokenStream,
10}
11
12impl Group {
13    #[inline]
14    pub fn new(delim: Delim, stream: TokenStream) -> Self {
15        Self {
16            delim,
17            span: DelimSpan::new(Span::call_site(), Span::call_site()),
18            tokens: stream,
19        }
20    }
21
22    #[inline]
23    pub fn delim(&self) -> Delim {
24        self.delim
25    }
26
27    #[inline]
28    pub fn span(&self) -> DelimSpan {
29        self.span
30    }
31
32    #[inline]
33    pub fn stream(&self) -> TokenStream {
34        self.tokens.clone()
35    }
36
37    #[inline]
38    pub fn set_span(&mut self, span: DelimSpan) {
39        self.span = span;
40    }
41
42    #[inline]
43    pub fn to_token_tree(&self) -> TokenTree {
44        TokenTree::Group(self.clone())
45    }
46
47    #[inline]
48    pub fn into_token_tree(self) -> TokenTree {
49        TokenTree::Group(self)
50    }
51}
52
53impl std::fmt::Display for Group {
54    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55        match self.delim {
56            Delim::None => write!(f, "{}", self.tokens),
57            d => write!(f, "{}{}{}", d.open(), self.tokens, d.close()),
58        }
59    }
60}
61
62impl Scan for Group {
63    fn scan(cursor: Cursor<'_>) -> Result<(Cursor<'_>, Self), LexError> {
64        let ch = cursor.first().ok_or(cursor.error())?;
65        let delim = Delim::from_open(ch).ok_or(cursor.error())?;
66        let c = cursor.advance(ch.len_utf8());
67        let (c, inner) = TokenStream::scan(c)?;
68        let close_ch = c
69            .first()
70            .ok_or_else(|| cursor.error().message(format!("unclosed delimiter '{}'", delim.open())))?;
71
72        let close_delim = Delim::from_close(close_ch).ok_or_else(|| {
73            c.error()
74                .message(format!("expected '{}', found '{}'", delim.close(), close_ch))
75        })?;
76
77        if delim != close_delim {
78            return Err(c.error().message(format!(
79                "mismatched delimiter: expected '{}', found '{}'",
80                delim.close(),
81                close_ch,
82            )));
83        }
84
85        let c = c.advance(close_ch.len_utf8());
86        let mut group = Self::new(delim, inner);
87        group.set_span(DelimSpan::new(cursor.span(), c.span()));
88
89        Ok((c, group))
90    }
91}
92
93impl crate::ToTokens for Group {
94    fn to_tokens(&self, tokens: &mut crate::TokenStream) {
95        tokens.extend_one(crate::TokenTree::Group(self.clone()));
96    }
97}
98
99impl crate::Spanner for Group {
100    fn span(&self) -> Span {
101        self.span.span()
102    }
103}
104
105impl crate::Parse for Group {
106    fn parse(stream: &mut crate::parser::ParseStream) -> Result<Self, crate::parser::ParseError> {
107        match stream.advance() {
108            Some(crate::TokenTree::Group(v)) => Ok(v.clone()),
109            _ => Err(crate::lex::LexError::new(stream.span()).message("expected Group").into()),
110        }
111    }
112}
113
114#[cfg(feature = "serde")]
115impl serde::Serialize for Group {
116    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
117    where
118        S: serde::Serializer,
119    {
120        use serde::ser::SerializeStruct;
121
122        let mut o = s.serialize_struct("Group", 2)?;
123        o.serialize_field("delim", &self.delim)?;
124        o.serialize_field("tokens", &self.tokens)?;
125        o.end()
126    }
127}