use crate::*;
#[derive(Clone)]
pub enum Infix<LHS, Operator, RHS> {
Found {
lhs: LHS,
operator: Operator,
rhs: RHS,
},
None(LHS),
}
impl<LHS, Operator, RHS> ::std::fmt::Debug
for Infix<LHS, Operator, RHS>
where
LHS: ::std::fmt::Debug,
RHS: ::std::fmt::Debug,
Operator: ::std::fmt::Debug,
{
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
match self {
Self::Found { lhs, operator, rhs } => f
.debug_map()
.entry(&"lhs", lhs)
.entry(&"operator", operator)
.entry(&"rhs", rhs)
.finish(),
Self::None(lhs) => std::fmt::Debug::fmt(lhs, f),
}
}
}
impl<'code, LHS, Operator, RHS> Lexer<'code>
for Infix<LHS, Operator, RHS>
where
LHS: Lexer<'code>,
Operator: Lexer<'code>,
RHS: Lexer<'code>,
{
fn lex(
buffer: &mut Buffer<'code>,
) -> Result<Self, Error<'code>> {
let mut local_buffer = buffer.clone();
let matched = 0usize;
let lhs = <LHS as Lexer>::lex(&mut local_buffer)?;
let matched = matched + 1;
match <Operator as Lexer>::lex(&mut local_buffer) {
Ok(operator) => {
let matched = matched + 1;
let rhs =
<RHS as Lexer>::lex(&mut local_buffer)
.map_err(|mut err| {
err.matched = matched;
err
})?;
*buffer = local_buffer;
Ok(Self::Found { lhs, operator, rhs })
}
Err(_none) => {
*buffer = local_buffer;
Ok(Self::None(lhs))
}
}
}
}
impl<'code, LHS, Operator, RHS> Token<'code>
for Infix<LHS, Operator, RHS>
where
LHS: Lexer<'code>,
Operator: Lexer<'code>,
RHS: Lexer<'code>,
{
fn buffer(&self) -> Option<Buffer<'code>> {
match self {
Infix::Found { lhs, rhs, operator } => {
let buffers = [
<LHS as Token>::buffer(lhs),
<Operator as Token>::buffer(operator),
<RHS as Token>::buffer(rhs),
]
.into_iter();
buffers
.flatten()
.reduce(|acc, current| acc + current)
}
Infix::None(lhs) => <LHS as Token>::buffer(lhs),
}
}
const NAME: &'static str = "Infix";
}
#[cfg(test)]
mod tests;