Dasch/parser, an easier to use parsing library

Before publishing a package and locking down the API I would love to get some feedback on a new parser combinator library I’ve written. I did it because I found elm/parser hard to use, and thought it would be interesting to see if a simpler API would be feasible. I think I’ve done pretty well, but bear in mind that this is a somewhat opinionated library:

  • Ease of use and readability is favored over performance.
  • Simplicity is favored over sophistication, e.g. when it comes to the ability to generate great error messages.

These are tradeoffs, and different from those made from elm/parser.

Please have a look at the tests/Examples dir for working examples.

2 Likes

One thing that sticks out to me is that followedBy feels really unintuitively named - it doesn’t describe at all what it actually does. Why not just use grab and ignore also in sub-parsers?

Thanks for taking a look!

grab and ignore only work when building up values using constructor function, e.g.

into (\a b -> (a, b))
  |> grab int
  |> ignore (char ',')
  |> grab int

While it’s possible to do e.g.

into ()
  |> ignore (char ':')
  |> int

That would seem a bit weird. Do you have a better name than followedBy in mind? The idea was that it would match one parser and then another, but throw away the first value. There’s also andThen, but that passes the value of the first parser into a function that returns a new parser, e.g.

int
  |> andThen (\x ->
      char '+'
        |> andThen (_ ->
          int
            |> andThen (\y -> succeed (x + y))
          )
        )
      )
    )

What about using with instead of into?

with Url
    |> grab protocol
    |> ignore (string "://")
    |> grab host
    |> grab (maybe port_)
    |> grab path
    |> grab (maybe query)
    |> grab (maybe fragment)
with identity
  |> ignore (char ':')
  |> int
with Time.millisToPosix
  |> ignore (char ':')
  |> int

More intuitive IMO, more flexible and fewer concepts to learn.

Is with already being used in other places? I’m not sure why it’s more intuitive that into, since the idea is that you feed values into a function. I actually considered renaming grab to feed.

You use it in stringWIth, of course, but I don’t know if it’s used elsewhere.

I find it more intuitive because into in my mind implies, or at least strongly indicates, that you’re putting it into something that will contain it. While with is more vague and fits better with both containers and transforming functions.

I think grab is good as it indicates it’s grabbing a single argument, while feed indicates it’s more of a stream, perhaps constructing a string to pass as a single argument.

How about build for into? The idea being that you are building a thing out of a series smaller things.

Mark

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.