Convert Figma logo to code with AI

jneen logoparsimmon

A monadic LL(infinity) parser combinator library for javascript

1,240
126
1,240
5

Top Related Projects

4,808

PEG.js: Parser generator for JavaScript

3,322

A pure Ruby code highlighter that is compatible with Pygments

3,586

📜🔜🌲 Simple, fast, powerful parser toolkit for JavaScript.

4,967

A library and language for building parsers, interpreters, compilers, etc.

Parser Building Toolkit for JavaScript

Quick Overview

Parsimmon is a small library for writing expressive parsers in JavaScript using parser combinators. It allows developers to build complex parsers from smaller, simpler building blocks, making it easier to create parsers for custom languages or data formats.

Pros

  • Easy to use and learn, with a clean and intuitive API
  • Composable and flexible, allowing for the creation of complex parsers
  • Provides helpful error messages for debugging
  • Works in both Node.js and browser environments

Cons

  • May have performance limitations for very large inputs
  • Less suitable for parsing highly ambiguous grammars
  • Limited built-in parsers compared to some other parsing libraries
  • Requires a functional programming mindset, which may be unfamiliar to some developers

Code Examples

Creating a simple parser for a number:

const P = require('parsimmon');

const number = P.regexp(/[0-9]+/).map(Number);
console.log(number.parse('123')); // { status: true, value: 123 }

Parsing a simple arithmetic expression:

const P = require('parsimmon');

const expr = P.lazy(() => P.alt(
  P.regexp(/[0-9]+/).map(Number),
  P.string('(').then(expr).skip(P.string(')')),
  expr.chain(left => P.alt(
    P.string('+').then(expr).map(right => left + right),
    P.string('-').then(expr).map(right => left - right)
  ))
));

console.log(expr.parse('(1+2)-3')); // { status: true, value: 0 }

Parsing a simple JSON-like structure:

const P = require('parsimmon');

const json = P.lazy(() => P.alt(
  P.string('null').result(null),
  P.string('true').result(true),
  P.string('false').result(false),
  P.regexp(/-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?/).map(Number),
  P.regexp(/"((?:\\.|.)*?)"/, 1).map(s => JSON.parse('"' + s + '"')),
  P.string('{').then(P.lazy(() => keyValue.sepBy(P.string(',')))).skip(P.string('}')).map(Object.fromEntries),
  P.string('[').then(json.sepBy(P.string(','))).skip(P.string(']'))
));

const keyValue = P.seqMap(
  P.regexp(/"((?:\\.|.)*?)"/, 1),
  P.string(':').then(json),
  (k, v) => [k, v]
);

console.log(json.parse('{"a": 1, "b": [true, null]}')); 
// { status: true, value: { a: 1, b: [true, null] } }

Getting Started

To use Parsimmon in your project, first install it via npm:

npm install parsimmon

Then, in your JavaScript file:

const P = require('parsimmon');

// Define your parsers
const myParser = P.string('hello').then(P.string(' world'));

// Use your parser
const result = myParser.parse('hello world');
console.log(result); // { status: true, value: ' world' }

Competitor Comparisons

4,808

PEG.js: Parser generator for JavaScript

Pros of PEG.js

  • Generates standalone parsers, allowing for easier distribution and integration
  • Provides a more declarative syntax for defining grammars
  • Offers built-in error reporting and recovery mechanisms

Cons of PEG.js

  • Less flexible for dynamic grammar modifications at runtime
  • Steeper learning curve for those unfamiliar with PEG syntax
  • Limited support for incremental parsing

Code Comparison

PEG.js grammar example:

start
  = additive

additive
  = left:multiplicative "+" right:additive { return left + right; }
  / multiplicative

multiplicative
  = left:primary "*" right:multiplicative { return left * right; }
  / primary

primary
  = integer
  / "(" additive:additive ")" { return additive; }

integer "integer"
  = digits:[0-9]+ { return parseInt(digits.join(""), 10); }

Parsimmon equivalent:

const P = require('parsimmon');

const parser = P.createLanguage({
  start: r => r.additive,
  additive: r => P.alt(
    P.seq(r.multiplicative, P.string('+'), r.additive).map(([l, _, r]) => l + r),
    r.multiplicative
  ),
  multiplicative: r => P.alt(
    P.seq(r.primary, P.string('*'), r.multiplicative).map(([l, _, r]) => l * r),
    r.primary
  ),
  primary: r => P.alt(
    r.integer,
    P.seq(P.string('('), r.additive, P.string(')')).map(([_, a, __]) => a)
  ),
  integer: () => P.regexp(/[0-9]+/).map(Number)
});
3,322

A pure Ruby code highlighter that is compatible with Pygments

Pros of Rouge

  • Supports a wide range of programming languages for syntax highlighting
  • Actively maintained with frequent updates and contributions
  • Designed specifically for syntax highlighting, making it more specialized for this task

Cons of Rouge

  • Limited to syntax highlighting, not a general-purpose parsing library
  • May have a steeper learning curve for custom language support
  • Ruby-specific, which might not be ideal for projects in other languages

Code Comparison

Parsimmon (JavaScript):

const P = require('parsimmon');
const parser = P.string('hello').then(P.string('world'));
const result = parser.parse('helloworld');

Rouge (Ruby):

require 'rouge'
lexer = Rouge::Lexers::HTML.new
formatter = Rouge::Formatters::HTML.new
highlighted = formatter.format(lexer.lex('<h1>Hello, world!</h1>'))

Summary

