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>>>;