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 pub open: $open,
36 pub $field: Vec<(T, Option<S>)>,
38 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 pub fn is_empty(&self) -> bool {
52 self.$field.is_empty()
53 }
54
55 pub fn len(&self) -> usize {
57 self.$field.len()
58 }
59
60 pub fn first(&self) -> Option<&(T, Option<S>)> {
62 self.$field.first()
63 }
64
65 pub fn last(&self) -> Option<&(T, Option<S>)> {
67 self.$field.last()
68 }
69
70 pub fn iter(&self) -> slice::Iter<'_, (T, Option<S>)> {
72 self.$field.iter()
73 }
74
75 pub fn iter_mut(&mut self) -> slice::IterMut<'_, (T, Option<S>)> {
77 self.$field.iter_mut()
78 }
79
80 pub fn as_slice(&self) -> &[(T, Option<S>)] {
82 &*self.$field
83 }
84
85 pub fn as_mut(&mut self) -> &mut [(T, Option<S>)] {
87 &mut *self.$field
88 }
89
90 #[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 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 Parenthesized { parenthesized, ast::OpenParen, ast::CloseParen }
201}
202
203grouped! {
204 Bracketed { bracketed, ast::OpenBracket, ast::CloseBracket }
206}
207
208grouped! {
209 Braced { braced, ast::OpenBrace, ast::CloseBrace }
211}
212
213grouped! {
214 AngleBracketed { angle_bracketed, ast::generated::Lt, ast::generated::Gt }
216}