If anyone is curious, I threw together a similar (although not commented yet) example of how I would write this using parser combinators in Haskell: https://gist.github.com/neilparikh/b8a9c758ebbbb5a3ee9b2ed99...
The JS example wrote everything from scratch, so to do the same, I wrote my own parser combinator library (based on https://www.cs.nott.ac.uk/~pszgmh/monparsing.pdf), but you could use an existing library, and get rid of `Parser.hs`.