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.

Reply via email to