macro_rules! token_leaves {
(
atom = $atom:ty, span = $span:ty, read_span = $read:expr;
$( $rule:tt );* $(;)?
) => {
$( token_leaves!(@one $atom, $span, $read, $rule); )*
};
(@one $atom:ty, $span:ty, $read:expr,
($variant:ident => $leaf:ident, $expect:literal)) => {
#[derive(Clone, Debug)]
pub struct $leaf(pub $span);
impl ::syan::parse::parse::Parse<$atom> for $leaf {
type Error = ::syan::error::ParseError<$span>;
fn parse_stream<__SyanS: ::syan::parse::parse_stream::ParseStream<Atom = $atom>>(
__stream: &mut __SyanS,
) -> ::core::result::Result<Self, Self::Error> {
use ::syan::parse::parse_stream::ParseStream;
let __read_span: fn(&$atom) -> $span = $read;
match ParseStream::next(__stream) {
::core::option::Option::Some(__atom) => match &__atom.slot {
$crate::token::Token::$variant => {
let __span = __read_span(&__atom);
::core::result::Result::Ok($leaf(__span))
}
_ => {
let __span = __read_span(&__atom);
ParseStream::push(__stream, __atom);
::core::result::Result::Err(::syan::error::ParseError::expected(__span, $expect))
}
},
::core::option::Option::None => {
::core::result::Result::Err(::syan::error::ParseError::eof(<$span as ::core::default::Default>::default()))
}
}
}
}
impl ::syan::parse::unparse::Unparse<$atom> for $leaf {
fn unparse<__E: ::syan::parse::unparse::Emitter<$atom>>(
&self,
__sink: &mut __E,
) -> ::core::result::Result<(), __E::Error> {
type __A = $atom;
::syan::parse::unparse::Emitter::write_one(
__sink,
__A {
slot: $crate::token::Token::$variant,
span: self.0.clone(),
},
)
}
}
impl ::syan::span::Spanned for $leaf {
type Span = $span;
fn span(&self) -> Self::Span {
self.0.clone()
}
}
};
(@one $atom:ty, $span:ty, $read:expr,
($variant:ident($fty:ty) => $leaf:ident, $expect:literal, field = $field:ident)) => {
#[derive(Clone, Debug)]
pub struct $leaf {
pub $field: $fty,
pub span: $span,
}
impl ::syan::parse::parse::Parse<$atom> for $leaf {
type Error = ::syan::error::ParseError<$span>;
fn parse_stream<__SyanS: ::syan::parse::parse_stream::ParseStream<Atom = $atom>>(
__stream: &mut __SyanS,
) -> ::core::result::Result<Self, Self::Error> {
use ::syan::parse::parse_stream::ParseStream;
let __read_span: fn(&$atom) -> $span = $read;
match ParseStream::next(__stream) {
::core::option::Option::Some(__atom) => match &__atom.slot {
$crate::token::Token::$variant(__v) => {
let __v = __v.clone();
let __span = __read_span(&__atom);
::core::result::Result::Ok($leaf {
$field: __v,
span: __span,
})
}
_ => {
let __span = __read_span(&__atom);
ParseStream::push(__stream, __atom);
::core::result::Result::Err(::syan::error::ParseError::expected(__span, $expect))
}
},
::core::option::Option::None => {
::core::result::Result::Err(::syan::error::ParseError::eof(<$span as ::core::default::Default>::default()))
}
}
}
}
impl ::syan::parse::unparse::Unparse<$atom> for $leaf {
fn unparse<__E: ::syan::parse::unparse::Emitter<$atom>>(
&self,
__sink: &mut __E,
) -> ::core::result::Result<(), __E::Error> {
type __A = $atom;
::syan::parse::unparse::Emitter::write_one(
__sink,
__A {
slot: $crate::token::Token::$variant(self.$field.clone()),
span: self.span.clone(),
},
)
}
}
impl ::syan::span::Spanned for $leaf {
type Span = $span;
fn span(&self) -> Self::Span {
self.span.clone()
}
}
};
}
#[cfg(test)]
mod tests {
use crate::span::Span;
use crate::token::Atom;
token_leaves! {
atom = Atom, span = Span, read_span = |a| a.span;
(Let => ProbeKwLet, "'let'")
}
#[test]
fn probe_leaf_parses_and_reports_its_span() {
use syan::span::Spanned;
let leaf = ProbeKwLet(Span::default());
let _: Span = leaf.span();
}
}