[racket] syntax/parse ellipses question
Eric Dobson wrote:
> I'm trying to use the syntax/parse library, and am running into a
> weird problem when using ~or. It works without ellipses, but with
> ellipses it complains about a duplicated attribute. I would assume
> that the attributes with the same name in an ~or pattern were the same
> attribute that could just match in different ways. A simplified
> version is below, the first 4 examples work, and the fifth does not.
> Is there a restriction that I am missing for why this does not work?
There are three variants of ~or: single-term ~or, head ~or, and
ellipsis-head ~or. Ellipsis-head ~or has different rules for attributes,
which the docs seem not to explain. I'll update the docs.
> (syntax-parse #'(1 2 3)
> [((~or x:number) ...) (syntax->datum #'(x ...))])
>
> (syntax-parse #'(a b c)
> [((~or x:id) ...) (syntax->datum #'(x ...))])
Both of the above are ellipsis-head ~or, not that it matters.
> (syntax-parse #'(1)
> [((~or x:id x:number)) (syntax->datum #'(x))])
>
> (syntax-parse #'(a)
> [((~or x:id x:number)) (syntax->datum #'(x))])
These are both single-term ~or.
> #;
> (syntax-parse #'(a 1 b)
> [((~or x:id x:number) ...) (syntax->datum #'(x ...))])
This is ellipsis-head ~or. The difference is that ellipsis-head ~or
accumulates different alternatives' attributes independently. The
different alternatives must have disjoint attributes. (For now, anyway;
I'm considering relaxing that restriction.) For example,
(syntax-parse #'(a b #:c d e #:f g)
[((~or x:id (~seq k:keyword kx:id)) ...)
#'((x ...) ((k kx) ...))])
=> #<syntax ((a b e) ((#:c d) (#:f g)))>
You can turn the ~or back into a single-term ~or by putting another
pattern form between it and the ellipses. For example,
(syntax-parse #'(a 1 b)
[((~and (~or x:id x:number)) ...) ___])
Hope that helps!
Ryan