blob: b2f5833fb1d89dffa07db851802616b7c96568aa [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnayf3198012018-01-06 20:00:42 -08009//! A punctuated sequence of syntax tree nodes separated by punctuation.
10//!
11//! Lots of things in Rust are punctuated sequences.
12//!
13//! - The fields of a struct are `Punctuated<Field, Token![,]>`.
14//! - The segments of a path are `Punctuated<PathSegment, Token![::]>`.
15//! - The bounds on a generic parameter are `Punctuated<TypeParamBound, Token![+]>`.
16//! - The arguments to a function call are `Punctuated<Expr, Token![,]>`.
17//!
18//! This module provides a common representation for these punctuated sequences
19//! in the form of the [`Punctuated<T, P>`] type. We store a vector of pairs of
20//! syntax tree node + punctuation, where every node in the sequence is followed
21//! by punctuation except for possibly the final one.
22//!
23//! [`Punctuated<T, P>`]: struct.Punctuated.html
24//!
25//! ```text
26//! a_function_call(arg1, arg2, arg3);
27//! ^^^^^ ~~~~~ ^^^^
28//! ```
29
David Tolnay8095c302018-03-31 19:34:17 +020030use std::iter::{self, FromIterator};
David Tolnaybb987132018-01-08 13:51:19 -080031use std::ops::{Index, IndexMut};
Alex Crichtonccbb45d2017-05-23 10:58:24 -070032use std::slice;
33use std::vec;
Nika Layzelld73a3652017-10-24 08:57:05 -040034#[cfg(feature = "extra-traits")]
35use std::fmt::{self, Debug};
Alex Crichtonccbb45d2017-05-23 10:58:24 -070036
David Tolnayf3198012018-01-06 20:00:42 -080037#[cfg(feature = "parsing")]
38use synom::{Synom, PResult};
39#[cfg(feature = "parsing")]
40use buffer::Cursor;
41#[cfg(feature = "parsing")]
42use parse_error;
43
44/// A punctuated sequence of syntax tree nodes of type `T` separated by
45/// punctuation of type `P`.
46///
47/// Refer to the [module documentation] for details about punctuated sequences.
48///
49/// [module documentation]: index.html
Nika Layzelld73a3652017-10-24 08:57:05 -040050#[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash))]
Alex Crichton7b9e02f2017-05-30 15:54:33 -070051#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayf2cfd722017-12-31 18:02:51 -050052pub struct Punctuated<T, P> {
53 inner: Vec<(T, Option<P>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070054}
55
David Tolnayf2cfd722017-12-31 18:02:51 -050056impl<T, P> Punctuated<T, P> {
David Tolnayf3198012018-01-06 20:00:42 -080057 /// Creates an empty punctuated sequence.
David Tolnayf2cfd722017-12-31 18:02:51 -050058 pub fn new() -> Punctuated<T, P> {
59 Punctuated { inner: Vec::new() }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070060 }
61
David Tolnayf3198012018-01-06 20:00:42 -080062 /// Determines whether this punctuated sequence is empty, meaning it
63 /// contains no syntax tree nodes or punctuation.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070064 pub fn is_empty(&self) -> bool {
65 self.inner.len() == 0
66 }
67
David Tolnayf3198012018-01-06 20:00:42 -080068 /// 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`.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070072 pub fn len(&self) -> usize {
73 self.inner.len()
74 }
75
David Tolnayf3198012018-01-06 20:00:42 -080076 /// Borrows the first punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080077 pub fn first(&self) -> Option<Pair<&T, &P>> {
David Tolnay51382052017-12-27 13:46:21 -050078 self.inner.first().map(|&(ref t, ref d)| match *d {
David Tolnay56080682018-01-06 14:01:52 -080079 Some(ref d) => Pair::Punctuated(t, d),
80 None => Pair::End(t),
Alex Crichton0aa50e02017-07-07 20:59:03 -070081 })
82 }
83
David Tolnayf3198012018-01-06 20:00:42 -080084 /// Borrows the last punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080085 pub fn last(&self) -> Option<Pair<&T, &P>> {
David Tolnay51382052017-12-27 13:46:21 -050086 self.inner.last().map(|&(ref t, ref d)| match *d {
David Tolnay56080682018-01-06 14:01:52 -080087 Some(ref d) => Pair::Punctuated(t, d),
88 None => Pair::End(t),
Alex Crichton0aa50e02017-07-07 20:59:03 -070089 })
90 }
91
David Tolnayf3198012018-01-06 20:00:42 -080092 /// Mutably borrows the last punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080093 pub fn last_mut(&mut self) -> Option<Pair<&mut T, &mut P>> {
David Tolnay51382052017-12-27 13:46:21 -050094 self.inner
95 .last_mut()
96 .map(|&mut (ref mut t, ref mut d)| match *d {
David Tolnay56080682018-01-06 14:01:52 -080097 Some(ref mut d) => Pair::Punctuated(t, d),
98 None => Pair::End(t),
David Tolnay51382052017-12-27 13:46:21 -050099 })
Alex Crichton0aa50e02017-07-07 20:59:03 -0700100 }
101
David Tolnayf3198012018-01-06 20:00:42 -0800102 /// Returns an iterator over borrowed syntax tree nodes of type `&T`.
David Tolnay8095c302018-03-31 19:34:17 +0200103 pub fn iter(&self) -> Iter<T> {
David Tolnay51382052017-12-27 13:46:21 -0500104 Iter {
David Tolnay8095c302018-03-31 19:34:17 +0200105 inner: Box::new(PrivateIter {
106 inner: self.inner.iter(),
107 }),
David Tolnay51382052017-12-27 13:46:21 -0500108 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700109 }
110
David Tolnayf3198012018-01-06 20:00:42 -0800111 /// Returns an iterator over mutably borrowed syntax tree nodes of type
112 /// `&mut T`.
David Tolnay8095c302018-03-31 19:34:17 +0200113 pub fn iter_mut(&mut self) -> IterMut<T> {
David Tolnaya0834b42018-01-01 21:30:02 -0800114 IterMut {
David Tolnay8095c302018-03-31 19:34:17 +0200115 inner: Box::new(PrivateIterMut {
116 inner: self.inner.iter_mut(),
117 }),
David Tolnaya0834b42018-01-01 21:30:02 -0800118 }
119 }
120
David Tolnayf3198012018-01-06 20:00:42 -0800121 /// Returns an iterator over the contents of this sequence as borrowed
122 /// punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800123 pub fn pairs(&self) -> Pairs<T, P> {
124 Pairs {
David Tolnay6eff4da2018-01-01 20:27:45 -0800125 inner: self.inner.iter(),
126 }
127 }
128
David Tolnayf3198012018-01-06 20:00:42 -0800129 /// Returns an iterator over the contents of this sequence as mutably
130 /// borrowed punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800131 pub fn pairs_mut(&mut self) -> PairsMut<T, P> {
132 PairsMut {
David Tolnay51382052017-12-27 13:46:21 -0500133 inner: self.inner.iter_mut(),
134 }
Alex Crichton164c5332017-07-06 13:18:34 -0700135 }
136
David Tolnayf3198012018-01-06 20:00:42 -0800137 /// Returns an iterator over the contents of this sequence as owned
138 /// punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800139 pub fn into_pairs(self) -> IntoPairs<T, P> {
140 IntoPairs {
David Tolnay6eff4da2018-01-01 20:27:45 -0800141 inner: self.inner.into_iter(),
142 }
143 }
144
David Tolnayf3198012018-01-06 20:00:42 -0800145 /// Appends a syntax tree node onto the end of this punctuated sequence. The
146 /// sequence must previously have a trailing punctuation.
147 ///
148 /// Use [`push`] instead if the punctuated sequence may or may not already
149 /// have trailing punctuation.
150 ///
151 /// [`push`]: #method.push
152 ///
153 /// # Panics
154 ///
155 /// Panics if the sequence does not already have a trailing punctuation when
156 /// this method is called.
David Tolnay56080682018-01-06 14:01:52 -0800157 pub fn push_value(&mut self, value: T) {
David Tolnaydc03aec2017-12-30 01:54:18 -0500158 assert!(self.empty_or_trailing());
David Tolnay56080682018-01-06 14:01:52 -0800159 self.inner.push((value, None));
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700160 }
161
David Tolnayf3198012018-01-06 20:00:42 -0800162 /// Appends a trailing punctuation onto the end of this punctuated sequence.
163 /// The sequence must be non-empty and must not already have trailing
164 /// punctuation.
165 ///
166 /// # Panics
167 ///
168 /// Panics if the sequence is empty or already has a trailing punctuation.
David Tolnaya0834b42018-01-01 21:30:02 -0800169 pub fn push_punct(&mut self, punctuation: P) {
David Tolnay660fd1f2017-12-31 01:52:57 -0500170 assert!(!self.is_empty());
171 let last = self.inner.last_mut().unwrap();
172 assert!(last.1.is_none());
David Tolnayf2cfd722017-12-31 18:02:51 -0500173 last.1 = Some(punctuation);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700174 }
175
David Tolnayf3198012018-01-06 20:00:42 -0800176 /// Removes the last punctuated pair from this sequence, or `None` if the
177 /// sequence is empty.
David Tolnay56080682018-01-06 14:01:52 -0800178 pub fn pop(&mut self) -> Option<Pair<T, P>> {
179 self.inner.pop().map(|(t, d)| Pair::new(t, d))
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700180 }
181
David Tolnayf3198012018-01-06 20:00:42 -0800182 /// Determines whether this punctuated sequence ends with a trailing
183 /// punctuation.
David Tolnaya0834b42018-01-01 21:30:02 -0800184 pub fn trailing_punct(&self) -> bool {
David Tolnay61037c62018-01-05 16:21:03 -0800185 self.inner
186 .last()
187 .map(|last| last.1.is_some())
188 .unwrap_or(false)
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700189 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400190
David Tolnayf2cfd722017-12-31 18:02:51 -0500191 /// Returns true if either this `Punctuated` is empty, or it has a trailing
192 /// punctuation.
David Tolnaydc03aec2017-12-30 01:54:18 -0500193 ///
David Tolnaya0834b42018-01-01 21:30:02 -0800194 /// Equivalent to `punctuated.is_empty() || punctuated.trailing_punct()`.
Michael Layzell3936ceb2017-07-08 00:28:36 -0400195 pub fn empty_or_trailing(&self) -> bool {
David Tolnay61037c62018-01-05 16:21:03 -0800196 self.inner
197 .last()
198 .map(|last| last.1.is_some())
199 .unwrap_or(true)
Michael Layzell3936ceb2017-07-08 00:28:36 -0400200 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700201}
202
David Tolnaya0834b42018-01-01 21:30:02 -0800203impl<T, P> Punctuated<T, P>
204where
205 P: Default,
206{
David Tolnayf3198012018-01-06 20:00:42 -0800207 /// Appends a syntax tree node onto the end of this punctuated sequence.
208 ///
209 /// If there is not a trailing punctuation in this sequence when this method
210 /// is called, the default value of punctuation type `P` is inserted before
211 /// the given value of type `T`.
David Tolnay56080682018-01-06 14:01:52 -0800212 pub fn push(&mut self, value: T) {
David Tolnaya0834b42018-01-01 21:30:02 -0800213 if !self.empty_or_trailing() {
214 self.push_punct(Default::default());
215 }
David Tolnay56080682018-01-06 14:01:52 -0800216 self.push_value(value);
David Tolnaya0834b42018-01-01 21:30:02 -0800217 }
David Tolnayb77d1802018-01-11 16:18:35 -0800218
219 /// Inserts an element at position `index`.
220 ///
221 /// # Panics
222 ///
223 /// Panics if `index` is greater than the number of elements previously in
224 /// this punctuated sequence.
225 pub fn insert(&mut self, index: usize, value: T) {
226 assert!(index <= self.len());
227
228 if index == self.len() {
229 self.push(value);
230 } else {
231 self.inner.insert(index, (value, Some(Default::default())));
232 }
233 }
David Tolnaya0834b42018-01-01 21:30:02 -0800234}
235
Nika Layzelld73a3652017-10-24 08:57:05 -0400236#[cfg(feature = "extra-traits")]
David Tolnayf2cfd722017-12-31 18:02:51 -0500237impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
Nika Layzelld73a3652017-10-24 08:57:05 -0400238 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
239 self.inner.fmt(f)
240 }
241}
242
David Tolnay9ef24bc2018-01-09 10:43:55 -0800243impl<T, P> FromIterator<T> for Punctuated<T, P>
244where
245 P: Default,
246{
247 fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
248 let mut ret = Punctuated::new();
249 ret.extend(i);
250 ret
251 }
252}
253
254impl<T, P> Extend<T> for Punctuated<T, P>
255where
256 P: Default,
257{
258 fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
259 for value in i {
260 self.push(value);
261 }
262 }
263}
264
David Tolnay56080682018-01-06 14:01:52 -0800265impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> {
266 fn from_iter<I: IntoIterator<Item = Pair<T, P>>>(i: I) -> Self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500267 let mut ret = Punctuated::new();
Alex Crichton24f12822017-07-14 07:15:32 -0700268 ret.extend(i);
Alex Crichton954046c2017-05-30 21:49:42 -0700269 ret
270 }
271}
272
David Tolnay56080682018-01-06 14:01:52 -0800273impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P> {
274 fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) {
275 for pair in i {
276 match pair {
277 Pair::Punctuated(a, b) => self.inner.push((a, Some(b))),
278 Pair::End(a) => self.inner.push((a, None)),
Alex Crichton24f12822017-07-14 07:15:32 -0700279 }
280 }
281 }
282}
283
David Tolnayf2cfd722017-12-31 18:02:51 -0500284impl<T, P> IntoIterator for Punctuated<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800285 type Item = T;
David Tolnayf2cfd722017-12-31 18:02:51 -0500286 type IntoIter = IntoIter<T, P>;
Alex Crichton954046c2017-05-30 21:49:42 -0700287
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500288 fn into_iter(self) -> Self::IntoIter {
David Tolnay51382052017-12-27 13:46:21 -0500289 IntoIter {
290 inner: self.inner.into_iter(),
291 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700292 }
293}
294
David Tolnay6eff4da2018-01-01 20:27:45 -0800295impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
296 type Item = &'a T;
David Tolnay8095c302018-03-31 19:34:17 +0200297 type IntoIter = Iter<'a, T>;
David Tolnay6eff4da2018-01-01 20:27:45 -0800298
299 fn into_iter(self) -> Self::IntoIter {
300 Punctuated::iter(self)
301 }
302}
303
David Tolnaya0834b42018-01-01 21:30:02 -0800304impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
305 type Item = &'a mut T;
David Tolnay8095c302018-03-31 19:34:17 +0200306 type IntoIter = IterMut<'a, T>;
David Tolnaya0834b42018-01-01 21:30:02 -0800307
308 fn into_iter(self) -> Self::IntoIter {
309 Punctuated::iter_mut(self)
310 }
311}
312
David Tolnayf2cfd722017-12-31 18:02:51 -0500313impl<T, P> Default for Punctuated<T, P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700314 fn default() -> Self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500315 Punctuated::new()
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700316 }
317}
318
David Tolnayf3198012018-01-06 20:00:42 -0800319/// An iterator over borrowed pairs of type `Pair<&T, &P>`.
320///
321/// Refer to the [module documentation] for details about punctuated sequences.
322///
323/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800324pub struct Pairs<'a, T: 'a, P: 'a> {
David Tolnayf2cfd722017-12-31 18:02:51 -0500325 inner: slice::Iter<'a, (T, Option<P>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700326}
327
David Tolnay56080682018-01-06 14:01:52 -0800328impl<'a, T, P> Iterator for Pairs<'a, T, P> {
329 type Item = Pair<&'a T, &'a P>;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700330
David Tolnay6eff4da2018-01-01 20:27:45 -0800331 fn next(&mut self) -> Option<Self::Item> {
David Tolnay51382052017-12-27 13:46:21 -0500332 self.inner.next().map(|pair| match pair.1 {
David Tolnay56080682018-01-06 14:01:52 -0800333 Some(ref p) => Pair::Punctuated(&pair.0, p),
334 None => Pair::End(&pair.0),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700335 })
336 }
337}
338
David Tolnayf3198012018-01-06 20:00:42 -0800339/// An iterator over mutably borrowed pairs of type `Pair<&mut T, &mut P>`.
340///
341/// Refer to the [module documentation] for details about punctuated sequences.
342///
343/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800344pub struct PairsMut<'a, T: 'a, P: 'a> {
David Tolnayf2cfd722017-12-31 18:02:51 -0500345 inner: slice::IterMut<'a, (T, Option<P>)>,
Alex Crichton164c5332017-07-06 13:18:34 -0700346}
347
David Tolnay56080682018-01-06 14:01:52 -0800348impl<'a, T, P> Iterator for PairsMut<'a, T, P> {
349 type Item = Pair<&'a mut T, &'a mut P>;
Alex Crichton164c5332017-07-06 13:18:34 -0700350
David Tolnay6eff4da2018-01-01 20:27:45 -0800351 fn next(&mut self) -> Option<Self::Item> {
David Tolnay51382052017-12-27 13:46:21 -0500352 self.inner.next().map(|pair| match pair.1 {
David Tolnay56080682018-01-06 14:01:52 -0800353 Some(ref mut p) => Pair::Punctuated(&mut pair.0, p),
354 None => Pair::End(&mut pair.0),
Alex Crichton164c5332017-07-06 13:18:34 -0700355 })
356 }
357}
358
David Tolnayf3198012018-01-06 20:00:42 -0800359/// An iterator over owned pairs of type `Pair<T, P>`.
360///
361/// Refer to the [module documentation] for details about punctuated sequences.
362///
363/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800364pub struct IntoPairs<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800365 inner: vec::IntoIter<(T, Option<P>)>,
366}
367
David Tolnay56080682018-01-06 14:01:52 -0800368impl<T, P> Iterator for IntoPairs<T, P> {
369 type Item = Pair<T, P>;
David Tolnay6eff4da2018-01-01 20:27:45 -0800370
371 fn next(&mut self) -> Option<Self::Item> {
372 self.inner.next().map(|pair| match pair.1 {
David Tolnay56080682018-01-06 14:01:52 -0800373 Some(p) => Pair::Punctuated(pair.0, p),
374 None => Pair::End(pair.0),
David Tolnay6eff4da2018-01-01 20:27:45 -0800375 })
376 }
377}
378
David Tolnayf3198012018-01-06 20:00:42 -0800379/// An iterator over owned values of type `T`.
380///
381/// Refer to the [module documentation] for details about punctuated sequences.
382///
383/// [module documentation]: index.html
David Tolnayf2cfd722017-12-31 18:02:51 -0500384pub struct IntoIter<T, P> {
385 inner: vec::IntoIter<(T, Option<P>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700386}
387
David Tolnayf2cfd722017-12-31 18:02:51 -0500388impl<T, P> Iterator for IntoIter<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800389 type Item = T;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700390
David Tolnay6eff4da2018-01-01 20:27:45 -0800391 fn next(&mut self) -> Option<Self::Item> {
392 self.inner.next().map(|pair| pair.0)
393 }
394}
395
David Tolnayf3198012018-01-06 20:00:42 -0800396/// An iterator over borrowed values of type `&T`.
397///
398/// Refer to the [module documentation] for details about punctuated sequences.
399///
400/// [module documentation]: index.html
David Tolnay8095c302018-03-31 19:34:17 +0200401pub struct Iter<'a, T: 'a> {
402 inner: Box<Iterator<Item = &'a T> + 'a>,
403}
404
405struct PrivateIter<'a, T: 'a, P: 'a> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800406 inner: slice::Iter<'a, (T, Option<P>)>,
407}
408
David Tolnay96a09d92018-01-16 22:24:03 -0800409#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay8095c302018-03-31 19:34:17 +0200410impl<'a, T> Iter<'a, T> {
David Tolnay96a09d92018-01-16 22:24:03 -0800411 // Not public API.
412 #[doc(hidden)]
413 pub fn private_empty() -> Self {
414 Iter {
David Tolnay8095c302018-03-31 19:34:17 +0200415 inner: Box::new(iter::empty()),
David Tolnay96a09d92018-01-16 22:24:03 -0800416 }
417 }
418}
419
David Tolnay8095c302018-03-31 19:34:17 +0200420impl<'a, T> Iterator for Iter<'a, T> {
421 type Item = &'a T;
422
423 fn next(&mut self) -> Option<Self::Item> {
424 self.inner.next()
425 }
426}
427
428impl<'a, T, P> Iterator for PrivateIter<'a, T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800429 type Item = &'a T;
430
431 fn next(&mut self) -> Option<Self::Item> {
432 self.inner.next().map(|pair| &pair.0)
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700433 }
434}
435
David Tolnayf3198012018-01-06 20:00:42 -0800436/// An iterator over mutably borrowed values of type `&mut T`.
437///
438/// Refer to the [module documentation] for details about punctuated sequences.
439///
440/// [module documentation]: index.html
David Tolnay8095c302018-03-31 19:34:17 +0200441pub struct IterMut<'a, T: 'a> {
442 inner: Box<Iterator<Item = &'a mut T> + 'a>,
443}
444
445struct PrivateIterMut<'a, T: 'a, P: 'a> {
David Tolnaya0834b42018-01-01 21:30:02 -0800446 inner: slice::IterMut<'a, (T, Option<P>)>,
447}
448
David Tolnay8095c302018-03-31 19:34:17 +0200449impl<'a, T> Iterator for IterMut<'a, T> {
450 type Item = &'a mut T;
451
452 fn next(&mut self) -> Option<Self::Item> {
453 self.inner.next()
454 }
455}
456
457impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> {
David Tolnaya0834b42018-01-01 21:30:02 -0800458 type Item = &'a mut T;
459
460 fn next(&mut self) -> Option<Self::Item> {
461 self.inner.next().map(|pair| &mut pair.0)
462 }
463}
464
David Tolnayf3198012018-01-06 20:00:42 -0800465/// A single syntax tree node of type `T` followed by its trailing punctuation
466/// of type `P` if any.
467///
468/// Refer to the [module documentation] for details about punctuated sequences.
469///
470/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800471pub enum Pair<T, P> {
David Tolnayf2cfd722017-12-31 18:02:51 -0500472 Punctuated(T, P),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700473 End(T),
474}
475
David Tolnay56080682018-01-06 14:01:52 -0800476impl<T, P> Pair<T, P> {
David Tolnayf3198012018-01-06 20:00:42 -0800477 /// Extracts the syntax tree node from this punctuated pair, discarding the
478 /// following punctuation.
David Tolnay56080682018-01-06 14:01:52 -0800479 pub fn into_value(self) -> T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700480 match self {
David Tolnay56080682018-01-06 14:01:52 -0800481 Pair::Punctuated(t, _) | Pair::End(t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700482 }
483 }
484
David Tolnayf3198012018-01-06 20:00:42 -0800485 /// Borrows the syntax tree node from this punctuated pair.
David Tolnay56080682018-01-06 14:01:52 -0800486 pub fn value(&self) -> &T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700487 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800488 Pair::Punctuated(ref t, _) | Pair::End(ref t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700489 }
490 }
491
David Tolnayf3198012018-01-06 20:00:42 -0800492 /// Mutably borrows the syntax tree node from this punctuated pair.
David Tolnay56080682018-01-06 14:01:52 -0800493 pub fn value_mut(&mut self) -> &mut T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700494 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800495 Pair::Punctuated(ref mut t, _) | Pair::End(ref mut t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700496 }
497 }
498
David Tolnayf3198012018-01-06 20:00:42 -0800499 /// Borrows the punctuation from this punctuated pair, unless this pair is
500 /// the final one and there is no trailing punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500501 pub fn punct(&self) -> Option<&P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700502 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800503 Pair::Punctuated(_, ref d) => Some(d),
504 Pair::End(_) => None,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700505 }
506 }
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400507
David Tolnayf3198012018-01-06 20:00:42 -0800508 /// Creates a punctuated pair out of a syntax tree node and an optional
509 /// following punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500510 pub fn new(t: T, d: Option<P>) -> Self {
David Tolnay660fd1f2017-12-31 01:52:57 -0500511 match d {
David Tolnay56080682018-01-06 14:01:52 -0800512 Some(d) => Pair::Punctuated(t, d),
513 None => Pair::End(t),
David Tolnay660fd1f2017-12-31 01:52:57 -0500514 }
515 }
516
David Tolnayf3198012018-01-06 20:00:42 -0800517 /// Produces this punctuated pair as a tuple of syntax tree node and
518 /// optional following punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500519 pub fn into_tuple(self) -> (T, Option<P>) {
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400520 match self {
David Tolnay56080682018-01-06 14:01:52 -0800521 Pair::Punctuated(t, d) => (t, Some(d)),
522 Pair::End(t) => (t, None),
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400523 }
524 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700525}
526
David Tolnaybb987132018-01-08 13:51:19 -0800527impl<T, P> Index<usize> for Punctuated<T, P> {
528 type Output = T;
529
530 fn index(&self, index: usize) -> &Self::Output {
531 &self.inner[index].0
532 }
533}
534
535impl<T, P> IndexMut<usize> for Punctuated<T, P> {
536 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
537 &mut self.inner[index].0
538 }
539}
540
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700541#[cfg(feature = "parsing")]
David Tolnayf3198012018-01-06 20:00:42 -0800542impl<T, P> Punctuated<T, P>
543where
544 T: Synom,
545 P: Synom,
546{
547 /// Parse **zero or more** syntax tree nodes with punctuation in between and
548 /// **no trailing** punctuation.
549 pub fn parse_separated(input: Cursor) -> PResult<Self> {
550 Self::parse_separated_with(input, T::parse)
551 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700552
David Tolnayf3198012018-01-06 20:00:42 -0800553 /// Parse **one or more** syntax tree nodes with punctuation in bewteen and
554 /// **no trailing** punctuation.
555 /// allowing trailing punctuation.
556 pub fn parse_separated_nonempty(input: Cursor) -> PResult<Self> {
557 Self::parse_separated_nonempty_with(input, T::parse)
558 }
Alex Crichton954046c2017-05-30 21:49:42 -0700559
David Tolnayf3198012018-01-06 20:00:42 -0800560 /// Parse **zero or more** syntax tree nodes with punctuation in between and
561 /// **optional trailing** punctuation.
562 pub fn parse_terminated(input: Cursor) -> PResult<Self> {
563 Self::parse_terminated_with(input, T::parse)
564 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700565
David Tolnayf3198012018-01-06 20:00:42 -0800566 /// Parse **one or more** syntax tree nodes with punctuation in between and
567 /// **optional trailing** punctuation.
568 pub fn parse_terminated_nonempty(input: Cursor) -> PResult<Self> {
569 Self::parse_terminated_nonempty_with(input, T::parse)
570 }
571}
Nika Layzellb49a9e52017-12-05 13:31:52 -0500572
David Tolnayf3198012018-01-06 20:00:42 -0800573#[cfg(feature = "parsing")]
574impl<T, P> Punctuated<T, P>
575where
576 P: Synom,
577{
578 /// Parse **zero or more** syntax tree nodes using the given parser with
579 /// punctuation in between and **no trailing** punctuation.
580 pub fn parse_separated_with(
581 input: Cursor,
582 parse: fn(Cursor) -> PResult<T>,
583 ) -> PResult<Self> {
584 Self::parse(input, parse, false)
585 }
586
587 /// Parse **one or more** syntax tree nodes using the given parser with
588 /// punctuation in between and **no trailing** punctuation.
589 pub fn parse_separated_nonempty_with(
590 input: Cursor,
591 parse: fn(Cursor) -> PResult<T>,
592 ) -> PResult<Self> {
593 match Self::parse(input, parse, false) {
594 Ok((ref b, _)) if b.is_empty() => parse_error(),
595 other => other,
Nika Layzellb49a9e52017-12-05 13:31:52 -0500596 }
Alex Crichton954046c2017-05-30 21:49:42 -0700597 }
598
David Tolnayf3198012018-01-06 20:00:42 -0800599 /// Parse **zero or more** syntax tree nodes using the given parser with
600 /// punctuation in between and **optional trailing** punctuation.
601 pub fn parse_terminated_with(
602 input: Cursor,
603 parse: fn(Cursor) -> PResult<T>,
604 ) -> PResult<Self> {
605 Self::parse(input, parse, true)
606 }
607
608 /// Parse **one or more** syntax tree nodes using the given parser with
609 /// punctuation in between and **optional trailing** punctuation.
610 pub fn parse_terminated_nonempty_with(
611 input: Cursor,
612 parse: fn(Cursor) -> PResult<T>,
613 ) -> PResult<Self> {
614 match Self::parse(input, parse, true) {
615 Ok((ref b, _)) if b.is_empty() => parse_error(),
616 other => other,
David Tolnaydc03aec2017-12-30 01:54:18 -0500617 }
David Tolnayf3198012018-01-06 20:00:42 -0800618 }
David Tolnaydc03aec2017-12-30 01:54:18 -0500619
David Tolnayf3198012018-01-06 20:00:42 -0800620 fn parse(
621 mut input: Cursor,
622 parse: fn(Cursor) -> PResult<T>,
623 terminated: bool,
624 ) -> PResult<Self> {
625 let mut res = Punctuated::new();
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700626
David Tolnayf3198012018-01-06 20:00:42 -0800627 // get the first element
628 match parse(input) {
629 Err(_) => Ok((res, input)),
630 Ok((o, i)) => {
631 if i == input {
632 return parse_error();
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700633 }
David Tolnayf3198012018-01-06 20:00:42 -0800634 input = i;
635 res.push_value(o);
636
637 // get the separator first
638 while let Ok((s, i2)) = P::parse(input) {
639 if i2 == input {
640 break;
641 }
642
643 // get the element next
644 if let Ok((o3, i3)) = parse(i2) {
645 if i3 == i2 {
646 break;
647 }
648 res.push_punct(s);
649 res.push_value(o3);
650 input = i3;
651 } else {
652 break;
653 }
654 }
655 if terminated {
656 if let Ok((sep, after)) = P::parse(input) {
657 res.push_punct(sep);
658 input = after;
659 }
660 }
661 Ok((res, input))
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700662 }
663 }
664 }
665}
666
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700667#[cfg(feature = "printing")]
668mod printing {
669 use super::*;
David Tolnay51382052017-12-27 13:46:21 -0500670 use quote::{ToTokens, Tokens};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700671
David Tolnayf2cfd722017-12-31 18:02:51 -0500672 impl<T, P> ToTokens for Punctuated<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500673 where
674 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500675 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700676 {
677 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay56080682018-01-06 14:01:52 -0800678 tokens.append_all(self.pairs())
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700679 }
680 }
681
David Tolnay56080682018-01-06 14:01:52 -0800682 impl<T, P> ToTokens for Pair<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500683 where
684 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500685 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700686 {
687 fn to_tokens(&self, tokens: &mut Tokens) {
688 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800689 Pair::Punctuated(ref a, ref b) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700690 a.to_tokens(tokens);
691 b.to_tokens(tokens);
692 }
David Tolnay56080682018-01-06 14:01:52 -0800693 Pair::End(ref a) => a.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700694 }
695 }
696 }
697}