#[cfg(feature = "proc_macro2")]
pub use proc_macro2::{Group, Ident, Literal, Punct, TokenStream, TokenTree};
#[cfg(not(feature = "proc_macro2"))]
pub use proc_macro::{Group, Ident, Literal, Punct, TokenStream, TokenTree};
#[allow(clippy::wildcard_imports)]
use crate::*;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
fn count_nested_tokens(stream: &TokenStream) -> usize {
stream
.clone()
.into_iter()
.map(|tt| match tt {
TokenTree::Group(g) => count_tokens_recursive(g.stream()),
_ => 0, })
.sum()
}
pub(crate) fn count_tokens_recursive(stream: TokenStream) -> usize {
stream
.into_iter()
.map(|tt| match tt {
TokenTree::Group(g) => 1 + count_tokens_recursive(g.stream()),
_ => 1,
})
.sum()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_count_tokens_recursive_basic() {
let stream: TokenStream = "a b c".parse().unwrap();
assert_eq!(count_tokens_recursive(stream), 3);
}
#[test]
fn test_count_tokens_recursive_with_group() {
let stream: TokenStream = "a { b c } d".parse().unwrap();
assert_eq!(count_tokens_recursive(stream), 5);
}
#[test]
fn test_count_tokens_recursive_nested_groups() {
let stream: TokenStream = "a { b { c } d } e".parse().unwrap();
assert_eq!(count_tokens_recursive(stream), 7);
}
#[test]
fn test_count_tokens_recursive_empty() {
let stream: TokenStream = "".parse().unwrap();
assert_eq!(count_tokens_recursive(stream), 0);
}
#[test]
fn test_count_tokens_recursive_empty_group() {
let stream: TokenStream = "a { } b".parse().unwrap();
assert_eq!(count_tokens_recursive(stream), 3);
}
#[test]
fn test_count_tokens_recursive_multiple_groups() {
let stream: TokenStream = "{ a } { b } { c }".parse().unwrap();
assert_eq!(count_tokens_recursive(stream), 6);
}
#[test]
fn test_count_nested_tokens() {
let stream: TokenStream = "a { b c } d".parse().unwrap();
assert_eq!(count_nested_tokens(&stream), 2);
}
#[test]
fn test_count_nested_tokens_nested() {
let stream: TokenStream = "a { b { c } d } e".parse().unwrap();
assert_eq!(count_nested_tokens(&stream), 4);
}
#[test]
fn test_count_nested_tokens_empty() {
let stream: TokenStream = "a b c".parse().unwrap();
assert_eq!(count_nested_tokens(&stream), 0);
}
#[test]
fn test_count_nested_tokens_empty_group() {
let stream: TokenStream = "a { } b".parse().unwrap();
assert_eq!(count_nested_tokens(&stream), 0);
}
#[test]
fn test_count_nested_tokens_multiple_groups() {
let stream: TokenStream = "{ a } { b } { c }".parse().unwrap();
assert_eq!(count_nested_tokens(&stream), 3);
}
}
impl Parser for TokenStream {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
let mut output = TokenStream::new();
output.extend(&mut *tokens);
let nested_count = count_nested_tokens(&output);
tokens.add(nested_count);
Ok(output)
}
}
impl ToTokens for TokenStream {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(self.clone());
}
}
pub struct NonEmptyTokenStream(pub TokenStream);
impl TryFrom<TokenStream> for NonEmptyTokenStream {
type Error = Error;
fn try_from(value: TokenStream) -> Result<Self> {
if value.is_empty() {
Error::unexpected_end()
} else {
Ok(Self(value))
}
}
}
impl Parser for NonEmptyTokenStream {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
tokens.parse::<Expect<TokenTree>>().refine_err::<Self>()?;
#[allow(clippy::unwrap_used)]
Ok(Self(TokenStream::parser(tokens).unwrap()))
}
}
impl ToTokens for NonEmptyTokenStream {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(self.0.clone());
}
}
#[test]
#[cfg(feature = "proc_macro2")]
fn test_non_empty_token_stream() {
let mut token_iter = "ident".to_token_iter();
let _ = NonEmptyTokenStream::parser(&mut token_iter).unwrap();
}
#[test]
#[cfg(feature = "proc_macro2")]
fn test_empty_token_stream() {
let mut token_iter = "".to_token_iter();
assert!(NonEmptyTokenStream::parser(&mut token_iter).is_err());
}
impl Parser for TokenTree {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
match tokens.next() {
Some(token) => Ok(token),
None => Error::unexpected_end(),
}
}
}
impl ToTokens for TokenTree {
#[inline]
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(std::iter::once(self.clone()));
}
}
impl Parser for Group {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
match tokens.next() {
Some(TokenTree::Group(group)) => {
let nested_count = count_tokens_recursive(group.stream());
tokens.add(nested_count);
Ok(group)
}
at => Error::unexpected_token(at, tokens),
}
}
}
impl ToTokens for Group {
#[inline]
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(std::iter::once(TokenTree::Group(self.clone())));
}
}
impl Parser for Ident {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
match tokens.next() {
Some(TokenTree::Ident(ident)) => Ok(ident),
at => Error::unexpected_token(at, tokens),
}
}
}
impl ToTokens for Ident {
#[inline]
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(std::iter::once(TokenTree::Ident(self.clone())));
}
}
impl Parser for Punct {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
match tokens.next() {
Some(TokenTree::Punct(punct)) => Ok(punct),
at => Error::unexpected_token(at, tokens),
}
}
}
impl ToTokens for Punct {
#[inline]
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(std::iter::once(TokenTree::Punct(self.clone())));
}
}
impl Parser for Literal {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
match tokens.next() {
Some(TokenTree::Literal(literal)) => Ok(literal),
at => Error::unexpected_token(at, tokens),
}
}
}
impl ToTokens for Literal {
#[inline]
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(std::iter::once(TokenTree::Literal(self.clone())));
}
}
#[derive(Clone)]
pub struct Cached<T> {
value: T,
string: String,
}
impl<T: Parse + ToTokens> Parser for Cached<T> {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
let value = T::parser(tokens).refine_err::<Self>()?;
let string = value.tokens_to_string();
Ok(Self { value, string })
}
}
impl<T: Parse + ToTokens> ToTokens for Cached<T> {
#[inline]
fn to_tokens(&self, tokens: &mut TokenStream) {
self.value.to_tokens(tokens);
}
}
impl<T: Parse + ToTokens> Cached<T> {
pub fn set(&mut self, value: T) {
self.value = value;
self.string = self.value.tokens_to_string();
}
}
impl<T: Parse> Cached<T> {
pub fn into_inner(self) -> T {
self.value
}
pub fn into_string(self) -> String {
self.string
}
#[allow(clippy::missing_const_for_fn)] pub fn as_str(&self) -> &str {
&self.string
}
}
#[cfg(feature = "proc_macro2")]
impl<T: Parse> Cached<T> {
#[must_use]
pub fn new(s: &str) -> Self {
let value = s.into_token_iter().parse().expect("Valid token");
Self {
value,
string: s.to_string(),
}
}
pub fn from_string(s: String) -> Result<Self> {
let value = s.to_token_iter().parse()?;
Ok(Self { value, string: s })
}
}
impl<T: Parse> Deref for Cached<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl<T: Parse> PartialEq<&str> for Cached<T> {
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}
impl<T: Parse> PartialEq for Cached<T> {
fn eq(&self, other: &Self) -> bool {
self.as_str() == other.as_str()
}
}
impl<T: Parse> Eq for Cached<T> {}
impl<T: Parse> std::hash::Hash for Cached<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.as_str().hash(state);
}
}
impl<T: Parse> AsRef<T> for Cached<T> {
fn as_ref(&self) -> &T {
&self.value
}
}
impl<T: Parse> AsRef<str> for Cached<T> {
fn as_ref(&self) -> &str {
self.as_str()
}
}
#[mutants::skip]
impl<T: Parse + std::fmt::Debug> std::fmt::Debug for Cached<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(&format!("Cached<{}>", std::any::type_name::<T>()))
.field("value", &self.value)
.field("string", &self.string)
.finish()
}
}
impl<T: Into<TokenTree>> From<Cached<T>> for TokenTree {
fn from(cached: Cached<T>) -> Self {
cached.value.into()
}
}
#[cfg(feature = "proc_macro2")]
impl<T: Parse> TryFrom<String> for Cached<T> {
type Error = Error;
fn try_from(value: String) -> Result<Self> {
let mut token_iter = value.to_token_iter();
let t = T::parser(&mut token_iter).refine_err::<Self>()?;
Ok(Self {
value: t,
string: value,
})
}
}
#[cfg(feature = "proc_macro2")]
impl<T: Parse> TryFrom<&str> for Cached<T> {
type Error = Error;
fn try_from(value: &str) -> Result<Self> {
Self::try_from(value.to_string())
}
}
#[test]
#[cfg(feature = "proc_macro2")]
fn test_cached_into_tt() {
let mut token_iter = "ident".to_token_iter();
let ident = Cached::<Ident>::parser(&mut token_iter).unwrap();
let _: TokenTree = ident.into();
}
macro_rules! gen_cached_types {
($($cached:ident = $basic:ident);* $(;)?) => {
$(
#[doc = concat!("[`", stringify!($basic), "`] with cached string representation.")]
pub type $cached = Cached<$basic>;
#[doc = concat!("Convert `", stringify!($cached), " into a `", stringify!($basic), "`.")]
impl From<$cached> for $basic {
fn from(cached: $cached) -> Self {
cached.value
}
}
)*
}
}
gen_cached_types! {
CachedGroup = Group;
CachedIdent = Ident;
CachedPunct = Punct;
CachedLiteral = Literal;
CachedLiteralString = LiteralString;
CachedLiteralInteger = LiteralInteger;
}
pub type CachedTokenTree = Cached<TokenTree>;
#[cfg(feature = "proc_macro2")]
#[macro_export]
macro_rules! format_ident {
($($args:tt)*) => {
<$crate::Ident as $crate::Parse>::parse(&mut format!($($args)*).into_token_iter()).expect("Not a valid identifier")
};
}
#[cfg(feature = "proc_macro2")]
#[macro_export]
macro_rules! format_cached_ident {
($($args:tt)*) => {
$crate::CachedIdent::from_string(format!($($args)*)).expect("Not a valid identifier")
};
}
#[cfg(feature = "proc_macro2")]
#[macro_export]
macro_rules! format_literal_string {
($fmt:literal $(, $($args:tt)*)?) => {
<$crate::LiteralString as $crate::Parse>::parse(&mut format!(concat!("\"",$fmt,"\"") $(, $($args)*)?)
.into_token_iter())
.expect("Not a valid string literal")
};
}
#[cfg(feature = "proc_macro2")]
#[macro_export]
macro_rules! format_literal{
($($args:tt)*) => {
<$crate::Literal as $crate::Parse>::parse(&mut format!($($args)*)
.into_token_iter())
.expect("Not a valid literal")
};
}
#[derive(Debug, Clone, Default)]
pub struct Nothing;
impl Parser for Nothing {
#[inline]
#[mutants::skip]
fn parser(_tokens: &mut TokenIter) -> Result<Self> {
Ok(Self)
}
}
impl ToTokens for Nothing {
#[inline]
fn to_tokens(&self, _tokens: &mut TokenStream) {
}
}
#[derive(Debug, Clone)]
pub struct Invalid;
impl Parser for Invalid {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
Error::unexpected_token(None, tokens)
}
}
impl ToTokens for Invalid {
#[inline]
fn to_tokens(&self, _tokens: &mut TokenStream) {
unimplemented!("`Invalid` can not be converted to tokens")
}
}
#[derive(Debug, Clone)]
pub struct NonParseable;
#[cfg(feature = "nonparseable")]
impl Parser for NonParseable {
#[inline]
fn parser(_tokens: &mut TokenIter) -> Result<Self> {
unimplemented!("`NonParseable` can not be parsed")
}
}
#[cfg(feature = "nonparseable")]
impl ToTokens for NonParseable {
#[mutants::skip]
#[inline]
fn to_tokens(&self, _tokens: &mut TokenStream) {
unimplemented!("`NonParseable` can not be converted to tokens")
}
}
#[derive(Clone)]
pub struct Except<T>(PhantomData<T>);
impl<T: Parse> Parser for Except<T> {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
let mut ptokens = tokens.clone();
match T::parser(&mut ptokens) {
Ok(_) => Error::unexpected_token(tokens.clone().next(), tokens),
Err(_) => Ok(Self(PhantomData)),
}
}
}
impl<T> ToTokens for Except<T> {
#[inline]
fn to_tokens(&self, _tokens: &mut TokenStream) {
}
}
#[mutants::skip]
impl<T: std::fmt::Debug> std::fmt::Debug for Except<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(&format!("Except<{}>", std::any::type_name::<T>()))
.finish()
}
}
#[derive(Clone)]
pub struct Expect<T>(PhantomData<T>);
impl<T: Parse> Parser for Expect<T> {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
let mut ptokens = tokens.clone();
match T::parser(&mut ptokens) {
Ok(_) => Ok(Self(PhantomData)),
Err(e) => Err(e),
}
}
}
impl<T> ToTokens for Expect<T> {
#[inline]
fn to_tokens(&self, _tokens: &mut TokenStream) {
}
}
#[mutants::skip]
impl<T: std::fmt::Debug> std::fmt::Debug for Expect<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(&format!("Expect<{}>", std::any::type_name::<T>()))
.finish()
}
}
#[derive(Debug, Clone)]
pub struct EndOfStream;
impl Parser for EndOfStream {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
match tokens.next() {
None => Ok(Self),
at => Error::unexpected_token(at, tokens),
}
}
}
impl ToTokens for EndOfStream {
#[inline]
fn to_tokens(&self, _tokens: &mut TokenStream) {
}
}
#[derive(Clone)]
pub struct HiddenState<T: Default>(pub T);
impl<T: Default> Deref for HiddenState<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: Default> DerefMut for HiddenState<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T: Default> Parser for HiddenState<T> {
#[inline]
#[mutants::skip]
fn parser(_ctokens: &mut TokenIter) -> Result<Self> {
Ok(Self(T::default()))
}
}
impl<T: Default> ToTokens for HiddenState<T> {
#[inline]
fn to_tokens(&self, _tokens: &mut TokenStream) {
}
}
impl<T: Default> Default for HiddenState<T> {
fn default() -> Self {
Self(Default::default())
}
}
#[mutants::skip]
impl<T: Default + std::fmt::Debug> std::fmt::Debug for HiddenState<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple(&format!("HiddenState<{}>", std::any::type_name::<T>()))
.field(&self.0)
.finish()
}
}