#![deny(missing_docs)]
pub trait Context {
#[cfg(feature = "radix-parsing")]
#[inline]
fn radix(&self) -> u32 {
10
}
}
impl Context for () {}
#[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 {
Symbol(String),
Parser(Parser),
}
impl Unit {
pub fn symbol(self) -> Result<String> {
use Unit::*;
match self {
Symbol(name) => Ok(name),
Parser(_) => Err(Error::ListNotAllowed),
}
}
pub fn parser(self) -> Result<Parser> {
use Unit::*;
match self {
Symbol(_) => Err(Error::SymbolNotAllowed),
Parser(parser) => Ok(parser),
}
}
}
pub trait Parsable<C: Context>: Sized {
fn parse_symbol(_name: String, _context: &C) -> Result<Self> {
Err(Error::SymbolNotAllowed)
}
fn parse_list(_parser: &mut Parser, _context: &C) -> Result<Self> {
Err(Error::ListNotAllowed)
}
}
fn parse<C: Context, P: Parsable<C>>(unit: Unit, context: &C) -> Result<P> {
use Unit::*;
match unit {
Symbol(name) => Parsable::parse_symbol(name, context),
Parser(mut parser) => parser.parse_rest(context),
}
}
impl<C: Context, 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(parser: &mut Parser, context: &C) -> Result<Self> {
Ok(Box::new(parser.parse_list(context)?))
}
}
impl<C: Context, T: Parsable<C>> Parsable<C> for Vec<T> {
fn parse_list(parser: &mut Parser, context: &C) -> Result<Self> {
let Parser { form, count } = parser;
let result = form
.drain(..)
.rev()
.map(|unit| {
*count += 1;
parse(unit, context)
})
.collect();
result
}
}
impl<C: Context> 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: $crate::Context> $crate::Parsable<C> for $t {
fn parse_symbol(name: String, _context: &C) -> $crate::Result<Self> {
if let Some(value) = name.parse().ok() {
Ok(value)
} else {
Err($crate::Error::StringParsing)
}
}
}
};
($t:ty, $($rest:ty),+) => {
derive_symbol_parsable!($t);
derive_symbol_parsable!($($rest),+);
};
}
#[cfg(not(feature = "radix-parsing"))]
mod numbers;
derive_symbol_parsable!(bool);
pub struct Parser {
form: Vec<Unit>,
count: usize,
}
impl Parser {
pub fn new<I: IntoIterator>(form: I) -> Self
where
I::Item: Into<Unit>,
{
let mut form: Vec<_> = form.into_iter().map(|unit| unit.into()).collect();
form.reverse();
Self { form, count: 0 }
}
pub fn parse_next<C: Context, T: Parsable<C>>(&mut self, context: &C) -> Result<T> {
self.count += 1;
if let Some(token) = self.form.pop() {
parse(token.into(), context)
} else {
Result::Err(Error::NotEnoughElements(self.count))
}
}
pub fn parse_rest<C: Context, T: Parsable<C>>(&mut self, context: &C) -> Result<T> {
let result = self.parse_list(context);
if let Some(_) = self.form.pop() {
let mut count = 1;
while let Some(_) = self.form.pop() {
count += 1;
}
Err(Error::TooManyElements(count))
} else {
result
}
}
pub fn parse_list<C: Context, T: Parsable<C>>(&mut self, context: &C) -> Result<T> {
Parsable::parse_list(self, context)
}
}
impl Iterator for Parser {
type Item = Result<Parser>;
fn next(&mut self) -> Option<Result<Parser>> {
self.count += 1;
Some(self.form.pop()?.parser())
}
}
#[cfg(feature = "radix-parsing")]
pub mod radix;