# re2c: a lexer generator that emits jumps, not tables

> re2c is a free and open-source lexer generator whose distinguishing choice is to encode the finite state automata as conditional jumps and comparisons rather than as a lookup table, which the project argues produces faster and often smaller lexers that are easier to debug. It generates for C, C++, Go and Rust, with examples for twelve languages, and it is built with autotools, CMake and Bazel.

**skvadrik/re2c** — Lexer generator for C, C++, D, Go, Haskell, Java, JS, OCaml, Python, Rust, Swift, V and Zig.

- Repository: https://github.com/skvadrik/re2c
- Website: https://re2c.org
- Stars: 1,315 · Forks: 201
- Language: C
- License: NOASSERTION
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/skvadrik-re2c

## The one decision that defines the tool

re2c is a free and open-source lexer generator, and its main goal is generating fast lexers, at least as fast as their reasonably optimized hand-coded counterparts.

The interesting part is the mechanism. Instead of using the traditional table-driven approach, re2c encodes the generated finite state automata directly in the form of conditional jumps and comparisons. The resulting programs are faster and often smaller than their table-driven analogues, and they are much easier to debug and understand.

That is a design decision with consequences on both sides. A table-driven lexer is a data structure plus a small loop, and the data structure is often unreadable, so debugging means reading a generated table or tracing through states. A re2c lexer is a sequence of comparisons, which is the shape a person would have written by hand, so a debugger step through it does something a debugger step through a table cannot.

The project also applies quite a few optimizations in order to speed up and compress the generated code, and the optimisations are part of the product rather than an afterthought. A generator that produced readable but slow code would not satisfy the goal of matching a well tuned hand written scanner, and a generator that produced fast but bloated code would not satisfy the size claim.

The history is short in the README's telling. re2c was originally written by Peter Bumbulis, and many volunteers have contributed since. The current maintainer is Ulya Trofimovich.

## You write the scaffolding, the generator writes the states

The second distinctive feature of re2c is its flexible interface. Instead of assuming a fixed program template, re2c lets the programmer write most of the interface code and adapt the generated lexer to any particular environment.

That is the opposite of how most generators work. A generator that assumes a template owns your whole program structure, and the interface between the lexer and the rest of your code is fixed by whoever wrote the template. re2c inverts that: you write the interface, and the generator fills in the state logic.

The practical reason to want that is that the interface is the part that has to match your project. A lexer needs to know how to read input, where to report an error, how to return a token, what your token type is called, and how the state is threaded through the calls. In a template-driven generator those are all fixed, and adapting the output means editing generated code, which is the one thing you should never do. With re2c, adapting the output means editing your own file, which is the one thing you should always do.

It also makes the generated code reviewable in the way generated code usually is not. Because the interface is yours, the diff between two versions of the generated file shows the state machine changing and nothing else, and the state machine is the part that is worth reviewing.

## Twelve languages of examples, and the two that matter most

The repository description lists the languages re2c supports as C, C++, D, Go, Haskell, Java, JS, OCaml, Python, Rust, Swift, V and Zig, and the examples directory has a directory for each of them, with c, d, go, haskell, java, js, ocaml, python, rust, swift, v and zig all present alongside the top level c example.

The README itself describes re2c as a lexer generator for C, C++, Go and Rust, which is a smaller list, and the difference is worth understanding rather than treating as a contradiction. The examples are there to show what the interface looks like in a given language, and a language with an example is a language whose output shape is known. C, C++, Go and Rust are the ones the project names as its targets, and the rest are there because the generated code adapts to whatever environment you describe.

For a reader trying to decide, the examples are the documentation. A generator's reference manual tells you what the options mean, and an example tells you what the result looks like in the language you actually write, which is the question that matters when you are deciding whether to adopt a code generator for a project you care about.

The repository also carries a unicode/ directory, a doc/ directory and a fuzz/ directory, and the last of those is the one to notice. Fuzzing a lexer generator is a serious commitment, and it applies to the generator rather than to the generated lexers.

## Two clones, and only one of them is current

The download section gives two source repositories and tells you which to trust.

```
$ git clone https://github.com/skvadrik/re2c.git
$ git clone https://git.code.sf.net/p/re2c/code-git
```

GitHub is the main repo, and SourceForge is a mirror and can be slightly outdated. That is a small sentence with a practical consequence: if you are pinning a version of re2c for a reproducible build, take the release tarball from the GitHub releases, or clone from GitHub, rather than assuming the two are in step.

