#lang scribble/manual @require[scribble/example "utils.rkt" @for-label[phc-toolkit/untyped extensible-parser-specifications generic-syntax-expanders racket/base syntax/parse (only-in racket/base [... …])]] @title{Defining reusable parser mixins} @defform[#:literals (pattern) (define-eh-alternative-mixin name maybe-splicing-class maybe-define-splicing-class (pattern clause-or-mixin) ...) #:grammar [(maybe-define-class (code:line) (code:line #:define-syntax-class class-name)) (maybe-define-splicing-class (code:line) (code:line #:define-splicing-syntax-class splicing-name)) (clause-or-mixin #,ntax-pattern (~mixin #,-alternative-mixin) (~or clause-or-mixin ...) derived-or)]]{ Defines an @deftech{eh-alternative mixin}, which is implemented as an @tech{ eh-mixin expander}. An eh-alternative mixin is like an @tech[#:doc '(lib "syntax/scribblings/syntax.scrbl")]{ellipsis-head alternative set}, except that it can only appear as part of a @racket[~no-order] (possibly nested under other eh-alternative mixins), and can contain some global constraints. The global constraints, detailed below, allow the parser to perform checks across two or more mixins. For example, given a set of options that can appear in any order, it is possible to specify that two of them are mutually exclusive, or that two other must appear in a certain order, regardless of the order of the other options. The @racket[derived-or] term covers any @tech[#:doc '(lib "syntax/scribblings/syntax.scrbl")]{pattern expander} or @tech{eh-mixin expander} application which expands to a @racket[clause-or-mixin]. The @racket[#:define-syntax-class] option defines a syntax class with the given @racket[class-name] which matches @racket[{~no-order {~mixin name}}]. The @racket[#:define-splicing-syntax-class] option defines a splicing syntax class with the given @racket[class-name] which matches @racket[{~seq-no-order {~mixin name}}].} @deftogether[[@defthing[#:kind "for-syntax value" eh-mixin-expander-type expander-type?] @defproc[#:kind "for-syntax procedure" (make-eh-mixin-expander) (and/c expander? eh-mixin-expander?)] @defproc[#:kind "for-syntax procedure" (eh-mixin-expander? [v any/c]) boolean?] @defform[(define-eh-mixin-expander id transformer-procedure)] @defproc[#:kind "for-syntax procedure" (expand-all-eh-mixin-expanders [stx-tree syntax?]) syntax?]]]{ These functions and forms allow the creation and manipulation of @deftech{ eh-mixin expanders}. These identifiers are generated by @racket[define-expander-type]. For more information, see the documentation for @racket[define-expander-type].} @section{Using mixins} @defform[(~mixin #,-alternative-mixin)]{ Expands the @racket[#,-alternative-mixin], with no arguments. This is equivalent to @racket[(_eh-alternative-mixin)], but @racket[~mixin] additionally checks that the given @racket[_eh-alternative-mixin] is indeed an @tech{eh-alternative mixin}. Otherwise, with the syntax, @racket[(_eh-alternative-mixin)] the name @racket[_eh-alternative-mixin] would be interpreted as a pattern variable by @racket[syntax-parse] if the expander was not available for some reason (e.g. a missing import).}