# Racc: the LALR(1) parser generator that ships inside Ruby itself

> Racc is an LALR(1) parser generator written in Ruby and generating Ruby programs, maintained as part of the Ruby project and published as a gem for CRuby and JRuby. It suits a Ruby developer who wants a generated parser from a yacc-style grammar, and its generated output carries no licence obligation.

**ruby/racc** — Racc is an LALR(1) parser generator.  It is written in Ruby itself, and generates ruby programs.

- Repository: https://github.com/ruby/racc
- Website: https://ruby.github.io/racc/
- Stars: 569 · Forks: 95
- Language: Yacc
- License: NOASSERTION
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/ruby-racc

## A parser generator that lives inside the Ruby project

Racc is an LALR(1) parser generator. It is written in Ruby itself, and generates Ruby programs.

That single paragraph covers the whole positioning. It is a parser generator in the yacc tradition, the kind of tool that reads a grammar file and produces a table-driven parser, and it is hosted in the ruby organisation on GitHub, with the homepage at ruby.github.io/racc. The primary language is recorded as Yacc, which is the grammar language rather than the implementation language, and the licence field is a custom one GitHub cannot classify, with the terms in the LICENSE file.

The fact that it is part of the Ruby project rather than a third-party gem is the thing that makes it different from the other parser generators you can install. The repository carries a ChangeLog, a TODO file, a Rakefile with a rakelib/ directory for the rake tasks, a Rakefile at the root, a racc.gemspec, a Gemfile, a test/ directory and a sample/ directory. There is a README.rdoc and a README.ja.rdoc, which tells you the documentation is written in Japanese as well as English, and the project lists Minero Aoki as its author.

The releases show a slow, deliberate cadence: v1.8.1 from 2024-07-30, v1.8.0 from 2024-05-20 and v1.7.3 from 2023-11-04, with the last push to the repository on 2026-10-13. A parser generator that changes its output format or its grammar dialect is not something to release often, and the version history is consistent with a tool whose interface is considered settled.

The topic list is minimal, just lalr-parser-generator and parser-generator, which is how the project describes itself.

## Installing and running the bundled calculator

The requirement is Ruby 2.5 or later, and the installation is the standard gem install:

```bash
gem install racc
```

Racc also comes with a simple calculator, and the documentation in the project README walks through the whole cycle, which is the fastest way to see what the tool does. You compile the grammar file with the generator, naming the output file:

```bash
racc -o calc calc.y
```

The documentation notes that this process costs a few seconds or less, and then you run the result:

```bash
ruby calc
```

The question the project asks at that point, Does it work?, is the whole tutorial. A grammar file in a .y file goes in, a Ruby program comes out, and the program is what you would actually ship.

The two supporting directories are worth knowing about. The HTML documents under doc/en/ hold the details of how Racc works and how to write a grammar for it, and the sample/ directory holds sample grammar files. That directory is more interesting than a list of examples, because it is a map of the tool's capabilities: sample/calc.y and sample/calc-ja.y are the calculator in two forms, sample/array.y and sample/array2.y cover arrays, sample/hash.y covers hashes, sample/lists.y covers lists, sample/lalr.y is about the LALR behaviour itself, sample/syntax.y is about the grammar syntax, sample/yyerr.y is about error handling, and sample/conflict.y is the one that demonstrates a conflict.

The conflict example is the most instructive file in the directory. A parser generator that can tell you your grammar is ambiguous is more useful than one that silently resolves the ambiguity for you, and having a file that demonstrates exactly what a conflict report looks like is how you learn to read one.

## Debug output, and what a bug report should contain

The project says any kind of bug report is welcome, and it says specifically what makes a report useful: your grammar file and the debug output generated by racc -t.

That detail is worth pausing on, because it tells you the generator has a debugging mode that is intended for exactly this purpose. A parser generator's hardest failures are grammar conflicts, and the useful artefact for diagnosing one is the state of the tables and the conflict list for the specific grammar that produced it. Being told to attach that output is the project saying that a grammar plus its racc -t dump is a reproducible bug report.

The same hint explains something about the LALR(1) choice, which the topic list and the sample directory both make clear. LALR(1) parsers are table-driven: the generator computes, for each state of the parser, what it can shift and what it can reduce, and the runtime is a loop over a pair of tables. That design is fast and the generated code is compact, but it only works for grammars that fit the algorithm, and a grammar that does not fit produces a conflict report at generation time rather than a mysterious failure at runtime.

So the tool's real interface is a two-stage conversation. You write a grammar, you run the generator, and it either produces a parser or tells you the grammar is ambiguous or not LALR(1). The sample/conflict.y file is the documentation of that second outcome, and the racc -t output is how you inspect it.

The repository also carries an ext/ directory, which holds the native extension side, and the release flow in the README says the gem provides two packages, one for CRuby and one for JRuby, so the same generator is usable from either implementation.

## The licence, and the part that surprises people

The legal section of the project documentation is short, and the second sentence is the one that matters.

Racc is distributed under the same terms as Ruby, with the COPYING file in the repository holding the text. The repository tree also contains a BSDL file, which is where the two-clause BSD licence text lives, so the licensing picture is the standard Ruby one of a BSD-style licence with the Ruby additions.

Then the note that catches people out: you do NOT need to follow the ruby license for your own parser, that is, for the output Racc produces. You can distribute those files under any licenses you want.

