1use crate::{
2 Error, IntoTokens, Parse, Parser, ToTokenStream, TokenStream, TokenTree, TokenTreeExt,
3};
4use std::{marker::PhantomData, ops::Deref};
5
6#[derive(Clone, Default, Debug)]
8pub struct Punctuated<M, D>(Vec<(M, Option<D>)>);
9
10impl<M, D> Punctuated<M, D> {
11 #[inline]
13 pub const fn new() -> Self {
14 Self(Vec::new())
15 }
16
17 #[inline]
19 pub fn as_slice(&self) -> &[(M, Option<D>)] {
20 &self.0
21 }
22}
23
24impl<M, D> Deref for Punctuated<M, D> {
25 type Target = [(M, Option<D>)];
26
27 #[inline]
28 fn deref(&self) -> &Self::Target {
29 &self.0
30 }
31}
32
33impl<M, D> IntoIterator for Punctuated<M, D> {
34 type Item = (M, Option<D>);
35 type IntoIter = <Vec<(M, Option<D>)> as IntoIterator>::IntoIter;
36
37 #[inline]
38 fn into_iter(self) -> Self::IntoIter {
39 self.0.into_iter()
40 }
41}
42
43impl<T: TokenTreeExt, M: Parse<T>, D: Parse<T>> Parse<T> for Punctuated<M, D> {
44 #[inline]
45 fn parse(buf: &mut &crate::TokenBuf<T>) -> Result<Self, Error<T::Span>> {
46 punctuated(M::parser(), D::parser()).parse(buf)
47 }
48}
49
50impl<T: TokenTree, M: IntoTokens<T>, D: IntoTokens<T>> IntoTokens<T> for Punctuated<M, D> {
51 #[inline]
52 fn into_tokens(self) -> impl Iterator<Item = T>
53 where
54 Self: Sized,
55 {
56 self.0.into_iter().flat_map(|i| i.into_tokens())
57 }
58}
59
60impl<T: TokenStream, M: ToTokenStream<T>, D: ToTokenStream<T>> ToTokenStream<T>
61 for Punctuated<M, D>
62{
63 #[inline]
64 fn extend_token_stream(&self, token_stream: &mut T) {
65 for (m, d) in self.0.iter() {
66 m.extend_token_stream(token_stream);
67 d.extend_token_stream(token_stream);
68 }
69 }
70}
71
72#[derive(Clone, Debug)]
74pub struct PunctuatedParser<T: TokenTree, M, D>(M, D, PhantomData<fn() -> T>);
75
76impl<T: TokenTreeExt, M: Parser<T>, D: Parser<T>> PunctuatedParser<T, M, D> {
77 #[inline]
80 pub const fn new(main: M, delim: D) -> Self {
81 Self(main, delim, PhantomData)
82 }
83}
84
85impl<T: TokenTreeExt, M: Parser<T>, D: Parser<T>> Parser<T> for PunctuatedParser<T, M, D> {
86 type Output<'p, 'b> = Punctuated<M::Output<'p, 'b>, D::Output<'p, 'b>> where Self: 'p;
87
88 #[inline]
89 fn parse<'p, 'b>(
90 &'p self,
91 buf: &mut &'b crate::TokenBuf<T>,
92 ) -> Result<Self::Output<'p, 'b>, Error<T::Span>> {
93 let mut vec = Vec::new();
94 let main = self.0.parse(buf)?;
95 let delim = self.1.parse(buf).ok();
96 let got_delim = delim.is_some();
97 vec.push((main, delim));
98 if got_delim {
99 while let Ok(main) = self.0.parse(buf) {
100 let delim = self.1.parse(buf).ok();
101 let got_delim = delim.is_some();
102 vec.push((main, delim));
103 if !got_delim {
104 break;
105 }
106 }
107 }
108 Ok(Punctuated(vec))
109 }
110}
111
112#[inline]
115pub const fn punctuated<T: TokenTreeExt, M: Parser<T>, D: Parser<T>>(
116 main: M,
117 delim: D,
118) -> PunctuatedParser<T, M, D> {
119 PunctuatedParser::new(main, delim)
120}