Does this work for what you want to do?
#lang racket
(require syntax/parse)
(define-syntax ~opts
(pattern-expander
(lambda (stx)
(syntax-case stx ()
[(opts [kw id] ...)
(with-syntax ([ooo (quote-syntax ...)])
#'(~seq (~or (~optional (~and (~seq kw) (~seq id ooo)) #:defaults
([(id 1) '()]))
...)
ooo))]))))
(define-splicing-syntax-class options
[pattern (~opts [#:a a?] [#:b b?] [#:c c?] [#:d d?])
#:attr a/b #'(a? ... b? ...)
#:attr c/d #'(c? ... d? ...)])
(syntax-parse #'(#:a #:d #:b)
[(opts:options)
#'(opts.a/b opts.c/d)])
On May 27, 2015, at 1:03 AM, Alexis King <[email protected]> wrote:
> When using syntax/parse, is there a good way to do something like this?
>
> (define-splicing-syntax-class options
> (pattern (~seq (~or (~optional (~seq (~and #:a a?)))
> (~optional (~seq (~and #:b b?)))
> (~optional (~seq (~and #:c c?)))
> (~optional (~seq (~and #:d d?))))
> ...)
> #:attr a/b #'(a? b?)
> #:attr c/d #'(c? d?)))
>
> When using the above syntax class to parse #'(#:a #:d #:b), then the a/b
> attribute should be #'(#:a #:b) and the c/d attribute should be #'(#:d).
> However, this doesn't work, of course, because if one of the options isn't
> defined, the attribute will be #f, and the attribute binding will fail.
>
> I can get around that by doing something like this:
>
> (define-splicing-syntax-class options
> (pattern (~seq (~or (~optional (~seq (~and #:a a?)))
> (~optional (~seq (~and #:b b?)))
> (~optional (~seq (~and #:c c?)))
> (~optional (~seq (~and #:d d?))))
> ...)
> #:attr a/b #`(#,@(if (attribute a?) #'(a?) #'())
> #,@(if (attribute b?) #'(b?) #'()))
> #:attr c/d #`(#,@(if (attribute c?) #'(c?) #'())
> #,@(if (attribute d?) #'(d?) #'()))))
>
> But that's rather long-winded and verbose. Even better would be a way to
> group the clauses within the pattern, something like this:
>
> (define-splicing-syntax-class options
> (pattern (~seq (~or (~and (~seq (~optional (~seq (~and #:a a?)))
> (~optional (~seq (~and #:b b?))))
> a/b)
> (~and (~seq (~optional (~seq (~and #:c c?)))
> (~optional (~seq (~and #:d d?))))
> c/d))
> ...)))
>
> But that obviously doesn't work, and I'm not sure what it would do even if it
> compiled.
>
> Anyway, is there a more concise way to do this? I know it's relatively easy
> using `template` from syntax/parse/experimental/template, but this is going
> into the Typed Racket code, so we're intentionally avoiding a dependency on
> that.
>
> Alexis
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.