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.

Combinators are functions that create or combine parsers. Parserator provides a rich set of combinators organized by their purpose.

Character Parsers

char()

Matches a single specific character:
const char: <T extends string>(ch: T) => Parser<T>
const openParen = char('(');
openParen.parse("(abc)"); // succeeds with "("
openParen.parse("abc");   // fails

string()

Matches an exact string:
const string: (str: string) => Parser<string>
const hello = string("hello");
hello.parse("hello world"); // succeeds with "hello"
hello.parse("goodbye");     // fails

narrowedString()

Like string() but preserves the literal type:
const narrowedString: <const T extends string>(str: T) => Parser<T>
const hello = narrowedString("hello"); // Parser<"hello">

regex()

Matches input against a regular expression:
const regex: (re: RegExp) => Parser<string>
const identifier = regex(/[a-zA-Z_][a-zA-Z0-9_]*/);
identifier.parse("myVar123"); // succeeds with "myVar123"

const number = regex(/-?[0-9]+/).map(Number);
number.parse("-42"); // succeeds with -42

anyChar()

Matches any single character:
const anyChar: () => Parser<string>
anyChar().parse("a"); // succeeds with "a"
anyChar().parse("");  // fails at end of input

notChar()

Matches any character except the specified one:
const notChar: (ch: string) => Parser<string>
const notQuote = notChar('"');
notQuote.parse("a"); // succeeds with "a"
notQuote.parse('"'); // fails

alphabet

Matches any alphabetic character (a-z, A-Z):
const alphabet: Parser<string>
alphabet.parse("a"); // succeeds with "a"
alphabet.parse("1"); // fails

digit

Matches any digit character (0-9):
const digit: Parser<string>
digit.parse("5"); // succeeds with "5"
digit.parse("a"); // fails

Repetition Combinators

many()

Matches zero or more occurrences:
const many: <T>(parser: Parser<T>) => Parser<T[]>
const digits = many(digit);
digits.parse("123");  // succeeds with ["1", "2", "3"]
digits.parse("");     // succeeds with []
digits.parse("abc");  // succeeds with []
Alias: many0()

many1()

Matches one or more occurrences:
const many1: <T>(parser: Parser<T>) => Parser<T[]>
const digits = many1(digit);
digits.parse("123");  // succeeds with ["1", "2", "3"]
digits.parse("");     // fails (requires at least one)

manyN()

Matches at least n occurrences:
const manyN: <T>(parser: Parser<T>, n: number) => Parser<T[]>
const atLeast3 = manyN(digit, 3);
atLeast3.parse("1234");  // succeeds with ["1", "2", "3", "4"]
atLeast3.parse("12");    // fails

count()

Matches exactly n occurrences:
const count: <T>(n: number, parser: Parser<T>) => Parser<T[]>
const threeDigits = count(3, digit);
threeDigits.parse("123");  // succeeds with ["1", "2", "3"]
threeDigits.parse("12");   // fails
threeDigits.parse("1234"); // succeeds with ["1", "2", "3"], leaves "4"

skipMany0(), skipMany1()

Skips zero or more / one or more occurrences:
const skipMany0: <T>(parser: Parser<T>) => Parser<undefined>
const skipMany1: <T>(parser: Parser<T>) => Parser<undefined>
const skipWhitespace = skipMany0(regex(/\s/));

Alternative Combinators

or()

Tries parsers in order until one succeeds:
const or: <Parsers extends Parser<any>[]>(
  ...parsers: Parsers
) => Parser<Parsers[number] extends Parser<infer T> ? T : never>
const value = or(
  string("true").map(() => true),
  string("false").map(() => false),
  number()
);

value.parse("true");  // succeeds with true
value.parse("false"); // succeeds with false
value.parse("42");    // succeeds with 42
The or() combinator is commit-aware. If any parser sets the committed flag during parsing, no further alternatives will be tried.

optional()

Makes a parser optional:
const optional: <T>(parser: Parser<T>) => Parser<T | undefined>
const sign = optional(or(char('+'), char('-')));
sign.parse("+");   // succeeds with "+"
sign.parse("123"); // succeeds with undefined

Sequence Combinators

sequence()

