[racket] Splicing nested syntax clauses

From: Alexander D. Knauth (alexander at knauth.org)
Date: Fri Jun 27 17:24:07 EDT 2014

Is this anything like what you wanted?

(require web-server/dispatch
         (for-syntax syntax/parse
                     racket/list))

(begin-for-syntax
  ;; mdr-clause->dr-clauses : Syntax -> (Listof Syntax)
  (define (mdr-clause->dr-clauses mdr-clause)
    (syntax-parse mdr-clause
      [[(thing ...) #:dispatch-rules sub-dr-clause ...]
       (for/list ([sub-dr-clause-stx (in-list (syntax->list #'(sub-dr-clause ...)))])
         (syntax-parse sub-dr-clause-stx
           [[(sub-thing ...) dispatch-fun]
            #'[(thing ... sub-thing ...) dispatch-fun]]
           [[(sub-thing ...) #:method method dispatch-fun]
            #'[(thing ... sub-thing ...) #:method method dispatch-fun]]))]
      [[(thing ...) #:my-dispatch-rules sub-mdr-clause ...]
       (with-syntax ([(sub-dr-clause ...) (append*
                                           (for/list ([sub-mdr-clause (in-list (syntax->list #'(sub-mdr-clause ...)))])
                                             (mdr-clause->dr-clauses sub-mdr-clause)))])
         (mdr-clause->dr-clauses #'[(thing ...) #:dispatch-rules sub-dr-clause ...]))]
      [_ (list mdr-clause)]
      ))
  )

(define-syntax (my-dispatch-rules stx)
  (syntax-parse stx
    [(my-dispatch-rules mdr-clause ...)
     (with-syntax ([(dr-clause ...) (append*
                                     (for/list ([mdr-clause (in-list (syntax->list #'(mdr-clause ...)))])
                                       (mdr-clause->dr-clauses mdr-clause)))])
       #'(dispatch-rules
          dr-clause ...))]))
      

(syntax->datum
 (expand-syntax-once
  #'(my-dispatch-rules
     [("page-a") #:my-dispatch-rules 
                 [("handler-a" (integer-arg)) handler-a]
                 [("handler-b" (integer-arg)) handler-b]]
     [("page-b") #:my-dispatch-rules 
                 [("handler-c" (integer-arg)) handler-c]
                 [("handler-d" (integer-arg)) handler-d]])))
; =>
;'(dispatch-rules
;  (("page-a" "handler-a" (integer-arg)) handler-a)
;  (("page-a" "handler-b" (integer-arg)) handler-b)
;  (("page-b" "handler-c" (integer-arg)) handler-c)
;  (("page-b" "handler-d" (integer-arg)) handler-d))

On Jun 27, 2014, at 3:47 PM, Jack Firth <jackhfirth at gmail.com> wrote:

> I'm working with some servlet dispatching code and I want to be able to use dispatch-rules to generate the url to response mappings, but I want to be able to group related handlers to subpages. Under dispatch-rules, that looks something like this:
> 
> (dispatch-rules
>     [("page-a" "handler-a" (integer-arg)) handler-a]
>     [("page-a" "handler-b" (integer-arg)) handler-b]
>     [("page-b" "handler-c" (integer-arg)) handler-c]
>     [("page-b" "handler-d" (integer-arg)) handler-d])
> 
> What I want is to be able to specify a tree structure of some sort like this:
> 
> (my-dispatch-rules
>     [(my-dispatch-rules "page-a"
>         [("handler-a" (integer-arg)) handler-a)]
>         [("handler-b" (integer-arg)) handler-b)]
>     [(my-dispatch-rules "page-b"
>         [("handler-c" (integer-arg)) handler-c)]
>         [("handler-d" (integer-arg)) handler-d)])
> 
> And have that expand, placing the page-a and page-b bits in the appropriate areas. From what I understand of macros, the appropriate way to do this is with quasiquoting and splicing unquotes, but I can't seem to figure out using splicing with syntax-case, and the various tutorials and documentation I've looked at haven't helped me really wrap my head around the specifics. If someone could point me towards enlightenment, that would be much appreciated.
> ____________________
>  Racket Users list:
>  http://lists.racket-lang.org/users

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140627/cb88aa7b/attachment.html>

Posted on the users mailing list.