80 lines
3.6 KiB
Racket
80 lines
3.6 KiB
Racket
#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).}
|
|
|