#[cfg(test)]
mod tests;
use nom::error::{ErrorKind, FromExternalError, ParseError};
use nom::{Check, Err, IResult, Input, Mode, OutputM, OutputMode, Parser};
pub struct Unary<V, Q: Ord + Copy> {
value: V,
precedence: Q,
}
pub struct Binary<V, Q: Ord + Copy> {
value: V,
precedence: Q,
assoc: Assoc,
}
pub enum Operation<P1, P2, P3, O> {
Prefix(P1, O),
Postfix(O, P2),
Binary(O, P3, O),
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Assoc {
Left,
Right,
}
enum Operator<P1, P2, P3, Q: Ord + Copy> {
Prefix(P1, Q),
Postfix(P2, Q),
Binary(P3, Q, Assoc),
}
impl<P1, P2, P3, Q> Operator<P1, P2, P3, Q>
where
Q: Ord + Copy,
{
fn precedence(&self) -> Q {
match self {
Operator::Prefix(_, p) => *p,
Operator::Postfix(_, p) => *p,
Operator::Binary(_, p, _) => *p,
}
}
fn is_postfix(&self) -> bool {
match self {
Operator::Postfix(_, _) => true,
_ => false,
}
}
}
pub fn unary_op<I, O, E, P, Q>(
precedence: Q,
mut parser: P,
) -> impl FnMut(I) -> IResult<I, Unary<O, Q>, E>
where
P: Parser<I, Output = O, Error = E>,
Q: Ord + Copy,
{
move |input| match parser.parse(input) {
Ok((i, value)) => Ok((i, Unary { value, precedence })),
Err(e) => Err(e),
}
}
pub fn binary_op<I, O, E, P, Q>(
precedence: Q,
assoc: Assoc,
mut parser: P,
) -> impl FnMut(I) -> IResult<I, Binary<O, Q>, E>
where
P: Parser<I, Output = O, Error = E>,
Q: Ord + Copy,
{
move |input| match parser.parse(input) {
Ok((i, value)) => Ok((
i,
Binary {
value,
precedence,
assoc,
},
)),
Err(e) => Err(e),
}
}
pub fn precedence<I, O, E, E2, F, G, H1, H3, H2, P1, P2, P3, Q>(
mut prefix: H1,
mut postfix: H2,
mut binary: H3,
mut operand: F,
mut fold: G,
) -> impl FnMut(I) -> IResult<I, O, E>
where
I: Clone + PartialEq,
E: ParseError<I> + FromExternalError<I, E2>,
F: Parser<I, Output = O, Error = E>,
G: FnMut(Operation<P1, P2, P3, O>) -> Result<O, E2>,
H1: Parser<I, Output = Unary<P1, Q>, Error = E>,
H2: Parser<I, Output = Unary<P2, Q>, Error = E>,
H3: Parser<I, Output = Binary<P3, Q>, Error = E>,
Q: Ord + Copy,
{
move |mut i| {
let mut operands = Vec::new();
let mut operators = Vec::new();
let mut i1 = i.clone();
'main: loop {
'prefix: loop {
match prefix.parse(i1.clone()) {
Err(Err::Error(_)) => break 'prefix,
Err(e) => return Err(e),
Ok((i2, o)) => {
if i2 == i1 {
return Err(Err::Error(E::from_error_kind(i1, ErrorKind::Precedence)));
}
i1 = i2;
operators.push(Operator::Prefix(o.value, o.precedence));
}
}
}
let (i2, o) = match operand.parse(i1.clone()) {
Ok((i, o)) => (i, o),
Err(Err::Error(e)) => return Err(Err::Error(E::append(i, ErrorKind::Precedence, e))),
Err(e) => return Err(e),
};
i1 = i2;
operands.push(o);
'postfix: loop {
match postfix.parse(i1.clone()) {
Err(Err::Error(_)) => break 'postfix,
Err(e) => return Err(e),
Ok((i2, o)) => {
if i2 == i1 {
return Err(Err::Error(E::from_error_kind(i1, ErrorKind::Precedence)));
}
while operators
.last()
.map(|op| op.precedence() <= o.precedence)
.unwrap_or(false)
{
let value = operands.pop().unwrap();
let operation = match operators.pop().unwrap() {
Operator::Prefix(op, _) => Operation::Prefix(op, value),
Operator::Postfix(op, _) => Operation::Postfix(value, op),
Operator::Binary(op, _, _) => match operands.pop() {
Some(lhs) => Operation::Binary(lhs, op, value),
None => return Err(Err::Error(E::from_error_kind(i1, ErrorKind::Precedence))),
},
};
let result = match fold(operation) {
Err(e) => {
return Err(Err::Error(E::from_external_error(
i,
ErrorKind::Precedence,
e,
)))
}
Ok(r) => r,
};
operands.push(result);
}
i1 = i2;
operators.push(Operator::Postfix(o.value, o.precedence));
}
}
}
match binary.parse(i1.clone()) {
Err(Err::Error(_)) => break 'main,
Err(e) => return Err(e),
Ok((i2, o)) => {
while operators
.last()
.map(|op| {
op.precedence() < o.precedence
|| (o.assoc == Assoc::Left && op.precedence() == o.precedence)
|| (op.is_postfix())
})
.unwrap_or(false)
{
let value = operands.pop().unwrap();
let operation = match operators.pop().unwrap() {
Operator::Prefix(op, _) => Operation::Prefix(op, value),
Operator::Postfix(op, _) => Operation::Postfix(value, op),
Operator::Binary(op, _, _) => match operands.pop() {
Some(lhs) => Operation::Binary(lhs, op, value),
None => return Err(Err::Error(E::from_error_kind(i1, ErrorKind::Precedence))),
},
};
let result = match fold(operation) {
Err(e) => {
return Err(Err::Error(E::from_external_error(
i,
ErrorKind::Precedence,
e,
)))
}
Ok(r) => r,
};
operands.push(result);
}
operators.push(Operator::Binary(o.value, o.precedence, o.assoc));
i1 = i2;
}
}
if i == i1 {
return Err(Err::Error(E::from_error_kind(i, ErrorKind::Precedence)));
}
i = i1.clone();
}
while operators.len() > 0 {
let value = match operands.pop() {
Some(o) => o,
None => return Err(Err::Error(E::from_error_kind(i, ErrorKind::Precedence))),
};
let operation = match operators.pop().unwrap() {
Operator::Prefix(op, _) => Operation::Prefix(op, value),
Operator::Postfix(op, _) => Operation::Postfix(value, op),
Operator::Binary(op, _, _) => match operands.pop() {
Some(lhs) => Operation::Binary(lhs, op, value),
None => return Err(Err::Error(E::from_error_kind(i, ErrorKind::Precedence))),
},
};
let result = match fold(operation) {
Ok(r) => r,
Err(e) => {
return Err(Err::Error(E::from_external_error(
i,
ErrorKind::Precedence,
e,
)))
}
};
operands.push(result);
}
if operands.len() == 1 {
return Ok((i1, operands.pop().unwrap()));
} else {
return Err(Err::Error(E::from_error_kind(i, ErrorKind::Precedence)));
}
}
}
pub fn left_assoc<I, E, O, OP, G, F, B>(
child: F,
operator: G,
builder: B,
) -> impl Parser<I, Output = O, Error = E>
where
I: Clone + Input,
E: ParseError<I>,
F: Parser<I, Output = O, Error = E>,
G: Parser<I, Output = OP, Error = E>,
B: FnMut(O, OP, O) -> O,
{
LeftAssoc {
child,
operator,
builder,
}
}
pub struct LeftAssoc<F, G, B> {
child: F,
operator: G,
builder: B,
}
impl<I, E, O, OP, G, F, B> Parser<I> for LeftAssoc<F, G, B>
where
I: Clone + Input,
E: ParseError<I>,
F: Parser<I, Output = O, Error = E>,
G: Parser<I, Output = OP, Error = E>,
B: FnMut(O, OP, O) -> O,
{
type Output = O;
type Error = E;
fn process<OM: OutputMode>(
&mut self,
mut i: I,
) -> nom::PResult<OM, I, Self::Output, Self::Error> {
let (i1, mut res) = self.child.process::<OM>(i)?;
i = i1;
loop {
let len = i.input_len();
match self
.operator
.process::<OutputM<OM::Output, Check, OM::Incomplete>>(i.clone())
{
Err(Err::Error(_)) => return Ok((i, res)),
Err(Err::Failure(e)) => return Err(Err::Failure(e)),
Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)),
Ok((i1, op)) => {
match self
.child
.process::<OutputM<OM::Output, Check, OM::Incomplete>>(i1.clone())
{
Err(Err::Error(_)) => return Ok((i, res)),
Err(Err::Failure(e)) => return Err(Err::Failure(e)),
Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)),
Ok((i2, rhs)) => {
if i2.input_len() == len {
return Err(Err::Error(OM::Error::bind(|| {
<F as Parser<I>>::Error::from_error_kind(i, ErrorKind::SeparatedList)
})));
}
let op_rhs = OM::Output::combine(op, rhs, |op, rhs| (op, rhs));
res = OM::Output::combine(res, op_rhs, |lhs, (op, rhs)| (self.builder)(lhs, op, rhs));
i = i2;
}
}
}
}
}
}
}