Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/saiashirwad/parserator/llms.txt

Use this file to discover all available pages before exploring further.

Quickstart

Let’s build a parser for coordinate points like (10,20). You’ll learn the core concepts of Parserator through a hands-on example.

What we’ll build

By the end of this tutorial, you’ll have a parser that:
  • Parses coordinates in the format (x,y)
  • Handles numbers with multiple digits
  • Provides helpful error messages
  • Has full TypeScript type inference
1

Parse a single digit

Start by importing the basic combinators and parsing a single digit:
import { digit } from "parserator";

const result = digit.parseOrThrow("5");
console.log(result); // "5"
The digit parser matches any single digit character (0-9) and returns it as a string.
Try changing the input to a non-digit like "a" to see what error message you get!
2

Parse multiple digits into a number

Use many1 to parse one or more digits, then transform them into a number:
import { digit, many1 } from "parserator";

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

const result = number.parseOrThrow("123");
console.log(result); // 123
console.log(typeof result); // "number"
Here’s what’s happening:
  • many1(digit) parses one or more digits, returning string[]
  • .map() transforms the array of digit strings into a single number
  • TypeScript infers the final type as number
3

Use generator syntax to parse coordinates

Now combine parsers using generator syntax to parse the full coordinate format:
import { parser, char, many1, digit } from "parserator";

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

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

const result = point.parseOrThrow("(10,20)");
console.log(result); // { x: 10, y: 20 }
The parser function creates a parser from a generator. Each yield* runs a parser and extracts its value. The final return is the parser’s result.
Notice how TypeScript automatically infers that x and y are numbers, and the final result is { x: number, y: number }.
4

Use .parse() for error handling

The parseOrThrow() method throws an exception on failure. Use .parse() for explicit error handling:
const result = point.parse("(10,20)");

if (result.result._tag === "Left") {
  // Parse failed
  const error = result.result.left;
  console.log(error.format("ansi")); // Pretty error with colors
} else {
  // Parse succeeded
  const value = result.result.right;
  console.log(value); // { x: 10, y: 20 }
}
The .parse() method returns a ParserOutput with an Either type:
  • Left contains the error bundle
  • Right contains the successful result
5

Add better error messages

Use .expect() to provide context-specific error messages:
const point = parser(function* () {
  yield* char("(").expect("opening parenthesis '('");
  const x = yield* number;
  yield* char(",").expect("comma between coordinates");
  const y = yield* number;
  yield* char(")").expect("closing parenthesis ')'");
  return { x, y };
});

// Try parsing invalid input
const result = point.parse("(10; 20)");
if (result.result._tag === "Left") {
  console.log(result.result.left.format("ansi"));
  // Error: Expected comma between coordinates
}
Now errors tell you exactly what went wrong instead of just “parse failed”.
6

Handle whitespace (optional)

Real-world input often has extra whitespace. Use string and regex to handle it:
import { parser, char, string, many1, digit, regex, optional } from "parserator";

const whitespace = regex(/\s*/);
function token<T>(p: any) {
  return p.trimLeft(whitespace);
}

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

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

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

Complete example

Here’s the full code from this tutorial:
import { parser, char, many1, digit } from "parserator";

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

const point = parser(function* () {
  yield* char("(").expect("opening parenthesis '('");
  const x = yield* number;
  yield* char(",").expect("comma between coordinates");
  const y = yield* number;
  yield* char(")").expect("closing parenthesis ')'");
  return { x, y };
});

// Success case
const result1 = point.parseOrThrow("(10,20)");
console.log(result1); // { x: 10, y: 20 }

// Error handling
const result2 = point.parse("(10; 20)");
if (result2.result._tag === "Left") {
  console.log(result2.result.left.format("ansi"));
}

Key concepts you learned

  • Basic parsers: digit, char(), string() match simple patterns
  • Combinators: many1() repeats a parser one or more times
  • Transformation: .map() transforms parser results
  • Generator syntax: parser(function* () { ... }) composes parsers sequentially
  • Error handling: .parse() vs .parseOrThrow()
  • Better errors: .expect() adds context to error messages

What’s next?

You now know enough to build useful parsers! Here are some ideas to explore:

Core concepts

Deep dive into parser combinators, generators, and error handling

API reference

Explore all available parsers and combinators

Error handling

Learn about commit, backtracking, and rich error messages

Examples

Study complete examples like JSON, INI, and language parsers
Try modifying the parser to support 3D coordinates like (10,20,30) or optional whitespace. Experimenting is the best way to learn!