More refined thoughts now.
The core idea is that we have a language that has simple features from programming languages (variable binding, casing including conditionals, and arbitrary expressions in some host language) and parser grammars that belong to some more static level of abstraction. (We might say it is stratified in the sense of 2-level type theory (2LTT), if we wanted to get fancy.)
The important point is that variable binding can be scoped just like you expect, left-to-right, and nesting inherits scope. It gets a bit tricky to encode in the actual typeclass API of select if you want to return – more on that later.
I'll resist the urge to bikeshed syntax right now ... instead I'll just describe the kinds of things you want.
Let's adopt the dichotomy of statements versus expressions. Expressions are from the host language. Statements can be:
- Run a parser and bind its result, possibly with a non-exhaustive pattern match (or discard it)
- Case on an expression, where each case matches on a pattern (binding variables from it) and runs a statement
- Return an expression
A sequence of statements can construct a parser.
Parsers can be constructed out of existing parsers via alternation, but … I don't think .
Now there's a lot of sugar you want to add onto this:
- Run a parser and discard its result (desugar by inserting a discard pattern)
- Bind/match against an expression (desugar by inserting a pure parser)
- Declare mandatory variables that are lifted out of each branch of a case statement
- Declare optional variables that are lifted out of each branch of a case statement, or set to a default value if not (using
Maybe/Optionalor whatever you want to call it)- These two are particularly important if the host language does not support easy tupling or anonymous records
- It might be possible to have them as separate assignment syntax, like
var != exprandvar ?= expr, but I worry about what that looks like for nested cases (how do you know what their scope is)
- If-then-else statements, via a case match on
TrueandFalse - When statements, via a case match on
Truewith a default of parsing nothing - Don't return an expression at the end of the sequence
- Maybe you want to treat this as a
Unitvalue - Or maybe you want to automatically tuple up all the variables that were bound, or stuff them into an anonymous record, or whatever
- Maybe you want to treat this as a
