More powerful list declarations
We would like the following aspects supported by a feature that allows us to define lists:
- Concerning even AST:
- several list categories for one category
- non-empty vs. possibly empty lists
- snoc (left associative) vs. cons (right associative) lists
- Concerning parsing:
- delimiters (markers for begin and end)
- separators (infix) vs. terminators (postfix) vs. "initiators" (prefix symbol, like bullet lists)
- Concerning printing:
- horizontal vs. vertical (currently only for ";" separator/terminator)
A possible grammar for a new list pragma could be:
ListPragma. Def ::= "#list" Ident "of" Ident [ListAttribute] ;
ListAttribute
::= "non-empty"
| "snoc" | "cons"
| "horizontal" | "vertical"
| "open" String
| "close" String
| {"prefix"|"postfix"}? "separator" String | "terminator" String | "initiator" String
Attributes listed on the same line are mutually exclusive.
How to print vertical lists?
separator-post = [
a,
b,
c ]
separator-pre =
[ a
, b
, c
]
separator-pre-without-delimiters =
a
+ b
+ c
terminator = {
a;
b;
c;
}
initiator = begin
- a
- b
- c
end
The current automatic parsing of cons lists as snoc lists #163 would be removed, is anyway just a buggy optimization.
See also #106 for the delimiters syntax.
Would there be any value in, and would it be feasible to implement, optional delimiters or multiple choices of delimiter?
(I'm not currently planning to use such a thing, just thinking out loud because the syntax I have omits a separator that is present in other languages.)
Right now I imagine to do such stuff you'd have to write something like, don't make a list of X, make a list of Y with separator "" where Y can be YPlain . Y ::= X;, YA . Y ::= X "some delimiter"; or YB . Y ::= X "some other delimiter"; – technically this would achieve optional terminators and there isn't an obvious way to get optional separators. And then, if you wanted to enforce that the same delimiter is used everywhere in the list, you'd just have to wrap X in three different types each of which has a different list separator/terminator, and then wrap those in turn in a type XList that can be a list of any of the X-wrapping types… (XAL . XList ::= [XA]; XA . XA ::= X; separator XA "~" now imagine XB, XC) In other words doable but a lot of boilerplate type wrappers.
Then again, how many languages do you know that have optional delimiters, not counting layout syntax? I can't think of any off the top of my head, so that's a lot of complication to use something that nobody seems to use anyway.
(Smarter definition of lists might make layout syntax more flexible, e.g. in what terminator/separator it supports? But that's another matter, I'm not as familiar with the layout syntax behavior or implementation in BNFC.)
Here's another question. Is it currently possible to have an optional terminator at the end of a whole list that is the same as the separator; or, alternatively, to optionally allow the separator after the last item in a list? Thinking of the whole thing about whether to have a comma after the last list item in JSON and JavaScript.