Frequently asked questions

Short answers, including the unflattering ones. If something here is wrong or missing, that's worth an issue.

The basics

What is tabnas?
A parsing engine you extend rather than replace. A grammar is data — a table of rules and token alternates the engine walks at runtime — so a new language is usually rules added to one that already parses. The long version is on why tabnas.
Why does it exist?
Writing a parser is expensive, so most formats never get a good one. Two things make it cheaper here: extension is the normal case instead of a fork, and the grammar is plain enough data that a language model can write it. See agents.
What does the name mean?
Tábla na nAistrithe — Irish for "a table of translations", which is what the engine walks.
Is it ready to use?
It works, and 28 packages are published — but everything is pre-1.0. Minor versions can break things, and grammar packages track the engine release they were built against. Pin exact versions. Per-repo CI and publish state is on the status page.
What's the licence?
MIT, across every repository in the org.

Using it

Do I have to write ABNF?
No. There are three levels, and they produce the same thing: ABNF when a person is writing, a declarative rule table when an agent is, and a programmatic API for parameterised grammars — the level expr and directive are built at. The playground takes the first two.
Can I connect an agent without installing anything?
Yes, but installing is better. npx --yes @tabnas/mcp mcp runs the MCP server locally and is the supported path — free, private, unlimited, and reproducible. For clients that cannot spawn a process, the same tools are served over streamable HTTP at mcp.tabnas.dev/mcp. It is bounded (a body cap and a per-IP rate limit, both stated by its /.well-known/mcp), and it keeps nothing: see privacy. Both answer byte-for-byte identically, because there is one implementation behind them.
Do I have to write a lexer?
Mostly, yes. tabnas draws a hard line between lexing and parsing and is really about the parsing half. It gives you tools — matchers, fixed tokens, built-ins like NR — but you assemble them. Lexing is the easy and boring part.
Can it handle ambiguous grammars?
No. The engine is deterministic and does not backtrack. If you need every valid parse of an ambiguous input, an Earley or GLR parser is the right tool — other parsers covers when to reach for one.
What about left recursion?
Accepted, but rewritten rather than natively supported. The ABNF compiler applies Paull's algorithm, so P = P a / b becomes P = b *(a). The resulting tree is flat rather than left-nested, and a purely left-recursive rule with no base branch is an error.
How do I extend an existing grammar?
Add rules and token alternates to it. That's the whole mechanism, and it's how the packages are built: JSON is a handful of rules, JSONC adds comments, jsonic relaxes the quoting. See extending a grammar.
My action never fires. Why?
Probably the mark name. An @ref alternate mark comes from the alternate's leading discriminator, which the compiler assigns — so ask it rather than guessing: tabnas-abnf --marks -f grammar.abnf. ABNF also desugars [ … ] and ( … ) into generated group rules, so a rule's parent at runtime is often one of those.
How fast is it?
Unmeasured, publicly. The design is a for-loop over tokens with a lookup table and no backtracking, which is a fast shape — but there are no published benchmarks, so treat any claim, including that one, as unproven until there are.

Scope

Saying no is part of describing a project. These are deliberate; arguing for them is welcome, but the current answer is no.

What can it actually parse?
Real languages, not just config formats. The strongest evidence is @tabnas/c, which parses C source into a concrete syntax tree — preserving every token, comment, macro definition, macro use and compiler extension as written. There is also a Protocol Buffers IDL parser (proto2, proto3, editions 2023/2024), and CSS, Markdown and XML. Beyond the org, boru is a complete programming language — types, macros, an LSP — with its whole front end on this engine.
The limits are shape rather than size: the grammar has to be deterministic. Ambiguity is the thing it can't do — not complexity, and not lookahead depth.
Is there a hosted service?
No, and there's nothing to host. tabnas is a library that runs in your process. No account, no API key, no paid tier.
Does it generate parser code?
No. Generating source would give back the drift problem the engine exists to avoid — grammars stay data, interpreted at runtime. It also means you can inspect a grammar while it runs, print it back as ABNF, or draw it.
Which runtimes?
TypeScript and Go. TypeScript is the reference implementation; the Go port tracks it and runs the same fixtures, so a grammar behaves the same in both.
Is there an MCP server, or a grammar catalog?
Not yet, and neither is promised. Both are under discussion in Discussions, which is where the argument about how they should work is happening.

The project

Who makes it?
Richard Rodger, who also wrote Seneca and jsonic — which is where tabnas came from. Development is sponsored by Voxgig; see sponsors.
Is anyone using it?
Yes — examples covers two real languages built on the engine, one in TypeScript and one in Go. Beyond that it's early, and pretending otherwise wouldn't help you.
Can I contribute with an AI agent?
Yes, and you don't have to disclose it. Every package repository ships an AGENTS.md, and the shared fixtures mean a change that doesn't actually work fails loudly. See community.
What would help most?
Roughly in order: a grammar for a format you actually use, a failing fixture for something that parses wrongly, and documentation for the parts you found hard. There are 17 language grammars so far, most of them extensions of another.