---
title: "How to · tabnas"
description: "Task-oriented guides for the parsing problems that come up in practice: includes, expressions, options, line-oriented formats, tokens, and errors."
source: "https://tabnas.dev/how-to/"
---

# How to

Short guides for the problems that come up while writing a parser. Each one takes a single task, solves it against a running grammar, and says what it costs. They assume you have already parsed something: the [quickstart](https://tabnas.dev/docs/quickstart/) is five minutes if you haven't.

## How these are written

A guide here is task-shaped, not feature-shaped. The title is the thing you are trying to do; the page is how to do it and what it costs. Where a published package already solves the problem, the guide uses it and says so, rather than reimplementing it for the sake of an example: [extension is the point of the engine](https://tabnas.dev/docs/extending/), and it applies to the documentation too.

Every code sample on these pages has been executed against the published packages, and the values in the `// =>` comments are what the engine actually returned. Where a package behaves in a way that will surprise you, the guide says so and explains its effect.

The reference solutions are the real grammars. When a guide points at [@tabnas/csv](https://github.com/tabnas/csv) or [@tabnas/expr](https://github.com/tabnas/expr), it is pointing at a grammar under a couple of thousand lines that you can read in one sitting: usually the fastest way to answer a question this section didn't anticipate.

## Before you write a grammar

The question to ask before any of this is _what already parses something close to my format?_ A new grammar is the expensive answer, and usually the wrong one. The [packages page](https://tabnas.dev/docs/packages/) lists what exists; the [comparisons page](https://tabnas.dev/comparisons/) describes when another parser may fit your task.

## Guides

### Composing grammars

Assemble a language out of pieces that already work: other sources, expression syntax, and plugins that take options.

-   [Include one source from another Splice a file, a package or an in-memory string into a parse at the point it is referenced.](https://tabnas.dev/how-to/include-other-sources/) [@tabnas/multisource](https://github.com/tabnas/multisource)[@tabnas/directive](https://github.com/tabnas/directive)
-   [Parse expressions with precedence Add infix, prefix, suffix and ternary operators to a grammar, with a binding-power scale you control.](https://tabnas.dev/how-to/expressions-with-precedence/) [@tabnas/expr](https://github.com/tabnas/expr)
-   [Write a parameterised parser One plugin, many dialects: take options and let them decide the tokens, the lexer, and the rules.](https://tabnas.dev/how-to/parameterised-parsers/) [@tabnas/directive](https://github.com/tabnas/directive)[@tabnas/csv](https://github.com/tabnas/csv)[@tabnas/expr](https://github.com/tabnas/expr)

### Shaping the parse

The rule table itself: how repetition and nesting are expressed, how the engine picks an alternate, and what changes when newlines matter.

-   [Handle recursion and repetition Repeat without nesting, nest without recursing forever, and get left recursion past a push-down engine.](https://tabnas.dev/how-to/recursion-and-repetition/) [@tabnas/abnf](https://github.com/tabnas/abnf)
-   [Choose between alternates Order, lookahead, conditions, counters and group tags: how the engine picks a branch, and how to make it pick yours.](https://tabnas.dev/how-to/choose-between-alternates/)
-   [Parse a line-oriented format Make newlines significant: records, sections and one-statement-per-line syntax.](https://tabnas.dev/how-to/line-oriented-formats/) [@tabnas/csv](https://github.com/tabnas/csv)

### Feeding the lexer

Everything that happens before the rules run: the tokens your language needs, and the ones it should throw away.

-   [Lex a token the engine doesn't know Fixed literals, regex tokens, value literals, and a hand-written matcher for the cases none of those reach.](https://tabnas.dev/how-to/custom-tokens/)
-   [Handle comments and whitespace Turn comment styles on, define your own, and decide what the parser is allowed to throw away.](https://tabnas.dev/how-to/comments-and-whitespace/)
-   [Handle strings, quotes, and escapes Change what quotes a string, which escapes exist, and what happens to the ones that don't.](https://tabnas.dev/how-to/strings-and-quoting/) [@tabnas/csv](https://github.com/tabnas/csv)

### Working on a grammar

Inspect a grammar, explain parse errors, and test its behaviour.

-   [Debug a grammar See the rules you actually have, watch a parse step by step, and draw the result.](https://tabnas.dev/how-to/debug-a-grammar/) [@tabnas/debug](https://github.com/tabnas/debug)[@tabnas/railroad](https://github.com/tabnas/railroad)
-   [Give good parse errors Name the file, define your own error codes, and raise them from the alternate that knows what went wrong.](https://tabnas.dev/how-to/parse-errors/)
-   [Test a grammar Assert what parses, what doesn't, and that the grammar is still the shape you think it is.](https://tabnas.dev/how-to/test-a-grammar/) [@tabnas/abnf](https://github.com/tabnas/abnf)[@tabnas/debug](https://github.com/tabnas/debug)

### Also in the docs

Three task-oriented pages live under [/docs](https://tabnas.dev/docs/) because they double as the way in to ABNF, actions, and extension. They belong to this section as much as to that one.

-   [ABNF grammars Define a language fast using the RFC 5234 ABNF dialect.](https://tabnas.dev/docs/abnf-grammars/)
-   [Attaching actions Turn a parse into a value: with builtins, named refs, or inline functions.](https://tabnas.dev/docs/actions/)
-   [Extending a grammar Add to a language that already parses, instead of forking it.](https://tabnas.dev/docs/extending/)

## If none of these fit

The [rule table reference](https://tabnas.dev/docs/rule-table/) is the whole format in one page, and is short enough to read end to end. The [playground](https://tabnas.dev/playground/) runs a grammar in the browser, so a guess can be checked in a few seconds. Failing both, [open an issue](https://tabnas.dev/community/): a question this section should have answered is a bug in this section.
