Parse logic operators right associative

This commit is contained in:
Joscha 2022-11-19 13:26:09 +01:00
parent 5e26d9550c
commit b590f640f4

View file

@ -64,19 +64,44 @@ fn left_assoc(
.boxed() .boxed()
} }
fn right_assoc(
op: impl Parser<char, BinOp, Error = Error> + Clone + 'static,
over: impl Parser<char, Expr, Error = Error> + Clone + 'static,
) -> BoxedParser<'static, char, Expr, Error> {
let over_op = over
.clone()
.then(space())
.then(op)
.then(space())
.map(|(((left, s0), op), s1)| (left, s0, op, s1));
over_op
.repeated()
.then(over)
.foldr(|(left, s0, op, s1), right| Expr::BinOp {
span: left.span().join(right.span()),
left: Box::new(left),
s0,
op,
s1,
right: Box::new(right),
})
.boxed()
}
pub fn expr( pub fn expr(
expr: impl Parser<char, Expr, Error = Error> + Clone + 'static, expr: impl Parser<char, Expr, Error = Error> + Clone + 'static,
) -> BoxedParser<'static, char, Expr, Error> { ) -> BoxedParser<'static, char, Expr, Error> {
// * / % // * / %
let prec0 = (just('*').to(BinOp::Mul)) let op_prec_4 = (just('*').to(BinOp::Mul))
.or(just('/').to(BinOp::Div)) .or(just('/').to(BinOp::Div))
.or(just('%').to(BinOp::Mod)); .or(just('%').to(BinOp::Mod));
// + - // + -
let prec1 = (just('+').to(BinOp::Add)).or(just('-').to(BinOp::Sub)); let op_prec_3 = (just('+').to(BinOp::Add)).or(just('-').to(BinOp::Sub));
// == != > >= < <= // == != > >= < <=
let prec2 = (just("==").to(BinOp::Eq)) let op_prec_2 = (just("==").to(BinOp::Eq))
.or(just("!=").to(BinOp::Neq)) .or(just("!=").to(BinOp::Neq))
.or(just('>').to(BinOp::Gt)) .or(just('>').to(BinOp::Gt))
.or(just(">=").to(BinOp::Ge)) .or(just(">=").to(BinOp::Ge))
@ -84,16 +109,19 @@ pub fn expr(
.or(just("<=").to(BinOp::Le)); .or(just("<=").to(BinOp::Le));
// and // and
let prec3 = text::keyword("and").to(BinOp::And); let op_prec_1 = text::keyword("and").to(BinOp::And);
// or // or
let prec4 = text::keyword("or").to(BinOp::Or); let op_prec_0 = text::keyword("or").to(BinOp::Or);
right_assoc(
op_prec_0,
right_assoc(
op_prec_1,
left_assoc( left_assoc(
prec4, op_prec_2,
left_assoc( left_assoc(op_prec_3, left_assoc(op_prec_4, atom(expr))),
prec3, ),
left_assoc(prec2, left_assoc(prec1, left_assoc(prec0, atom(expr)))),
), ),
) )
} }