Skip to main content

Introduction

Parserator is a parser combinator library for TypeScript that lets you build complex parsers by composing small, reusable functions. Write parsers that feel like the grammar they implement, with full type inference and zero dependencies.
import { parser, char, many1, digit } from "parserator";

const number = many1(digit).map(d => parseInt(d.join("")));

const point = parser(function* () {
  yield* char("(");
  const x = yield* number;
  yield* char(",");
  const y = yield* number;
  yield* char(")");
  return { x, y };
});

point.parseOrThrow("(10,20)"); // { x: 10, y: 20 }

Why parser combinators?

Parser combinators offer a sweet spot between regex and parser generators:

vs Regex

Regex works for simple patterns but becomes unreadable for nested structures. Parser combinators handle recursion, context, and complex grammars naturally.

vs Parser generators

Tools like ANTLR require separate grammar files and build steps. Parser combinators are just TypeScript—no tooling needed.

vs Hand-written

Hand-written parsers give you control but are tedious and error-prone. Combinators give you the same power with less code.

Key features

Generator syntax

Use function* and yield* to write parsers that mirror your grammar structure. No callback hell, no deeply nested code.

Full type inference

TypeScript infers types throughout your parser chain. Get autocomplete and type safety for free.

Rich error messages

Get detailed error messages with source snippets, position tracking, and typo suggestions via Levenshtein distance.

Commit/backtracking

Control when the parser commits to a path. Better error messages instead of generic “expected one of…” failures.

Zero dependencies

No external dependencies. Just TypeScript and your code.

Performance optimized

Fast-path optimizations for common patterns. Use manyDigit() instead of many(digit) for hot paths.

How it works

Small parsers combine into complex ones:
// A parser for a single digit
const digit = parser(/* ... */);

// Combine with many1 to get one or more digits
const digits = many1(digit);

// Transform the array of digits into a number
const number = digits.map(d => parseInt(d.join("")));

// Compose parsers with generator syntax
const point = parser(function* () {
  yield* char("(");
  const x = yield* number;  // Full type inference here!
  yield* char(",");
  const y = yield* number;
  yield* char(")");
  return { x, y };  // Type: { x: number, y: number }
});
The generator syntax lets you write imperative-looking code that’s actually building a composable parser. Each yield* runs a parser and extracts its value.
The generator syntax is syntactic sugar over monadic combinators. You can also use .map(), .flatMap(), and other functional methods.

What you can build

Parserator is suitable for:
  • Configuration parsers - INI, TOML, custom formats
  • Data formats - JSON, CSV, custom protocols
  • Expression languages - Math expressions, template languages
  • Programming languages - Complete language parsers with type checking
  • Command-line parsers - Shell-like syntax, arguments
  • Protocol parsers - Binary formats, network protocols
Check out the examples directory for complete parsers including JSON, Scheme, and a full ML-like language with pattern matching.

Next steps

Installation

Install Parserator and set up your project

Quickstart

Build your first parser in 5 minutes

Core concepts

Learn the fundamental concepts

Build docs developers (and LLMs) love