Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Casual Parsing in JavaScript (brandons.me)
38 points by ingve on Aug 19, 2021 | hide | past | favorite | 10 comments


Parser combinators [0] are great for quick parsing, usage from typescript is very neat. You can collapse tokenisation, parsing and some evaluation for simple grammars (they appear in production from time to time) into single parser combinator phase (there’s nothing else) where you get desired, typed result from your parser. It’s really fun to play with and imho one of the best ways to grasp monads really - when you write parser combinator by yourself it really clicks in.

[0] https://github.com/appliedblockchain/parser-combinators


Hi, I've written recursive descent in JS similar to Brandon's examples. Do you have any examples of what usage of this library (or parser combinators in general) would look like? I found a few docs about the idea and it makes sense at a high level but I haven't been able to turn that into a clear idea of what such a parser looks like in practice.


It's Haskell, not Typescript, but http://dev.stephendiehl.com/fun/002_parsers.html goes over how parser combinators work and how to use them. I've also got a simple example on my github, https://github.com/DylanSp/three-pass-compiler.



I’ve found generator functions work great for parsers. You yield the tokens you expect to be next. The token could be a string, a regular expression to be matched, or another generator function.

The library is open source here, contributions welcome: https://github.com/RoyalIcing/yieldparser

Generator functions have great support in modern browsers (not IE) and Node.js.

For example here’s a simple v4 IP address parser:

  import { parse, mustEnd } from 'yieldparser';
  
  function* Digit() {
    const [digit]: [string] = yield /^\d+/;
    const value = parseInt(digit, 10);
    if (value < 0 || value > 255) {
      return new Error(`Digit must be between 0 and 255, was ${value}`);
    }
    return value;
  }
  
  function* IPAddress() {
    const first = yield Digit;
    yield '.';
    const second = yield Digit;
    yield '.';
    const third = yield Digit;
    yield '.';
    const fourth = yield Digit;
    yield mustEnd;
    return [first, second, third, fourth];
  }
  
  parse('1.2.3.4', IPAddress());
  /*
  {
    success: true,
    result: [1, 2, 3, 4],
    remaining: '',
  }
  */


Hi Brandon, earlier this year, I wrote an interpreting (interactive) parser in JavaScript. The code is embedded in the page https://fransfaase.github.io/ParserWorkshop/Online_inter_par... . I have not yet made a library out of it. Maybe you can have a look at it.


Cool! I'd recommend the author make the title more clearly "Writing a JSON parser in JavaScript/TypeScript" since I've got a similar post on writing a JSON parser in Python and it gets some of the most search engine traffic of any of my posts. Clearly a lot of people are interested in parsing basics.


Parser Combinators are fun and quick for simple grammars, but for more complex grammars I will always turn to a PEG parser based on an EBNF grammar.

In Python, my go-to library is Tatsu[0], but I guess I should also give a try to ANTLR4[1].

Also, for parser combinators, Elixir have the amazing NimbleParsec[2] library which is amazingly easy to use.

  [0] - https://tatsu.readthedocs.io/en/stable/
  [1] - https://www.antlr.org
  [2] - https://hexdocs.pm/nimble_parsec/NimbleParsec.html


You might enjoy checking out Instaparse, a Clojure library. Its project page reads, “What if context-free grammars were as easy to use as regular expressions?”

It’s not over-promising, either. I went from never having heard of it before to getting complete and correct parse trees of some ancient JSP Expression Language in about 20 minutes. Most of that time was spent typing in the BNF description that I could find only in an image.

https://github.com/Engelberg/instaparse


Probably not a bad idea, I guess I just think writing a JSON parser in JavaScript is an inherently silly task if not done for learning/fun/demonstration, so I wanted to emphasize the latter aspect :)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: