chumsky
A parser library for humans with powerful error recovery
0.13.0
27M downloads/mo
#1801 most downloaded on crates.io
source
What this package is like to depend on
Last release 3 months ago
06 May 2026
Release timing varies
gaps range from 2 weeks to 10 months
Most releases are documented
notes for 13 of 21 stable releases
4 versions withdrawn
withdrawn after publishing
5 years old
34 releases · first in 2021
5 releases in the last 12 months
see the full history below
Release timeline
34 releases · Jul 2021 to May 2026Releases
latest 34-
1.0.0-alpha.822 Jan 2025 pre-releaseNothing published for this version
-
1.0.0-alpha.706 Apr 2024 pre-releaseNothing published for this version
-
1.0.0-alpha.611 Oct 2023 pre-releaseNothing published for this version
-
1.0.0-alpha.508 Oct 2023 pre-releaseNothing published for this version
-
1.0.0-alpha.413 May 2023 pre-releaseNothing published for this version
-
1.0.0-alpha.310 Mar 2023 pre-releaseNothing published for this version
-
1.0.0-alpha.207 Mar 2023 pre-releaseNothing published for this version
-
1.0.0-alpha.105 Mar 2023 pre-releaseNothing published for this version
-
1.0.0-alpha.002 Mar 2023 pre-releaseRelease notes
Open source →This is the first released version of
chumsky's 'zero-copy' rewrite.This release has no precise changelog, although one will be added when
1.0.0is eventually released in full form. For now, things are still fluctuating enough that a full changelog would inevitably be out of date in a few weeks.Thanks
This release has been over a year in development and represents the work of a lot of people. In particular:
- @CraftSpider, who effectively co-developed the rewrite with me and came up with large chunks of the core API
- @wackbyte, who ported many combinators over to the new codebase as well as adding no_std support
- @bew, who reworked many combinators around changes to the core API
- @Zij-IT, who ported all of the text combinators across, as well as the (yet to be merged) pratt parser combinator created by @alvra
- Many other contributors who worked on smaller items
How you can help
This is the first alpha release. Do not expect a finished product: many minor API features are still incomplete, missing, or subject to change. Some documentation is incomplete, or still refers to concepts from past versions of the crate. In particular, the tutorial has not yet been updated. You may experience bugs, API footguns, and more issues besides. That said, we're releasing this version because we believe the core of the rewrite is ready to be exposed to users and we want to find out what problems there are and catch them before a full release.
We'd like folks to open issues if they find:
- Bugs
- API oddities (things that don't look/feel right, or could be expressed more neatly)
- Things that feel like they should work, but don't (lifetime issues, unnecessary cloning, etc.)
- Missing features
If you're an even awesome-er sort of person and you feel like contributing to the crate, there's still a lot of work that needs doing in the following areas:
- Documentation
- Writing/updating examples
- Filling API 'holes'
- Porting old APIs over
- Small improvements to existing combinators
- Writing tests
- API design: there's still work to be done on the context-sensitivity, recovery, and iterable parser APIs
All this aside, you'd be helping us out a bunch just by using this alpha release (especially porting existing chumsky parsers over to it) and telling us how you got on: what worked, what didn't work, what things you got stuck on or confused by, etc. If you'd like to give a more casual report like this, feel free to start a discussion.
What's new?
Needless to say, the crate has received a substantial upgrade, overhauling virtually every aspect of its API. It's substantially more capable than it ever was, and now supports the following:
- Zero-copy parsing: parser outputs can hold references to the input
- Nested parsing: parsers can handle nested data structures like token trees
- Stateful parsing: parsers can be parameterised by state, allowing for the natural integration of arena allocators, string interners, etc.
- Memoisation: parsers can opt into memoisation, allowing you to quickly parse awkward grammars that would normally produce exponential behaviour in a traditional recursive descent parser
- Left recursion: the aforementioned memoisation feature can also properly handle left recursive grammars elegantly
- Context-sensitive parsing: parsers can use built-in context sensitivity to carefully parameterise future parsers, allowing you to parse things like Rust-style raw strings, Pythonic indentation, and other context-sensitive syntax that context-free parsers traditionally struggle with
- Iterable parsers: parsers that produce multiple outputs can now be turned into iterators, similar to
logoslexers
Performance
On top of all of that, we've worked really hard to push performance as far as we can using an innovative use of Generic Associated Types (GATs) internally that allows
chumskyto automatically detect when an output is never used (such as with.then_ignore(...)) and avoid generating it all in the first place. You can find some technical details about this approach in Niko Matsakis' blog where they discusschumsky.Our work on performance has paid off:
chumsky's JSON benchmark is now extremely competitive, beating outnomand others, and even banging on the door of more traditional hand-written JSON parsers.In general, you can probably expect this new release to be several times faster than older releases for similar parsers. The JSON benchmark is about 12x faster.
Conclusion
Pushing zero-copy to the point of a release was always going to be a very long road to walk, but we're finally approaching the end. Thanks for using chumsky, and - if you're fortunate enough to have the resources and kind enough to consider donating them - please support the other contributors I listed at the top of this release!
-
0.13.006 May 2026Release notes
Open source →Added
select!andselect_ref!now support cfg attributes.- You can now call
as_terminalandas_non_terminalon labels that will hide the internals for the debug info RichReasoncan now be provided with an arbitraryRichReason::Customtype parameter- Implemented
ConfigParserforOneOf Rich::map_spanParser::map_err_withParser::filter_map
Removed
- Unused
spinandsyncfeature flags
Changed
- Debug info now uses the
Displayimpl to render labels with instead ofDebug - Migrated to Codeberg, updated links accordingly
- Removed the unstable
CacheAPI due to soundness issues - Added
DefaultExpected::NothingElseto allow parsers that can never succeed to generate correct errors - Removed the
Containertrait in favour of std'sFromIterator, allowing.collect()to work with a greater range of types
Fixed
Labelled->LabelledWithconversion now carries over the proper debug settings- Fixed crash when using memoisation with certain kinds of error generation
DefaultExpected::into_ownednow has more permissive lifetime constraints
-
0.12.015 Dec 2025Release notes
Open source →Added
MapExtra::emit, which allows emitting secondary errors during mapping operationsInputRef::emit, which allows emitting secondary errors withincustomparserslabelled_with, which avoids the need to implementClonefor labelsInput::split_token_span, a convenience function for splitting(Token, Span)inputs so that chumsky can understand themInput::split_spanned, which does the same as above, but for implementors ofWrappingSpanspanned, a combinator which automatically annotates a parser output with a span- Experimental:
IterParser::parse_iter, a way to turn anIterParser(likex.repeated()) into an iteratorParser::debug, which provides access to various parser debugging utilities.
Changed
- Made
nested_inmore flexible by allowing it to map between different input types instead of requiring the same input as the outer parser
Fixed
- A prioritisation bug with
nested_in
-
0.11.205 Nov 2025Release notes
Open source →Added
- Implement
Default,PartialOrd, andOrdforSimpleSpan - Implement
PartialOrdandOrdforRich
- Implement
-
0.11.112 Sep 2025 -
0.11.011 Sep 2025 withdrawnRelease notes
Open source →Added
- The
set(...)combinator, which may be used to conveniently parse a set of patterns, in any order - Support for non-associative infix operators are now supported by the
.pratt(...)combinator Parser::try_foldl, allowing folding operations to short-circuit in a manner similar toParser::try_mapParser::contextual, which allows a parser to be disabled or enabled in a context-sensitive manner- Implemented
ValueInputforIterInput, which was previously missing - More types that implement the
Statetrait:RollbackState, which reverts parser state when a parser rewinds and may be used to, for example, count the number of times a pattern appears in the inputTruncateState, which truncates a vector when a parser rewinds, and may be used to implement an arena allocator for AST nodes
- Implemented
IterParserfora.then(b)when bothaandbare bothIterParsers that produce the same output type
Changed
- Made lifetime bounds on
recursiveandParserExtramore permissive - Improved support for grapheme parsing
- Text parsers now report labels
Parser::filternow generates aDefaultExpected::SomethingElselabel instead of nothing (this can be overridden with the.labelled(...)function)- Improved areas of documentation
- Make whitespace parsers reject codepoints that are vulnerable to CVE-2021-42574
- Maybe the
select!parser more permissive, accepting any implementor ofInputinstead of requiringValueInputtoo
Fixed
- Many minor incorrect debug-only sanity checks have been fixed
- Many minor span and error prioritisation behavioural problems have been fixed (most notably,
Parser::try_map) - The
.rewind()parser no longer rewinds any secondary error that were encountered - Accidental
text::ascii::keywordlifetime regression
- The
-
0.10.113 Apr 2025Release notes
Open source →Added
- Implemented
ContainerforVecDeque - New section covering recursion in the guide
Changed
Boxedtypes now have a default type parameter ofextra::Default, likeParserandIterParser- The tutorial has been updated for
0.10and has been moved to the guide
Fixed
- Nonsense spans occasionally generated for non-existent tokens
- Improved docs have been added for several items
- Many minor documentation issues have been fixed
- Implemented
-
0.10.022 Mar 2025Release notes
Open source →The 0.10.0 release of chumsky is a from-scratch rewrite of the crate based on the work that's been ongoing for several years in the 1.0.0 alpha builds. The release of 0.10.0 is, in many ways, a concession to a few inconvenient facts:
- Users were rightly complaining that the latest stable release of chumsky (i.e: that which docs.rs shows by default) was the 0.9.x release, despite the fact that we've been recommending that new users use 1.0.0 alpha builds for a long time now. Many users have accidentally tried to run code taken from the 1.0.0 examples, only to find that they don't work with 0.9.
- 1.0.0 has been in development for a long time, and there are still some breaking changes left to make (although we're getting closer!). Users wants to be able to pull in a stable version and start working productively, and the existing situation was becoming cumbersome.
- Although 1.0.0 is not yet finished, it is moving closer and closer to its final form. It is unlikely that much about the surface API will change between 0.10.0 and 1.0.0, although some changes left to be made are technically breaking.
We recommend that users of chumsky depend on 0.10.0, if they can. Despite that, there are a few things to consider:
- (This has now been resolved) Not all documentation has been properly updated yet. Some docs still reference 0.9.x concepts or are not yet complete.
- Some features are still in a state of partial completeness. We don't anticipate significant breakage going forwards, but some features are explicitly in need of more work and future 0.x releases will address them.
Any help from the community to assist in resolving these points is greatly appreciated!
Here follows the changelog for 0.10.0. I also wrote up an informal migration guide.
Added
- Support for zero-copy parsing (i.e: parser outputs that hold references to the parser input)
- Support for parsing nested inputs like token trees
- Support for parsing context-sensitive grammars such as Python-style indentation, Rust-style raw strings, and much
more - Support for parsing by graphemes as well as unicode codepoints
- Support for caching parsers independent of the lifetime of the parser
- A new trait,
IterParser, that allows expressing parsers that generate many outputs - Added the ability to collect iterable parsers into fixed-size arrays, along with a plethora of other container types
- Support for manipulating shared state during parsing, elegantly allowing support for arena allocators, cstrees,
interners, and much more - Support for a vast array of new input types: slices, strings, arrays,
impl Readers, iterators, etc. - Experimental support for memoization, allowing chumsky to parse left-recursive grammars and reducing the
computational complexity of parsing certain grammars - An extension API, allowing third-party crates to extend chumsky's capabilities and introduce new combinators
- A
prattparser combinator, allowing for conveniently and simply creating expression parsers with precise operator
precedence - A
regexcombinator, allowing the parsing of terms based on a specific regex pattern - Properly differentiated ASCII and Unicode text parsers
Removed
Parser::then_withhas been removed in favour of the new context-sensitive combinators
Changed
- Performance has radically improved
- Error generation and handling is now significantly more flexible
Release notes
Open source →Note: version 0.10 is a from-scratch rewrite of chumsky with innumerable small changes. To avoid this changelog being longer than the compiled works of Douglas Adams, the following is a high-level overview of the major feature additions and does not include small details.
Added
- Support for zero-copy parsing (i.e: parser outputs that hold references to the parser input)
- Support for parsing nested inputs like token trees
- Support for parsing context-sensitive grammars such as Python-style indentation, Rust-style raw strings, and much more
- Support for parsing by graphemes as well as unicode codepoints
- Support for caching parsers independent of the lifetime of the parser
- A new trait,
IterParser, that allows expressing parsers that generate many outputs - Added the ability to collect iterable parsers into fixed-size arrays, along with a plethora of other container types
- Support for manipulating shared state during parsing, elegantly allowing support for arena allocators, cstrees, interners, and much more
- Support for a vast array of new input types: slices, strings, arrays,
impl Readers, iterators, etc. - Experimental support for memoization, allowing chumsky to parse left-recursive grammars and reducing the computational complexity of parsing certain grammars
- An extension API, allowing third-party crates to extend chumsky's capabilities and introduce new combinators
- A
prattparser combinator, allowing for conveniently and simply creating expression parsers with precise operator precedence - A
regexcombinator, allowing the parsing of terms based on a specific regex pattern - Properly differentiated ASCII and Unicode text parsers
Removed
Parser::then_withhas been removed in favour of the new context-sensitive combinators
Changed
- Performance has radically improved
- Error generation and handling is now significantly more flexible
-
0.9.324 Oct 2023Nothing published for this version
-
0.9.202 Mar 2023 -
0.9.102 Mar 2023 withdrawn -
0.9.007 Feb 2023Release notes
Open source →Added
- A
spill-stackfeature that usesstackerto avoid stack overflow errors for deeply recursive parsers - The ability to access the token span when using
select!likeselect! { |span| Token::Num(x) => (x, span) } - Added a
skip_parserrecovery strategy that allows you to implement your own recovery strategies in terms of other
parsers. For example,.recover_with(skip_parser(take_until(just(';'))))skips tokens until after the next semicolon - A
notcombinator that consumes a single token if it is not the start of a given pattern. For example,
just("\\n").or(just('"')).not()matches anycharthat is not either the final quote of a string, and is not the
start of a newline escape sequence - A
semantic_indentationparser for parsing indentation-sensitive languages. Note that this is likely to be
deprecated/removed in the future in favour of a more powerful solution #[must_use]attribute for parsers to ensure that they're not accidentally created without being usedOption<Vec<T>>andVec<Option<T>>now implementChain<T>andOption<String>implementsChain<char>choicenow supports both arrays and vectors of parsers in addition to tuples- The
Simpleerror type now implementsEq
Changed
text::whitespacereturns aRepeatedinstead of animpl Parser, allowing you to call methods likeat_leastand
exactlyon it.- Improved
no_stdsupport - Improved examples and documentation
- Use zero-width spans for EoI by default
- Don't allow defining a recursive parser more than once
- Various minor bug fixes
- Improved
Displayimplementations for various built-in error types andSimpleReason - Use an
OrderedContainertrait to avoid unexpected behaviour for unordered containers in combination withjust
Fixed
- Made several parsers (
todo,unwrapped, etc.) more useful by reporting the parser's location on panic - Boxing a parser that is already boxed just gives you the original parser to avoid double indirection
- Improved compilation speeds
Release notes
Open source →Added
- A
spill-stackfeature that usesstackerto avoid stack overflow errors for deeply recursive parsers - The ability to access the token span when using
select!likeselect! { |span| Token::Num(x) => (x, span) } - Added a
skip_parserrecovery strategy that allows you to implement your own recovery strategies in terms of other parsers. For example,.recover_with(skip_parser(take_until(just(';'))))skips tokens until after the next semicolon - A
notcombinator that consumes a single token if it is not the start of a given pattern. For example,just("\\n").or(just('"')).not()matches anycharthat is not either the final quote of a string, and is not the start of a newline escape sequence - A
semantic_indentationparser for parsing indentation-sensitive languages. Note that this is likely to be deprecated/removed in the future in favour of a more powerful solution #[must_use]attribute for parsers to ensure that they're not accidentally created without being usedOption<Vec<T>>andVec<Option<T>>now implementChain<T>andOption<String>implementsChain<char>choicenow supports both arrays and vectors of parsers in addition to tuples- The
Simpleerror type now implementsEq
Changed
text::whitespacereturns aRepeatedinstead of animpl Parser, allowing you to call methods likeat_leastandexactlyon it.- Improved
no_stdsupport - Improved examples and documentation
- Use zero-width spans for EoI by default
- Don't allow defining a recursive parser more than once
- Various minor bug fixes
- Improved
Displayimplementations for various built-in error types andSimpleReason - Use an
OrderedContainertrait to avoid unexpected behaviour for unordered containers in combination withjust
Fixed
- Made several parsers (
todo,unwrapped, etc.) more useful by reporting the parser's location on panic - Boxing a parser that is already boxed just gives you the original parser to avoid double indirection
- Improved compilation speeds
- A
-
0.8.007 Feb 2022Release notes
Open source →Added
then_withcombinator to allow limited support for parsing nested patterns- impl From<&[T; N]> for Stream
SkipUntil/SkipThenRetryUntil::skip_start/consume_endfor more precise control over skip-based recovery
Changed
- Allowed
Validateto map the output type - Switched to zero-size End Of Input spans for default implementations of
Stream - Made
delimited_bytake combinators instead of specific tokens - Minor optimisations
- Documentation improvements
Fixed
- Compilation error with
--no-default-features - Made default behaviour of
skip_untilmore sensible
-
0.7.016 Dec 2021Release notes
Open source →Added
-
A new tutorial to help new users
-
selectmacro, a wrapper overfilter_mapthat makes extracting data from specific tokens easy -
choiceparser, a better alternative to longorchains (which sometimes have poor compilation performance) -
todoparser, that panics when used (but not when created) (akin to Rust'stodo!macro, but for parsers) -
keywordparser, that parses exact identifiers -
from_strcombinator to allow converting a pattern to a value inline, usingstd::str::FromStr -
unwrappedcombinator, to automatically unwrap an output value inline -
rewindcombinator, that allows reverting the input stream on success. It's most useful when requiring that a pattern is followed by some terminating pattern without the first parser greedily consuming it -
map_err_with_spancombinator, to allow fetching the span of the input that was parsed by a parser before an error was encountered -
or_elsecombinator, to allow processing and potentially recovering from a parser error -
SeparatedBy::at_mostto require that a separated pattern appear at most a specific number of times -
SeparatedBy::exactlyto require that a separated pattern be repeated exactly a specific number of times -
Repeated::exactlyto require that a pattern be repeated exactly a specific number of times -
More trait implementations for various things, making the crate more useful
Changed
- Made
just,one_of, andnone_ofsignificant more useful. They can now accept strings, arrays, slices, vectors, sets, or just single tokens as before - Added the return type of each parser to its documentation
- More explicit documentation of parser behaviour
- More doc examples
- Deprecated
seq(justhas been generalised and can now be used to parse specific input sequences) - Sealed the
Charactertrait so that future changes are not breaking - Sealed the
Chaintrait and made it more powerful - Moved trait constraints on
Parserto where clauses for improved readability
Fixed
- Fixed a subtle bug that allowed
separated_byto parse an extra trailing separator when it shouldn't - Filled a 'hole' in the
Errortrait's API that conflated a lack of expected tokens with expectation of end of input - Made recursive parsers use weak reference-counting to avoid memory leaks
-
-
0.6.022 Nov 2021Release notes
Open source →Added
skip_untilerror recovery strategySeparatedBy::at_leastandSeparatedBy::at_mostfor parsing a specific number of separated itemsParser::validatefor integrated AST validationRecursive::declareandRecursive::definefor more precise control over recursive declarations
Changed
- Improved
separated_byerror messages - Improved documentation
- Hid a new (probably) unused implementation details
-
0.5.1-alpha22 Oct 2021 pre-release withdrawnNothing published for this version
-
0.5.030 Oct 2021Release notes
Open source →Added
take_untilprimitive
Changed
- Added span to fallback output function in
nested_delimiters
-
0.5.0-alpha03 Oct 2021 pre-release withdrawnNothing published for this version
-
0.4.128 Oct 2021Nothing published for this version
-
0.4.028 Oct 2021Release notes
Open source →Added
- Support for LL(k) parsing
- Custom error recovery strategies
- Debug mode
- Nested input flattening
Changed
- Radically improved error quality
-
0.3.223 Jul 2021Nothing published for this version
-
0.3.117 Jul 2021Nothing published for this version
-
0.3.012 Jul 2021Nothing published for this version
-
0.2.011 Jul 2021Nothing published for this version
-
0.1.011 Jul 2021Nothing published for this version
-
0.0.010 Jul 2021Nothing published for this version