Repository navigation
fix(combinators): stop non-advancing loops and correct edge cases - #4
Merged
Merged
Conversation
- manyTill, until, postfix, prefix, separatedBy, interleaved, chainLeft1,
chainRight1 and optionalSeparatedBy stop when an iteration consumes no
input, instead of looping until the process runs out of memory
- chainLeft/chainRight now succeed with null on zero terms, as their
type and the zero-or-more naming promise, instead of duplicating the
`1` variants
- grammar and lazy build each parser once, so memoize inside a rule
actually caches
- separatedEndBy no longer consumes a separator that has no item before it
- optionalSeparatedBy keeps empty slots between separators as null
- oneOf docs now say first match wins, which is what the code and its
tests always did; regex documents that only a leading ^ is stripped
BREAKING CHANGE: chainLeft and chainRight return { ok: true, value: null }
on input with no term, where they previously failed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes logic bugs found while reviewing the library. Each one now has a regression test.
Infinite loops.
manyTill,until,postfix,prefix,separatedBy,interleaved,chainLeft1,chainRight1andoptionalSeparatedBylooped forever when an iteration consumed no input (e.g.postfix(digit, pure(x => x))), until the process ran out of memory. They now stop the same waymanyalready did.Breaking:
chainLeft/chainRight. They wrapped the1variant inoptionaland then failed onnull, so they behaved likechainLeft1/chainRight1and also failed when a term legitimately parsed tonull. They now succeed withnullon zero terms, which matches theirT | nulltype and the zero-or-more pattern used bymany,separatedByandfold.grammar/lazy. These rebuilt the parser on every call, so amemoizeinside a rule never got a cache hit. Each parser is now built once.separatedEndBy. No longer consumes a separator that has no item before it (','→[]at index 0).optionalSeparatedBy. Empty slots between separators are now kept asnull('1,,2'→[1, null, 2]). Before, parsing stopped at the second comma.Docs only. The
oneOfdocs claimed "longest match wins", but the code and its original tests use first match, so the docs now say that.regexnow documents that only a leading^is stripped.README.md,doc/api/andtest/examples.test.tswere regenerated. All 1386 tests and lint pass.🤖 Generated with Claude Code