What's new
Curated highlights of what's changed in PLCC-ng and why it matters to you. For the full commit-level history, see GitHub Releases.
2026-07-29 — PLCC-ng v2.0.1
A patch release fixing a parsing bug in repetition rules, and making sure fixes like it reach projects you have already built.
Repetition rules keep their uncaptured tokens
A repetition rule (**=) whose body contains a token you don't capture —
the EQUALS in <Decls> **= <SYMBOL> EQUALS <Exp> — used to drop that
token silently. The grammar passed LL(1) analysis, and then parsing failed
at the first uncaptured token with a confusing "no production for" error.
PLCC-ng now matches every symbol in a repetition body on every repetition,
building lists only from the ones you captured. See
Repetition rules.
Upgrading rebuilds your project automatically
PLCC-ng caches its work in plcc-ng/ and skips stages whose inputs
haven't changed. That cache used to key on your spec alone, so
upgrading PLCC-ng left an existing build directory untouched — and a
fix like the one above silently never reached you. The cache now keys
on the PLCC-ng version as well, so the first plcc-make after an
upgrade rebuilds once, on its own. See
plcc-make.
2026-07-26 — PLCC-ng v2.0.0
The first release since 1.0 tightens the language runtime and fixes
several ways generated code could surprise you. One change is breaking:
if you have specs written against v1.0.0, update your _run() methods
before upgrading — see below and the migration guide's
breaking behavior changes.
_run() now returns a string
Your semantics' entry point, _run(), now returns its output as a
string and lets the runtime print it — the same contract in all four
languages. Java's _run() changes from void to String; Python and
JavaScript's _run() must return an actual str/string rather than an
int, list, or other value. A non-string return is now reported as a
specification_error instead of silently producing quoted or malformed
output, and no language's _run() may print to stdout directly. This is
the one breaking change in this release: existing v1.0.0 specs need
updating, and the
migration guide shows the
before/after for each language.
Field names can't collide with reserved words
A captured field whose name is a reserved word in your target language —
for example a field auto-named var in JavaScript — used to slip through
and fail later with a confusing error from the generated code. PLCC-ng
now detects this and reports it against your spec, in Python, Java,
Haskell, and JavaScript. Because the check is per target language, it
fires when you emit or run for that language, not during language-neutral
grammar validation. See
Reserved words.
More predictable auto-generated field names
Two bugs in how PLCC-ng derives captured-field names are fixed. An
alternative name (:name) now keeps its original case, so a camelCase
alt-name no longer produces a mismatched field. And a bare multi-word
nonterminal capture now decapitalizes only its first letter
(<OneMore> → field oneMore) instead of lowercasing the whole name
(onemore), matching the naming rule in the
migration guide. A v1.0.0
spec that relied on the old full-lowercasing will see its generated field
names change.
More correct LL(1) grammar analysis
PLCC-ng's LL(1) analysis now recognizes a nullable production no matter when it is registered, so FOLLOW sets are computed correctly (including end-of-input) for grammars whose nullable productions appear late. Grammars that were previously mis-analyzed are now handled correctly.
Documentation examples that actually run
Every language's quick-reference example grammar is now genuinely LL(1), and its generated code compiles and runs exactly as shown — so copying an example straight from the docs works the first time. See the per-language guides for Python, Java, Haskell, and JavaScript.
2026-07-06 — PLCC-ng v1.0.0
PLCC-ng reaches 1.0: the next generation of PLCC is ready for classroom use. If you're coming from PLCC, here's a tour of what's changed and why it matters. Migrating a course? Start with the migration guide.
Write semantics in four languages
PLCC generated Java, and only Java. PLCC-ng generates scanners, parsers, and interpreters in Python, Java, Haskell, or JavaScript — pick the language your course teaches and write your semantics in it. Start with the Language Guide, then see the per-language pages for Python, Java, Haskell, and JavaScript.
Simpler native installation
Installing PLCC-ng natively is now a single pip install plcc-ng —
no shell-script installer to fetch and configure. See
Installation for upgrade, pinning, and uninstall
instructions.
Three commands to run your language
Day-to-day work needs just three commands, with no separate compile
step: plcc-scan tokenizes input,
plcc-parse shows the parse tree, and
plcc-rep runs your full language in a
read-eval-print loop. Each one orchestrates smaller composable
commands underneath — emitting generated code, building it, feeding
it input — that you can run directly to explore each stage of the
pipeline and how the pieces fit together. See
Author-facing commands and
Under the hood.
Diagrams from your spec
The plcc-diagram add-on package draws diagrams straight from your
spec file: class diagrams of the object model your semantics program
against, and syntax (EBNF) diagrams of your grammar. See
plcc-diagram and
plcc-diagram-syntax.
Built to extend
The pipeline is open: language extensions add new target languages, parser extensions add new parsing algorithms, and diagram extensions add new visualizations — all discovered and dispatched through the same CLI conventions. See the language, parser, and diagram extension guides.
A real documentation site
You're reading it. The Language Guide covers every section of a spec file with worked examples, and the CLI reference documents every command and flag.
Spec syntax has changed
PLCC-ng is not backwards compatible with PLCC: spec files need updating. Regular expressions switch from Java to Python flavor, nonterminals become PascalCase, subclass and captured-field syntax change, and more. The migration guide walks through every change step by step, and its features not yet in PLCC-ng section lists what hasn't made the jump, so you know both sides of the trade before switching.