blob: a4b884d64c1d9a1b5f3309e1fd962b65fdf523e1 [file] [log] [blame]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001use std::iter::FromIterator;
2use std::slice;
3use std::vec;
Nika Layzelld73a3652017-10-24 08:57:05 -04004#[cfg(feature = "extra-traits")]
5use std::fmt::{self, Debug};
Alex Crichtonccbb45d2017-05-23 10:58:24 -07006
Nika Layzelld73a3652017-10-24 08:57:05 -04007#[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash))]
Alex Crichton7b9e02f2017-05-30 15:54:33 -07008#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayf2cfd722017-12-31 18:02:51 -05009pub struct Punctuated<T, P> {
10 inner: Vec<(T, Option<P>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070011}
12
David Tolnayf2cfd722017-12-31 18:02:51 -050013impl<T, P> Punctuated<T, P> {
14 pub fn new() -> Punctuated<T, P> {
15 Punctuated { inner: Vec::new() }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070016 }
17
18 pub fn is_empty(&self) -> bool {
19 self.inner.len() == 0
20 }
21
22 pub fn len(&self) -> usize {
23 self.inner.len()
24 }
25
David Tolnayf2cfd722017-12-31 18:02:51 -050026 pub fn first(&self) -> Option<Element<&T, &P>> {
David Tolnay51382052017-12-27 13:46:21 -050027 self.inner.first().map(|&(ref t, ref d)| match *d {
David Tolnayf2cfd722017-12-31 18:02:51 -050028 Some(ref d) => Element::Punctuated(t, d),
David Tolnay51382052017-12-27 13:46:21 -050029 None => Element::End(t),
Alex Crichton0aa50e02017-07-07 20:59:03 -070030 })
31 }
32
David Tolnayf2cfd722017-12-31 18:02:51 -050033 pub fn last(&self) -> Option<Element<&T, &P>> {
David Tolnay51382052017-12-27 13:46:21 -050034 self.inner.last().map(|&(ref t, ref d)| match *d {
David Tolnayf2cfd722017-12-31 18:02:51 -050035 Some(ref d) => Element::Punctuated(t, d),
David Tolnay51382052017-12-27 13:46:21 -050036 None => Element::End(t),
Alex Crichton0aa50e02017-07-07 20:59:03 -070037 })
38 }
39
David Tolnayf2cfd722017-12-31 18:02:51 -050040 pub fn last_mut(&mut self) -> Option<Element<&mut T, &mut P>> {
David Tolnay51382052017-12-27 13:46:21 -050041 self.inner
42 .last_mut()
43 .map(|&mut (ref mut t, ref mut d)| match *d {
David Tolnayf2cfd722017-12-31 18:02:51 -050044 Some(ref mut d) => Element::Punctuated(t, d),
Alex Crichton0aa50e02017-07-07 20:59:03 -070045 None => Element::End(t),
David Tolnay51382052017-12-27 13:46:21 -050046 })
Alex Crichton0aa50e02017-07-07 20:59:03 -070047 }
48
David Tolnayf2cfd722017-12-31 18:02:51 -050049 pub fn iter(&self) -> Iter<T, P> {
David Tolnay51382052017-12-27 13:46:21 -050050 Iter {
51 inner: self.inner.iter(),
52 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070053 }
54
David Tolnayf2cfd722017-12-31 18:02:51 -050055 pub fn iter_mut(&mut self) -> IterMut<T, P> {
David Tolnay51382052017-12-27 13:46:21 -050056 IterMut {
57 inner: self.inner.iter_mut(),
58 }
Alex Crichton164c5332017-07-06 13:18:34 -070059 }
60
David Tolnay660fd1f2017-12-31 01:52:57 -050061 pub fn push(&mut self, token: T) {
David Tolnaydc03aec2017-12-30 01:54:18 -050062 assert!(self.empty_or_trailing());
Alex Crichtonccbb45d2017-05-23 10:58:24 -070063 self.inner.push((token, None));
64 }
65
David Tolnayf2cfd722017-12-31 18:02:51 -050066 pub fn push_trailing(&mut self, punctuation: P) {
David Tolnay660fd1f2017-12-31 01:52:57 -050067 assert!(!self.is_empty());
68 let last = self.inner.last_mut().unwrap();
69 assert!(last.1.is_none());
David Tolnayf2cfd722017-12-31 18:02:51 -050070 last.1 = Some(punctuation);
Alex Crichtonccbb45d2017-05-23 10:58:24 -070071 }
72
David Tolnayf2cfd722017-12-31 18:02:51 -050073 pub fn pop(&mut self) -> Option<Element<T, P>> {
David Tolnay660fd1f2017-12-31 01:52:57 -050074 self.inner.pop().map(|(t, d)| Element::new(t, d))
Alex Crichtonccbb45d2017-05-23 10:58:24 -070075 }
76
77 pub fn trailing_delim(&self) -> bool {
David Tolnay660fd1f2017-12-31 01:52:57 -050078 self.inner.last().map(|last| last.1.is_some()).unwrap_or(false)
Alex Crichtonccbb45d2017-05-23 10:58:24 -070079 }
Michael Layzell3936ceb2017-07-08 00:28:36 -040080
David Tolnayf2cfd722017-12-31 18:02:51 -050081 /// Returns true if either this `Punctuated` is empty, or it has a trailing
82 /// punctuation.
David Tolnaydc03aec2017-12-30 01:54:18 -050083 ///
David Tolnayf2cfd722017-12-31 18:02:51 -050084 /// Equivalent to `punctuated.is_empty() || punctuated.trailing_delim()`.
Michael Layzell3936ceb2017-07-08 00:28:36 -040085 pub fn empty_or_trailing(&self) -> bool {
David Tolnay660fd1f2017-12-31 01:52:57 -050086 self.inner.last().map(|last| last.1.is_some()).unwrap_or(true)
Michael Layzell3936ceb2017-07-08 00:28:36 -040087 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070088}
89
Nika Layzelld73a3652017-10-24 08:57:05 -040090#[cfg(feature = "extra-traits")]
David Tolnayf2cfd722017-12-31 18:02:51 -050091impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
Nika Layzelld73a3652017-10-24 08:57:05 -040092 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93 self.inner.fmt(f)
94 }
95}
96
David Tolnayf2cfd722017-12-31 18:02:51 -050097impl<T, P> FromIterator<Element<T, P>> for Punctuated<T, P> {
98 fn from_iter<I: IntoIterator<Item = Element<T, P>>>(i: I) -> Self {
99 let mut ret = Punctuated::new();
Alex Crichton24f12822017-07-14 07:15:32 -0700100 ret.extend(i);
Alex Crichton954046c2017-05-30 21:49:42 -0700101 ret
102 }
103}
104
David Tolnayf2cfd722017-12-31 18:02:51 -0500105impl<T, P> Extend<Element<T, P>> for Punctuated<T, P> {
106 fn extend<I: IntoIterator<Item = Element<T, P>>>(&mut self, i: I) {
David Tolnay660fd1f2017-12-31 01:52:57 -0500107 for elem in i {
108 match elem {
David Tolnayf2cfd722017-12-31 18:02:51 -0500109 Element::Punctuated(a, b) => self.inner.push((a, Some(b))),
Alex Crichton24f12822017-07-14 07:15:32 -0700110 Element::End(a) => self.inner.push((a, None)),
111 }
112 }
113 }
114}
115
David Tolnayf2cfd722017-12-31 18:02:51 -0500116impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
117 type Item = Element<&'a T, &'a P>;
118 type IntoIter = Iter<'a, T, P>;
Alex Crichton954046c2017-05-30 21:49:42 -0700119
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500120 fn into_iter(self) -> Self::IntoIter {
David Tolnayf2cfd722017-12-31 18:02:51 -0500121 Punctuated::iter(self)
Alex Crichton954046c2017-05-30 21:49:42 -0700122 }
123}
124
David Tolnayf2cfd722017-12-31 18:02:51 -0500125impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
126 type Item = Element<&'a mut T, &'a mut P>;
127 type IntoIter = IterMut<'a, T, P>;
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500128
129 fn into_iter(self) -> Self::IntoIter {
David Tolnayf2cfd722017-12-31 18:02:51 -0500130 Punctuated::iter_mut(self)
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500131 }
132}
133
David Tolnayf2cfd722017-12-31 18:02:51 -0500134impl<T, P> IntoIterator for Punctuated<T, P> {
135 type Item = Element<T, P>;
136 type IntoIter = IntoIter<T, P>;
Alex Crichton954046c2017-05-30 21:49:42 -0700137
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500138 fn into_iter(self) -> Self::IntoIter {
David Tolnay51382052017-12-27 13:46:21 -0500139 IntoIter {
140 inner: self.inner.into_iter(),
141 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700142 }
143}
144
David Tolnayf2cfd722017-12-31 18:02:51 -0500145impl<T, P> Default for Punctuated<T, P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700146 fn default() -> Self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500147 Punctuated::new()
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700148 }
149}
150
David Tolnayf2cfd722017-12-31 18:02:51 -0500151pub struct Iter<'a, T: 'a, P: 'a> {
152 inner: slice::Iter<'a, (T, Option<P>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700153}
154
David Tolnayf2cfd722017-12-31 18:02:51 -0500155impl<'a, T, P> Iterator for Iter<'a, T, P> {
156 type Item = Element<&'a T, &'a P>;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700157
David Tolnayf2cfd722017-12-31 18:02:51 -0500158 fn next(&mut self) -> Option<Element<&'a T, &'a P>> {
David Tolnay51382052017-12-27 13:46:21 -0500159 self.inner.next().map(|pair| match pair.1 {
David Tolnayf2cfd722017-12-31 18:02:51 -0500160 Some(ref p) => Element::Punctuated(&pair.0, p),
David Tolnay51382052017-12-27 13:46:21 -0500161 None => Element::End(&pair.0),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700162 })
163 }
164}
165
David Tolnayf2cfd722017-12-31 18:02:51 -0500166pub struct IterMut<'a, T: 'a, P: 'a> {
167 inner: slice::IterMut<'a, (T, Option<P>)>,
Alex Crichton164c5332017-07-06 13:18:34 -0700168}
169
David Tolnayf2cfd722017-12-31 18:02:51 -0500170impl<'a, T, P> Iterator for IterMut<'a, T, P> {
171 type Item = Element<&'a mut T, &'a mut P>;
Alex Crichton164c5332017-07-06 13:18:34 -0700172
David Tolnayf2cfd722017-12-31 18:02:51 -0500173 fn next(&mut self) -> Option<Element<&'a mut T, &'a mut P>> {
David Tolnay51382052017-12-27 13:46:21 -0500174 self.inner.next().map(|pair| match pair.1 {
David Tolnayf2cfd722017-12-31 18:02:51 -0500175 Some(ref mut p) => Element::Punctuated(&mut pair.0, p),
David Tolnay51382052017-12-27 13:46:21 -0500176 None => Element::End(&mut pair.0),
Alex Crichton164c5332017-07-06 13:18:34 -0700177 })
178 }
179}
180
David Tolnayf2cfd722017-12-31 18:02:51 -0500181pub struct IntoIter<T, P> {
182 inner: vec::IntoIter<(T, Option<P>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700183}
184
David Tolnayf2cfd722017-12-31 18:02:51 -0500185impl<T, P> Iterator for IntoIter<T, P> {
186 type Item = Element<T, P>;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700187
David Tolnayf2cfd722017-12-31 18:02:51 -0500188 fn next(&mut self) -> Option<Element<T, P>> {
David Tolnay51382052017-12-27 13:46:21 -0500189 self.inner.next().map(|pair| match pair.1 {
David Tolnayf2cfd722017-12-31 18:02:51 -0500190 Some(v) => Element::Punctuated(pair.0, v),
David Tolnay51382052017-12-27 13:46:21 -0500191 None => Element::End(pair.0),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700192 })
193 }
194}
195
David Tolnayf2cfd722017-12-31 18:02:51 -0500196pub enum Element<T, P> {
197 Punctuated(T, P),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700198 End(T),
199}
200
David Tolnayf2cfd722017-12-31 18:02:51 -0500201impl<T, P> Element<T, P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700202 pub fn into_item(self) -> T {
203 match self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500204 Element::Punctuated(t, _) | Element::End(t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700205 }
206 }
207
208 pub fn item(&self) -> &T {
209 match *self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500210 Element::Punctuated(ref t, _) | Element::End(ref t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700211 }
212 }
213
214 pub fn item_mut(&mut self) -> &mut T {
215 match *self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500216 Element::Punctuated(ref mut t, _) | Element::End(ref mut t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700217 }
218 }
219
David Tolnayf2cfd722017-12-31 18:02:51 -0500220 pub fn punct(&self) -> Option<&P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700221 match *self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500222 Element::Punctuated(_, ref d) => Some(d),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700223 Element::End(_) => None,
224 }
225 }
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400226
David Tolnayf2cfd722017-12-31 18:02:51 -0500227 pub fn new(t: T, d: Option<P>) -> Self {
David Tolnay660fd1f2017-12-31 01:52:57 -0500228 match d {
David Tolnayf2cfd722017-12-31 18:02:51 -0500229 Some(d) => Element::Punctuated(t, d),
David Tolnay660fd1f2017-12-31 01:52:57 -0500230 None => Element::End(t),
231 }
232 }
233
David Tolnayf2cfd722017-12-31 18:02:51 -0500234 pub fn into_tuple(self) -> (T, Option<P>) {
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400235 match self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500236 Element::Punctuated(t, d) => (t, Some(d)),
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400237 Element::End(t) => (t, None),
238 }
239 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700240}
241
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700242#[cfg(feature = "parsing")]
243mod parsing {
David Tolnayf2cfd722017-12-31 18:02:51 -0500244 use super::Punctuated;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500245 use synom::Synom;
246 use cursor::Cursor;
David Tolnay203557a2017-12-27 23:59:33 -0500247 use parse_error;
248 use synom::PResult;
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700249
David Tolnayf2cfd722017-12-31 18:02:51 -0500250 impl<T, P> Punctuated<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500251 where
252 T: Synom,
David Tolnayf2cfd722017-12-31 18:02:51 -0500253 P: Synom,
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700254 {
David Tolnay51382052017-12-27 13:46:21 -0500255 pub fn parse_separated(input: Cursor) -> PResult<Self> {
Alex Crichton954046c2017-05-30 21:49:42 -0700256 Self::parse(input, T::parse, false)
257 }
258
David Tolnay51382052017-12-27 13:46:21 -0500259 pub fn parse_separated_nonempty(input: Cursor) -> PResult<Self> {
Alex Crichton954046c2017-05-30 21:49:42 -0700260 Self::parse_separated_nonempty_with(input, T::parse)
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700261 }
262
David Tolnay51382052017-12-27 13:46:21 -0500263 pub fn parse_terminated(input: Cursor) -> PResult<Self> {
Alex Crichton954046c2017-05-30 21:49:42 -0700264 Self::parse_terminated_with(input, T::parse)
265 }
Nika Layzellb49a9e52017-12-05 13:31:52 -0500266
David Tolnay51382052017-12-27 13:46:21 -0500267 pub fn parse_terminated_nonempty(input: Cursor) -> PResult<Self> {
Nika Layzellb49a9e52017-12-05 13:31:52 -0500268 Self::parse_terminated_nonempty_with(input, T::parse)
269 }
Alex Crichton954046c2017-05-30 21:49:42 -0700270 }
271
David Tolnayf2cfd722017-12-31 18:02:51 -0500272 impl<T, P> Punctuated<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500273 where
David Tolnayf2cfd722017-12-31 18:02:51 -0500274 P: Synom,
Alex Crichton954046c2017-05-30 21:49:42 -0700275 {
David Tolnaydc03aec2017-12-30 01:54:18 -0500276 pub fn parse_separated_with(
277 input: Cursor,
278 parse: fn(Cursor) -> PResult<T>,
279 ) -> PResult<Self> {
280 Self::parse(input, parse, false)
281 }
282
Alex Crichton954046c2017-05-30 21:49:42 -0700283 pub fn parse_separated_nonempty_with(
David Tolnay51382052017-12-27 13:46:21 -0500284 input: Cursor,
285 parse: fn(Cursor) -> PResult<T>,
286 ) -> PResult<Self> {
Alex Crichton954046c2017-05-30 21:49:42 -0700287 match Self::parse(input, parse, false) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500288 Ok((ref b, _)) if b.is_empty() => parse_error(),
Alex Crichton954046c2017-05-30 21:49:42 -0700289 other => other,
290 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700291 }
292
Alex Crichton954046c2017-05-30 21:49:42 -0700293 pub fn parse_terminated_with(
David Tolnay51382052017-12-27 13:46:21 -0500294 input: Cursor,
295 parse: fn(Cursor) -> PResult<T>,
296 ) -> PResult<Self> {
Alex Crichton954046c2017-05-30 21:49:42 -0700297 Self::parse(input, parse, true)
298 }
299
Nika Layzellb49a9e52017-12-05 13:31:52 -0500300 pub fn parse_terminated_nonempty_with(
David Tolnay51382052017-12-27 13:46:21 -0500301 input: Cursor,
302 parse: fn(Cursor) -> PResult<T>,
303 ) -> PResult<Self> {
Nika Layzellb49a9e52017-12-05 13:31:52 -0500304 match Self::parse(input, parse, true) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500305 Ok((ref b, _)) if b.is_empty() => parse_error(),
Nika Layzellb49a9e52017-12-05 13:31:52 -0500306 other => other,
307 }
308 }
309
David Tolnay51382052017-12-27 13:46:21 -0500310 fn parse(
311 mut input: Cursor,
312 parse: fn(Cursor) -> PResult<T>,
313 terminated: bool,
314 ) -> PResult<Self> {
David Tolnayf2cfd722017-12-31 18:02:51 -0500315 let mut res = Punctuated::new();
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700316
317 // get the first element
Alex Crichton954046c2017-05-30 21:49:42 -0700318 match parse(input) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500319 Err(_) => Ok((res, input)),
320 Ok((o, i)) => {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400321 if i == input {
Michael Layzell760fd662017-05-31 22:46:05 -0400322 return parse_error();
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700323 }
324 input = i;
David Tolnay660fd1f2017-12-31 01:52:57 -0500325 res.push(o);
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700326
327 // get the separator first
David Tolnayf2cfd722017-12-31 18:02:51 -0500328 while let Ok((s, i2)) = P::parse(input) {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400329 if i2 == input {
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700330 break;
331 }
332
333 // get the element next
David Tolnayf4aa6b42017-12-31 16:40:33 -0500334 if let Ok((o3, i3)) = parse(i2) {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400335 if i3 == i2 {
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700336 break;
337 }
David Tolnay660fd1f2017-12-31 01:52:57 -0500338 res.push_trailing(s);
339 res.push(o3);
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700340 input = i3;
341 } else {
342 break;
343 }
344 }
345 if terminated {
David Tolnayf2cfd722017-12-31 18:02:51 -0500346 if let Ok((sep, after)) = P::parse(input) {
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700347 res.push_trailing(sep);
348 input = after;
349 }
350 }
David Tolnayf4aa6b42017-12-31 16:40:33 -0500351 Ok((res, input))
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700352 }
353 }
354 }
355 }
356}
357
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700358#[cfg(feature = "printing")]
359mod printing {
360 use super::*;
David Tolnay51382052017-12-27 13:46:21 -0500361 use quote::{ToTokens, Tokens};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700362
David Tolnayf2cfd722017-12-31 18:02:51 -0500363 impl<T, P> ToTokens for Punctuated<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500364 where
365 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500366 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700367 {
368 fn to_tokens(&self, tokens: &mut Tokens) {
369 tokens.append_all(self.iter())
370 }
371 }
372
David Tolnayf2cfd722017-12-31 18:02:51 -0500373 impl<T, P> ToTokens for Element<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500374 where
375 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500376 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700377 {
378 fn to_tokens(&self, tokens: &mut Tokens) {
379 match *self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500380 Element::Punctuated(ref a, ref b) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700381 a.to_tokens(tokens);
382 b.to_tokens(tokens);
383 }
384 Element::End(ref a) => a.to_tokens(tokens),
385 }
386 }
387 }
388}