unsynn/
transform.rs

1//! This module contains the transforming parsers. This are the parsers that add, remove,
2//! replace or reorder Tokens while parsing.
3//!
4//! **Note**: When the `proc_macro2` feature is disabled, `IntoIdent<T>` is not available
5//! because it requires parsing from strings (`&str.into_token_iter()`) which is only
6//! available with `proc_macro2`.
7
8#[allow(clippy::wildcard_imports)]
9use crate::*;
10
11use std::marker::PhantomData;
12use std::ops::Deref;
13
14/// Succeeds when the next token matches `T`. The token will be removed from the stream but not stored.
15/// Consequently the `ToTokens` implementations will panic with a message that it can not be emitted.
16/// This can only be used when a token should be present but not stored and never emitted.
17///
18/// # Example
19///
20/// ```
21/// # use unsynn::*;
22/// let mut token_iter = "ident ()".to_token_iter();
23///
24/// let _ = Discard::<Ident>::parse(&mut token_iter).unwrap();
25/// assert!(ParenthesisGroup::parse(&mut token_iter).is_ok());
26/// ```
27#[derive(Clone)]
28pub struct Discard<T>(PhantomData<T>);
29
30impl<T: Parse> Parser for Discard<T> {
31    fn parser(tokens: &mut TokenIter) -> Result<Self> {
32        match T::parser(tokens).refine_err::<Self>() {
33            Ok(_) => Ok(Self(PhantomData)),
34            Err(e) => Err(e),
35        }
36    }
37}
38
39impl<T> ToTokens for Discard<T> {
40    #[inline]
41    #[mutants::skip]
42    fn to_tokens(&self, _tokens: &mut TokenStream) {
43        unimplemented!("Can not emit tokens for Discard<T>")
44    }
45}
46
47#[mutants::skip]
48impl<T: std::fmt::Debug> std::fmt::Debug for Discard<T> {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        f.debug_struct(&format!("Discard<{}>", std::any::type_name::<T>()))
51            .finish()
52    }
53}
54
55/// Skips over expected tokens. Will parse and consume the tokens but not store them.
56/// Consequently the `ToTokens` implementations will not output any tokens.
57///
58/// # Example
59///
60/// ```
61/// # use unsynn::*;
62/// let mut token_iter = "ident,".to_token_iter();
63///
64/// let _ = Skip::<Cons<Ident, Comma>>::parse_all(&mut token_iter).unwrap();
65/// ```
66#[derive(Clone)]
67pub struct Skip<T>(PhantomData<T>);
68
69impl<T: Parse> Parser for Skip<T> {
70    fn parser(tokens: &mut TokenIter) -> Result<Self> {
71        T::parser(tokens).refine_err::<Self>()?;
72        Ok(Self(PhantomData))
73    }
74}
75
76impl<T> ToTokens for Skip<T> {
77    #[inline]
78    fn to_tokens(&self, _tokens: &mut TokenStream) {
79        /*NOP*/
80    }
81}
82
83#[mutants::skip]
84impl<T: std::fmt::Debug> std::fmt::Debug for Skip<T> {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        f.debug_struct(&format!("Skip<{}>", std::any::type_name::<T>()))
87            .finish()
88    }
89}
90
91/// Injects tokens without parsing anything.
92///
93/// # Example
94///
95/// ```
96/// # use unsynn::*;
97/// let mut token_iter = "foo bar".to_token_iter();
98///
99/// let parsed = <Cons<Ident, Insert<Plus>, Ident>>::parser(&mut token_iter).unwrap();
100/// assert_tokens_eq!(parsed, "foo + bar");
101/// ```
102pub struct Insert<T>(pub T);
103
104impl<T: Default> Parser for Insert<T> {
105    #[inline]
106    fn parser(_tokens: &mut TokenIter) -> Result<Self> {
107        Ok(Self(T::default()))
108    }
109}
110
111impl<T: ToTokens> ToTokens for Insert<T> {
112    #[inline]
113    fn to_tokens(&self, tokens: &mut TokenStream) {
114        self.0.to_tokens(tokens);
115    }
116}
117
118impl<T> Deref for Insert<T> {
119    type Target = T;
120    fn deref(&self) -> &Self::Target {
121        &self.0
122    }
123}
124
125#[mutants::skip]
126impl<T: std::fmt::Debug> std::fmt::Debug for Insert<T> {
127    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128        f.debug_tuple(&format!("Insert<{}>", std::any::type_name::<T>()))
129            .field(&self.0)
130            .finish()
131    }
132}
133
134/// Tries to parse a `T` or inserts a `D` when that fails.
135///
136/// # Example
137///
138/// ```
139/// # use unsynn::*;
140/// let mut token_iter = "foo".to_token_iter();
141///
142/// let parsed = <OrDefault<u32, Question>>::parser(&mut token_iter).unwrap();
143/// assert_tokens_eq!(parsed, "?");
144/// ```
145pub type OrDefault<T, D = T> = Either<T, Insert<D>>;
146
147/// Parse-skip a `T` and inserts a `U: Default` in place. This is a zero sized type.
148pub type Replace<T, U> = Cons<Skip<T>, Insert<U>>;
149
150/// Parse a `T` and replace it with its default value. This is a zero sized type.  It can be
151/// used for no allocation replacement elements in a `Vec` since it has a optimization for
152/// zero-sized-types where it wont allocate any memory but just act as counter then.
153///
154/// # Example
155///
156/// ```
157/// # use unsynn::*;
158/// let mut token_iter = "..........".to_token_iter();
159///
160/// let parsed = <Vec<AsDefault<Dot>>>::parser(&mut token_iter).unwrap();
161/// assert_eq!(parsed.len(), 10);
162/// // Vec's ZST optimization at work:
163/// assert_eq!(parsed.capacity(), usize::MAX);
164/// assert_tokens_eq!(parsed, ". . . . . . . . . .");
165/// ```
166pub type AsDefault<T> = Replace<T, T>;
167
168/// Swaps the order of two entities.
169///
170/// # Example
171///
172/// ```
173/// # use unsynn::*;
174/// let mut token_iter = "foo bar".to_token_iter();
175///
176/// let parsed = <Swap<Ident, Ident>>::parser(&mut token_iter).unwrap();
177/// assert_tokens_eq!(parsed, "bar foo");
178/// ```
179#[derive(Debug)]
180pub struct Swap<A, B>(pub B, pub A);
181
182impl<A: Parse, B: Parse> Parser for Swap<A, B> {
183    fn parser(tokens: &mut TokenIter) -> Result<Self> {
184        let a: A = tokens.parse()?;
185        let b: B = tokens.parse()?;
186        Ok(Self(b, a))
187    }
188}
189
190impl<A: ToTokens, B: ToTokens> ToTokens for Swap<A, B> {
191    #[inline]
192    fn to_tokens(&self, tokens: &mut TokenStream) {
193        self.0.to_tokens(tokens);
194        self.1.to_tokens(tokens);
195    }
196}
197
198/// Parses `T` and creates a `LiteralString` from it. When `T` implements `Default`, such as
199/// single string (non group) keywords, operators and `Const*` literals. It can be used to
200/// create `IntoLiteralString` on the fly.
201///
202///
203/// # Example
204///
205/// ```
206/// # use unsynn::*;
207/// let mut token_iter = "foo 123".to_token_iter();
208///
209/// let parsed = <IntoLiteralString<Cons<Ident, LiteralInteger>>>::parser(&mut token_iter).unwrap();
210/// assert_tokens_eq!(parsed, r#" "foo 123" "#);
211///
212/// keyword!{Foo = "foo"}
213/// let default = <IntoLiteralString<Cons<Foo, ConstInteger<1234>>>>::default();
214/// assert_tokens_eq!(default, r#" "foo 1234" "#);
215/// ```
216#[derive(Debug)]
217pub struct IntoLiteralString<T>(LiteralString, PhantomData<T>);
218
219impl<T: ToTokens> IntoLiteralString<T> {
220    /// Creates a `IntoLiteralString` from an AST.
221    ///
222    /// ```
223    /// # use unsynn::*;
224    /// let mut token_iter = "foo 123".to_token_iter();
225    ///
226    /// let parsed = <Cons<Ident, LiteralInteger>>::parser(&mut token_iter).unwrap();
227    /// let as_string = IntoLiteralString::from(&parsed);
228    ///
229    /// assert_eq!(as_string.as_str(), "foo 123");
230    /// ```
231    pub fn from(from: &T) -> Self {
232        Self(
233            LiteralString::from_str(from.tokens_to_string()),
234            PhantomData,
235        )
236    }
237}
238
239impl<T> IntoLiteralString<T> {
240    /// Returns the underlying `&str`without its surrounding quotes.
241    #[inline]
242    #[must_use]
243    pub fn as_str(&self) -> &str {
244        self.0.as_str()
245    }
246
247    /// Destructures `IntoLiteralString<T>` to get the inner `LiteralString`.
248    #[inline]
249    #[must_use]
250    pub fn into_inner(self) -> LiteralString {
251        self.0
252    }
253}
254
255impl<T: Parse + ToTokens> Parser for IntoLiteralString<T> {
256    fn parser(tokens: &mut TokenIter) -> Result<Self> {
257        Ok(Self(
258            LiteralString::from_str(tokens.parse::<T>()?.tokens_to_string()),
259            PhantomData,
260        ))
261    }
262}
263
264impl<T> ToTokens for IntoLiteralString<T> {
265    #[inline]
266    fn to_tokens(&self, tokens: &mut TokenStream) {
267        self.0.to_tokens(tokens);
268    }
269}
270
271impl<T: Default + ToTokens> Default for IntoLiteralString<T> {
272    fn default() -> Self {
273        Self(
274            LiteralString::from_str(T::default().tokens_to_string()),
275            PhantomData,
276        )
277    }
278}
279
280/// Parses `T` and concats all its elements to a single identifier by removing all characters
281/// that are not valid in identifiers.  When `T` implements `Default`, such as single string
282/// (non group) keywords, operators and `Const*` literals. Then it can be used to create
283/// `IntoIdentifier` on the fly. Note that construction may still fail when one tries to
284/// create a invalid identifier such as one starting with digits for example.
285///
286///
287/// # Example
288///
289/// ```
290/// # use unsynn::*;
291/// let mut token_iter = "foo 123".to_token_iter();
292///
293/// let parsed = <IntoIdent<Cons<Ident, LiteralInteger>>>::parser(&mut token_iter).unwrap();
294/// assert_tokens_eq!(parsed, "foo123");
295///
296/// keyword!{Foo = "foo"}
297/// let default = <IntoIdent<Cons<Foo, ConstInteger<1234>>>>::default();
298/// assert_tokens_eq!(default, "foo1234");
299/// ```
300#[cfg(feature = "proc_macro2")]
301#[derive(Debug)]
302pub struct IntoIdent<T>(CachedIdent, PhantomData<T>);
303
304#[cfg(feature = "proc_macro2")]
305impl<T: ToTokens> IntoIdent<T> {
306    /// Creates a `IntoIdent` from an AST.
307    ///
308    /// # Errors
309    ///
310    /// This function returns an error when the provided data cannot be parsed as an
311    /// identifier.
312    ///
313    /// ```
314    /// # use unsynn::*;
315    /// let mut token_iter = r#" foo "123" "#.to_token_iter();
316    ///
317    /// let parsed = <Cons<Ident, LiteralString>>::parser(&mut token_iter).unwrap();
318    /// let ident = IntoIdent::from(&parsed).unwrap();
319    ///
320    /// assert_eq!(ident.as_str(), "foo123");
321    /// ```
322    pub fn from(from: &T) -> Result<Self> {
323        let mut string = from.tokens_to_string();
324        string.retain(|c| c.is_alphanumeric() || c == '_');
325        Ok(Self(CachedIdent::from_string(string)?, PhantomData))
326    }
327}
328
329#[cfg(feature = "proc_macro2")]
330impl<T> IntoIdent<T> {
331    /// Returns the underlying `&str`without its surrounding quotes.
332    #[inline]
333    #[must_use]
334    pub fn as_str(&self) -> &str {
335        self.0.as_str()
336    }
337
338    /// Destructures `IntoIdent<T>` to get the inner `CachedIdent`.
339    #[inline]
340    #[must_use]
341    pub fn into_inner(self) -> CachedIdent {
342        self.0
343    }
344}
345
346/// Converts `IntoIdent<T>` into `Ident` by consuming the `IntoIdent<T>`.
347#[cfg(feature = "proc_macro2")]
348impl<T> From<IntoIdent<T>> for Ident {
349    fn from(this: IntoIdent<T>) -> Self {
350        this.0.into_inner()
351    }
352}
353
354#[cfg(feature = "proc_macro2")]
355impl<T: Parse + ToTokens> Parser for IntoIdent<T> {
356    fn parser(tokens: &mut TokenIter) -> Result<Self> {
357        let mut string = tokens.parse::<T>().refine_err::<Self>()?.tokens_to_string();
358        string.retain(|c| c.is_alphanumeric() || c == '_');
359        Ok(Self(CachedIdent::from_string(string)?, PhantomData))
360    }
361}
362
363#[cfg(feature = "proc_macro2")]
364impl<T: ToTokens> ToTokens for IntoIdent<T> {
365    #[inline]
366    fn to_tokens(&self, tokens: &mut TokenStream) {
367        self.0.to_tokens(tokens);
368    }
369}
370
371/// Creates a default constructed `IntoIdent<T>` from `T`
372///
373/// # Panics
374///
375/// When the concatenation of `T` does not form a valid `Ident`.
376#[cfg(feature = "proc_macro2")]
377impl<T: Default + ToTokens> Default for IntoIdent<T> {
378    fn default() -> Self {
379        let mut string = T::default().tokens_to_string();
380        string.retain(|c| c.is_alphanumeric() || c == '_');
381        Self(
382            CachedIdent::from_string(string).expect("invalid default constructed IntoIdent"),
383            PhantomData,
384        )
385    }
386}
387
388/// Parses `T` and keeps it as opaque `TokenStream`. This is useful when one wants to parse a
389/// sequence of tokens and keep it as opaque unit or re-parse it later as something else.
390///
391///
392/// # Example
393///
394/// ```
395/// # use unsynn::*;
396/// let mut token_iter = "foo 123".to_token_iter();
397///
398/// let parsed = <IntoTokenStream<Cons<Ident, LiteralInteger>>>::parser(&mut token_iter).unwrap();
399/// assert_tokens_eq!(parsed, "foo 123");
400/// # assert_tokens_eq!(parsed.into_inner(), "foo 123")
401/// ```
402#[derive(Debug)]
403pub struct IntoTokenStream<T>(TokenStream, PhantomData<T>);
404
405impl<T: ToTokens> IntoTokenStream<T> {
406    /// Creates a `IntoTokenStream` from an AST.
407    pub fn from(from: &T) -> Self {
408        Self(from.to_token_stream(), PhantomData)
409    }
410}
411
412impl<T> IntoTokenStream<T> {
413    /// Destructures `IntoTokenStream<T>` to get the inner `TokenStream`.
414    #[inline]
415    #[must_use]
416    pub fn into_inner(self) -> TokenStream {
417        self.0
418    }
419}
420
421impl<T> Deref for IntoTokenStream<T> {
422    type Target = TokenStream;
423
424    #[inline]
425    fn deref(&self) -> &Self::Target {
426        &self.0
427    }
428}
429
430impl<T: Parse + ToTokens> Parser for IntoTokenStream<T> {
431    fn parser(tokens: &mut TokenIter) -> Result<Self> {
432        let tokenstream = tokens
433            .parse::<T>()
434            .refine_err::<Self>()?
435            .into_token_stream();
436        Ok(Self(tokenstream, PhantomData))
437    }
438}
439
440impl<T: ToTokens> ToTokens for IntoTokenStream<T> {
441    #[inline]
442    fn to_tokens(&self, tokens: &mut TokenStream) {
443        self.0.to_tokens(tokens);
444    }
445}
446
447/// Creates a default constructed `IntoTokenStream<T>` from `T`
448impl<T: Default + ToTokens> Default for IntoTokenStream<T> {
449    fn default() -> Self {
450        Self(T::default().into_token_stream(), PhantomData)
451    }
452}
453
454/// Parses a `TokenStream` until, but excluding `T`. The presence of `T` is mandatory.
455///
456///
457/// # Example
458///
459/// ```
460/// # use unsynn::*;
461/// let mut token_iter = "foo bar ; baz".to_token_iter();
462///
463/// let parsed = <TokenStreamUntil<Semicolon>>::parser(&mut token_iter).unwrap();
464/// assert_tokens_eq!(parsed, "foo bar");
465/// # <TokenStreamUntil<Plus>>::parser(&mut token_iter).unwrap_err();
466/// ```
467pub type TokenStreamUntil<T> = IntoTokenStream<Cons<Vec<Cons<Except<T>, TokenTree>>, Expect<T>>>;