use std::char;
use std::fmt;
use std::marker::PhantomData;
#[cfg(feature = "trace_attempts")]
use crate::Expectation;
use crate::bnf::Expr;
use crate::char_class;
use crate::grammar::{AnyCharFirst, CharFirst, CharFirstCI, EmptyFirst, First, Grammar};
use crate::state::State;
use crate::{IntoInner, Raw};
pub trait CharClass: 'static {
fn matches(ch: char) -> bool;
fn name() -> &'static str;
}
char_class!(pub AnyChar, "any", |_c| true);
pub struct CharOf<M: CharClass>(pub char, PhantomData<M>);
impl<M: CharClass> Clone for CharOf<M> {
fn clone(&self) -> Self {
Self(self.0, self.1)
}
}
impl<M: CharClass> PartialEq for CharOf<M> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<M: CharClass> Eq for CharOf<M> {}
impl<M: CharClass> fmt::Debug for CharOf<M> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "CharOf({:?})", self.0)
}
}
impl<M: CharClass> CharOf<M> {
pub fn new(ch: char) -> Self {
CharOf(ch, PhantomData)
}
pub fn value(&self) -> char {
self.0
}
}
impl<M: CharClass> Grammar for CharOf<M> {
type First = AnyCharFirst;
#[inline]
fn parse_at(
input: &str,
pos: usize,
#[allow(unused_variables, unused_mut)] mut state: State,
) -> Option<(Self, usize)> {
let ch = match input.as_bytes().get(pos) {
Some(&b) if b < 0x80 => {
if M::matches(b as char) {
Some((b as char, 1))
} else {
None
}
}
Some(_) => input[pos..]
.chars()
.next()
.filter(|c: &char| M::matches(*c))
.map(|c| (c, c.len_utf8())),
None => None,
};
if let Some((ch, len)) = ch {
Some((CharOf(ch, PhantomData), pos + len))
} else {
#[cfg(feature = "trace_any")]
state.expect(
pos,
#[cfg(feature = "trace_attempts")]
Expectation::CharClass(M::name()),
);
None
}
}
#[inline]
fn scan_at(input: &str, pos: usize, state: State) -> Option<usize> {
Self::parse_at(input, pos, state).map(|(_, pos)| pos)
}
fn print_to(&self, buf: &mut String) {
buf.push(self.0);
}
fn to_bnf() -> Expr {
Expr::CharOf(M::name().to_string())
}
}
pub struct StringOf<C: CharClass>(Raw<Vec<CharOf<C>>>);
impl<C: CharClass> Grammar for StringOf<C> {
type First = <Raw<Vec<CharOf<C>>> as Grammar>::First;
fn parse_at(input: &str, pos: usize, state: State) -> Option<(Self, usize)> {
let (inner, pos) = Raw::parse_at(input, pos, state)?;
Some((StringOf(inner), pos))
}
fn scan_at(input: &str, pos: usize, state: State) -> Option<usize> {
Raw::<Vec<CharOf<C>>>::scan_at(input, pos, state)
}
fn print_to(&self, buf: &mut String) {
self.0.print_to(buf);
}
fn to_bnf() -> Expr {
Raw::<Vec<CharOf<C>>>::to_bnf()
}
}
pub struct StringOf1<C: CharClass>(Raw<(CharOf<C>, Vec<CharOf<C>>)>);
impl<C: CharClass> Grammar for StringOf1<C> {
type First = <Raw<(CharOf<C>, Vec<CharOf<C>>)> as Grammar>::First;
fn parse_at(input: &str, pos: usize, state: State) -> Option<(Self, usize)> {
let (inner, pos) = Raw::parse_at(input, pos, state)?;
Some((StringOf1(inner), pos))
}
fn scan_at(input: &str, pos: usize, state: State) -> Option<usize> {
Raw::<(CharOf<C>, Vec<CharOf<C>>)>::scan_at(input, pos, state)
}
fn print_to(&self, buf: &mut String) {
self.0.print_to(buf);
}
fn to_bnf() -> Expr {
Raw::<(CharOf<C>, Vec<CharOf<C>>)>::to_bnf()
}
}
macro_rules! impl_string_wrapper {
($ty:ident) => {
impl<C: CharClass> fmt::Debug for $ty<C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl<C: CharClass> fmt::Display for $ty<C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl<C: CharClass> Clone for $ty<C> {
fn clone(&self) -> Self {
$ty(self.0.clone())
}
}
impl<C: CharClass> PartialEq for $ty<C> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<C: CharClass> Eq for $ty<C> {}
impl<C: CharClass> std::hash::Hash for $ty<C> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl<C: CharClass> std::ops::Deref for $ty<C> {
type Target = str;
fn deref(&self) -> &str {
&self.0
}
}
impl<C: CharClass> AsRef<str> for $ty<C> {
fn as_ref(&self) -> &str {
&self.0
}
}
impl<C: CharClass> IntoInner<String> for $ty<C> {
fn into_inner(self) -> String {
self.0.0
}
}
};
}
impl_string_wrapper!(StringOf);
impl_string_wrapper!(StringOf1);
#[doc(hidden)]
pub trait Token: 'static {
type First: First;
fn scan_at(input: &str, pos: usize, state: State) -> Option<usize>;
fn add_expectation(str: &mut String);
fn expectation() -> String {
let mut str = String::new();
Self::add_expectation(&mut str);
str
}
}
impl Token for () {
type First = EmptyFirst;
fn scan_at(_input: &str, pos: usize, _state: State) -> Option<usize> {
Some(pos)
}
fn add_expectation(_: &mut String) {}
}
pub struct CharThen<const CH: char, T>(PhantomData<T>);
impl<const CH: char, T: Token> Token for CharThen<CH, T> {
type First = CharFirst<CH>;
#[inline]
fn scan_at(
input: &str,
pos: usize,
#[allow(unused_variables, unused_mut)] mut state: State,
) -> Option<usize> {
if input[pos..].starts_with(CH) {
T::scan_at(input, pos + CH.len_utf8(), state)
} else {
#[cfg(feature = "trace_any")]
state.expect(
pos,
#[cfg(feature = "trace_attempts")]
Expectation::StringEq(Self::expectation()),
);
None
}
}
fn add_expectation(str: &mut String) {
str.push(CH);
T::add_expectation(str);
}
}
pub struct CharCIThen<const CH: char, T>(PhantomData<T>);
impl<const CH: char, T: Token> Token for CharCIThen<CH, T> {
type First = CharFirstCI<CH>;
#[inline]
fn scan_at(
input: &str,
pos: usize,
#[allow(unused_variables, unused_mut)] mut state: State,
) -> Option<usize> {
match input[pos..].chars().next() {
Some(c) if c.eq_ignore_ascii_case(&CH) => T::scan_at(input, pos + c.len_utf8(), state),
_ => {
#[cfg(feature = "trace_any")]
state.expect(
pos,
#[cfg(feature = "trace_attempts")]
Expectation::StringEqCI(Self::expectation()),
);
None
}
}
}
fn add_expectation(str: &mut String) {
str.push(CH);
T::add_expectation(str);
}
}
pub struct StringEq<T>(PhantomData<T>);
impl<T: Token> Grammar for StringEq<T> {
type First = T::First;
#[inline]
fn parse_at(input: &str, pos: usize, state: State) -> Option<(Self, usize)> {
let end = T::scan_at(input, pos, state)?;
Some((StringEq(PhantomData), end))
}
#[inline]
fn scan_at(input: &str, pos: usize, state: State) -> Option<usize> {
T::scan_at(input, pos, state)
}
fn print_to(&self, buf: &mut String) {
T::add_expectation(buf);
}
fn to_bnf() -> Expr {
Expr::Literal(T::expectation())
}
}
impl<T: Token> fmt::Debug for StringEq<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("StringEq").field(&T::expectation()).finish()
}
}
impl<T> Clone for StringEq<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for StringEq<T> {}
impl<T> Default for StringEq<T> {
fn default() -> Self {
StringEq(PhantomData)
}
}
impl<T> PartialEq for StringEq<T> {
fn eq(&self, _other: &Self) -> bool {
true
}
}
impl<T> Eq for StringEq<T> {}
pub struct StringEqCI<T>(String, PhantomData<T>);
impl<T: Token> Grammar for StringEqCI<T> {
type First = T::First;
#[inline]
fn parse_at(input: &str, pos: usize, state: State) -> Option<(Self, usize)> {
let end = T::scan_at(input, pos, state)?;
Some((StringEqCI(input[pos..end].to_string(), PhantomData), end))
}
#[inline]
fn scan_at(input: &str, pos: usize, state: State) -> Option<usize> {
T::scan_at(input, pos, state)
}
fn print_to(&self, buf: &mut String) {
buf.push_str(&self.0);
}
fn to_bnf() -> Expr {
Expr::LiteralCI(T::expectation())
}
}
impl<T> fmt::Debug for StringEqCI<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("StringEqCI").field(&self.0).finish()
}
}
impl<T> Clone for StringEqCI<T> {
fn clone(&self) -> Self {
StringEqCI(self.0.clone(), PhantomData)
}
}
impl<T: Token> Default for StringEqCI<T> {
fn default() -> Self {
StringEqCI(T::expectation(), PhantomData)
}
}
impl<T> PartialEq for StringEqCI<T> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<T> Eq for StringEqCI<T> {}