Runs multiple parsers in sequence and returns all results:
const sequence: <const T extends any[]>(
  parsers: T
) => Parser<SequenceOutput<T>>
const date = sequence([digit, digit, char('/'), digit, digit]);
date.parse("12/25"); // succeeds with ["1", "2", "/", "2", "5"]

sepBy()

Parses zero or more occurrences separated by a separator:
const sepBy: <S, T>(
  parser: Parser<T>,
  sepParser: Parser<S>
) => Parser<T[]>
const numbers = sepBy(number(), char(','));
numbers.parse("1,2,3"); // succeeds with [1, 2, 3]
numbers.parse("");      // succeeds with []

sepBy1()

Parses one or more occurrences separated by a separator:
const sepBy1: <S, T>(
  parser: Parser<T>,
  sepParser: Parser<S>
) => Parser<T[]>
const numbers = sepBy1(number(), char(','));
numbers.parse("1,2,3"); // succeeds with [1, 2, 3]
numbers.parse("");      // fails (requires at least one)

sepEndBy()

Parses a list with optional trailing separator:
const sepEndBy: <S, T>(
  parser: Parser<T>,
  sep: Parser<S>
) => Parser<T[]>
const list = sepEndBy(number(), char(','));
list.parse("1,2,3");  // succeeds with [1, 2, 3]
list.parse("1,2,3,"); // succeeds with [1, 2, 3] (trailing comma OK)

between()

Parses content between two delimiters:
const between: <T>(
  start: Parser<any>,
  end: Parser<any>,
  parser: Parser<T>
) => Parser<T>
const parens = between(char('('), char(')'), number());
parens.parse("(42)"); // succeeds with 42

const quoted = between(char('"'), char('"'), regex(/[^"]*/))
quoted.parse('"hello"'); // succeeds with "hello"

Lookahead Combinators

lookahead()

Looks ahead without consuming input:
const lookahead: <T>(parser: Parser<T>) => Parser<T | undefined>
const nextIsDigit = lookahead(digit);
// Succeeds if next char is a digit, but doesn't consume it

notFollowedBy()

Succeeds only if the given parser fails:
const notFollowedBy: <T>(parser: Parser<T>) => Parser<boolean>
const notA = notFollowedBy(char('a'));
notA.parse("bcd"); // succeeds
notA.parse("abc"); // fails

Utility Combinators

takeUntil()

Takes input until the given parser succeeds:
const takeUntil: <T>(parser: Parser<T>) => Parser<string>
const untilQuote = takeUntil(char('"'));
untilQuote.parse('hello"world'); // succeeds with "hello"

takeUpto()

Takes input until before the given parser would succeed:
const takeUpto: <T>(parser: Parser<T>) => Parser<string>

skipUntil()

Skips input until the given parser succeeds:
const skipUntil: <T>(parser: Parser<T>) => Parser<undefined>

eof

Matches only at the end of input:
const eof: Parser<void>
const complete = identifier().thenDiscard(eof);
complete.parse("hello");       // succeeds
complete.parse("hello world"); // fails (not at end)

Control Flow Combinators

commit()

Prevents backtracking after this point:
const commit: () => Parser<void>
import { parser, commit, keyword, char } from 'parserator';

const ifStatement = parser(function* () {
  yield* keyword("if");
  yield* commit();  // No backtracking after this
  yield* char('(').expect("opening parenthesis");
  // ...
});
Alias: cut() See the Error Handling guide for more details.

atomic()

Makes a parser all-or-nothing (resets state on failure):
const atomic: <T>(parser: Parser<T>) => Parser<T>
const keyword = atomic(regex(/[a-z]+/));
// If it fails, no input is consumed

Position Combinators

position

Gets the current source position:
const position: Parser<SourcePosition>
type SourcePosition = {
  line: number;
  column: number;
  offset: number;
}
const withPosition = parser(function* () {
  const start = yield* position;
  const value = yield* identifier();
  const end = yield* position;
  return { value, start, end };
});

Whitespace Helpers

skipSpaces

Skips any number of space characters:
const skipSpaces: Parser<undefined>
const token = <T>(p: Parser<T>) => p.trimLeft(skipSpaces);