Skip to content

Commit 04a048f

Browse files
Parser: fix exponential parse time on compound chains
1 parent 05428be commit 04a048f

1 file changed

Lines changed: 11 additions & 14 deletions

File tree

src/parser/mod.rs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2028,14 +2028,16 @@ impl<'a> Parser<'a> {
20282028
chain.push(AccessExpr::Dot(expr));
20292029
self.advance_token(); // The consumed placeholder
20302030
}
2031-
// Fallback to parsing an arbitrary expression, but restrict to expression
2032-
// types that are valid after the dot operator. This ensures that e.g.
2033-
// `T.interval` is parsed as a compound identifier, not as an interval
2034-
// expression.
2031+
// Parse a single field component, restricted to expression types valid
2032+
// after `.` (so e.g. `T.interval` is a compound identifier, not an
2033+
// interval expression). Using `parse_prefix` here rather than
2034+
// `parse_subexpr` avoids 2^N work on inputs like `IF a.b.c...x.#`:
2035+
// the outer loop already consumes successive `.field` segments, so a
2036+
// recursive `parse_subexpr` would re-walk the rest of the chain at
2037+
// every dot.
20352038
_ => {
20362039
let expr = self.maybe_parse(|parser| {
2037-
let expr = parser
2038-
.parse_subexpr(parser.dialect.prec_value(Precedence::Period))?;
2040+
let expr = parser.parse_prefix()?;
20392041
match &expr {
20402042
Expr::CompoundFieldAccess { .. }
20412043
| Expr::CompoundIdentifier(_)
@@ -2050,14 +2052,9 @@ impl<'a> Parser<'a> {
20502052
})?;
20512053

20522054
match expr {
2053-
// If we get back a compound field access or identifier,
2054-
// we flatten the nested expression.
2055-
// For example if the current root is `foo`
2056-
// and we get back a compound identifier expression `bar.baz`
2057-
// The full expression should be `foo.bar.baz` (i.e.
2058-
// a root with an access chain with 2 entries) and not
2059-
// `foo.(bar.baz)` (i.e. a root with an access chain with
2060-
// 1 entry`).
2055+
// `parse_prefix` does not itself follow compound chains, but a
2056+
// dialect override could still return a compound expression, so
2057+
// keep the flatten arms for safety.
20612058
Some(Expr::CompoundFieldAccess { root, access_chain }) => {
20622059
chain.push(AccessExpr::Dot(*root));
20632060
chain.extend(access_chain);

0 commit comments

Comments
 (0)