{"id":19904727,"url":"https://github.com/mnemnion/mvzr","last_synced_at":"2026-05-10T21:04:16.629Z","repository":{"id":248609807,"uuid":"829187404","full_name":"mnemnion/mvzr","owner":"mnemnion","description":"Minimum Viable Zig Regex","archived":false,"fork":false,"pushed_at":"2025-04-18T22:12:45.000Z","size":221,"stargazers_count":64,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"trunk","last_synced_at":"2025-04-19T09:10:29.754Z","etag":null,"topics":["pattern-matching","regex","regular-expressions","zig","zig-package"],"latest_commit_sha":null,"homepage":"","language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mnemnion.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-07-16T00:02:45.000Z","updated_at":"2025-04-18T22:12:43.000Z","dependencies_parsed_at":"2024-11-09T22:17:17.171Z","dependency_job_id":"a017e2e2-65be-4826-b5e5-8ae111a814d7","html_url":"https://github.com/mnemnion/mvzr","commit_stats":null,"previous_names":["mnemnion/mvzr"],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnemnion%2Fmvzr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnemnion%2Fmvzr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnemnion%2Fmvzr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnemnion%2Fmvzr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mnemnion","download_url":"https://codeload.github.com/mnemnion/mvzr/tar.gz/refs/heads/trunk","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252126586,"owners_count":21698964,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["pattern-matching","regex","regular-expressions","zig","zig-package"],"created_at":"2024-11-12T20:29:28.953Z","updated_at":"2026-05-10T21:04:16.622Z","avatar_url":"https://github.com/mnemnion.png","language":"Zig","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mvzr: The Minimum Viable Zig Regex Library\n\n\nFinding myself in need of a regular expressions library for a Zig\nproject, and needing it to build regex at runtime, not just comptime,\nI ended up speedrunning a little library for just that purpose.\n\nThis is that library.  It's a simple bytecode-based VM, inspired by\n[LPEG](https://www.inf.puc-rio.br/~roberto/docs/peg.pdf).  Under 2000\nlines of load-bearing code, no dependencies other than `std`.\n\nThe provided Regex type allows 64 'operations' and 8 unique ASCII\ncharacter sets.  If you would like more, or less, you can call\n`SizedRegex(num_ops, num_sets)` to customize the type.\n\n\n## Installation\n\nDrop the file into your project, or use the Zig build system:\n\n```zig\nzig fetch --save \"https://github.com/mnemnion/mvzr/archive/refs/tags/v0.3.9.tar.gz\"\n```\n\nI'll do my best to keep that URL fresh, but it pays to check over here:\n➔\n\nFor the latest release version.\n\n`v0.3.9` only differs from `v0.3.8` in metadata, marking it as\nZig 0.16 compatible.  It works fine with Zig `0.15.2`, but has the\n`.minimum_zig_version` field in the Zon file set higher to cooperate\nwith modern practices.\n\n\n## Features\n\n- Zero allocation, comptime and runtime compiling and matching\n- X operations per regex\n- Y character sets per regex\n- Greedy qualifiers: `*`, `+`, `?`\n- Lazy qualifiers: `*?`, `+?`, `??`\n- Possessive/eager qualifiers: `*+`, `++`, `?+`\n- Alternation: `foo|bar|baz`\n- Grouping `foo|(bar|baz)+|quux`\n- Sets: `[abc]`, `[^abc]`, `[a-z]`, `[^a-z]`, `[\\w+-]`, `[\\x04-\\x1b]`\n- Built-in character groups (ASCII): `\\w`, `\\W`, `\\s`, `\\S`, `\\d`, `\\D`\n- Escape sequences: `\\t`, `\\n`, `\\r`, `\\xXX` hex format\n    - Same set as Zig: if you need the weird C ones, use `\\x` format\n- Begin and end `^` and `$`\n- Word boundaries `\\b`, `\\B`\n- `{M}`, `{M,}`, `{M,N}`, `{,N}`\n\n\n## Limitations and Quirks\n\n- Minimal multibyte / Unicode support\n    - This has improved somewhat.  A regex like `λ?` now matches an\n      optional lambda, not just an optional final byte.  Additionally,\n      ranges of bytes greater than 0x7f are now supported, this (with\n      some care) can match certain sets: for instance `(\\xce[\\x91-\n      \\xa9])+` will match a string of uppercase Greek letters,\n      `\\xc2[\\x80-\\x9f]` matches a C1 control code, and so on.  But\n      you'll still need to work at the byte level, and use `\\x` format,\n      to do these tasks.\n- No fancy modifiers (you want case-insensitive, great, lowercase your\n  string)\n- `.` matches any one byte.  `[^\\n\\r]` works fine if that's not what you\n  want\n    - Or split into lines first, divide and conquer\n    - Note: `$` permits a final newline, but `^` must be the beginning\n      of a string, and `$` _only_ matches a final newline.\n- Backtracks (sorry.  For this design to work without backtracking,\n  we need async back)\n- Compiler does some best-effort validation but I haven't really pounded\n  on it\n- No capture groups.  Divide and conquer\n\nAs long as you color within the lines, it should be fine.\n\nThis library is not intended for use where an attacker could conceivably\ncontrol the regex pattern.\n\nMuch like managing your own memory, if you know your tools and are smart\nabout it, you can get a lot done with `mvzr`.\n\n\n## Interface\n\n`mvzr.Regex` is available at `comptime` or runtime, and returns an\n`mvzr.Match`, consisting of a `.slice` field containing the match,\nas well as the `.start` and `.end` locations in the haystack.  This\nis a borrowed slice, to own it, call `match.toOwnedMatch(allocator)`,\nand deallocate later with `match.deinit(allocator)`, or just free the\n`.slice`.\n\nSimilarly, if you need to store a `Regex` or `SizedRegex` for\nlater, call `regex.toOwnedRegex(allocator)`, freeing later with\n`allocator.destroy(heap_regex)`.\n\n```zig\n// aka SizedRegex(64, 8)\nconst regex: mvzr.Regex = mvzr.compile(patt_str).?;\n// or mvzr.Regex.compile(patt_str)\nconst match: mvzr.Match = regex.match(haystack).?;\nconst match2: mvzr.Match = match(haystack, patt_str).?;\nconst did_match: bool = regex.isMatch(haystack);\nconst iter: mvzr.RegexIterator = regex.iterator(haystack);\n\nwhile (iter.next()) |m| {\n    // ...\n}\n\n// Comptime-only\nconst ops, const sets = mvzr.resourcesNeeded(\"abc?d*[^efgh]++2\");\n\n// I suggest adding the values directly here once they're established\nconst SlimmedDownRegex = mvzr.SizedRegex(ops, sets);\n```\n\n\n## Compile Errors\n\nIf a regex string is unable to compile, `mvzr` will return `null`.\nIt will also log an informative error message.  While this is\nuseful, it may not be desirable, so `mvzr` uses a [scoped logger]\n(https://ziglang.org/documentation/0.12.0/std/#std.log) with the scope\n`.mvzr`, to make it easy for a custom logging function to filter those\nmessages out.\n\n\n## Bugs\n\nFewer over time, I hope.  The test suite never shrinks.\n\n\n### Bug Reports\n\nAlways welcome.  Ideally, presented as a failing test block, with a note\non expected behavior.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmnemnion%2Fmvzr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmnemnion%2Fmvzr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmnemnion%2Fmvzr/lists"}