RDP.js

Write parsers, not boilerplate. Drop in a grammar, get a fully typed TypeScript parser — zero dependencies, dual ESM/CJS, batteries included.

Quick start

# scaffold a new parser project in seconds
npm install -g @configuredthings/rdp.js
mkdir my-parser && cd my-parser
rdp-gen init --name my-parser
npm install
Recursquirrel — the RDP.js mascot

"Hi, I'm recursquirrel, your friendly recursively descending parsing squirrel"

Typed base class

Subclass RDParser, implement grammar productions as methods, and get buffer management and position tracking for free.

Code generator

Write your grammar in EBNF or ABNF. rdp-gen scaffolds a fully typed TypeScript parser class in one command.

Parse debugger

Step through every production call with ObservableRDParser. Watch the call stack grow and shrink as the parser works.

LL(1) focus

Purpose-built for LL(1) grammars: config files, data formats, expression languages, and protocol frames — where top-down parsing shines.

Zero runtime dependencies

The core RDParser base class ships with zero runtime dependencies. TypeScript 6, dual ESM/CJS output.

Readable, testable code

The generated code mirrors the grammar exactly — one method per rule, easy to read, test, and debug without any parser magic.

Grammar → parser in seconds

Write the grammar rule, implement the method — one-to-one correspondence makes the code easy to review, extend, and test.

// Grammar: Expr = wsp, Term, {wsp, ('+' | '-'), wsp, Term}, wsp;
//          Term = Factor, {wsp, ('*' | '/'), wsp, Factor};

class ArithmeticParser extends RDParser {
  parse(): boolean {
    return this.expr() && this.atEnd()
  }

  private expr(): boolean {
    if (!this.term()) return false
    while (this.peek() === '+' || this.peek() === '-') {
      this.consume()
      if (!this.term()) return this.error('expected term')
    }
    return true
  }
}
Full tutorialTry it live