That is a more permissive arrangement than most people assume about a parser generator, and it is the practical reason to use one at all in a commercial codebase. The generator is copyleft-ish Ruby licensed, but the generated parser is a derived artefact that the licence explicitly leaves free. A tool whose output inherits its licence would be a problem for a Ruby developer shipping a closed-source product, because every generated file in the repository would carry an obligation.

The same reassurance applies to the grammar file, since the grammar is your own input rather than the tool's output.

The repository tree reflects the usual split for a project of this type, with a BSDL and COPYING at the root, a ChangeLog, a TODO, the bin/ directory holding the command line entry point, lib/ for the generator's own Ruby code, ext/ for the native extension, doc/, sample/, test/ and the packaging files racc.gemspec and Gemfile.

## The release flow, and how the version is kept in two places

The release process is documented in the project README, and it is short enough to quote in full because the detail is instructive.

There are two steps to updating the version number, and they are in two different files in two different languages. RACC_VERSION is in ext/racc/com/headius/racc/Cparse.java, and VERSION is in lib/racc/info.rb. The first of those is the Java implementation of the parser runtime, which is what makes the JRuby package possible, and the second is the Ruby side that the gem reports.

Then the release itself is done by rake release, and the documentation is explicit that it is run with CRuby and JRuby because the Racc gem provides two packages. Finally a new release is created on GitHub.

Three things fall out of that. The generator has two implementations of its runtime, one for each Ruby implementation, and they are versioned separately, which means a release is a coordinated act across two languages. The rake task is the entry point, so the release is scripted rather than a sequence of manual steps. And the fact that the version has to be edited in two places by hand is a small fragility in an otherwise automated flow.

For a user, the practical consequence is that the gem you install contains both packages, and the compatibility you care about is Ruby version compatibility, which the project states as Ruby 2.5 or later.

## Where Racc is the wrong tool

The first limit is the algorithm. LALR(1) is a restricted family of grammars, and a language whose syntax is genuinely ambiguous, which means it needs more than one parse tree for the same input, will not go through it. Most programming languages you would want to parse are LALR(1) or close to it, and configuration formats and domain specific languages are usually fine, but a grammar with the classic dangling else, or one that mixes expressions and statements without a separator, will produce conflict reports rather than a parser.

The second is the error recovery story. The sample directory includes yyerr.y, so error handling is part of the tool's surface, but a generated table-driven parser is not the right structure for a parser that has to resynchronise and keep going on arbitrary garbage. If you are writing a configuration parser that must report several errors in a file, a recursive descent parser with hand-written recovery gives you more control, at the cost of writing the parser yourself.

The third is that a generated parser is a build artifact, and that has consequences for a project that does not otherwise have a build step. You now need the grammar file, the generator, and a rule that regenerates the parser when the grammar changes, and you need to decide whether the generated file is committed. For a gem or an application with a release process, that is normal. For a small script repository, it is overhead for a problem you could solve with a regular expression or a hand-written recursive descent function.

The fourth is the size of the generated code. A table-driven parser with its action tables and its state machine is a large generated file that is unpleasant to read in a diff and impossible to review by eye, and a reviewer looking at a pull request that changes a grammar has to trust the generator.

And the fifth is the alternative that fits many cases better. A hand-written recursive descent parser in plain Ruby is often shorter than a grammar plus a generated parser, is trivially debuggable with a debugger or a puts, and imposes no dependency at all, because the only cost is the code you would have written anyway. Racc earns its keep when the grammar is large, when the language is fixed and the parser is reused, or when the team wants the grammar to be a separate, reviewable artefact. For a one-off parser of a small format, it is a heavier way to arrive at the same result.

## Conclusion

Racc is worth reaching for when you need a parser for a Ruby application and want it generated rather than hand-written, because the table-driven approach handles a large grammar without the function-per-rule sprawl of a recursive descent parser, because the generator itself is Ruby code you can read and patch, and because the project is maintained inside the Ruby repository rather than by a single outside author. It is the wrong tool for a grammar with ambiguity or context-sensitive rules, and it is the wrong tool if you want an error-tolerant parser for arbitrary user input. Before you start, check three things: that your grammar is genuinely LALR(1), since that is the algorithm Racc implements and the sample/ directory includes a conflict.y grammar that shows what a conflict looks like; that you have Ruby 2.5 or later, which is the stated requirement; and that the licence question is the one you expect, because the project states that the generated parser output can be distributed under any licence you want, even though Racc itself follows the same terms as Ruby.

## FAQ

### How do I install Racc and build a parser?

Run gem install racc, which requires Ruby 2.5 or later. Write your grammar in a .y file, generate the parser with racc -o calc calc.y, and run the result with ruby calc. The project documentation uses the bundled calculator in the sample/ directory as that walkthrough, and the HTML documents under doc/en/ carry the details.

### Can I use the parser Racc generates in a project with a different licence?

Yes. Racc itself is distributed under the same terms as Ruby, but the project documentation states that you do not need to follow the Ruby licence for your own parser, meaning the output of Racc, and that you can distribute those files under any licence you want.

### What should I include in a bug report for Racc?

Your grammar file and the debug output generated by racc -t. The project documentation says both are helpful, and the sample/ directory includes a conflict.y grammar that shows what a conflict looks like in that output.

## Sources

- [Issues](https://github.com/ruby/racc/issues)
- [Project website](https://ruby.github.io/racc/)
- [README](https://github.com/ruby/racc/blob/master/README.md)
- [Releases](https://github.com/ruby/racc/releases)
- [ruby/racc on GitHub](https://github.com/ruby/racc)

---

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