use more `syntax-parse`

pull/13/merge
Matthew Butterick 7 years ago
parent 91281379f3
commit 3c452e4d90

@ -97,6 +97,7 @@
;; `syntax-parse` classes shared by `define-macro` and `define-macro-cases` ;; `syntax-parse` classes shared by `define-macro` and `define-macro-cases`
(begin-for-syntax (begin-for-syntax
(require syntax/parse) (require syntax/parse)
(define-syntax-class syntaxed-id (define-syntax-class syntaxed-id
#:literals (syntax quasisyntax) #:literals (syntax quasisyntax)
#:description "id in syntaxed form" #:description "id in syntaxed form"
@ -133,7 +134,6 @@
"no matching case for calling pattern" "no matching case for calling pattern"
(syntax->datum stx))])) (syntax->datum stx))]))
(define-syntax (define-macro-cases stx) (define-syntax (define-macro-cases stx)
(syntax-parse stx (syntax-parse stx
[(_ id:id) [(_ id:id)
@ -143,12 +143,15 @@
[(_ id:id (pat:expr . result-exprs:expr) ... else-clause:else-clause) [(_ id:id (pat:expr . result-exprs:expr) ... else-clause:else-clause)
(unless (all-...-follow-wildcards #'(pat ...)) (unless (all-...-follow-wildcards #'(pat ...))
(raise-syntax-error 'define-macro-cases "found ellipses after non-wildcard variable" (syntax->datum stx))) (raise-syntax-error 'define-macro-cases "found ellipses after non-wildcard variable" (syntax->datum stx)))
(with-syntax ([(LITERAL ...) (generate-literals #'(pat ...))]) (with-syntax ([(BOUND-LITS UNBOUND-LITS)
(generate-bound-and-unbound-literals #'(pat ...) #:treat-as-bound #'id)])
#'(define-macro id #'(define-macro id
(λ (stx) (λ (stx)
(define result (define result
(syntax-parameterize ([caller-stx (make-rename-transformer #'stx)]) (syntax-parameterize ([caller-stx (make-rename-transformer #'stx)])
(syntax-case stx (LITERAL ...) (syntax-parse (syntax-case stx () [any #'any])
#:literals BOUND-LITS
#:datum-literals UNBOUND-LITS
[pat . result-exprs] ... [pat . result-exprs] ...
else-clause))) else-clause)))
(if (syntax? result) (if (syntax? result)

@ -1,6 +1,6 @@
#lang racket/base #lang racket/base
(require "syntax-flatten.rkt") (require "syntax-flatten.rkt" racket/list)
(provide all-...-follow-wildcards generate-literals) (provide all-...-follow-wildcards generate-literals generate-bound-and-unbound-literals)
(define (literal-identifier? pat-datum) (define (literal-identifier? pat-datum)
(and (symbol? pat-datum) (and (symbol? pat-datum)
@ -21,6 +21,15 @@
#:when (literal-identifier? pat-datum)) #:when (literal-identifier? pat-datum))
pat-arg)) pat-arg))
(define (generate-bound-and-unbound-literals pats #:treat-as-bound [bound-id #f])
(define-values (bound-literals unbound-literals)
(partition identifier-binding (for/list ([pat (in-list (generate-literals pats))]
#:unless (and bound-id (bound-identifier=? pat bound-id)))
pat)))
;; return as list of two lists so it's easy to match them in syntax pattern
(list (if bound-id (cons bound-id bound-literals) bound-literals)
unbound-literals))
(define (all-...-follow-wildcards pats) (define (all-...-follow-wildcards pats)
(define prev-datum (box #f)) (define prev-datum (box #f))
(and (and

@ -8,6 +8,7 @@
racket/format racket/format
syntax/stx syntax/stx
syntax/strip-context syntax/strip-context
syntax/parse
br/define br/define
br/private/syntax-flatten) br/private/syntax-flatten)
(provide (all-defined-out) (provide (all-defined-out)
@ -35,13 +36,20 @@
#:when result) #:when result)
result))) result)))
(define-macro (syntax-parse/easy STX LITS . EXPS)
(with-syntax ([(BOUND-LITS UNBOUND-LITS) (generate-bound-and-unbound-literals #'LITS)])
#'(syntax-parse (syntax-case STX () [any #'any])
#:literals BOUND-LITS
#:datum-literals UNBOUND-LITS
. EXPS)))
(define-macro-cases pattern-case (define-macro-cases pattern-case
[(_ STX-ARG [(_ STX-ARG
[PAT . BODY] ... [PAT . BODY] ...
[else . ELSEBODY]) (with-syntax ([(LITERAL ...) (generate-literals #'(PAT ...))]) [else . ELSEBODY]) #'(syntax-parse/easy STX-ARG (PAT ...)
#'(syntax-case STX-ARG (LITERAL ...)
[PAT . BODY] ... [PAT . BODY] ...
[else . ELSEBODY]))] [else . ELSEBODY])]
[(_ STX-ARG PAT+BODY ...) [(_ STX-ARG PAT+BODY ...)
#'(pattern-case STX-ARG #'(pattern-case STX-ARG
PAT+BODY ... PAT+BODY ...
@ -51,11 +59,10 @@
(define-macro-cases with-pattern (define-macro-cases with-pattern
[(_ () . BODY) #'(begin . BODY)] [(_ () . BODY) #'(begin . BODY)]
[(_ ([PAT0 STX0] PAT+STX ...) . BODY) [(_ ([PAT0 STX0] PAT+STX ...) . BODY)
(with-syntax ([(LITERAL ...) (generate-literals #'PAT0)]) #'(syntax-parse/easy STX0 PAT0
#'(syntax-case STX0 (LITERAL ...)
[PAT0 (with-pattern (PAT+STX ...) (let () . BODY))] [PAT0 (with-pattern (PAT+STX ...) (let () . BODY))]
[else (raise-syntax-error 'with-pattern [else (raise-syntax-error 'with-pattern
(format "unable to match pattern ~a" 'PAT0) STX0)]))]) (format "unable to match pattern ~a" 'PAT0) STX0)])])
(define-macro (format-string FMT ID0 ID ...) (define-macro (format-string FMT ID0 ID ...)

Loading…
Cancel
Save