npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@honungsburk/kombo

v3.0.0

Published

Are you tired of complex regex? Do you want good error messages? Use kombo!

Downloads

354

Readme

NOTE: This is a port of Elm's Parser Combinators library to typescript. This includes large part of the documentation

Kombo

Regular expressions are quite confusing and difficult to use. This library provides a coherent alternative that handles more cases and produces clearer code.

The particular goals of this library are:

  • Make writing parsers as simple and fun as possible.
  • Produce excellent error messages.
  • Go pretty fast.
  • Works with CommonJS and ESM. Browser or node.

Installation

npm install @honungsburk/kombo

Parser Pipelines

To parse a 2D point like "( 3, 4 )", you might create a point parser like this:

import {
  Parser,
  succeed,
  symbol,
  float,
  spaces,
} from "@honungsburk/kombo/Simple";

type Point = {
  x: number;
  y: number;
};

const point: Parser<Point> = succeed((x: number) => (y: number) => {
  x, y;
})
  .skip(symbol("("))
  .skip(spaces)
  .apply(float)
  .skip(spaces)
  .skip(symbol(","))
  .skip(spaces)
  .apply(float)
  .skip(spaces)
  .skip(symbol(")"));

// Running the parser returns a Result wrapper that can either be OK or Err
const pointResult = point.run("( 123.09, 23.123)");

// If it is Ok the parsing succeeded
if (pointResult.isOk) {
  console.log("x:", pointResult.value.x);
  console.log("y:", pointResult.value.y);
}

// If there was an error can deal with it accordingly
if(pointResult.isErr){
  ...
}

All the interesting stuff is happening in point. It uses two operators:

  • skip means “parse this, but ignore the result”
  • apply means “parse this, and apply the result to the function”

So the point function only gets the result of the two float parsers.

I recommend having one line per operator in your parser pipeline. If you need multiple lines for some reason, use a let or make a helper function.

If you want to have look at a larger example head over to the Kombo-Json repository, and if you still feel unsure you can clone the Kombo Workshop repository and go through the exercises.

Backtracking

To make fast parsers with precise error messages, all of the parsers in this package do not backtrack by default. Once you start going down a path, you keep going down it.

This is nice in a string like [ 1, 23zm5, 3 ] where you want the error at the z. If we had backtracking by default, you might get the error on [ instead. That is way less specific and harder to fix!

So the defaults are nice, but sometimes the easiest way to write a parser is to look ahead a bit and see what is going to happen. It is definitely more costly to do this, but it can be handy if there is no other way. This is the role of backtrackable parsers. Check out the semantics page for more details!

Tracking Context

Most parsers tell you the row and column of the problem:

Something went wrong at (4:17)

That may be true, but it is not how humans think. It is how text editors think! It would be better to say:

I found a problem with this list:

      [ 1, 23zm5, 3 ]
           ^

I wanted an integer, like 6 or 90219.

Notice that the error messages says this list. That is context! That is the language my brain speaks, not rows and columns.

Once you get comfortable with the Simple module, you can switch over to Advanced and use inContext to track exactly what your parser thinks it is doing at the moment. You can let the parser know “I am trying to parse a "list" right now” so if an error happens anywhere in that context, you get the hand annotation!

This technique is used by the parser in the Elm compiler to give more helpful error messages.

FAQ

Why did you name this library Kombo?

This is a parser combinator library, and the Swedish word for combo is , you guessed it, kombo.

Do you have any large examples on how to build a real parser using Kombo?

Checkout the Kombo JSON Parser

I still don't know how to use it!

Don't fret! Clone the Kombo Workshop repository and go through the exercises.

Links