Fix binop parsing bug

This commit is contained in:
Richard Feldman 2019-11-09 03:30:22 -05:00
parent 5dd3d1ff54
commit cf1306c463
2 changed files with 129 additions and 9 deletions

View file

@ -39,7 +39,7 @@ use parse::ident::{ident, unqualified_ident, variant_or_ident, Ident};
use parse::number_literal::number_literal;
use parse::parser::{
allocated, and, attempt, between, char, either, loc, map, map_with_arena, not, not_followed_by,
one_of10, one_of16, one_of2, one_of3, one_of5, one_of6, one_or_more, optional, skip_first,
one_of10, one_of17, one_of2, one_of3, one_of5, one_of6, one_or_more, optional, skip_first,
skip_second, string, then, unexpected, unexpected_eof, zero_or_more, Either, Fail, FailReason,
ParseResult, Parser, State,
};
@ -1130,25 +1130,30 @@ fn ident_to_expr<'a>(src: Ident<'a>) -> Expr<'a> {
}
fn binop<'a>() -> impl Parser<'a, BinOp> {
one_of16(
one_of17(
// Sorted from highest to lowest predicted usage in practice,
// so that successful matches shorrt-circuit as early as possible.
// The only exception to this is that operators which begin
// with other valid operators (e.g. "<=" begins with "<") must
// come before the shorter ones; otherwise, they will never
// be reached because the shorter one will pass and consume!
map(string("|>"), |_| BinOp::Pizza),
map(string("=="), |_| BinOp::Equals),
map(string("!="), |_| BinOp::NotEquals),
map(string("&&"), |_| BinOp::And),
map(string("||"), |_| BinOp::Or),
map(char('+'), |_| BinOp::Plus),
map(char('*'), |_| BinOp::Star),
map(char('-'), |_| BinOp::Minus),
map(char('/'), |_| BinOp::Slash),
map(char('<'), |_| BinOp::LessThan),
map(char('>'), |_| BinOp::GreaterThan),
map(string("<="), |_| BinOp::LessThanOrEq),
map(string(">="), |_| BinOp::GreaterThanOrEq),
map(char('^'), |_| BinOp::Caret),
map(char('%'), |_| BinOp::Percent),
map(string("//"), |_| BinOp::DoubleSlash),
map(char('/'), |_| BinOp::Slash),
map(string("<="), |_| BinOp::LessThanOrEq),
map(char('<'), |_| BinOp::LessThan),
map(string(">="), |_| BinOp::GreaterThanOrEq),
map(char('>'), |_| BinOp::GreaterThan),
map(char('^'), |_| BinOp::Caret),
map(string("%%"), |_| BinOp::DoublePercent),
map(char('%'), |_| BinOp::Percent),
)
}

View file

@ -1195,6 +1195,121 @@ where
)
}
pub fn one_of17<'a, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, A>(
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17,
) -> impl Parser<'a, A>
where
P1: Parser<'a, A>,
P2: Parser<'a, A>,
P3: Parser<'a, A>,
P4: Parser<'a, A>,
P5: Parser<'a, A>,
P6: Parser<'a, A>,
P7: Parser<'a, A>,
P8: Parser<'a, A>,
P9: Parser<'a, A>,
P10: Parser<'a, A>,
P11: Parser<'a, A>,
P12: Parser<'a, A>,
P13: Parser<'a, A>,
P14: Parser<'a, A>,
P15: Parser<'a, A>,
P16: Parser<'a, A>,
P17: Parser<'a, A>,
{
one_of2(
p1,
one_of16(
p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17,
),
)
}
pub fn one_of18<
'a,
P1,
P2,
P3,
P4,
P5,
P6,
P7,
P8,
P9,
P10,
P11,
P12,
P13,
P14,
P15,
P16,
P17,
P18,
A,
>(
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17,
p18: P18,
) -> impl Parser<'a, A>
where
P1: Parser<'a, A>,
P2: Parser<'a, A>,
P3: Parser<'a, A>,
P4: Parser<'a, A>,
P5: Parser<'a, A>,
P6: Parser<'a, A>,
P7: Parser<'a, A>,
P8: Parser<'a, A>,
P9: Parser<'a, A>,
P10: Parser<'a, A>,
P11: Parser<'a, A>,
P12: Parser<'a, A>,
P13: Parser<'a, A>,
P14: Parser<'a, A>,
P15: Parser<'a, A>,
P16: Parser<'a, A>,
P17: Parser<'a, A>,
P18: Parser<'a, A>,
{
one_of2(
p1,
one_of17(
p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18,
),
)
}
// DEBUG COMBINATORS
//
// These use dyn for runtime dynamic dispatch. It prevents combinatoric