rune/ast/
grouped.rs

1use core::slice;
2
3use crate::alloc::vec;
4use crate::ast::prelude::*;
5
6#[test]
7#[cfg(not(miri))]
8fn ast_parse() {
9    rt::<ast::Parenthesized<ast::Expr, T![,]>>("(1, \"two\")");
10    rt::<ast::Parenthesized<ast::Expr, T![,]>>("(1, 2,)");
11    rt::<ast::Parenthesized<ast::Expr, T![,]>>("(1, 2, foo())");
12
13    rt::<ast::Bracketed<ast::Expr, T![,]>>("[1, \"two\"]");
14    rt::<ast::Bracketed<ast::Expr, T![,]>>("[1, 2,]");
15    rt::<ast::Bracketed<ast::Expr, T![,]>>("[1, 2, foo()]");
16
17    rt::<ast::Braced<ast::Expr, T![,]>>("{1, \"two\"}");
18    rt::<ast::Braced<ast::Expr, T![,]>>("{1, 2,}");
19    rt::<ast::Braced<ast::Expr, T![,]>>("{1, 2, foo()}");
20
21    rt::<ast::AngleBracketed<ast::Path, T![,]>>("<Foo, Bar>");
22    rt::<ast::AngleBracketed<ast::PathSegmentExpr, T![,]>>("<1, \"two\">");
23    rt::<ast::AngleBracketed<ast::PathSegmentExpr, T![,]>>("<1, 2,>");
24    rt::<ast::AngleBracketed<ast::PathSegmentExpr, T![,]>>("<1, 2, foo()>");
25}
26
27macro_rules! grouped {
28    ($(#[$meta:meta])* $name:ident { $field:ident, $open:ty, $close:ty }) => {
29        $(#[$meta])*
30        #[derive(Debug, TryClone, PartialEq, Eq, ToTokens)]
31        #[try_clone(bound = {T: TryClone, S: TryClone})]
32        #[non_exhaustive]
33        pub struct $name<T, S> {
34            /// The open parenthesis.
35            pub open: $open,
36            /// Values in the type.
37            pub $field: Vec<(T, Option<S>)>,
38            /// The close parenthesis.
39            pub close: $close,
40        }
41
42        impl<T, S> Spanned for $name<T, S> {
43            #[inline]
44            fn span(&self) -> Span {
45                self.open.span().join(self.close.span())
46            }
47        }
48
49        impl<T, S> $name<T, S> {
50            /// Test if group is empty.
51            pub fn is_empty(&self) -> bool {
52                self.$field.is_empty()
53            }
54
55            /// Get the length of elements in the group.
56            pub fn len(&self) -> usize {
57                self.$field.len()
58            }
59
60            /// Get the first element in the group.
61            pub fn first(&self) -> Option<&(T, Option<S>)> {
62                self.$field.first()
63            }
64
65            /// Get the last element in the group.
66            pub fn last(&self) -> Option<&(T, Option<S>)> {
67                self.$field.last()
68            }
69
70            /// Iterate over elements in the group.
71            pub fn iter(&self) -> slice::Iter<'_, (T, Option<S>)> {
72                self.$field.iter()
73            }
74
75            /// Iterate mutably over elements in the group.
76            pub fn iter_mut(&mut self) -> slice::IterMut<'_, (T, Option<S>)> {
77                self.$field.iter_mut()
78            }
79
80            /// Get the group values as a slice.
81            pub fn as_slice(&self) -> &[(T, Option<S>)] {
82                &*self.$field
83            }
84
85            /// Get the group values as a mutable slice.
86            pub fn as_mut(&mut self) -> &mut [(T, Option<S>)] {
87                &mut *self.$field
88            }
89
90            /// Drain all items from the group.
91            #[allow(unused)]
92            pub(crate) fn drain(&mut self) -> impl Iterator<Item = (T, Option<S>)> + '_ {
93                self.$field.drain(..)
94            }
95        }
96
97        impl<'a, T, S> IntoIterator for &'a $name<T, S> {
98            type Item = &'a (T, Option<S>);
99            type IntoIter = slice::Iter<'a, (T, Option<S>)>;
100
101            fn into_iter(self) -> Self::IntoIter {
102                self.iter()
103            }
104        }
105
106        impl<'a, T, S> IntoIterator for &'a mut $name<T, S> {
107            type Item = &'a mut (T, Option<S>);
108            type IntoIter = slice::IterMut<'a, (T, Option<S>)>;
109
110            fn into_iter(self) -> Self::IntoIter {
111                self.iter_mut()
112            }
113        }
114
115        impl<T, S> IntoIterator for $name<T, S> {
116            type Item = (T, Option<S>);
117            type IntoIter = vec::IntoIter<(T, Option<S>)>;
118
119            fn into_iter(self) -> Self::IntoIter {
120                self.$field.into_iter()
121            }
122        }
123
124        impl<T, S> $name<T, S>
125        where
126            T: Parse,
127            S: Peek + Parse,
128        {
129            /// Parse with the first element already specified.
130            pub fn parse_from_first(
131                parser: &mut Parser<'_>,
132                open: $open,
133                mut current: T,
134            ) -> Result<Self> {
135                let mut $field = Vec::new();
136
137                loop {
138                    let comma = parser.parse::<Option<S>>()?;
139                    let is_end = comma.is_none();
140                    $field.try_push((current, comma))?;
141
142                    if is_end || parser.peek::<$close>()? {
143                        break;
144                    }
145
146                    current = parser.parse()?;
147                }
148
149                let close = parser.parse()?;
150
151                Ok(Self {
152                    open,
153                    $field,
154                    close,
155                })
156            }
157        }
158
159        impl<T, S> Parse for $name<T, S>
160        where
161            T: Parse,
162            S: Peek + Parse,
163        {
164            fn parse(parser: &mut Parser<'_>) -> Result<Self> {
165                let open = parser.parse()?;
166
167                let mut $field = Vec::new();
168
169                while !parser.peek::<$close>()? {
170                    let expr = parser.parse()?;
171                    let sep = parser.parse::<Option<S>>()?;
172                    let is_end = sep.is_none();
173                    $field.try_push((expr, sep))?;
174
175                    if is_end {
176                        break;
177                    }
178                }
179
180                let close = parser.parse()?;
181
182                Ok(Self {
183                    open,
184                    $field,
185                    close,
186                })
187            }
188        }
189
190        impl<T, S> Peek for $name<T, S> {
191            fn peek(p: &mut Peeker<'_>) -> bool {
192                <$open>::peek(p)
193            }
194        }
195    }
196}
197
198grouped! {
199    /// Parse something parenthesis, that is separated by `((T, S?)*)`.
200    Parenthesized { parenthesized, ast::OpenParen, ast::CloseParen }
201}
202
203grouped! {
204    /// Parse something bracketed, that is separated by `[(T, S?)*]`.
205    Bracketed { bracketed, ast::OpenBracket, ast::CloseBracket }
206}
207
208grouped! {
209    /// Parse something braced, that is separated by `{(T, S?)*}`.
210    Braced { braced, ast::OpenBrace, ast::CloseBrace }
211}
212
213grouped! {
214    /// Parse something bracketed, that is separated by `<(T, S?)*>`.
215    AngleBracketed { angle_bracketed, ast::generated::Lt, ast::generated::Gt }
216}