syn_pub_items/
punctuated.rs

1//! A punctuated sequence of syntax tree nodes separated by punctuation.
2//!
3//! Lots of things in Rust are punctuated sequences.
4//!
5//! - The fields of a struct are `Punctuated<Field, Token![,]>`.
6//! - The segments of a path are `Punctuated<PathSegment, Token![::]>`.
7//! - The bounds on a generic parameter are `Punctuated<TypeParamBound,
8//!   Token![+]>`.
9//! - The arguments to a function call are `Punctuated<Expr, Token![,]>`.
10//!
11//! This module provides a common representation for these punctuated sequences
12//! in the form of the [`Punctuated<T, P>`] type. We store a vector of pairs of
13//! syntax tree node + punctuation, where every node in the sequence is followed
14//! by punctuation except for possibly the final one.
15//!
16//! [`Punctuated<T, P>`]: struct.Punctuated.html
17//!
18//! ```text
19//! a_function_call(arg1, arg2, arg3);
20//!                 ^^^^^ ~~~~~ ^^^^
21//! ```
22
23#[cfg(feature = "extra-traits")]
24use std::fmt::{self, Debug};
25#[cfg(any(feature = "full", feature = "derive"))]
26use std::iter;
27use std::iter::FromIterator;
28use std::ops::{Index, IndexMut};
29use std::option;
30use std::slice;
31use std::vec;
32
33#[cfg(feature = "parsing")]
34use parse::{Parse, ParseStream, Result};
35#[cfg(any(feature = "full", feature = "derive"))]
36use private;
37#[cfg(feature = "parsing")]
38use token::Token;
39
40/// A punctuated sequence of syntax tree nodes of type `T` separated by
41/// punctuation of type `P`.
42///
43/// Refer to the [module documentation] for details about punctuated sequences.
44///
45/// [module documentation]: index.html
46#[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash))]
47#[cfg_attr(feature = "clone-impls", derive(Clone))]
48pub struct Punctuated<T, P> {
49    inner: Vec<(T, P)>,
50    last: Option<Box<T>>,
51}
52
53impl<T, P> Punctuated<T, P> {
54    /// Creates an empty punctuated sequence.
55    pub fn new() -> Punctuated<T, P> {
56        Punctuated {
57            inner: Vec::new(),
58            last: None,
59        }
60    }
61
62    /// Determines whether this punctuated sequence is empty, meaning it
63    /// contains no syntax tree nodes or punctuation.
64    pub fn is_empty(&self) -> bool {
65        self.inner.len() == 0 && self.last.is_none()
66    }
67
68    /// Returns the number of syntax tree nodes in this punctuated sequence.
69    ///
70    /// This is the number of nodes of type `T`, not counting the punctuation of
71    /// type `P`.
72    pub fn len(&self) -> usize {
73        self.inner.len() + if self.last.is_some() { 1 } else { 0 }
74    }
75
76    /// Borrows the first punctuated pair in this sequence.
77    pub fn first(&self) -> Option<Pair<&T, &P>> {
78        self.pairs().next()
79    }
80
81    /// Borrows the last punctuated pair in this sequence.
82    pub fn last(&self) -> Option<Pair<&T, &P>> {
83        if self.last.is_some() {
84            self.last.as_ref().map(|t| Pair::End(t.as_ref()))
85        } else {
86            self.inner
87                .last()
88                .map(|&(ref t, ref d)| Pair::Punctuated(t, d))
89        }
90    }
91
92    /// Mutably borrows the last punctuated pair in this sequence.
93    pub fn last_mut(&mut self) -> Option<Pair<&mut T, &mut P>> {
94        if self.last.is_some() {
95            self.last.as_mut().map(|t| Pair::End(t.as_mut()))
96        } else {
97            self.inner
98                .last_mut()
99                .map(|&mut (ref mut t, ref mut d)| Pair::Punctuated(t, d))
100        }
101    }
102
103    /// Returns an iterator over borrowed syntax tree nodes of type `&T`.
104    pub fn iter(&self) -> Iter<T> {
105        Iter {
106            inner: Box::new(PrivateIter {
107                inner: self.inner.iter(),
108                last: self.last.as_ref().map(Box::as_ref).into_iter(),
109            }),
110        }
111    }
112
113    /// Returns an iterator over mutably borrowed syntax tree nodes of type
114    /// `&mut T`.
115    pub fn iter_mut(&mut self) -> IterMut<T> {
116        IterMut {
117            inner: Box::new(PrivateIterMut {
118                inner: self.inner.iter_mut(),
119                last: self.last.as_mut().map(Box::as_mut).into_iter(),
120            }),
121        }
122    }
123
124    /// Returns an iterator over the contents of this sequence as borrowed
125    /// punctuated pairs.
126    pub fn pairs(&self) -> Pairs<T, P> {
127        Pairs {
128            inner: self.inner.iter(),
129            last: self.last.as_ref().map(Box::as_ref).into_iter(),
130        }
131    }
132
133    /// Returns an iterator over the contents of this sequence as mutably
134    /// borrowed punctuated pairs.
135    pub fn pairs_mut(&mut self) -> PairsMut<T, P> {
136        PairsMut {
137            inner: self.inner.iter_mut(),
138            last: self.last.as_mut().map(Box::as_mut).into_iter(),
139        }
140    }
141
142    /// Returns an iterator over the contents of this sequence as owned
143    /// punctuated pairs.
144    pub fn into_pairs(self) -> IntoPairs<T, P> {
145        IntoPairs {
146            inner: self.inner.into_iter(),
147            last: self.last.map(|t| *t).into_iter(),
148        }
149    }
150
151    /// Appends a syntax tree node onto the end of this punctuated sequence. The
152    /// sequence must previously have a trailing punctuation.
153    ///
154    /// Use [`push`] instead if the punctuated sequence may or may not already
155    /// have trailing punctuation.
156    ///
157    /// [`push`]: #method.push
158    ///
159    /// # Panics
160    ///
161    /// Panics if the sequence does not already have a trailing punctuation when
162    /// this method is called.
163    pub fn push_value(&mut self, value: T) {
164        assert!(self.empty_or_trailing());
165        self.last = Some(Box::new(value));
166    }
167
168    /// Appends a trailing punctuation onto the end of this punctuated sequence.
169    /// The sequence must be non-empty and must not already have trailing
170    /// punctuation.
171    ///
172    /// # Panics
173    ///
174    /// Panics if the sequence is empty or already has a trailing punctuation.
175    pub fn push_punct(&mut self, punctuation: P) {
176        assert!(self.last.is_some());
177        let last = self.last.take().unwrap();
178        self.inner.push((*last, punctuation));
179    }
180
181    /// Removes the last punctuated pair from this sequence, or `None` if the
182    /// sequence is empty.
183    pub fn pop(&mut self) -> Option<Pair<T, P>> {
184        if self.last.is_some() {
185            self.last.take().map(|t| Pair::End(*t))
186        } else {
187            self.inner.pop().map(|(t, d)| Pair::Punctuated(t, d))
188        }
189    }
190
191    /// Determines whether this punctuated sequence ends with a trailing
192    /// punctuation.
193    pub fn trailing_punct(&self) -> bool {
194        self.last.is_none() && !self.is_empty()
195    }
196
197    /// Returns true if either this `Punctuated` is empty, or it has a trailing
198    /// punctuation.
199    ///
200    /// Equivalent to `punctuated.is_empty() || punctuated.trailing_punct()`.
201    pub fn empty_or_trailing(&self) -> bool {
202        self.last.is_none()
203    }
204
205    /// Appends a syntax tree node onto the end of this punctuated sequence.
206    ///
207    /// If there is not a trailing punctuation in this sequence when this method
208    /// is called, the default value of punctuation type `P` is inserted before
209    /// the given value of type `T`.
210    pub fn push(&mut self, value: T)
211    where
212        P: Default,
213    {
214        if !self.empty_or_trailing() {
215            self.push_punct(Default::default());
216        }
217        self.push_value(value);
218    }
219
220    /// Inserts an element at position `index`.
221    ///
222    /// # Panics
223    ///
224    /// Panics if `index` is greater than the number of elements previously in
225    /// this punctuated sequence.
226    pub fn insert(&mut self, index: usize, value: T)
227    where
228        P: Default,
229    {
230        assert!(index <= self.len());
231
232        if index == self.len() {
233            self.push(value);
234        } else {
235            self.inner.insert(index, (value, Default::default()));
236        }
237    }
238
239    /// Parses zero or more occurrences of `T` separated by punctuation of type
240    /// `P`, with optional trailing punctuation.
241    ///
242    /// Parsing continues until the end of this parse stream. The entire content
243    /// of this parse stream must consist of `T` and `P`.
244    ///
245    /// *This function is available if Syn is built with the `"parsing"`
246    /// feature.*
247    #[cfg(feature = "parsing")]
248    pub fn parse_terminated(input: ParseStream) -> Result<Self>
249    where
250        T: Parse,
251        P: Parse,
252    {
253        Self::parse_terminated_with(input, T::parse)
254    }
255
256    /// Parses zero or more occurrences of `T` using the given parse function,
257    /// separated by punctuation of type `P`, with optional trailing
258    /// punctuation.
259    ///
260    /// Like [`parse_terminated`], the entire content of this stream is expected
261    /// to be parsed.
262    ///
263    /// [`parse_terminated`]: #method.parse_terminated
264    ///
265    /// *This function is available if Syn is built with the `"parsing"`
266    /// feature.*
267    #[cfg(feature = "parsing")]
268    pub fn parse_terminated_with(
269        input: ParseStream,
270        parser: fn(ParseStream) -> Result<T>,
271    ) -> Result<Self>
272    where
273        P: Parse,
274    {
275        let mut punctuated = Punctuated::new();
276
277        loop {
278            if input.is_empty() {
279                break;
280            }
281            let value = parser(input)?;
282            punctuated.push_value(value);
283            if input.is_empty() {
284                break;
285            }
286            let punct = input.parse()?;
287            punctuated.push_punct(punct);
288        }
289
290        Ok(punctuated)
291    }
292
293    /// Parses one or more occurrences of `T` separated by punctuation of type
294    /// `P`, not accepting trailing punctuation.
295    ///
296    /// Parsing continues as long as punctuation `P` is present at the head of
297    /// the stream. This method returns upon parsing a `T` and observing that it
298    /// is not followed by a `P`, even if there are remaining tokens in the
299    /// stream.
300    ///
301    /// *This function is available if Syn is built with the `"parsing"`
302    /// feature.*
303    #[cfg(feature = "parsing")]
304    pub fn parse_separated_nonempty(input: ParseStream) -> Result<Self>
305    where
306        T: Parse,
307        P: Token + Parse,
308    {
309        Self::parse_separated_nonempty_with(input, T::parse)
310    }
311
312    /// Parses one or more occurrences of `T` using the given parse function,
313    /// separated by punctuation of type `P`, not accepting trailing
314    /// punctuation.
315    ///
316    /// Like [`parse_separated_nonempty`], may complete early without parsing
317    /// the entire content of this stream.
318    ///
319    /// [`parse_separated_nonempty`]: #method.parse_separated_nonempty
320    ///
321    /// *This function is available if Syn is built with the `"parsing"`
322    /// feature.*
323    #[cfg(feature = "parsing")]
324    pub fn parse_separated_nonempty_with(
325        input: ParseStream,
326        parser: fn(ParseStream) -> Result<T>,
327    ) -> Result<Self>
328    where
329        P: Token + Parse,
330    {
331        let mut punctuated = Punctuated::new();
332
333        loop {
334            let value = parser(input)?;
335            punctuated.push_value(value);
336            if !P::peek(input.cursor()) {
337                break;
338            }
339            let punct = input.parse()?;
340            punctuated.push_punct(punct);
341        }
342
343        Ok(punctuated)
344    }
345}
346
347#[cfg(feature = "extra-traits")]
348impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
349    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
350        let mut list = f.debug_list();
351        for &(ref t, ref p) in &self.inner {
352            list.entry(t);
353            list.entry(p);
354        }
355        if let Some(ref last) = self.last {
356            list.entry(last);
357        }
358        list.finish()
359    }
360}
361
362impl<T, P> FromIterator<T> for Punctuated<T, P>
363where
364    P: Default,
365{
366    fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
367        let mut ret = Punctuated::new();
368        ret.extend(i);
369        ret
370    }
371}
372
373impl<T, P> Extend<T> for Punctuated<T, P>
374where
375    P: Default,
376{
377    fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
378        for value in i {
379            self.push(value);
380        }
381    }
382}
383
384impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> {
385    fn from_iter<I: IntoIterator<Item = Pair<T, P>>>(i: I) -> Self {
386        let mut ret = Punctuated::new();
387        ret.extend(i);
388        ret
389    }
390}
391
392impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P> {
393    fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) {
394        assert!(self.empty_or_trailing());
395        let mut nomore = false;
396        for pair in i {
397            if nomore {
398                panic!("Punctuated extended with items after a Pair::End");
399            }
400            match pair {
401                Pair::Punctuated(a, b) => self.inner.push((a, b)),
402                Pair::End(a) => {
403                    self.last = Some(Box::new(a));
404                    nomore = true;
405                }
406            }
407        }
408    }
409}
410
411impl<T, P> IntoIterator for Punctuated<T, P> {
412    type Item = T;
413    type IntoIter = IntoIter<T, P>;
414
415    fn into_iter(self) -> Self::IntoIter {
416        IntoIter {
417            inner: self.inner.into_iter(),
418            last: self.last.map(|t| *t).into_iter(),
419        }
420    }
421}
422
423impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
424    type Item = &'a T;
425    type IntoIter = Iter<'a, T>;
426
427    fn into_iter(self) -> Self::IntoIter {
428        Punctuated::iter(self)
429    }
430}
431
432impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
433    type Item = &'a mut T;
434    type IntoIter = IterMut<'a, T>;
435
436    fn into_iter(self) -> Self::IntoIter {
437        Punctuated::iter_mut(self)
438    }
439}
440
441impl<T, P> Default for Punctuated<T, P> {
442    fn default() -> Self {
443        Punctuated::new()
444    }
445}
446
447/// An iterator over borrowed pairs of type `Pair<&T, &P>`.
448///
449/// Refer to the [module documentation] for details about punctuated sequences.
450///
451/// [module documentation]: index.html
452pub struct Pairs<'a, T: 'a, P: 'a> {
453    inner: slice::Iter<'a, (T, P)>,
454    last: option::IntoIter<&'a T>,
455}
456
457impl<'a, T, P> Iterator for Pairs<'a, T, P> {
458    type Item = Pair<&'a T, &'a P>;
459
460    fn next(&mut self) -> Option<Self::Item> {
461        self.inner
462            .next()
463            .map(|&(ref t, ref p)| Pair::Punctuated(t, p))
464            .or_else(|| self.last.next().map(Pair::End))
465    }
466}
467
468impl<'a, T, P> ExactSizeIterator for Pairs<'a, T, P> {
469    fn len(&self) -> usize {
470        self.inner.len() + self.last.len()
471    }
472}
473
474/// An iterator over mutably borrowed pairs of type `Pair<&mut T, &mut P>`.
475///
476/// Refer to the [module documentation] for details about punctuated sequences.
477///
478/// [module documentation]: index.html
479pub struct PairsMut<'a, T: 'a, P: 'a> {
480    inner: slice::IterMut<'a, (T, P)>,
481    last: option::IntoIter<&'a mut T>,
482}
483
484impl<'a, T, P> Iterator for PairsMut<'a, T, P> {
485    type Item = Pair<&'a mut T, &'a mut P>;
486
487    fn next(&mut self) -> Option<Self::Item> {
488        self.inner
489            .next()
490            .map(|&mut (ref mut t, ref mut p)| Pair::Punctuated(t, p))
491            .or_else(|| self.last.next().map(Pair::End))
492    }
493}
494
495impl<'a, T, P> ExactSizeIterator for PairsMut<'a, T, P> {
496    fn len(&self) -> usize {
497        self.inner.len() + self.last.len()
498    }
499}
500
501/// An iterator over owned pairs of type `Pair<T, P>`.
502///
503/// Refer to the [module documentation] for details about punctuated sequences.
504///
505/// [module documentation]: index.html
506pub struct IntoPairs<T, P> {
507    inner: vec::IntoIter<(T, P)>,
508    last: option::IntoIter<T>,
509}
510
511impl<T, P> Iterator for IntoPairs<T, P> {
512    type Item = Pair<T, P>;
513
514    fn next(&mut self) -> Option<Self::Item> {
515        self.inner
516            .next()
517            .map(|(t, p)| Pair::Punctuated(t, p))
518            .or_else(|| self.last.next().map(Pair::End))
519    }
520}
521
522impl<T, P> ExactSizeIterator for IntoPairs<T, P> {
523    fn len(&self) -> usize {
524        self.inner.len() + self.last.len()
525    }
526}
527
528/// An iterator over owned values of type `T`.
529///
530/// Refer to the [module documentation] for details about punctuated sequences.
531///
532/// [module documentation]: index.html
533pub struct IntoIter<T, P> {
534    inner: vec::IntoIter<(T, P)>,
535    last: option::IntoIter<T>,
536}
537
538impl<T, P> Iterator for IntoIter<T, P> {
539    type Item = T;
540
541    fn next(&mut self) -> Option<Self::Item> {
542        self.inner
543            .next()
544            .map(|pair| pair.0)
545            .or_else(|| self.last.next())
546    }
547}
548
549impl<T, P> ExactSizeIterator for IntoIter<T, P> {
550    fn len(&self) -> usize {
551        self.inner.len() + self.last.len()
552    }
553}
554
555/// An iterator over borrowed values of type `&T`.
556///
557/// Refer to the [module documentation] for details about punctuated sequences.
558///
559/// [module documentation]: index.html
560pub struct Iter<'a, T: 'a> {
561    inner: Box<ExactSizeIterator<Item = &'a T> + 'a>,
562}
563
564struct PrivateIter<'a, T: 'a, P: 'a> {
565    inner: slice::Iter<'a, (T, P)>,
566    last: option::IntoIter<&'a T>,
567}
568
569#[cfg(any(feature = "full", feature = "derive"))]
570impl private {
571    pub fn empty_punctuated_iter<'a, T>() -> Iter<'a, T> {
572        Iter {
573            inner: Box::new(iter::empty()),
574        }
575    }
576}
577
578impl<'a, T> Iterator for Iter<'a, T> {
579    type Item = &'a T;
580
581    fn next(&mut self) -> Option<Self::Item> {
582        self.inner.next()
583    }
584}
585
586impl<'a, T> ExactSizeIterator for Iter<'a, T> {
587    fn len(&self) -> usize {
588        self.inner.len()
589    }
590}
591
592impl<'a, T, P> Iterator for PrivateIter<'a, T, P> {
593    type Item = &'a T;
594
595    fn next(&mut self) -> Option<Self::Item> {
596        self.inner
597            .next()
598            .map(|pair| &pair.0)
599            .or_else(|| self.last.next())
600    }
601}
602
603impl<'a, T, P> ExactSizeIterator for PrivateIter<'a, T, P> {
604    fn len(&self) -> usize {
605        self.inner.len() + self.last.len()
606    }
607}
608
609/// An iterator over mutably borrowed values of type `&mut T`.
610///
611/// Refer to the [module documentation] for details about punctuated sequences.
612///
613/// [module documentation]: index.html
614pub struct IterMut<'a, T: 'a> {
615    inner: Box<ExactSizeIterator<Item = &'a mut T> + 'a>,
616}
617
618struct PrivateIterMut<'a, T: 'a, P: 'a> {
619    inner: slice::IterMut<'a, (T, P)>,
620    last: option::IntoIter<&'a mut T>,
621}
622
623#[cfg(any(feature = "full", feature = "derive"))]
624impl private {
625    pub fn empty_punctuated_iter_mut<'a, T>() -> IterMut<'a, T> {
626        IterMut {
627            inner: Box::new(iter::empty()),
628        }
629    }
630}
631
632impl<'a, T> Iterator for IterMut<'a, T> {
633    type Item = &'a mut T;
634
635    fn next(&mut self) -> Option<Self::Item> {
636        self.inner.next()
637    }
638}
639
640impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
641    fn len(&self) -> usize {
642        self.inner.len()
643    }
644}
645
646impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> {
647    type Item = &'a mut T;
648
649    fn next(&mut self) -> Option<Self::Item> {
650        self.inner
651            .next()
652            .map(|pair| &mut pair.0)
653            .or_else(|| self.last.next())
654    }
655}
656
657impl<'a, T, P> ExactSizeIterator for PrivateIterMut<'a, T, P> {
658    fn len(&self) -> usize {
659        self.inner.len() + self.last.len()
660    }
661}
662
663/// A single syntax tree node of type `T` followed by its trailing punctuation
664/// of type `P` if any.
665///
666/// Refer to the [module documentation] for details about punctuated sequences.
667///
668/// [module documentation]: index.html
669pub enum Pair<T, P> {
670    Punctuated(T, P),
671    End(T),
672}
673
674impl<T, P> Pair<T, P> {
675    /// Extracts the syntax tree node from this punctuated pair, discarding the
676    /// following punctuation.
677    pub fn into_value(self) -> T {
678        match self {
679            Pair::Punctuated(t, _) | Pair::End(t) => t,
680        }
681    }
682
683    /// Borrows the syntax tree node from this punctuated pair.
684    pub fn value(&self) -> &T {
685        match *self {
686            Pair::Punctuated(ref t, _) | Pair::End(ref t) => t,
687        }
688    }
689
690    /// Mutably borrows the syntax tree node from this punctuated pair.
691    pub fn value_mut(&mut self) -> &mut T {
692        match *self {
693            Pair::Punctuated(ref mut t, _) | Pair::End(ref mut t) => t,
694        }
695    }
696
697    /// Borrows the punctuation from this punctuated pair, unless this pair is
698    /// the final one and there is no trailing punctuation.
699    pub fn punct(&self) -> Option<&P> {
700        match *self {
701            Pair::Punctuated(_, ref d) => Some(d),
702            Pair::End(_) => None,
703        }
704    }
705
706    /// Creates a punctuated pair out of a syntax tree node and an optional
707    /// following punctuation.
708    pub fn new(t: T, d: Option<P>) -> Self {
709        match d {
710            Some(d) => Pair::Punctuated(t, d),
711            None => Pair::End(t),
712        }
713    }
714
715    /// Produces this punctuated pair as a tuple of syntax tree node and
716    /// optional following punctuation.
717    pub fn into_tuple(self) -> (T, Option<P>) {
718        match self {
719            Pair::Punctuated(t, d) => (t, Some(d)),
720            Pair::End(t) => (t, None),
721        }
722    }
723}
724
725impl<T, P> Index<usize> for Punctuated<T, P> {
726    type Output = T;
727
728    fn index(&self, index: usize) -> &Self::Output {
729        if index == self.len() - 1 {
730            match self.last {
731                Some(ref t) => t,
732                None => &self.inner[index].0,
733            }
734        } else {
735            &self.inner[index].0
736        }
737    }
738}
739
740impl<T, P> IndexMut<usize> for Punctuated<T, P> {
741    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
742        if index == self.len() - 1 {
743            match self.last {
744                Some(ref mut t) => t,
745                None => &mut self.inner[index].0,
746            }
747        } else {
748            &mut self.inner[index].0
749        }
750    }
751}
752
753#[cfg(feature = "printing")]
754mod printing {
755    use super::*;
756    use proc_macro2::TokenStream;
757    use quote::{ToTokens, TokenStreamExt};
758
759    impl<T, P> ToTokens for Punctuated<T, P>
760    where
761        T: ToTokens,
762        P: ToTokens,
763    {
764        fn to_tokens(&self, tokens: &mut TokenStream) {
765            tokens.append_all(self.pairs())
766        }
767    }
768
769    impl<T, P> ToTokens for Pair<T, P>
770    where
771        T: ToTokens,
772        P: ToTokens,
773    {
774        fn to_tokens(&self, tokens: &mut TokenStream) {
775            match *self {
776                Pair::Punctuated(ref a, ref b) => {
777                    a.to_tokens(tokens);
778                    b.to_tokens(tokens);
779                }
780                Pair::End(ref a) => a.to_tokens(tokens),
781            }
782        }
783    }
784}