Parsimmon is a general-purpose parsing library for JavaScript, offering flexibility for various parsing tasks. Rouge, on the other hand, is a Ruby-based syntax highlighter with extensive language support. While Parsimmon allows for custom parser creation, Rouge excels in out-of-the-box syntax highlighting for numerous languages. The choice between them depends on the specific project requirements, programming language preference, and whether the focus is on general parsing or syntax highlighting.

3,586

📜🔜🌲 Simple, fast, powerful parser toolkit for JavaScript.

Pros of Nearley

  • Supports a wider range of grammar types, including context-sensitive grammars
  • Generates fast, standalone JavaScript parsers
  • Includes a built-in tokenizer (Moo) for lexical analysis

Cons of Nearley

  • Steeper learning curve due to its unique grammar syntax
  • Less flexibility in combining and manipulating parsers
  • May produce larger output files for complex grammars

Code Comparison

Nearley grammar example:

main -> "hello" ws "world" {% d => ({ greeting: d[0], target: d[2] }) %}
ws -> [ \t\n\v\f]+

Parsimmon equivalent:

const parser = Parsimmon.seq(
  Parsimmon.string("hello"),
  Parsimmon.regexp(/[ \t\n\v\f]+/),
  Parsimmon.string("world")
).map(([greeting, _, target]) => ({ greeting, target }));

Both Nearley and Parsimmon are powerful parser libraries for JavaScript, but they cater to different use cases. Nearley excels in handling complex grammars and generating standalone parsers, while Parsimmon offers a more flexible, combinatorial approach that may be easier for developers familiar with functional programming concepts.

4,967

A library and language for building parsers, interpreters, compilers, etc.

Pros of Ohm

  • More powerful and flexible grammar definition syntax
  • Built-in support for left-recursive rules
  • Includes a visual debugger and editor for grammar development

Cons of Ohm

  • Steeper learning curve due to its unique approach
  • Less idiomatic JavaScript syntax compared to Parsimmon
  • May be overkill for simpler parsing tasks

Code Comparison

Parsimmon example:

const P = require('parsimmon');
const parser = P.string('hello')
  .then(P.string(' '))
  .then(P.string('world'));

Ohm example:

const ohm = require('ohm-js');
const grammar = ohm.grammar(`
  Greeting {
    greeting = "hello" " " "world"
  }
`);

Both Parsimmon and Ohm are popular parsing libraries for JavaScript, but they have different approaches and strengths. Parsimmon uses a more functional, combinator-based style, while Ohm employs a grammar-based approach inspired by PEG parsers.

Parsimmon is generally easier to get started with for JavaScript developers, as its API closely resembles typical JavaScript patterns. It's well-suited for smaller parsing tasks and can be easily integrated into existing projects.

Ohm, on the other hand, offers more advanced features and is better suited for complex grammars. Its separate grammar definition syntax allows for more expressive and maintainable parser definitions, especially for larger projects. The visual tools provided by Ohm can be particularly helpful during development and debugging.

Parser Building Toolkit for JavaScript

Pros of Chevrotain

  • Higher performance due to its optimized parsing algorithm
  • Better error reporting and recovery capabilities
  • Supports a wider range of parsing techniques, including LL(k) and LR(1)

Cons of Chevrotain

  • Steeper learning curve and more complex API
  • Requires more boilerplate code for simple grammars
  • Larger library size, which may impact bundle size in browser environments

Code Comparison

Parsimmon example:

const P = require('parsimmon');
const parser = P.string('hello').then(P.string('world'));
const result = parser.parse('helloworld');

Chevrotain example:

const { Lexer, CstParser } = require('chevrotain');
class MyParser extends CstParser {
  constructor() {
    super([/* token definitions */]);
    this.RULE('expression', () => {
      this.CONSUME('Hello');
      this.CONSUME('World');
    });
  }
}

Summary

Chevrotain offers more advanced features and better performance, making it suitable for complex parsing tasks. Parsimmon, on the other hand, provides a simpler API and is easier to get started with for basic parsing needs. The choice between the two depends on the complexity of the parsing requirements and the developer's familiarity with parsing concepts.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Parsimmon

!!! PARSIMMON IS CURRENTLY UNMAINTAINED !!!

Please contact @jneen if you would like to become the new maintainer.

Parsimmon

Original Authors: @jneen and @laughinghan

Previous Maintainer: @wavebeem

Parsimmon is a small library for writing big parsers made up of lots of little parsers. The API is inspired by parsec and Promises/A+.

Parsimmon supports IE7 and newer browsers, along with Node.js. It can be used as a standard Node module through npm (named parsimmon), or directly in the browser through a script tag, where it exports a global variable called Parsimmon. To download the latest browser build, use the unpkg version. For more information on how to use unpkg, see the unpkg homepage.

Code of Conduct

Everyone is expected to abide by the Contributor Covenant.

API Documentation

Examples

See the examples directory for annotated examples of parsing JSON, Lisp, a Python-ish language, and math.

Common Functions

Questions

Feel free to ask a question by filing a GitHub Issue. I'm happy to help point you in the right direction with the library, and hopefully improve the documentation so less people get confused in the future.

Contributing

Contributions are not just pull requests.

Issues clearly describing bugs or confusing parts of Parsimmon are welcome! Also, documentation enhancements and examples are very desirable.

Feeling overwhelmed about contributing? Open an issue about what you want to contribute and I'm happy to help you through to completion!

Performance

Thanks to @bd82 we have a good benchmark comparing Parsimmon CPU performance to several other parser libraries with a simple JSON parser example.

Fantasy Land

Fantasyland

Parsimmon is also compatible with fantasyland. It implements Semigroup, Apply, Applicative, Functor, Chain, and Monad.

NPM DownloadsLast 30 Days