From c0140d0671e81b57e8fd142c66c675a659fd50f8 Mon Sep 17 00:00:00 2001 From: Dennis Ranke Date: Sun, 21 Nov 2021 22:41:00 +0100 Subject: [PATCH] fix two exponential parse time blow-ups --- src/parser.rs | 48 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index b88ed1d..8b02e10 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -388,16 +388,6 @@ fn script_parser() -> impl Parser> + C }) .boxed(); - let tee = identifier - .clone() - .then_ignore(just(Token::Op(":=".to_string()))) - .then(expression.clone()) - .map(|(name, value)| ast::Expr::LocalTee { - name, - value: Box::new(value), - }) - .boxed(); - let assign = identifier .clone() .then_ignore(just(Token::Op("=".to_string()))) @@ -443,7 +433,6 @@ fn script_parser() -> impl Parser> + C }); let atom = val - .or(tee) .or(function_call) .or(assign) .or(local_tee) @@ -560,23 +549,31 @@ fn script_parser() -> impl Parser> + C let memory_op = op_cast .clone() .or(short_memory_op.clone()) - .then(mem_op.clone().repeated().at_least(1)) .then( - just(Token::Op("=".to_string())) - .ignore_then(expression.clone()) + mem_op + .clone() + .repeated() + .at_least(1) + .then( + just(Token::Op("=".to_string())) + .ignore_then(expression.clone()) + .or_not(), + ) .or_not(), ) - .map(|((left, mut peek_ops), poke_op)| { - if let Some(value) = poke_op { - let poke_op = Some((peek_ops.pop().unwrap(), value)); - make_memory_op(left, peek_ops, poke_op) + .map(|(left, ops)| { + if let Some((mut peek_ops, poke_op)) = ops { + if let Some(value) = poke_op { + let poke_op = Some((peek_ops.pop().unwrap(), value)); + make_memory_op(left, peek_ops, poke_op) + } else { + make_memory_op(left, peek_ops, None) + } } else { - make_memory_op(left, peek_ops, None) + left } }) - .boxed() - .or(op_cast.clone()) - .or(short_memory_op.clone()); + .boxed(); let op_product = memory_op .clone() @@ -715,10 +712,11 @@ fn script_parser() -> impl Parser> + C let block_expression = block_expression.unwrap(); - expression + block_expression .clone() - .then(just(Token::Ctrl(';')).to(false)) - .or(block_expression.map_with_span(|expr, span| (expr.with_span(span), true))) + .then(just(Token::Ctrl(';')).or_not()) + .map_with_span(|(expr, semi), span| (expr.with_span(span), semi.is_none())) + .or(expression.clone().then(just(Token::Ctrl(';')).to(false))) .repeated() .then(expression.clone().or_not()) .map_with_span(|(mut statements, mut final_expression), span| {