use crate::Lexicon;
use std::borrow::Cow;
use std::{any::TypeId, marker::PhantomData};
use super::MetadataBuilder;
pub struct Epsilon<L: Lexicon + 'static>(PhantomData<L>);
impl<L: Lexicon + 'static> Production for Epsilon<L> {
type L = L;
fn debug() -> Cow<'static, str> {
Cow::Borrowed("()")
}
fn register(meta: &mut MetadataBuilder<Self::L>) {
let t = Self::id();
if meta.visit(t, || Self::debug().into_owned()) {
meta.add_epsilon(t);
}
}
}
pub trait Production: 'static {
type L: Lexicon + 'static;
#[inline]
fn id() -> TypeId {
TypeId::of::<Self>()
}
#[inline]
fn debug() -> Cow<'static, str> {
Cow::Borrowed(std::any::type_name::<Self>())
}
fn register(meta: &mut MetadataBuilder<Self::L>);
}
#[macro_export]
#[doc(hidden)]
macro_rules! production_passthrough {
($P:ty) => {
type L = <$P as $crate::syntax::Production>::L;
#[inline]
fn id() -> ::core::any::TypeId {
<$P>::id()
}
#[inline]
fn debug() -> ::std::borrow::Cow<'static, str> {
<$P>::debug()
}
#[inline]
fn register(meta: &mut $crate::syntax::MetadataBuilder<Self::L>) {
<$P>::register(meta)
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! register_sequence {
($meta:ident, $($T:ty),*) => {{
let t = Self::id();
if $meta.visit(t, ||Self::debug().into_owned()) {
$meta.add_sequence(t, &[ $(<$T>::id()),* ]);
$(<$T>::register($meta);)*
}
}};
}
#[macro_export]
#[doc(hidden)]
macro_rules! register_union {
($meta:ident, $($T:ty),*) => {{
let t = Self::id();
if $meta.visit(t, ||Self::debug().into_owned()) {
$meta.add_union(t, &[ $(<$T>::id()),* ]);
$(<$T>::register($meta);)*
}
}};
}