pub use token_parser_derive::*;
#[derive(Debug)]
pub enum Error {
NotEnoughElements(usize),
TooManyElements(usize),
ListNotAllowed,
SymbolNotAllowed,
StringParsing,
InvalidElement,
}
pub type Result<T> = std::result::Result<T, Error>;
pub enum Unit<I: Iterator>
where
I::Item: Into<Unit<I>>,
{
Symbol(String),
Parser(Parser<I>),
}
impl<I: Iterator> Unit<I>
where
I::Item: Into<Unit<I>>,
{
pub fn symbol(self) -> Result<String> {
use Unit::*;
match self {
Symbol(name) => Ok(name),
Parser(_) => Err(Error::ListNotAllowed),
}
}
pub fn parser(self) -> Result<Parser<I>> {
use Unit::*;
match self {
Symbol(_) => Err(Error::SymbolNotAllowed),
Parser(parser) => Ok(parser),
}
}
}
pub trait Parsable<C>: Sized {
fn parse_symbol(_name: String, _context: &C) -> Result<Self> {
Err(Error::SymbolNotAllowed)
}
fn parse_list<I: Iterator>(_parser: &mut Parser<I>, _context: &C) -> Result<Self>
where
I::Item: Into<Unit<I>>,
{
Err(Error::ListNotAllowed)
}
}
fn parse<C, P: Parsable<C>, I: Iterator>(unit: Unit<I>, context: &C) -> Result<P>
where
I::Item: Into<Unit<I>>,
{
use Unit::*;
match unit {
Symbol(name) => Parsable::parse_symbol(name, context),
Parser(mut parser) => parser.parse_rest(context),
}
}
impl<C, T: Parsable<C>> Parsable<C> for Box<T> {
fn parse_symbol(name: String, context: &C) -> Result<Self> {
Ok(Box::new(Parsable::parse_symbol(name, context)?))
}
fn parse_list<I: Iterator>(parser: &mut Parser<I>, context: &C) -> Result<Self>
where
I::Item: Into<Unit<I>>,
{
Ok(Box::new(parser.parse_list(context)?))
}
}
impl<C, T: Parsable<C>> Parsable<C> for Vec<T> {
fn parse_list<I: Iterator>(parser: &mut Parser<I>, context: &C) -> Result<Self>
where
I::Item: Into<Unit<I>>,
{
let Parser { form, count } = parser;
let result = form
.map(|token| {
*count += 1;
parse(token.into(), context)
})
.collect();
result
}
}
impl<C> Parsable<C> for String {
fn parse_symbol(name: String, _context: &C) -> Result<Self> {
Ok(name)
}
}
#[macro_export]
macro_rules! derive_symbol_parsable {
($t:ty) => {
impl<C> Parsable<C> for $t {
fn parse_symbol(name: String, _context: &C) -> Result<Self> {
if let Some(value) = name.parse().ok() {
Ok(value)
} else {
Err(Error::StringParsing)
}
}
}
};
($t:ty, $($rest:ty),+) => {
derive_symbol_parsable!($t);
derive_symbol_parsable!($($rest),+);
};
}
derive_symbol_parsable!(i8, i16, i32, i64, i128);
derive_symbol_parsable!(u8, u16, u32, u64, u128);
derive_symbol_parsable!(f32, f64);
derive_symbol_parsable!(usize);
derive_symbol_parsable!(bool);
pub struct Parser<I: Iterator> {
form: I,
count: usize,
}
impl<I: Iterator> Parser<I>
where
I::Item: Into<Unit<I>>,
{
pub fn new(form: I) -> Self {
Self { form, count: 0 }
}
pub fn parse_next<C, T: Parsable<C>>(&mut self, context: &C) -> Result<T> {
self.count += 1;
if let Some(token) = self.form.next() {
parse(token.into(), context)
} else {
Result::Err(Error::NotEnoughElements(self.count))
}
}
pub fn parse_rest<C, T: Parsable<C>>(&mut self, context: &C) -> Result<T> {
let result = self.parse_list(context);
if let Some(_) = self.form.next() {
let mut count = 1;
while let Some(_) = self.form.next() {
count += 1;
}
Err(Error::TooManyElements(count))
} else {
result
}
}
pub fn parse_list<C, T: Parsable<C>>(&mut self, context: &C) -> Result<T> {
Parsable::parse_list(self, context)
}
}
impl<I: Iterator> Iterator for Parser<I>
where
I::Item: Into<Unit<I>>,
{
type Item = Result<Parser<I>>;
fn next(&mut self) -> Option<Result<Parser<I>>> {
self.count += 1;
let unit: Unit<I> = self.form.next()?.into();
Some(unit.parser())
}
}