Release tarballs are linked from the GitHub releases page, and the version numbers make the cadence visible. The recent tags are 4.5 on 2026-03-23, 4.5.1 on 2026-03-27 and 4.6 on 2026-08-29, so minor releases arrive every few months with patch releases for the rough edges. The repository was last pushed to on 2026-09-17.

The project describes itself as an open source, community-driven project, and the feedback channels are the usual for a tool of this age and size: a GitHub issue tracker, two mailing lists, one general and one for development, and two IRC channels on different networks, irc.oftc.net and irc.libera.chat. The presence of IRC alongside issues is a good sign about the project's age, and the mailing list archive is where the accumulated knowledge about lexer construction lives.

## Three build systems in one tree, and a 2024 licence file

The build section points at BUILD.md and the online documentation rather than repeating itself, which is sensible for a project with this many build paths.

The repository carries all three of the usual systems. There is a CMakeLists.txt with CMakePresets.json, an autotools side with configure.ac, Makefile.am, Makefile.lib.am, autogen.sh and a bootstrap/ directory, and Bazel with BUILD.bazel, MODULE.bazel, WORKSPACE, WORKSPACE.bzlmod and a bazel/ directory. The autotools build is the oldest and CMake the most commonly used, and the Bazel files exist for projects that already build with Bazel.

The rest of the tree explains what the project contains. There is src/ and include/ for the generator, lib/ and a curious libre2c_old/ directory, doc/ for the manual, examples/ for the per language samples, test/ and fuzz/ for the harnesses, unicode/ for the character tables, benchmarks/ for the performance work, and scripts/ and utils/ for the supporting machinery. There is a run_tests.py.in, so the test driver is generated by the build system, and release.sh with add-release.txt for cutting a release.

The licensing deserves a note. The repository metadata classifies it as a custom licence that GitHub cannot categorise, and the tree contains a NO_WARRANTY file, which is the standard way a project states that it comes with no warranty. The LICENSE file is what governs, and for a generator whose output lands in your source tree, it is worth reading before you adopt it.

## Conclusion

re2c fits a project with a hand written lexer that is either slow or unreadable, and whose author is willing to maintain a .re file and a small build step in exchange for generated code that is as fast as a careful hand written scanner. It does not fit a project that wants a self contained single file parser with no generator in the build, and it does not fit a team that will not take on the responsibility of reading generated code when the grammar changes. Verify three things before you adopt it: that your language has the binding and the example you need, since the description lists C, C++, D, Go, Haskell, Java, JavaScript, OCaml, Python, Rust, Swift, V and Zig, that your build can carry the extra step, because re2c has to run before the compiler and the tree supports three different build systems, and that you take the output from the current source, since the SourceForge mirror is described as potentially slightly outdated.

## FAQ

### What does re2c do differently from a table driven lexer generator?

Instead of the traditional table-driven approach, re2c encodes the generated finite state automata directly in the form of conditional jumps and comparisons. The README says the resulting programs are faster and often smaller than their table-driven analogues, and much easier to debug and understand, and re2c applies a range of optimisations to speed up and compress the generated code.

### Which languages can re2c generate code for?

The repository description lists C, C++, D, Go, Haskell, Java, JavaScript, OCaml, Python, Rust, Swift, V and Zig, and the examples directory has a sample for each. The README describes re2c as a lexer generator for C, C++, Go and Rust, and the flexibility of the interface is what lets the same generator adapt to other environments.

### How flexible is re2c's interface?

Instead of assuming a fixed program template, re2c lets the programmer write most of the interface code and adapt the generated lexer to any particular environment. You write the scaffolding that reads input, reports errors and returns tokens, and the generator fills in the state logic.

### Where do I get re2c and which source should I use?

Release tarballs are on the GitHub releases page. For source, clone from GitHub or from the SourceForge mirror, and the README says GitHub is the main repo while SourceForge is a mirror that can be slightly outdated, so prefer GitHub or a release tarball if you need a specific version.

### How do I build re2c?

The README points at BUILD.md and the online build documentation. The tree carries three build systems, CMake with CMakePresets.json, autotools with configure.ac and autogen.sh, and Bazel with BUILD.bazel and MODULE.bazel, so you can use whichever your project already uses.

## Sources

- [Issues](https://github.com/skvadrik/re2c/issues)
- [Project website](https://re2c.org)
- [README](https://github.com/skvadrik/re2c/blob/master/README.md)
- [Releases](https://github.com/skvadrik/re2c/releases)
- [skvadrik/re2c on GitHub](https://github.com/skvadrik/re2c)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/skvadrik-re2c
