CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-parsimmon

A monadic LL(infinity) parser combinator library

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

string-parsers.mddocs/

String and Character Parsing

Built-in parsers for common string and character matching patterns. These provide convenient shortcuts for frequently used parsing operations.

Capabilities

Pre-built Character Parsers

Ready-to-use parsers for common character types and patterns.

// Single character parsers
Parsimmon.any;           // Matches any single character
Parsimmon.digit;         // Matches single digit [0-9]
Parsimmon.letter;        // Matches single letter [a-zA-Z]

// Multiple character parsers
Parsimmon.digits;        // Matches zero or more digits
Parsimmon.letters;       // Matches zero or more letters
Parsimmon.whitespace;    // Matches one or more whitespace characters
Parsimmon.optWhitespace; // Matches zero or more whitespace characters

Usage Examples:

// Parse single characters
Parsimmon.digit.parse("5"); // { status: true, value: "5" }
Parsimmon.letter.parse("a"); // { status: true, value: "a" }
Parsimmon.any.parse("@"); // { status: true, value: "@" }

// Parse multiple characters
Parsimmon.digits.parse("123"); // { status: true, value: "123" }
Parsimmon.letters.parse("hello"); // { status: true, value: "hello" }
Parsimmon.whitespace.parse("  \t"); // { status: true, value: "  \t" }

// Combining with other parsers
const word = Parsimmon.letters.skip(Parsimmon.optWhitespace);
const number = Parsimmon.digits.map(Number);

Line Ending Parsers

Parsers for different line ending formats across platforms.

Parsimmon.cr;       // Matches carriage return (\r)
Parsimmon.lf;       // Matches line feed (\n)
Parsimmon.crlf;     // Matches Windows line ending (\r\n)
Parsimmon.newline;  // Matches any line ending (CR, LF, or CRLF)
Parsimmon.end;      // Matches newline or end of input

Usage Examples:

// Parse different line endings
Parsimmon.newline.parse("\n"); // { status: true, value: "\n" }
Parsimmon.newline.parse("\r\n"); // { status: true, value: "\r\n" }
Parsimmon.crlf.parse("\r\n"); // { status: true, value: "\r\n" }

// Use in line-based parsing
const line = Parsimmon.regexp(/[^\r\n]*/).skip(Parsimmon.newline);
const lines = line.many();
lines.parse("line1\nline2\nline3\n");

Special Position Parsers

Parsers for special positions and conditions in the input.

Parsimmon.eof;    // Matches end of input
Parsimmon.all;    // Consumes all remaining input
Parsimmon.index;  // Returns current position information

Usage Examples:

// Ensure complete parsing
const completeNumber = Parsimmon.digits.skip(Parsimmon.eof);
completeNumber.parse("123"); // Success
completeNumber.parse("123abc"); // Fails - not at end

// Get all remaining input
const remaining = Parsimmon.string("start:").then(Parsimmon.all);
remaining.parse("start:everything else"); // { status: true, value: "everything else" }

// Track position
const withPosition = Parsimmon.seq(
  Parsimmon.index,
  Parsimmon.string("hello"),
  Parsimmon.index
).map(([start, value, end]) => ({ value, start, end }));

Character Set Parsers

Parsers for matching characters from specific sets or ranges.

/**
 * Matches any character from the given string
 * @param {string} str - String containing valid characters
 * @returns {Parser} Parser that matches any character in str
 */
Parsimmon.oneOf(str);

/**
 * Matches any character NOT in the given string
 * @param {string} str - String containing invalid characters
 * @returns {Parser} Parser that matches any character not in str
 */
Parsimmon.noneOf(str);

/**
 * Matches any character in the given range (inclusive)
 * @param {string} begin - Start character of range
 * @param {string} end - End character of range
 * @returns {Parser} Parser that matches characters in range
 */
Parsimmon.range(begin, end);

Usage Examples:

// Parse vowels
const vowel = Parsimmon.oneOf("aeiouAEIOU");
vowel.parse("a"); // { status: true, value: "a" }
vowel.parse("x"); // { status: false, ... }

// Parse consonants
const consonant = Parsimmon.noneOf("aeiouAEIOU0123456789 \t\n");
consonant.parse("b"); // { status: true, value: "b" }

// Parse letter ranges
const lowercase = Parsimmon.range("a", "z");
const uppercase = Parsimmon.range("A", "Z");
const hexDigit = Parsimmon.oneOf("0123456789abcdefABCDEF");

// Combine ranges
const alphanumeric = Parsimmon.alt(
  Parsimmon.range("a", "z"),
  Parsimmon.range("A", "Z"),
  Parsimmon.range("0", "9")
);

Predicate-based Parsers

Parsers that use custom functions to test characters.

/**
 * Matches a single character/byte that satisfies the predicate
 * @param {Function} predicate - Function that tests a character
 * @returns {Parser} Parser that matches when predicate returns true
 */
Parsimmon.test(predicate);

/**
 * Consumes characters while predicate is true
 * @param {Function} predicate - Function that tests each character
 * @returns {Parser} Parser that consumes matching characters
 */
Parsimmon.takeWhile(predicate);

Usage Examples:

// Parse uppercase letters
const isUppercase = (ch) => ch >= "A" && ch <= "Z";
const uppercase = Parsimmon.test(isUppercase);
uppercase.parse("H"); // { status: true, value: "H" }

// Parse identifiers
const isAlphaNum = (ch) => /[a-zA-Z0-9_]/.test(ch);
const identifier = Parsimmon.test(ch => /[a-zA-Z_]/.test(ch))
  .then(Parsimmon.takeWhile(isAlphaNum))
  .map((first, rest) => first + rest);

// Parse numbers with custom logic
const isDigit = (ch) => ch >= "0" && ch <= "9";
const naturalNumber = Parsimmon.takeWhile(isDigit)
  .assert(str => str.length > 0, "at least one digit")
  .map(Number);

// Parse until delimiter
const isNotComma = (ch) => ch !== ",";
const csvField = Parsimmon.takeWhile(isNotComma);

Lookahead Parsers

Parsers that check ahead without consuming input.

/**
 * Succeeds if parser would succeed, but consumes no input
 * @param {Parser|string|RegExp} x - Parser, string, or regex to look ahead for
 * @returns {Parser} Parser that looks ahead without consuming
 */
Parsimmon.lookahead(x);

/**
 * Succeeds if parser would fail, consumes no input
 * @param {Parser} parser - Parser that should not match
 * @returns {Parser} Parser that succeeds when parser fails
 */
Parsimmon.notFollowedBy(parser);

Usage Examples:

// Parse numbers not followed by letters
const numberNotInWord = Parsimmon.digits
  .skip(Parsimmon.notFollowedBy(Parsimmon.letter));

numberNotInWord.parse("123"); // Success
numberNotInWord.parse("123abc"); // Fails

// Look ahead for keywords
const keywordIf = Parsimmon.string("if")
  .skip(Parsimmon.lookahead(Parsimmon.regexp(/\s/)));

keywordIf.parse("if "); // Success  
keywordIf.parse("ifelse"); // Fails

// Conditional parsing based on lookahead
const stringOrNumber = Parsimmon.lookahead(Parsimmon.digit)
  .then(Parsimmon.digits.map(Number))
  .or(Parsimmon.letters);

Install with Tessl CLI

npx tessl i tessl/npm-parsimmon

docs

binary-parsing.md

combinators.md

core-parsers.md

index.md

language-creation.md

string-parsers.md

transformation.md

tile.json