Fantastic, thank you for getting me on my way. I followed your advice where I do not use string-producing expressions and ended up with a follow up question.
New syntax classes are below for those reading.
(define (unbounded? v)
(equal? "*" v))
(define-syntax-class racket-version-or-*
(pattern (~var bound string)
#:when (let ([v (syntax-e #'bound)])
(or (unbounded? v)
(valid-version? v)))))
(define-syntax-class racket-version-selection
#:attributes (min max)
(pattern (~and (min:racket-version-or-* max:racket-version-or-*)
(~fail #:unless (let ([min-v (syntax-e #'min)] [max-v (syntax-e #'max)])
(or (unbounded? min-v)
(unbounded? max-v)
(version<=? min-v max-v)))
"minimum Racket version cannot exceed maximum Racket version")))
(pattern (~and (~var v racket-version-or-*)
(~bind [min #'v] [max #'v]))))
Note the condition set in racket-version-selection that checks for backwards ranges. From what I understand, it only raises a pattern failure, which means I only see the ~fail error message for:
(syntax-parse #'(("8.4" "8.3"))
[(v:racket-version-selection ...) #t])
but not
(syntax-parse #'(("8.4" "8.3"))
[(v:racket-version-selection ...) #t]
[_ #f])
In this case, is it better form to use raise-syntax-error in a #:when pattern directive for a syntax class, or beneath a clause of syntax-parse? I suspect that syntax classes should not have an opinion about flow control.
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