Skip to content

Releases: purpleclay/chomp

v0.7.0

03 Feb 06:49
v0.7.0
a6a166b

Choose a tag to compare

v0.7.0 - February 03, 2026

Contributors

Performance Improvements

  • 841e0d9 optimize Take using utf8.DecodeRuneInString avoiding allocations (#106) (@purpleclay)

    Use utf8.DecodeRuneInString to iterate through runes instead of converting the entire string to []rune, eliminating unnecessary allocations.

    benchstat results (n=10):

                    │   baseline   │             optimized              │
                    │    sec/op    │   sec/op     vs base               │
    Take/Ascii-12      75.35n ± 1%   15.65n ± 0%  -79.24% (p=0.000)
    Take/Unicode-12    95.28n ± 0%   10.17n ± 1%  -89.32% (p=0.000)
  • a54ca13 optimize AnyChar and Satisfy using utf8.DecodeRuneInString avoiding allocations (#104) (@purpleclay)

    Use utf8.DecodeRuneInString instead of []rune(s) conversion to extract the first character, eliminating unnecessary allocations.

    benchstat results (n=10):

                         │   baseline   │             optimized              │
                         │    sec/op    │   sec/op     vs base               │
    AnyChar/Ascii-10        56.51n ± 1%    1.80n ± 11%  -96.81% (p=0.000)
    AnyChar/Unicode-10      55.43n ± 0%    1.65n ± 10%  -97.03% (p=0.000)
    Satisfy/Ascii-10        56.94n ± 1%    2.06n ±  7%  -96.39% (p=0.000)
    Satisfy/Unicode-10      54.70n ± 2%    1.78n ±  5%  -96.74% (p=0.000)
  • 04bb974 pre-compute character sets for Any and Not combinators (#103) (@purpleclay)

    Build a map[rune]struct{} at combinator creation time to reduce character lookup complexity from O(m) to O(1) per input character, where m is the charset length.

    A threshold of 8 characters is used to determine when to use the map-based approach versus linear scanning. For small charsets (<8 chars), linear scanning is faster due to better cache locality and lower overhead. For larger charsets, the map lookup becomes more efficient.

    benchstat results (n=10):

                         │   baseline   │             optimized              │
                         │    sec/op    │   sec/op     vs base               │
    Any/Small/Ascii-12       11.45n ± 1%    9.53n ± 1%  -16.73% (p=0.000)
    Any/Large/Ascii-12       92.95n ± 0%   67.51n ± 2%  -27.38% (p=0.000)
    Any/Small/Unicode-12     29.05n ± 1%   27.92n ± 1%   -3.87% (p=0.000)
    Any/Large/Unicode-12    129.10n ± 1%   60.27n ± 2%  -53.32% (p=0.000)
    Not/Small/Ascii-12       62.27n ± 1%   52.23n ± 3%  -16.12% (p=0.000)
    Not/Large/Ascii-12       142.9n ± 1%   109.8n ± 0%  -23.20% (p=0.000)
    Not/Small/Unicode-12     98.23n ± 0%   96.01n ± 1%   -2.26% (p=0.000)
    Not/Large/Unicode-12     273.8n ± 0%   110.3n ± 1%  -59.70% (p=0.000)
  • b27af34 replace len(string(rune)) with utf8.RuneLen avoiding temporary string allocations (#100) (@purpleclay)

    Replace the len(string(c)) pattern with utf8.RuneLen(c) across predicate loops in basic.go and predicate.go. This avoids creating temporary string allocations when calculating rune byte lengths.

    Also optimized Escaped and EscapedTransform to use utf8.DecodeRuneInString instead of converting the entire remaining string to []rune just to check the first character.

    benchstat results (n=10):

                              │   baseline   │             optimized              │
                              │    sec/op    │   sec/op     vs base               │
    Any/Ascii-12                 40.65n ± 1%   38.29n ± 0%   -5.79% (p=0.000)
    Any/Unicode-12               62.34n ± 1%   54.76n ± 2%  -12.17% (p=0.000)
    Not/Ascii-12                 67.46n ± 1%   63.11n ± 1%   -6.44% (p=0.000)
    Not/Unicode-12              116.65n ± 1%   98.93n ± 0%  -15.19% (p=0.000)
    While/Digit-12               28.36n ± 0%   23.43n ± 0%  -17.39% (p=0.000)
    While/Letter/Ascii-12       10.480n ± 1%   8.715n ± 1%  -16.85% (p=0.000)
    While/Letter/Unicode-12      249.9n ± 0%   222.9n ± 1%  -10.80% (p=0.000)
    While/Alphanumeric-12        60.57n ± 0%   50.73n ± 0%  -16.25% (p=0.000)
    While/Space-12               21.95n ± 0%   17.52n ± 6%  -20.19% (p=0.000)
    WhileNot/Digit/Ascii-12      125.7n ± 1%   103.6n ± 0%  -17.55% (p=0.000)
    WhileNot/Digit/Unicode-12    205.6n ± 1%   178.8n ± 1%  -13.04% (p=0.000)
  • 742117b optimize Eol by inlining logic avoiding combinator composition overhead (#99) (@purpleclay)

    Replace the composed combinator chain Suffixed(WhileNotN(IsLineEnding, 0), Opt(Crlf())) with inlined logic using direct string iteration and byte comparisons to avoid heap allocations from combinator composition on each call.

    benchstat results (n=10):

                   │   baseline   │             optimized              │
                   │    sec/op    │   sec/op     vs base               │
    Eol/Ascii-12      159.95n ± 1%   54.90n ± 0%  -65.67% (p=0.000)
    Eol/Unicode-12    146.55n ± 0%   55.17n ± 1%  -62.35% (p=0.000)
  • ba03235 optimize Char, OneOf, and NoneOf using utf8.DecodeRuneInString avoiding allocations (#98) (@purpleclay)

    Replace []rune(s) conversions with utf8.DecodeRuneInString to avoid heap allocations when checking the first character of input strings.

    benchstat results (n=10):

                      │   baseline   │            optimized             │
                      │    sec/op    │   sec/op     vs base             │
    Char/Ascii-12        60.20n ± 3%   1.75n ± 6%   -97.09% (p=0.000)
    Char/Unicode-12      81.64n ± 1%   2.34n ± 1%   -97.13% (p=0.000)
    OneOf/Ascii-12       63.33n ± 1%  11.12n ± 2%   -82.44% (p=0.000)
    OneOf/Unicode-12     77.16n ± 1%   4.34n ± 1%   -94.37% (p=0.000)
    NoneOf/Ascii-12      55.41n ± 2%   3.35n ± 1%   -93.95% (p=0.000)
    NoneOf/Unicode-12    79.86n ± 1%   6.13n ± 1%   -92.33% (p=0.000)

Generated with release-note

v0.6.0

26 Jan 05:17
v0.6.0
f1ec4b4

Choose a tag to compare

v0.6.0 - January 26, 2026

2 new features

Contributors

New Features

  • 7661a47 add dedicated control flow combinators (#89) (@purpleclay)

    Add new control flow combinators to improve parser validation, error handling, and flow control:

    • Verify: validate parsed results against a predicate
    • Recognize: return consumed input as output
    • Consumed: return both raw consumed text and parsed output
    • Eof: match only at end of input
    • AllConsuming: ensure entire input is consumed
    • Rest: return all remaining unconsumed input
    • Value: return fixed value on parser success
    • Cond: conditionally apply parser based on boolean
    • Cut: convert recoverable errors to fatal failures (prevents backtracking)
    • PeekNot: negative lookahead (succeed when inner parser fails)
  • 1c613d3 add repetition combinators and single-character matchers (#87) (@purpleclay)

Generated with release-note

v0.5.0

24 Jan 07:04
v0.5.0
1c9fc70

Choose a tag to compare

v0.5.0 - January 24, 2026

2 new features

Contributors

New Features

Dependency Updates

Generated with release-note

v0.4.0

14 Oct 04:17
v0.4.0
6b1061e

Choose a tag to compare

Changelog

New Features

  • 12c9d0e: feat: add a flatten combinator, that will flatten a slice of strings into a single string (#65) (@purpleclay)

Full Changelog: v0.3.0...v0.4.0

What to do next?

v0.3.0

16 Aug 05:37
v0.3.0
bba4768

Choose a tag to compare

Changelog

New Features

  • a065c1a: feat: write a utility parser that will consumer text until the end of a line (#52) (@purpleclay)
  • 4aebf35: feat: support mapping the output of a combinator to any other type (#61) (@purpleclay)
  • db938ef: feat: extend existing predicate combinators to support variable number of matches (#51) (@purpleclay)
  • 9cfe72f: feat: add the ability to peek into the input text without chomping any of the input (#56) (@purpleclay)

Documentation Updates

Other Work

  • 6798a29: feat!: switch around the order of arguments to both prefixed and suffixed to match strings standard library (#58) (@purpleclay)

Full Changelog: v0.2.2...v0.3.0

What to do next?

v0.2.2

07 Jul 06:03
v0.2.2
47ee954

Choose a tag to compare

Changelog

Bug Fixes

Full Changelog: v0.2.1...v0.2.2

What to do next?

v0.2.1

07 Jul 05:45
v0.2.1
81ba8de

Choose a tag to compare

Changelog

Bug Fixes

Full Changelog: v0.2.0...v0.2.1

What to do next?

v0.2.0

17 Feb 05:47
v0.2.0
4ac5038

Choose a tag to compare

Changelog

New Features

  • bec3e33: feat: support repeating a combinator between a configurable range of times (#31) (@purpleclay)
  • e7df717: feat: add combinators to handle text that is prefixed or suffixed (#33) (@purpleclay)
  • 4ac5038: feat: add a new combinator that will keep parsing input text until it no longer matches (#35) (@purpleclay)

Full Changelog: v0.1.0...v0.2.0

What to do next?

v0.1.0

05 Feb 06:30
v0.1.0
e3c25ec

Choose a tag to compare

Changelog

New Features

Full Changelog: v0.1.0-beta.2...v0.1.0

What to do next?

v0.1.0-beta.2

15 Jan 13:55
v0.1.0-beta.2
2e080ea

Choose a tag to compare

Changelog

New Features

  • 2e080ea: feat: add basic conversion combinators to enable greater chaining of combinators (#27) (@purpleclay)

Full Changelog: v0.1.0-beta.1...v0.1.0-beta.2

What to do next?