use crate::{IntoTokens, Parse, ProcMacro, ToTokenStream, ToTokens};
use std::fmt::Display;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TokenTreeKind {
Group,
Ident,
Punct,
Literal,
}
pub trait TokenTree:
ProcMacro<TokenTree = Self>
+ Display
+ From<Self::Group>
+ From<Self::Ident>
+ From<Self::Punct>
+ From<Self::Literal>
{
fn span(&self) -> Self::Span;
fn set_span(&mut self, span: Self::Span);
}
pub trait TokenTreeExt:
crate::ProcMacroExt<TokenTreeExt = Self>
+ TokenTree
+ Parse<Self>
+ IntoTokens<Self>
+ ToTokens<Self>
+ ToTokenStream<Self::TokenStreamExt>
{
fn kind(&self) -> TokenTreeKind;
#[inline]
fn is_group(&self) -> bool {
self.kind() == TokenTreeKind::Group
}
fn group(&self) -> Option<&Self::Group>;
fn group_mut(&mut self) -> Option<&mut Self::Group>;
fn into_group(self) -> Option<Self::Group>;
#[inline]
fn is_ident(&self) -> bool {
self.kind() == TokenTreeKind::Ident
}
fn ident(&self) -> Option<&Self::Ident>;
fn ident_mut(&mut self) -> Option<&mut Self::Ident>;
fn into_ident(self) -> Option<Self::Ident>;
#[inline]
fn is_punct(&self) -> bool {
self.kind() == TokenTreeKind::Punct
}
fn punct(&self) -> Option<&Self::Punct>;
fn punct_mut(&mut self) -> Option<&mut Self::Punct>;
fn into_punct(self) -> Option<Self::Punct>;
#[inline]
fn is_literal(&self) -> bool {
self.kind() == TokenTreeKind::Literal
}
fn literal(&self) -> Option<&Self::Literal>;
fn literal_mut(&mut self) -> Option<&mut Self::Literal>;
fn into_literal(self) -> Option<Self::Literal>;
#[inline]
fn flatten_group(&mut self) {
if let Some(group) = self.group() {
if let Some(tt) = group.flatten() {
*self = tt;
}
}
}
}
pub trait Group: ProcMacro<Group = Self> + Display {
fn new(delimiter: Self::Delimiter, stream: Self::TokenStream) -> Self;
fn delimiter(&self) -> Self::Delimiter;
fn stream(&self) -> Self::TokenStream;
fn span(&self) -> Self::Span;
fn span_open(&self) -> Self::Span;
fn span_close(&self) -> Self::Span;
fn set_span(&mut self, span: Self::Span);
}
pub trait GroupExt:
crate::ProcMacroExt<GroupExt = Self>
+ Group
+ Parse<Self::TokenTree>
+ IntoTokens<Self::TokenTree>
+ ToTokens<Self::TokenTree>
+ ToTokenStream<Self::TokenStream>
{
fn with_span(delimiter: Self::Delimiter, stream: Self::TokenStream, span: Self::Span) -> Self {
let mut group = Self::new(delimiter, stream);
group.set_span(span);
group
}
#[inline]
fn delimiter_kind(&self) -> DelimiterKind {
self.delimiter().into()
}
fn stream_buffer(&self) -> crate::TokenBuffer<Self::TokenTree>;
#[inline]
fn flatten(&self) -> Option<Self::TokenTree> {
if self.delimiter().is_none() {
let mut stream = self.stream().into_iter();
if let Some(tt) = stream.next() {
if stream.next().is_none() {
if let Some(group) = tt.group() {
if let Some(tt) = group.flatten() {
return Some(tt);
}
}
return Some(tt);
}
}
}
None
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DelimiterKind {
Parenthesis,
Brace,
Bracket,
None,
}
#[allow(non_upper_case_globals)]
pub trait Delimiter: ProcMacro<Delimiter = Self> + Copy + Eq {
const Parenthesis: Self;
const Brace: Self;
const Bracket: Self;
const None: Self;
}
pub trait DelimiterExt:
crate::ProcMacroExt<DelimiterExt = Self>
+ Delimiter
+ From<DelimiterKind>
+ Into<DelimiterKind>
+ PartialEq<DelimiterKind>
{
#[inline]
fn kind(&self) -> DelimiterKind {
(*self).into()
}
#[inline]
fn is_parenthesis(&self) -> bool {
*self == Self::Parenthesis
}
#[inline]
fn is_brace(&self) -> bool {
*self == Self::Brace
}
#[inline]
fn is_bracket(&self) -> bool {
*self == Self::Bracket
}
#[inline]
fn is_none(&self) -> bool {
*self == Self::None
}
}
pub trait Ident: ProcMacro<Ident = Self> + Display {
fn new(string: &str, span: Self::Span) -> Self;
fn new_raw(string: &str, span: Self::Span) -> Self;
fn span(&self) -> Self::Span;
fn set_span(&mut self, span: Self::Span);
}
pub trait IdentExt:
crate::ProcMacroExt<IdentExt = Self>
+ Ident
+ Parse<Self::TokenTree>
+ IntoTokens<Self::TokenTree>
+ ToTokens<Self::TokenTree>
+ ToTokenStream<Self::TokenStream>
{
}
pub trait Punct: ProcMacro<Punct = Self> + Display {
fn new(ch: char, spacing: Self::Spacing) -> Self;
fn as_char(&self) -> char;
fn spacing(&self) -> Self::Spacing;
fn span(&self) -> Self::Span;
fn set_span(&mut self, span: Self::Span);
}
pub trait PunctExt:
crate::ProcMacroExt<PunctExt = Self>
+ Punct
+ Parse<Self::TokenTree>
+ IntoTokens<Self::TokenTree>
+ ToTokens<Self::TokenTree>
+ ToTokenStream<Self::TokenStream>
{
#[inline]
fn with_span(ch: char, spacing: Self::Spacing, span: Self::Span) -> Self {
let mut punct = Self::Punct::new(ch, spacing);
punct.set_span(span);
punct
}
#[inline]
fn set_spacing(&mut self, spacing: Self::Spacing) {
*self = Self::with_span(self.as_char(), spacing, self.span());
}
}
#[allow(non_upper_case_globals)]
pub trait Spacing: ProcMacro<Spacing = Self> + Copy + Eq {
const Joint: Self;
const Alone: Self;
}
pub trait SpacingExt: crate::ProcMacroExt<SpacingExt = Self> + Spacing {
#[inline]
fn is_joint(&self) -> bool {
*self == Self::Joint
}
#[inline]
fn is_alone(&self) -> bool {
*self == Self::Alone
}
}
macro_rules! impl_token_tree {
($($pm:ident: $feature:literal),*) => { $(
#[cfg(feature = $feature)]
impl TokenTree for $pm::TokenTree {
#[inline]
fn span(&self) -> Self::Span {
self.span()
}
#[inline]
fn set_span(&mut self, span: Self::Span) {
self.set_span(span);
}
}
#[cfg(feature = $feature)]
impl TokenTreeExt for $pm::TokenTree {
#[inline]
fn kind(&self) -> TokenTreeKind {
match self {
Self::Group(_) => TokenTreeKind::Group,
Self::Ident(_) => TokenTreeKind::Ident,
Self::Punct(_) => TokenTreeKind::Punct,
Self::Literal(_) => TokenTreeKind::Literal,
}
}
#[inline]
fn group(&self) -> Option<&<Self as ProcMacro>::Group> {
if let Self::Group(group) = self {
Some(group)
} else {
None
}
}
#[inline]
fn group_mut(&mut self) -> Option<&mut <Self as ProcMacro>::Group> {
if let Self::Group(group) = self {
Some(group)
} else {
None
}
}
#[inline]
fn into_group(self) -> Option<<Self as ProcMacro>::Group> {
if let Self::Group(group) = self {
Some(group)
} else {
None
}
}
#[inline]
fn ident(&self) -> Option<&<Self as ProcMacro>::Ident> {
if let Self::Ident(ident) = self {
Some(ident)
} else {
None
}
}
#[inline]
fn ident_mut(&mut self) -> Option<&mut <Self as ProcMacro>::Ident> {
if let Self::Ident(ident) = self {
Some(ident)
} else {
None
}
}
#[inline]
fn into_ident(self) -> Option<<Self as ProcMacro>::Ident> {
if let Self::Ident(ident) = self {
Some(ident)
} else {
None
}
}
#[inline]
fn punct(&self) -> Option<&<Self as ProcMacro>::Punct> {
if let Self::Punct(punct) = self {
Some(punct)
} else {
None
}
}
#[inline]
fn punct_mut(&mut self) -> Option<&mut <Self as ProcMacro>::Punct> {
if let Self::Punct(punct) = self {
Some(punct)
} else {
None
}
}
#[inline]
fn into_punct(self) -> Option<<Self as ProcMacro>::Punct> {
if let Self::Punct(punct) = self {
Some(punct)
} else {
None
}
}
#[inline]
fn literal(&self) -> Option<&<Self as ProcMacro>::Literal> {
if let Self::Literal(literal) = self {
Some(literal)
} else {
None
}
}
#[inline]
fn literal_mut(&mut self) -> Option<&mut <Self as ProcMacro>::Literal> {
if let Self::Literal(literal) = self {
Some(literal)
} else {
None
}
}
#[inline]
fn into_literal(self) -> Option<<Self as ProcMacro>::Literal> {
if let Self::Literal(literal) = self {
Some(literal)
} else {
None
}
}
}
#[cfg(feature = $feature)]
impl crate::Parse<$pm::TokenTree> for $pm::TokenTree {
#[inline]
fn parse(buf: &mut &crate::TokenBuf<$pm::TokenTree>) -> Result<Self, crate::Error<$pm::Span>> {
if let Some(tt) = buf.first() {
let result = tt.clone();
*buf = &buf[1..];
Ok(result)
} else {
Err(crate::Error::new("unexpected end of input"))
}
}
}
#[cfg(all(feature = $feature))]
impl crate::IntoTokens<$pm::TokenTree> for $pm::TokenTree {
#[inline]
fn into_tokens(mut self) -> impl Iterator<Item = $pm::TokenTree> {
self.flatten_group();
std::iter::once(self)
}
}
#[cfg(feature = $feature)]
impl crate::ToTokenStream<$pm::TokenStream> for $pm::TokenTree {
#[inline]
fn extend_token_stream(&self, token_stream: &mut $pm::TokenStream) {
token_stream.extend(self.clone().into_tokens())
}
}
#[cfg(feature = $feature)]
impl Group for $pm::Group {
#[inline]
fn new(delimiter: Self::Delimiter, stream: Self::TokenStream) -> Self {
Self::new(delimiter, stream)
}
#[inline]
fn delimiter(&self) -> Self::Delimiter {
self.delimiter()
}
#[inline]
fn stream(&self) -> Self::TokenStream {
self.stream()
}
#[inline]
fn span(&self) -> Self::Span {
self.span()
}
#[inline]
fn span_open(&self) -> Self::Span {
self.span_open()
}
#[inline]
fn span_close(&self) -> Self::Span {
self.span_close()
}
#[inline]
fn set_span(&mut self, span: Self::Span) {
self.set_span(span)
}
}
#[cfg(feature = $feature)]
impl GroupExt for $pm::Group {
#[inline]
fn stream_buffer(&self) -> crate::TokenBuffer<$pm::TokenTree> {
crate::TokenBuffer::from(self.stream())
}
}
#[cfg(feature = $feature)]
impl crate::Parse<$pm::TokenTree> for $pm::Group {
#[inline]
fn parse(buf: &mut &crate::TokenBuf<$pm::TokenTree>) -> Result<Self, crate::Error<$pm::Span>> {
buf.parse_prefix(|token| {
if let $pm::TokenTree::Group(t) = token {
crate::Match::Complete(t.clone())
} else {
crate::Match::NoMatch
}
}).map_err(|mut e|{ e.set_message("expected group"); e })
}
}
#[cfg(all(feature = $feature))]
impl crate::IntoTokens<$pm::TokenTree> for $pm::Group {
#[inline]
fn into_tokens(self) -> impl Iterator<Item = $pm::TokenTree> {
std::iter::once($pm::TokenTree::Group(self))
}
}
#[cfg(feature = $feature)]
impl crate::ToTokenStream<$pm::TokenStream> for $pm::Group {
#[inline]
fn extend_token_stream(&self, token_stream: &mut $pm::TokenStream) {
token_stream.extend([$pm::TokenTree::from(self.clone())])
}
}
#[cfg(feature = $feature)]
impl From<$pm::Delimiter> for DelimiterKind {
#[inline]
fn from(value: $pm::Delimiter) -> Self {
match value {
$pm::Delimiter::Parenthesis => Self::Parenthesis,
$pm::Delimiter::Brace => Self::Brace,
$pm::Delimiter::Bracket => Self::Bracket,
$pm::Delimiter::None => Self::None,
}
}
}
#[cfg(feature = $feature)]
impl From<DelimiterKind> for $pm::Delimiter {
#[inline]
fn from(value: DelimiterKind) -> Self {
match value {
DelimiterKind::Parenthesis => Self::Parenthesis,
DelimiterKind::Brace => Self::Brace,
DelimiterKind::Bracket => Self::Bracket,
DelimiterKind::None => Self::None,
}
}
}
#[cfg(feature = $feature)]
impl PartialEq<$pm::Delimiter> for DelimiterKind {
#[inline]
fn eq(&self, rhs: &$pm::Delimiter) -> bool {
*self == rhs.kind()
}
}
#[cfg(feature = $feature)]
impl PartialEq<DelimiterKind> for $pm::Delimiter {
#[inline]
fn eq(&self, rhs: &DelimiterKind) -> bool {
self.kind() == *rhs
}
}
#[cfg(feature = $feature)]
#[allow(non_upper_case_globals)]
impl Delimiter for $pm::Delimiter {
const Parenthesis: Self = Self::Parenthesis;
const Brace: Self = Self::Brace;
const Bracket: Self = Self::Bracket;
const None: Self = Self::None;
}
#[cfg(feature = $feature)]
impl DelimiterExt for $pm::Delimiter {}
#[cfg(feature = $feature)]
impl Ident for $pm::Ident {
#[inline]
fn new(string: &str, span: Self::Span) -> Self {
Self::new(string, span)
}
#[inline]
fn new_raw(string: &str, span: Self::Span) -> Self {
Self::new_raw(string, span)
}
#[inline]
fn span(&self) -> Self::Span {
self.span()
}
#[inline]
fn set_span(&mut self, span: Self::Span) {
self.set_span(span)
}
}
#[cfg(feature = $feature)]
impl IdentExt for $pm::Ident {}
#[cfg(feature = $feature)]
impl crate::Parse<$pm::TokenTree> for $pm::Ident {
#[inline]
fn parse(buf: &mut &crate::TokenBuf<$pm::TokenTree>) -> Result<Self, crate::Error<$pm::Span>> {
buf.parse_prefix(|token| {
if let $pm::TokenTree::Ident(t) = token {
crate::Match::Complete(t.clone())
} else {
crate::Match::NoMatch
}
}).map_err(|mut e|{ e.set_message("expected ident"); e })
}
}
#[cfg(all(feature = $feature))]
impl crate::IntoTokens<$pm::TokenTree> for $pm::Ident {
#[inline]
fn into_tokens(self) -> impl Iterator<Item = $pm::TokenTree> {
std::iter::once($pm::TokenTree::Ident(self))
}
}
#[cfg(feature = $feature)]
impl crate::ToTokenStream<$pm::TokenStream> for $pm::Ident {
#[inline]
fn extend_token_stream(&self, token_stream: &mut $pm::TokenStream) {
token_stream.extend([$pm::TokenTree::from(self.clone())])
}
}
#[cfg(feature = $feature)]
impl Punct for $pm::Punct {
#[inline]
fn new(ch: char, spacing: Self::Spacing) -> Self {
Self::new(ch, spacing)
}
#[inline]
fn as_char(&self) -> char {
self.as_char()
}
#[inline]
fn spacing(&self) -> Self::Spacing {
self.spacing()
}
#[inline]
fn span(&self) -> Self::Span {
self.span()
}
#[inline]
fn set_span(&mut self, span: Self::Span) {
self.set_span(span)
}
}
#[cfg(feature = $feature)]
impl PunctExt for $pm::Punct {}
#[cfg(feature = $feature)]
impl crate::Parse<$pm::TokenTree> for $pm::Punct {
#[inline]
fn parse(buf: &mut &crate::TokenBuf<$pm::TokenTree>) -> Result<Self, crate::Error<$pm::Span>> {
buf.parse_prefix(|token| {
if let $pm::TokenTree::Punct(t) = token {
crate::Match::Complete(t.clone())
} else {
crate::Match::NoMatch
}
}).map_err(|mut e|{ e.set_message("expected punct"); e })
}
}
#[cfg(feature = $feature)]
impl crate::IntoTokens<$pm::TokenTree> for $pm::Punct {
#[inline]
fn into_tokens(self) -> impl Iterator<Item = $pm::TokenTree> {
std::iter::once($pm::TokenTree::Punct(self))
}
}
#[cfg(feature = $feature)]
impl crate::ToTokenStream<$pm::TokenStream> for $pm::Punct {
#[inline]
fn extend_token_stream(&self, token_stream: &mut $pm::TokenStream) {
token_stream.extend([$pm::TokenTree::from(self.clone())])
}
}
#[cfg(feature = $feature)]
#[allow(non_upper_case_globals)]
impl Spacing for $pm::Spacing {
const Joint: Self = Self::Joint;
const Alone: Self = Self::Alone;
}
#[cfg(feature = $feature)]
impl SpacingExt for $pm::Spacing {}
)* };
}
impl_token_tree!(proc_macro: "proc-macro", proc_macro2: "proc-macro2");