invertible-syntax icon indicating copy to clipboard operation
invertible-syntax copied to clipboard

example of composing parsers with Coproduct

Open mossprescott opened this issue 8 years ago • 4 comments

Num literals, Add, and Mul nodes each implemented as separate parsers, injecting their results into an arbitrary type.

Successive example parsers constructed by adding more types to a Coproduct, and finally a proper recursive parser using parens.

Now using Matryoshka just for Fix.

mossprescott avatar Jun 19 '16 02:06 mossprescott

Had some time before getting back on the road and couldn't resist giving this a try. It certainly works, and without any changes to the actual Iso/Syntax library. On the other hand, it's fairly cumbersome and inference seems to go off the rails in a couple of places. Surprise, surprise.

Furthermore, the added complexity seems to call for a re-thinking of some of the types and their names. Namely, Syntax, Parser, and Printer all seem to be misleading. A better scheme might be something like:

  • what's currently Syntax will become SyntaxHandler. This type will only ever be implemented twice, by the library, as ParserSyntaxHandler and PrinterSyntaxHandler, unless someone thinks of a new way to use these declarations (like generating parse-tree visualizations or something.)
  • what's currently Parser becomes type ParserF[A] = Source => .... This is the strange internal type which handles partial parsing, which users never see.
  • type Syntax[P[_], T[_]] = SyntaxHandler[P] => P[T]. This ends up being the type of the function you actually need to write, and it's always been confusing that it wasn't actually called Syntax.
  • type Parser[A] = String => (ParseFailure \/ A). This will be the type you actually get to use for parsing, and now it would be called Parser, which makes sense.
  • type Printer[A] = A => Option[Cord] remains the same, because it happens to work for both since printing is always unambiguous. I suppose we could do type PrinterF[A] = A => Option[Cord] and type Printer[A] = A => Option[String], just because dealing with Cord is annoying. I know you'd like to see Option go away, but I think it's inherent in the fact that some values might not be representable in String form (for example, my new syntax that says vars are arbitrary Symbols but happens to only parse and print single-char names.)

I will probably give that reworking a try, because I think it will help quite a bit. Unfortunately it will take this library even further away from the original paper.

mossprescott avatar Jun 19 '16 03:06 mossprescott

This looks pretty cool. I just glanced at it, but I’ll take a deeper look tomorrow or Monday.

sellout avatar Jun 19 '16 04:06 sellout

@sellout: just getting around to pushing some minor changes I did the other day.

I think this is promising and probably worth merging but before I would call the experiment a success I would want to implement a properly complex grammar, with a dozen or more operators and precedence levels. But I hesitate to try it because inference is already not really working when I add just the third type to the coproduct. Not sure how to proceed.

mossprescott avatar Jun 29 '16 20:06 mossprescott

Try adding the SI-2712 plugin. Just a good idea in general, maybe it'll help the inference here.

sellout avatar Jun 30 '16 05:06 sellout