fix quadratic parsing of expression
This commit is contained in:
parent
a69c6ab0b3
commit
dfc74b4b24
|
@ -2,7 +2,7 @@ use super::tokens::{token, Token, TokenKind as tk, TokenSpan};
|
|||
use super::{IResult, Span};
|
||||
use nom::{
|
||||
branch::alt,
|
||||
combinator::map,
|
||||
combinator::{map, opt},
|
||||
multi::separated_list0,
|
||||
sequence::{delimited, preceded, separated_pair, tuple},
|
||||
};
|
||||
|
@ -88,12 +88,18 @@ fn bitop_kind(input: TokenSpan) -> IResult<TokenSpan, BinOpKind> {
|
|||
/// bit and, or, xor e.g. a ^ b & c
|
||||
/// TODO: make precedence rules for bit ops
|
||||
fn bitop(input: TokenSpan) -> IResult<TokenSpan, Expression> {
|
||||
alt((
|
||||
map(tuple((unary, bitop_kind, bitop)), |(a, kind, b)| {
|
||||
Expression::BinOp(Box::new(BinOp { a, b, kind }))
|
||||
}),
|
||||
unary,
|
||||
))(input)
|
||||
// special care is given to avoid parsing `unary` twice, as that would
|
||||
// make this parser quadratic
|
||||
map(
|
||||
tuple((unary, opt(tuple((bitop_kind, bitop))))),
|
||||
|(a, rest)| {
|
||||
if let Some((kind, b)) = rest {
|
||||
Expression::BinOp(Box::new(BinOp { a, b, kind }))
|
||||
} else {
|
||||
a
|
||||
}
|
||||
},
|
||||
)(input)
|
||||
}
|
||||
|
||||
pub fn call_item(input: TokenSpan) -> IResult<TokenSpan, Call> {
|
||||
|
@ -140,6 +146,10 @@ mod test {
|
|||
fn test_atoms() {
|
||||
fullexpr(TokenSpan::new(&tok("a"))).unwrap();
|
||||
fullexpr(TokenSpan::new(&tok("(a)"))).unwrap();
|
||||
fullexpr(TokenSpan::new(&tok(
|
||||
"(((((((((((((((((((a)))))))))))))))))))",
|
||||
)))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -147,7 +157,7 @@ mod test {
|
|||
fullexpr(TokenSpan::new(&tok("asdf"))).unwrap();
|
||||
fullexpr(TokenSpan::new(&tok("~(asdf)"))).unwrap();
|
||||
fullexpr(TokenSpan::new(&tok("!asdf"))).unwrap();
|
||||
// unary(TokenSpan::new(&tok("~!(asdf)"))).unwrap();
|
||||
fullexpr(TokenSpan::new(&tok("~!(asdf)"))).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in New Issue