use crate::always_impl;
#[allow(clippy::wildcard_imports)]
use crate::prelude::*;
#[derive(Debug, Clone, Copy, Default)]
pub struct Newline;
impl<'a> Tool<'a> for Newline {
type Data = ();
type Error = Cursor<'a>;
fn parse(&self, st: CursorStart<'a>) -> Result<CursorLen<'a, Self::Data>, Self::Error> {
Seq {
first: RepeatAny::new_bounds('\r', TrueTool, 1),
second: '\n',
}
.parse(st)
.map(|d| d.get_data().1)
.map_err(Either::into_second)
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct WhiteSP;
impl<'a> AlwaysTool<'a> for WhiteSP {
fn parse_always(&self, st: CursorStart<'a>) -> CursorLen<'a, Self::Data> {
RepeatAny::new_unbounded(Predicate::new(char::is_whitespace), TrueTool)
.parse_always(st)
.get_data()
.1
}
}
always_impl!(WhiteSP);
#[derive(Debug, Clone, Copy, Default)]
pub struct Ident;
impl<'a> Tool<'a> for Ident {
type Data = &'a str;
type Error = Cursor<'a>;
fn parse(&self, st: CursorStart<'a>) -> Result<CursorLen<'a, Self::Data>, Self::Error> {
let su = Seq {
first: Predicate::new(char::is_alphabetic),
second: RepeatAny::new_unbounded(Predicate::new(char::is_alphanumeric), TrueTool),
};
GetStr(su).parse(st).map_err(Either::into_first)
}
}
struct NumberCount {
num: usize,
radix: u32,
}
impl<Z> InsertB<u32, Z> for NumberCount {
fn insert(&mut self, data: u32) {
self.num = self.num * (self.radix as usize) + (data as usize);
}
fn insert_sep(&mut self, _: Z) {}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct AsciiNumber(u32);
impl AsciiNumber {
#[must_use]
pub fn new(radix: u32) -> Self {
assert!((2..=36).contains(&radix), "Invalid radix");
Self(radix)
}
}
impl<'a> Tool<'a> for AsciiNumber {
type Data = usize;
type Error = Cursor<'a>;
fn parse(&self, st: CursorStart<'a>) -> Result<CursorLen<'a, Self::Data>, Self::Error> {
let mut count = NumberCount {
num: 0,
radix: self.0,
};
let st = Repeat::new_unbounded(
PredicateData::new(|c: char| c.to_digit(self.0)).map(|(d, _)| d),
TrueTool.set_error::<Self::Error>(),
1,
)
.parse_logic(st, &mut count)?;
Ok(st.map_data(|()| count.num))
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct PfxAsciiNumber;
impl<'a> Tool<'a> for PfxAsciiNumber {
type Data = usize;
type Error = Cursor<'a>;
fn parse(&self, st: CursorStart<'a>) -> Result<CursorLen<'a, Self::Data>, Self::Error> {
let st = Cursor::from(st);
st.chain("0x").map_or_else(
|er| {
er.chain("0o").map_or_else(
|eer| {
eer.chain("0b").map_or_else(
|eeer| eeer.chain(&AsciiNumber::new(10)),
|nnnx| nnnx.chain_replace(&AsciiNumber::new(2)),
)
},
|nnx| nnx.chain_replace(&AsciiNumber::new(8)),
)
},
|nx| nx.chain_replace(&AsciiNumber::new(16)),
)
}
}