#lang racket (require syntax/parse extensible-parser-specifications phc-toolkit/untyped rackunit) (define-syntax-class abc-order (pattern {~no-order {~optional {~order-point a-point #:a {~post-fail "#:a must appear after #:b" #:when (order-point> a-point b-point)}}} {~optional {~order-point b-point #:b}} {~optional {~order-point c-point #:c}}})) (define-syntax-rule (check-parse-abc stx) (check-true (syntax-parse stx [:abc-order #t] [_ #f]))) (define-syntax-rule (check-fail-abc stx exn) (check-exn exn (λ () (syntax-parse stx [:abc-order 'ok])))) (check-parse-abc #'(#:a)) (check-parse-abc #'(#:b)) (check-parse-abc #'(#:c)) (check-parse-abc #'(#:a #:b)) (check-parse-abc #'(#:c #:a)) (check-parse-abc #'(#:a #:c)) (check-parse-abc #'(#:c #:b)) (check-parse-abc #'(#:b #:c)) (check-parse-abc #'(#:c #:a #:b)) (check-parse-abc #'(#:a #:c #:b)) (check-parse-abc #'(#:a #:b #:c)) (check-fail-abc #'(#:b #:a) #px"#:a must appear after #:b") (check-fail-abc #'(#:c #:b #:a) #px"#:a must appear after #:b") (check-fail-abc #'(#:b #:c #:a) #px"#:a must appear after #:b") (check-fail-abc #'(#:b #:a #:c) #px"#:a must appear after #:b") (check-fail-abc #'(#:a #:a) #px"expected abc-order") (check-fail-abc #'(#:c #:c) #px"expected abc-order")