blob: 63d289e04606343bbf11498e4149f24700f80a15 [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 Tolnay6c0a6092018-03-31 22:47:39 +020030#[cfg(any(feature = "full", feature = "derive"))]
31use std::iter;
32use std::iter::FromIterator;
David Tolnaybb987132018-01-08 13:51:19 -080033use std::ops::{Index, IndexMut};
Alex Crichtonccbb45d2017-05-23 10:58:24 -070034use std::slice;
35use std::vec;
Nika Layzelld73a3652017-10-24 08:57:05 -040036#[cfg(feature = "extra-traits")]
37use std::fmt::{self, Debug};
Alex Crichtonccbb45d2017-05-23 10:58:24 -070038
David Tolnayf3198012018-01-06 20:00:42 -080039#[cfg(feature = "parsing")]
40use synom::{Synom, PResult};
41#[cfg(feature = "parsing")]
42use buffer::Cursor;
43#[cfg(feature = "parsing")]
44use parse_error;
45
46/// A punctuated sequence of syntax tree nodes of type `T` separated by
47/// punctuation of type `P`.
48///
49/// Refer to the [module documentation] for details about punctuated sequences.
50///
51/// [module documentation]: index.html
Nika Layzelld73a3652017-10-24 08:57:05 -040052#[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash))]
Alex Crichton7b9e02f2017-05-30 15:54:33 -070053#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayf2cfd722017-12-31 18:02:51 -050054pub struct Punctuated<T, P> {
55 inner: Vec<(T, Option<P>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070056}
57
David Tolnayf2cfd722017-12-31 18:02:51 -050058impl<T, P> Punctuated<T, P> {
David Tolnayf3198012018-01-06 20:00:42 -080059 /// Creates an empty punctuated sequence.
David Tolnayf2cfd722017-12-31 18:02:51 -050060 pub fn new() -> Punctuated<T, P> {
61 Punctuated { inner: Vec::new() }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070062 }
63
David Tolnayf3198012018-01-06 20:00:42 -080064 /// Determines whether this punctuated sequence is empty, meaning it
65 /// contains no syntax tree nodes or punctuation.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070066 pub fn is_empty(&self) -> bool {
67 self.inner.len() == 0
68 }
69
David Tolnayf3198012018-01-06 20:00:42 -080070 /// Returns the number of syntax tree nodes in this punctuated sequence.
71 ///
72 /// This is the number of nodes of type `T`, not counting the punctuation of
73 /// type `P`.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070074 pub fn len(&self) -> usize {
75 self.inner.len()
76 }
77
David Tolnayf3198012018-01-06 20:00:42 -080078 /// Borrows the first punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080079 pub fn first(&self) -> Option<Pair<&T, &P>> {
David Tolnay51382052017-12-27 13:46:21 -050080 self.inner.first().map(|&(ref t, ref d)| match *d {
David Tolnay56080682018-01-06 14:01:52 -080081 Some(ref d) => Pair::Punctuated(t, d),
82 None => Pair::End(t),
Alex Crichton0aa50e02017-07-07 20:59:03 -070083 })
84 }
85
David Tolnayf3198012018-01-06 20:00:42 -080086 /// Borrows the last punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080087 pub fn last(&self) -> Option<Pair<&T, &P>> {
David Tolnay51382052017-12-27 13:46:21 -050088 self.inner.last().map(|&(ref t, ref d)| match *d {
David Tolnay56080682018-01-06 14:01:52 -080089 Some(ref d) => Pair::Punctuated(t, d),
90 None => Pair::End(t),
Alex Crichton0aa50e02017-07-07 20:59:03 -070091 })
92 }
93
David Tolnayf3198012018-01-06 20:00:42 -080094 /// Mutably borrows the last punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080095 pub fn last_mut(&mut self) -> Option<Pair<&mut T, &mut P>> {
David Tolnay51382052017-12-27 13:46:21 -050096 self.inner
97 .last_mut()
98 .map(|&mut (ref mut t, ref mut d)| match *d {
David Tolnay56080682018-01-06 14:01:52 -080099 Some(ref mut d) => Pair::Punctuated(t, d),
100 None => Pair::End(t),
David Tolnay51382052017-12-27 13:46:21 -0500101 })
Alex Crichton0aa50e02017-07-07 20:59:03 -0700102 }
103
David Tolnayf3198012018-01-06 20:00:42 -0800104 /// Returns an iterator over borrowed syntax tree nodes of type `&T`.
David Tolnay8095c302018-03-31 19:34:17 +0200105 pub fn iter(&self) -> Iter<T> {
David Tolnay51382052017-12-27 13:46:21 -0500106 Iter {
David Tolnay8095c302018-03-31 19:34:17 +0200107 inner: Box::new(PrivateIter {
108 inner: self.inner.iter(),
109 }),
David Tolnay51382052017-12-27 13:46:21 -0500110 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700111 }
112
David Tolnayf3198012018-01-06 20:00:42 -0800113 /// Returns an iterator over mutably borrowed syntax tree nodes of type
114 /// `&mut T`.
David Tolnay8095c302018-03-31 19:34:17 +0200115 pub fn iter_mut(&mut self) -> IterMut<T> {
David Tolnaya0834b42018-01-01 21:30:02 -0800116 IterMut {
David Tolnay8095c302018-03-31 19:34:17 +0200117 inner: Box::new(PrivateIterMut {
118 inner: self.inner.iter_mut(),
119 }),
David Tolnaya0834b42018-01-01 21:30:02 -0800120 }
121 }
122
David Tolnayf3198012018-01-06 20:00:42 -0800123 /// Returns an iterator over the contents of this sequence as borrowed
124 /// punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800125 pub fn pairs(&self) -> Pairs<T, P> {
126 Pairs {
David Tolnay6eff4da2018-01-01 20:27:45 -0800127 inner: self.inner.iter(),
128 }
129 }
130
David Tolnayf3198012018-01-06 20:00:42 -0800131 /// Returns an iterator over the contents of this sequence as mutably
132 /// borrowed punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800133 pub fn pairs_mut(&mut self) -> PairsMut<T, P> {
134 PairsMut {
David Tolnay51382052017-12-27 13:46:21 -0500135 inner: self.inner.iter_mut(),
136 }
Alex Crichton164c5332017-07-06 13:18:34 -0700137 }
138
David Tolnayf3198012018-01-06 20:00:42 -0800139 /// Returns an iterator over the contents of this sequence as owned
140 /// punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800141 pub fn into_pairs(self) -> IntoPairs<T, P> {
142 IntoPairs {
David Tolnay6eff4da2018-01-01 20:27:45 -0800143 inner: self.inner.into_iter(),
144 }
145 }
146
David Tolnayf3198012018-01-06 20:00:42 -0800147 /// Appends a syntax tree node onto the end of this punctuated sequence. The
148 /// sequence must previously have a trailing punctuation.
149 ///
150 /// Use [`push`] instead if the punctuated sequence may or may not already
151 /// have trailing punctuation.
152 ///
153 /// [`push`]: #method.push
154 ///
155 /// # Panics
156 ///
157 /// Panics if the sequence does not already have a trailing punctuation when
158 /// this method is called.
David Tolnay56080682018-01-06 14:01:52 -0800159 pub fn push_value(&mut self, value: T) {
David Tolnaydc03aec2017-12-30 01:54:18 -0500160 assert!(self.empty_or_trailing());
David Tolnay56080682018-01-06 14:01:52 -0800161 self.inner.push((value, None));
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700162 }
163
David Tolnayf3198012018-01-06 20:00:42 -0800164 /// Appends a trailing punctuation onto the end of this punctuated sequence.
165 /// The sequence must be non-empty and must not already have trailing
166 /// punctuation.
167 ///
168 /// # Panics
169 ///
170 /// Panics if the sequence is empty or already has a trailing punctuation.
David Tolnaya0834b42018-01-01 21:30:02 -0800171 pub fn push_punct(&mut self, punctuation: P) {
David Tolnay660fd1f2017-12-31 01:52:57 -0500172 assert!(!self.is_empty());
173 let last = self.inner.last_mut().unwrap();
174 assert!(last.1.is_none());
David Tolnayf2cfd722017-12-31 18:02:51 -0500175 last.1 = Some(punctuation);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700176 }
177
David Tolnayf3198012018-01-06 20:00:42 -0800178 /// Removes the last punctuated pair from this sequence, or `None` if the
179 /// sequence is empty.
David Tolnay56080682018-01-06 14:01:52 -0800180 pub fn pop(&mut self) -> Option<Pair<T, P>> {
181 self.inner.pop().map(|(t, d)| Pair::new(t, d))
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700182 }
183
David Tolnayf3198012018-01-06 20:00:42 -0800184 /// Determines whether this punctuated sequence ends with a trailing
185 /// punctuation.
David Tolnaya0834b42018-01-01 21:30:02 -0800186 pub fn trailing_punct(&self) -> bool {
David Tolnay61037c62018-01-05 16:21:03 -0800187 self.inner
188 .last()
189 .map(|last| last.1.is_some())
190 .unwrap_or(false)
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700191 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400192
David Tolnayf2cfd722017-12-31 18:02:51 -0500193 /// Returns true if either this `Punctuated` is empty, or it has a trailing
194 /// punctuation.
David Tolnaydc03aec2017-12-30 01:54:18 -0500195 ///
David Tolnaya0834b42018-01-01 21:30:02 -0800196 /// Equivalent to `punctuated.is_empty() || punctuated.trailing_punct()`.
Michael Layzell3936ceb2017-07-08 00:28:36 -0400197 pub fn empty_or_trailing(&self) -> bool {
David Tolnay61037c62018-01-05 16:21:03 -0800198 self.inner
199 .last()
200 .map(|last| last.1.is_some())
201 .unwrap_or(true)
Michael Layzell3936ceb2017-07-08 00:28:36 -0400202 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700203}
204
David Tolnaya0834b42018-01-01 21:30:02 -0800205impl<T, P> Punctuated<T, P>
206where
207 P: Default,
208{
David Tolnayf3198012018-01-06 20:00:42 -0800209 /// Appends a syntax tree node onto the end of this punctuated sequence.
210 ///
211 /// If there is not a trailing punctuation in this sequence when this method
212 /// is called, the default value of punctuation type `P` is inserted before
213 /// the given value of type `T`.
David Tolnay56080682018-01-06 14:01:52 -0800214 pub fn push(&mut self, value: T) {
David Tolnaya0834b42018-01-01 21:30:02 -0800215 if !self.empty_or_trailing() {
216 self.push_punct(Default::default());
217 }
David Tolnay56080682018-01-06 14:01:52 -0800218 self.push_value(value);
David Tolnaya0834b42018-01-01 21:30:02 -0800219 }
David Tolnayb77d1802018-01-11 16:18:35 -0800220
221 /// Inserts an element at position `index`.
222 ///
223 /// # Panics
224 ///
225 /// Panics if `index` is greater than the number of elements previously in
226 /// this punctuated sequence.
227 pub fn insert(&mut self, index: usize, value: T) {
228 assert!(index <= self.len());
229
230 if index == self.len() {
231 self.push(value);
232 } else {
233 self.inner.insert(index, (value, Some(Default::default())));
234 }
235 }
David Tolnaya0834b42018-01-01 21:30:02 -0800236}
237
Nika Layzelld73a3652017-10-24 08:57:05 -0400238#[cfg(feature = "extra-traits")]
David Tolnayf2cfd722017-12-31 18:02:51 -0500239impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
Nika Layzelld73a3652017-10-24 08:57:05 -0400240 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
241 self.inner.fmt(f)
242 }
243}
244
David Tolnay9ef24bc2018-01-09 10:43:55 -0800245impl<T, P> FromIterator<T> for Punctuated<T, P>
246where
247 P: Default,
248{
249 fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
250 let mut ret = Punctuated::new();
251 ret.extend(i);
252 ret
253 }
254}
255
256impl<T, P> Extend<T> for Punctuated<T, P>
257where
258 P: Default,
259{
260 fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
261 for value in i {
262 self.push(value);
263 }
264 }
265}
266
David Tolnay56080682018-01-06 14:01:52 -0800267impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> {
268 fn from_iter<I: IntoIterator<Item = Pair<T, P>>>(i: I) -> Self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500269 let mut ret = Punctuated::new();
Alex Crichton24f12822017-07-14 07:15:32 -0700270 ret.extend(i);
Alex Crichton954046c2017-05-30 21:49:42 -0700271 ret
272 }
273}
274
David Tolnay56080682018-01-06 14:01:52 -0800275impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P> {
276 fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) {
277 for pair in i {
278 match pair {
279 Pair::Punctuated(a, b) => self.inner.push((a, Some(b))),
280 Pair::End(a) => self.inner.push((a, None)),
Alex Crichton24f12822017-07-14 07:15:32 -0700281 }
282 }
283 }
284}
285
David Tolnayf2cfd722017-12-31 18:02:51 -0500286impl<T, P> IntoIterator for Punctuated<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800287 type Item = T;
David Tolnayf2cfd722017-12-31 18:02:51 -0500288 type IntoIter = IntoIter<T, P>;
Alex Crichton954046c2017-05-30 21:49:42 -0700289
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500290 fn into_iter(self) -> Self::IntoIter {
David Tolnay51382052017-12-27 13:46:21 -0500291 IntoIter {
292 inner: self.inner.into_iter(),
293 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700294 }
295}
296
David Tolnay6eff4da2018-01-01 20:27:45 -0800297impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
298 type Item = &'a T;
David Tolnay8095c302018-03-31 19:34:17 +0200299 type IntoIter = Iter<'a, T>;
David Tolnay6eff4da2018-01-01 20:27:45 -0800300
301 fn into_iter(self) -> Self::IntoIter {
302 Punctuated::iter(self)
303 }
304}
305
David Tolnaya0834b42018-01-01 21:30:02 -0800306impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
307 type Item = &'a mut T;
David Tolnay8095c302018-03-31 19:34:17 +0200308 type IntoIter = IterMut<'a, T>;
David Tolnaya0834b42018-01-01 21:30:02 -0800309
310 fn into_iter(self) -> Self::IntoIter {
311 Punctuated::iter_mut(self)
312 }
313}
314
David Tolnayf2cfd722017-12-31 18:02:51 -0500315impl<T, P> Default for Punctuated<T, P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700316 fn default() -> Self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500317 Punctuated::new()
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700318 }
319}
320
David Tolnayf3198012018-01-06 20:00:42 -0800321/// An iterator over borrowed pairs of type `Pair<&T, &P>`.
322///
323/// Refer to the [module documentation] for details about punctuated sequences.
324///
325/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800326pub struct Pairs<'a, T: 'a, P: 'a> {
David Tolnayf2cfd722017-12-31 18:02:51 -0500327 inner: slice::Iter<'a, (T, Option<P>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700328}
329
David Tolnay56080682018-01-06 14:01:52 -0800330impl<'a, T, P> Iterator for Pairs<'a, T, P> {
331 type Item = Pair<&'a T, &'a P>;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700332
David Tolnay6eff4da2018-01-01 20:27:45 -0800333 fn next(&mut self) -> Option<Self::Item> {
David Tolnay51382052017-12-27 13:46:21 -0500334 self.inner.next().map(|pair| match pair.1 {
David Tolnay56080682018-01-06 14:01:52 -0800335 Some(ref p) => Pair::Punctuated(&pair.0, p),
336 None => Pair::End(&pair.0),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700337 })
338 }
339}
340
David Tolnayf3198012018-01-06 20:00:42 -0800341/// An iterator over mutably borrowed pairs of type `Pair<&mut T, &mut P>`.
342///
343/// Refer to the [module documentation] for details about punctuated sequences.
344///
345/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800346pub struct PairsMut<'a, T: 'a, P: 'a> {
David Tolnayf2cfd722017-12-31 18:02:51 -0500347 inner: slice::IterMut<'a, (T, Option<P>)>,
Alex Crichton164c5332017-07-06 13:18:34 -0700348}
349
David Tolnay56080682018-01-06 14:01:52 -0800350impl<'a, T, P> Iterator for PairsMut<'a, T, P> {
351 type Item = Pair<&'a mut T, &'a mut P>;
Alex Crichton164c5332017-07-06 13:18:34 -0700352
David Tolnay6eff4da2018-01-01 20:27:45 -0800353 fn next(&mut self) -> Option<Self::Item> {
David Tolnay51382052017-12-27 13:46:21 -0500354 self.inner.next().map(|pair| match pair.1 {
David Tolnay56080682018-01-06 14:01:52 -0800355 Some(ref mut p) => Pair::Punctuated(&mut pair.0, p),
356 None => Pair::End(&mut pair.0),
Alex Crichton164c5332017-07-06 13:18:34 -0700357 })
358 }
359}
360
David Tolnayf3198012018-01-06 20:00:42 -0800361/// An iterator over owned pairs of type `Pair<T, P>`.
362///
363/// Refer to the [module documentation] for details about punctuated sequences.
364///
365/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800366pub struct IntoPairs<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800367 inner: vec::IntoIter<(T, Option<P>)>,
368}
369
David Tolnay56080682018-01-06 14:01:52 -0800370impl<T, P> Iterator for IntoPairs<T, P> {
371 type Item = Pair<T, P>;
David Tolnay6eff4da2018-01-01 20:27:45 -0800372
373 fn next(&mut self) -> Option<Self::Item> {
374 self.inner.next().map(|pair| match pair.1 {
David Tolnay56080682018-01-06 14:01:52 -0800375 Some(p) => Pair::Punctuated(pair.0, p),
376 None => Pair::End(pair.0),
David Tolnay6eff4da2018-01-01 20:27:45 -0800377 })
378 }
379}
380
David Tolnayf3198012018-01-06 20:00:42 -0800381/// An iterator over owned values of type `T`.
382///
383/// Refer to the [module documentation] for details about punctuated sequences.
384///
385/// [module documentation]: index.html
David Tolnayf2cfd722017-12-31 18:02:51 -0500386pub struct IntoIter<T, P> {
387 inner: vec::IntoIter<(T, Option<P>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700388}
389
David Tolnayf2cfd722017-12-31 18:02:51 -0500390impl<T, P> Iterator for IntoIter<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800391 type Item = T;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700392
David Tolnay6eff4da2018-01-01 20:27:45 -0800393 fn next(&mut self) -> Option<Self::Item> {
394 self.inner.next().map(|pair| pair.0)
395 }
396}
397
David Tolnayf3198012018-01-06 20:00:42 -0800398/// An iterator over borrowed values of type `&T`.
399///
400/// Refer to the [module documentation] for details about punctuated sequences.
401///
402/// [module documentation]: index.html
David Tolnay8095c302018-03-31 19:34:17 +0200403pub struct Iter<'a, T: 'a> {
404 inner: Box<Iterator<Item = &'a T> + 'a>,
405}
406
407struct PrivateIter<'a, T: 'a, P: 'a> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800408 inner: slice::Iter<'a, (T, Option<P>)>,
409}
410
David Tolnay96a09d92018-01-16 22:24:03 -0800411#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay8095c302018-03-31 19:34:17 +0200412impl<'a, T> Iter<'a, T> {
David Tolnay96a09d92018-01-16 22:24:03 -0800413 // Not public API.
414 #[doc(hidden)]
415 pub fn private_empty() -> Self {
416 Iter {
David Tolnay8095c302018-03-31 19:34:17 +0200417 inner: Box::new(iter::empty()),
David Tolnay96a09d92018-01-16 22:24:03 -0800418 }
419 }
420}
421
David Tolnay8095c302018-03-31 19:34:17 +0200422impl<'a, T> Iterator for Iter<'a, T> {
423 type Item = &'a T;
424
425 fn next(&mut self) -> Option<Self::Item> {
426 self.inner.next()
427 }
428}
429
430impl<'a, T, P> Iterator for PrivateIter<'a, T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800431 type Item = &'a T;
432
433 fn next(&mut self) -> Option<Self::Item> {
434 self.inner.next().map(|pair| &pair.0)
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700435 }
436}
437
David Tolnayf3198012018-01-06 20:00:42 -0800438/// An iterator over mutably borrowed values of type `&mut T`.
439///
440/// Refer to the [module documentation] for details about punctuated sequences.
441///
442/// [module documentation]: index.html
David Tolnay8095c302018-03-31 19:34:17 +0200443pub struct IterMut<'a, T: 'a> {
444 inner: Box<Iterator<Item = &'a mut T> + 'a>,
445}
446
447struct PrivateIterMut<'a, T: 'a, P: 'a> {
David Tolnaya0834b42018-01-01 21:30:02 -0800448 inner: slice::IterMut<'a, (T, Option<P>)>,
449}
450
David Tolnay8095c302018-03-31 19:34:17 +0200451impl<'a, T> Iterator for IterMut<'a, T> {
452 type Item = &'a mut T;
453
454 fn next(&mut self) -> Option<Self::Item> {
455 self.inner.next()
456 }
457}
458
459impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> {
David Tolnaya0834b42018-01-01 21:30:02 -0800460 type Item = &'a mut T;
461
462 fn next(&mut self) -> Option<Self::Item> {
463 self.inner.next().map(|pair| &mut pair.0)
464 }
465}
466
David Tolnayf3198012018-01-06 20:00:42 -0800467/// A single syntax tree node of type `T` followed by its trailing punctuation
468/// of type `P` if any.
469///
470/// Refer to the [module documentation] for details about punctuated sequences.
471///
472/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800473pub enum Pair<T, P> {
David Tolnayf2cfd722017-12-31 18:02:51 -0500474 Punctuated(T, P),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700475 End(T),
476}
477
David Tolnay56080682018-01-06 14:01:52 -0800478impl<T, P> Pair<T, P> {
David Tolnayf3198012018-01-06 20:00:42 -0800479 /// Extracts the syntax tree node from this punctuated pair, discarding the
480 /// following punctuation.
David Tolnay56080682018-01-06 14:01:52 -0800481 pub fn into_value(self) -> T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700482 match self {
David Tolnay56080682018-01-06 14:01:52 -0800483 Pair::Punctuated(t, _) | Pair::End(t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700484 }
485 }
486
David Tolnayf3198012018-01-06 20:00:42 -0800487 /// Borrows the syntax tree node from this punctuated pair.
David Tolnay56080682018-01-06 14:01:52 -0800488 pub fn value(&self) -> &T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700489 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800490 Pair::Punctuated(ref t, _) | Pair::End(ref t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700491 }
492 }
493
David Tolnayf3198012018-01-06 20:00:42 -0800494 /// Mutably borrows the syntax tree node from this punctuated pair.
David Tolnay56080682018-01-06 14:01:52 -0800495 pub fn value_mut(&mut self) -> &mut T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700496 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800497 Pair::Punctuated(ref mut t, _) | Pair::End(ref mut t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700498 }
499 }
500
David Tolnayf3198012018-01-06 20:00:42 -0800501 /// Borrows the punctuation from this punctuated pair, unless this pair is
502 /// the final one and there is no trailing punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500503 pub fn punct(&self) -> Option<&P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700504 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800505 Pair::Punctuated(_, ref d) => Some(d),
506 Pair::End(_) => None,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700507 }
508 }
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400509
David Tolnayf3198012018-01-06 20:00:42 -0800510 /// Creates a punctuated pair out of a syntax tree node and an optional
511 /// following punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500512 pub fn new(t: T, d: Option<P>) -> Self {
David Tolnay660fd1f2017-12-31 01:52:57 -0500513 match d {
David Tolnay56080682018-01-06 14:01:52 -0800514 Some(d) => Pair::Punctuated(t, d),
515 None => Pair::End(t),
David Tolnay660fd1f2017-12-31 01:52:57 -0500516 }
517 }
518
David Tolnayf3198012018-01-06 20:00:42 -0800519 /// Produces this punctuated pair as a tuple of syntax tree node and
520 /// optional following punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500521 pub fn into_tuple(self) -> (T, Option<P>) {
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400522 match self {
David Tolnay56080682018-01-06 14:01:52 -0800523 Pair::Punctuated(t, d) => (t, Some(d)),
524 Pair::End(t) => (t, None),
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400525 }
526 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700527}
528
David Tolnaybb987132018-01-08 13:51:19 -0800529impl<T, P> Index<usize> for Punctuated<T, P> {
530 type Output = T;
531
532 fn index(&self, index: usize) -> &Self::Output {
533 &self.inner[index].0
534 }
535}
536
537impl<T, P> IndexMut<usize> for Punctuated<T, P> {
538 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
539 &mut self.inner[index].0
540 }
541}
542
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700543#[cfg(feature = "parsing")]
David Tolnayf3198012018-01-06 20:00:42 -0800544impl<T, P> Punctuated<T, P>
545where
546 T: Synom,
547 P: Synom,
548{
549 /// Parse **zero or more** syntax tree nodes with punctuation in between and
550 /// **no trailing** punctuation.
551 pub fn parse_separated(input: Cursor) -> PResult<Self> {
552 Self::parse_separated_with(input, T::parse)
553 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700554
David Tolnayf3198012018-01-06 20:00:42 -0800555 /// Parse **one or more** syntax tree nodes with punctuation in bewteen and
556 /// **no trailing** punctuation.
557 /// allowing trailing punctuation.
558 pub fn parse_separated_nonempty(input: Cursor) -> PResult<Self> {
559 Self::parse_separated_nonempty_with(input, T::parse)
560 }
Alex Crichton954046c2017-05-30 21:49:42 -0700561
David Tolnayf3198012018-01-06 20:00:42 -0800562 /// Parse **zero or more** syntax tree nodes with punctuation in between and
563 /// **optional trailing** punctuation.
564 pub fn parse_terminated(input: Cursor) -> PResult<Self> {
565 Self::parse_terminated_with(input, T::parse)
566 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700567
David Tolnayf3198012018-01-06 20:00:42 -0800568 /// Parse **one or more** syntax tree nodes with punctuation in between and
569 /// **optional trailing** punctuation.
570 pub fn parse_terminated_nonempty(input: Cursor) -> PResult<Self> {
571 Self::parse_terminated_nonempty_with(input, T::parse)
572 }
573}
Nika Layzellb49a9e52017-12-05 13:31:52 -0500574
David Tolnayf3198012018-01-06 20:00:42 -0800575#[cfg(feature = "parsing")]
576impl<T, P> Punctuated<T, P>
577where
578 P: Synom,
579{
580 /// Parse **zero or more** syntax tree nodes using the given parser with
581 /// punctuation in between and **no trailing** punctuation.
582 pub fn parse_separated_with(
583 input: Cursor,
584 parse: fn(Cursor) -> PResult<T>,
585 ) -> PResult<Self> {
586 Self::parse(input, parse, false)
587 }
588
589 /// Parse **one or more** syntax tree nodes using the given parser with
590 /// punctuation in between and **no trailing** punctuation.
591 pub fn parse_separated_nonempty_with(
592 input: Cursor,
593 parse: fn(Cursor) -> PResult<T>,
594 ) -> PResult<Self> {
595 match Self::parse(input, parse, false) {
596 Ok((ref b, _)) if b.is_empty() => parse_error(),
597 other => other,
Nika Layzellb49a9e52017-12-05 13:31:52 -0500598 }
Alex Crichton954046c2017-05-30 21:49:42 -0700599 }
600
David Tolnayf3198012018-01-06 20:00:42 -0800601 /// Parse **zero or more** syntax tree nodes using the given parser with
602 /// punctuation in between and **optional trailing** punctuation.
603 pub fn parse_terminated_with(
604 input: Cursor,
605 parse: fn(Cursor) -> PResult<T>,
606 ) -> PResult<Self> {
607 Self::parse(input, parse, true)
608 }
609
610 /// Parse **one or more** syntax tree nodes using the given parser with
611 /// punctuation in between and **optional trailing** punctuation.
612 pub fn parse_terminated_nonempty_with(
613 input: Cursor,
614 parse: fn(Cursor) -> PResult<T>,
615 ) -> PResult<Self> {
616 match Self::parse(input, parse, true) {
617 Ok((ref b, _)) if b.is_empty() => parse_error(),
618 other => other,
David Tolnaydc03aec2017-12-30 01:54:18 -0500619 }
David Tolnayf3198012018-01-06 20:00:42 -0800620 }
David Tolnaydc03aec2017-12-30 01:54:18 -0500621
David Tolnayf3198012018-01-06 20:00:42 -0800622 fn parse(
623 mut input: Cursor,
624 parse: fn(Cursor) -> PResult<T>,
625 terminated: bool,
626 ) -> PResult<Self> {
627 let mut res = Punctuated::new();
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700628
David Tolnayf3198012018-01-06 20:00:42 -0800629 // get the first element
630 match parse(input) {
631 Err(_) => Ok((res, input)),
632 Ok((o, i)) => {
633 if i == input {
634 return parse_error();
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700635 }
David Tolnayf3198012018-01-06 20:00:42 -0800636 input = i;
637 res.push_value(o);
638
639 // get the separator first
640 while let Ok((s, i2)) = P::parse(input) {
641 if i2 == input {
642 break;
643 }
644
645 // get the element next
646 if let Ok((o3, i3)) = parse(i2) {
647 if i3 == i2 {
648 break;
649 }
650 res.push_punct(s);
651 res.push_value(o3);
652 input = i3;
653 } else {
654 break;
655 }
656 }
657 if terminated {
658 if let Ok((sep, after)) = P::parse(input) {
659 res.push_punct(sep);
660 input = after;
661 }
662 }
663 Ok((res, input))
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700664 }
665 }
666 }
667}
668
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700669#[cfg(feature = "printing")]
670mod printing {
671 use super::*;
David Tolnay51382052017-12-27 13:46:21 -0500672 use quote::{ToTokens, Tokens};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700673
David Tolnayf2cfd722017-12-31 18:02:51 -0500674 impl<T, P> ToTokens for Punctuated<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500675 where
676 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500677 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700678 {
679 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay56080682018-01-06 14:01:52 -0800680 tokens.append_all(self.pairs())
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700681 }
682 }
683
David Tolnay56080682018-01-06 14:01:52 -0800684 impl<T, P> ToTokens for Pair<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500685 where
686 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500687 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700688 {
689 fn to_tokens(&self, tokens: &mut Tokens) {
690 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800691 Pair::Punctuated(ref a, ref b) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700692 a.to_tokens(tokens);
693 b.to_tokens(tokens);
694 }
David Tolnay56080682018-01-06 14:01:52 -0800695 Pair::End(ref a) => a.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700696 }
697 }
698 }
699}