syntax/parse: fix use of evaluators in docs

This commit is contained in:
Ryan Culpepper 2015-09-11 17:19:07 -04:00
parent 808a6ca266
commit 4f5c54db54
12 changed files with 174 additions and 121 deletions

View File

@ -6,6 +6,8 @@
"parse-common.rkt" "parse-common.rkt"
(for-label syntax/parse/define)) (for-label syntax/parse/define))
@(define the-eval (make-sp-eval))
@title{Defining Simple Macros} @title{Defining Simple Macros}
@defmodule[syntax/parse/define] @defmodule[syntax/parse/define]
@ -22,7 +24,7 @@ Defines a macro named @racket[macro-id]; equivalent to the following:
] ]
@(the-eval '(require syntax/parse/define)) @(the-eval '(require syntax/parse/define))
@myexamples[ @examples[#:eval the-eval
(define-simple-macro (fn x:id rhs:expr) (lambda (x) rhs)) (define-simple-macro (fn x:id rhs:expr) (lambda (x) rhs))
((fn x x) 17) ((fn x x) 17)
(fn 1 2) (fn 1 2)
@ -47,7 +49,7 @@ Defines a macro named @racket[macro-id]; equivalent to:
(syntax-parser parse-option ... clause ...)) (syntax-parser parse-option ... clause ...))
] ]
@myexamples[ @examples[#:eval the-eval
(define-syntax-parser fn3 (define-syntax-parser fn3
[(fn3 x:id rhs:expr) [(fn3 x:id rhs:expr)
#'(lambda (x) rhs)] #'(lambda (x) rhs)]
@ -59,3 +61,4 @@ Defines a macro named @racket[macro-id]; equivalent to:
(fn3 a #:b 'c) (fn3 a #:b 'c)
]} ]}
@(close-eval the-eval)

View File

@ -6,6 +6,8 @@
"parse-common.rkt" "parse-common.rkt"
(for-label racket/class)) (for-label racket/class))
@(define the-eval (make-sp-eval))
@title[#:tag "exprc"]{Contracts on Macro Sub-expressions} @title[#:tag "exprc"]{Contracts on Macro Sub-expressions}
Just as procedures often expect certain kinds of values as arguments, Just as procedures often expect certain kinds of values as arguments,
@ -17,7 +19,7 @@ For example, here is a macro @racket[myparameterize] that behaves like
@racket[parameterize] but enforces the @racket[parameter?] contract on @racket[parameterize] but enforces the @racket[parameter?] contract on
the parameter expressions. the parameter expressions.
@myinteraction[ @interaction[#:eval the-eval
(define-syntax (myparameterize stx) (define-syntax (myparameterize stx)
(syntax-parse stx (syntax-parse stx
[(_ ((p v:expr) ...) body:expr) [(_ ((p v:expr) ...) body:expr)
@ -37,3 +39,5 @@ template, the expansion would have used the raw, unchecked
expressions. The @racket[expr/c] syntax class does not change how expressions. The @racket[expr/c] syntax class does not change how
pattern variables are bound; it only computes an attribute that pattern variables are bound; it only computes an attribute that
represents the checked expression. represents the checked expression.
@(close-eval the-eval)

View File

@ -6,6 +6,8 @@
"parse-common.rkt" "parse-common.rkt"
(for-label racket/class)) (for-label racket/class))
@(define the-eval (make-sp-eval))
@title{Optional Keyword Arguments} @title{Optional Keyword Arguments}
This section explains how to write a macro that accepts (simple) This section explains how to write a macro that accepts (simple)
@ -22,7 +24,7 @@ head-pattern forms are @racket[~seq], @racket[~or], and
Here's one way to do it: Here's one way to do it:
@myinteraction[ @interaction[#:eval the-eval
(define-syntax (mycond stx) (define-syntax (mycond stx)
(syntax-parse stx (syntax-parse stx
[(mycond (~or (~seq #:error-on-fallthrough who:expr) (~seq)) [(mycond (~or (~seq #:error-on-fallthrough who:expr) (~seq))
@ -47,7 +49,7 @@ argument is omitted. Instead we must write @racket[(attribute who)],
which produces @racket[#f] if matching did not assign a value to the which produces @racket[#f] if matching did not assign a value to the
attribute. attribute.
@myinteraction[ @interaction[#:eval the-eval
(mycond [(even? 13) 'blue] (mycond [(even? 13) 'blue]
[(odd? 4) 'red]) [(odd? 4) 'red])
(mycond #:error-on-fallthrough 'myfun (mycond #:error-on-fallthrough 'myfun
@ -62,7 +64,7 @@ There's a simpler way of writing the @racket[~or] pattern above:
Yet another way is to introduce a @tech{splicing syntax class}, which Yet another way is to introduce a @tech{splicing syntax class}, which
is like an ordinary syntax class but for head patterns. is like an ordinary syntax class but for head patterns.
@myinteraction[ @interaction[#:eval the-eval
(define-syntax (mycond stx) (define-syntax (mycond stx)
(define-splicing-syntax-class maybe-fallthrough-option (define-splicing-syntax-class maybe-fallthrough-option
@ -84,3 +86,5 @@ syntax class's variants. (This is possible to do in the inline pattern
version too, using @racket[~and] and @racket[~parse], just less version too, using @racket[~and] and @racket[~parse], just less
convenient.) Splicing syntax classes also closely parallel the style convenient.) Splicing syntax classes also closely parallel the style
of grammars in macro documentation. of grammars in macro documentation.
@(close-eval the-eval)

View File

@ -6,6 +6,8 @@
"parse-common.rkt" "parse-common.rkt"
(for-label racket/class)) (for-label racket/class))
@(define the-eval (make-sp-eval))
@title{More Keyword Arguments} @title{More Keyword Arguments}
This section shows how to express the syntax of @racket[struct]'s This section shows how to express the syntax of @racket[struct]'s
@ -15,7 +17,7 @@ The part of @racket[struct]'s syntax that is difficult to specify is
the sequence of struct options. Let's get the easy part out of the way the sequence of struct options. Let's get the easy part out of the way
first. first.
@myinteraction[ @interaction[#:eval the-eval
(define-splicing-syntax-class maybe-super (define-splicing-syntax-class maybe-super
(pattern (~seq super:id)) (pattern (~seq super:id))
(pattern (~seq))) (pattern (~seq)))
@ -135,3 +137,5 @@ both @racket[#:guard] and @racket[#:property]. Repetition constraints
cannot express arbitrary incompatibility relations. The best way to cannot express arbitrary incompatibility relations. The best way to
handle such constraints is with a side condition using handle such constraints is with a side condition using
@racket[#:fail-when]. @racket[#:fail-when].
@(close-eval the-eval)

View File

@ -6,6 +6,8 @@
"parse-common.rkt" "parse-common.rkt"
(for-label racket/class)) (for-label racket/class))
@(define the-eval (make-sp-eval))
@title{Phases and Reusable Syntax Classes} @title{Phases and Reusable Syntax Classes}
As demonstrated in the @secref{stxparse-intro}, the simplest place to As demonstrated in the @secref{stxparse-intro}, the simplest place to
@ -17,7 +19,7 @@ classes requires some awareness of the Racket @tech[#:doc '(lib
syntax class defined immediately within a module cannot be used by syntax class defined immediately within a module cannot be used by
macros in the same module; it is defined at the wrong phase. macros in the same module; it is defined at the wrong phase.
@myinteraction[ @interaction[#:eval the-eval
(module phase-mismatch-mod racket (module phase-mismatch-mod racket
(require syntax/parse (for-syntax syntax/parse)) (require syntax/parse (for-syntax syntax/parse))
(define-syntax-class foo (define-syntax-class foo
@ -37,7 +39,7 @@ phase level incompatibility.)
The phase level mismatch is easily remedied by putting the syntax The phase level mismatch is easily remedied by putting the syntax
class definition within a @racket[begin-for-syntax] block: class definition within a @racket[begin-for-syntax] block:
@myinteraction[ @interaction[#:eval the-eval
(module phase-ok-mod racket (module phase-ok-mod racket
(require (for-syntax syntax/parse)) (require (for-syntax syntax/parse))
(begin-for-syntax (begin-for-syntax
@ -55,7 +57,7 @@ An alternative to @racket[begin-for-syntax] is to define the syntax
class in a separate module and require that module class in a separate module and require that module
@racket[for-syntax]. @racket[for-syntax].
@myinteraction[ @interaction[#:eval the-eval
(module stxclass-mod racket (module stxclass-mod racket
(require syntax/parse) (require syntax/parse)
(define-syntax-class foo (define-syntax-class foo
@ -77,7 +79,7 @@ expressions via syntax templates, then the module containing the
syntax class must generally require @racket[for-template] the bindings syntax class must generally require @racket[for-template] the bindings
referred to in the patterns and templates. referred to in the patterns and templates.
@myinteraction[ @interaction[#:eval the-eval
(module arith-keywords-mod racket (module arith-keywords-mod racket
(define-syntax plus (syntax-rules ())) (define-syntax plus (syntax-rules ()))
(define-syntax times (syntax-rules ())) (define-syntax times (syntax-rules ()))
@ -124,3 +126,5 @@ implicit syntax @racket[#%app]) must be bound at ``absolute'' phase
level 0. Since the module @racket['arith-stxclass-mod] is required level 0. Since the module @racket['arith-stxclass-mod] is required
with a phase level offset of 1 (that is, @racket[for-syntax]), it must with a phase level offset of 1 (that is, @racket[for-syntax]), it must
compensate with a phase level offset of -1, or @racket[for-template]. compensate with a phase level offset of -1, or @racket[for-template].
@(close-eval the-eval)

View File

@ -5,6 +5,8 @@
scribble/eval scribble/eval
"parse-common.rkt") "parse-common.rkt")
@(define the-eval (make-sp-eval))
@title{Experimental} @title{Experimental}
The following facilities are experimental. The following facilities are experimental.
@ -118,7 +120,7 @@ must be specified explicitly.
Like @racket[~reflect] but for reified splicing syntax classes. Like @racket[~reflect] but for reified splicing syntax classes.
} }
@myexamples[ @examples[#:eval the-eval
(define-syntax-class (nat> x) (define-syntax-class (nat> x)
#:description (format "natural number greater than ~s" x) #:description (format "natural number greater than ~s" x)
#:attributes (diff) #:attributes (diff)
@ -216,7 +218,7 @@ Includes the alternatives of @racket[eh-alternative-set-id], prefixing
their attributes with @racket[name]. their attributes with @racket[name].
} }
@myexamples[ @examples[#:eval the-eval
(define-eh-alternative-set options (define-eh-alternative-set options
(pattern (~once (~seq #:a a:expr) #:name "#:a option")) (pattern (~once (~seq #:a a:expr) #:name "#:a option"))
(pattern (~seq #:b b:expr))) (pattern (~seq #:b b:expr)))
@ -443,3 +445,5 @@ If @racket[join] were defined as a macro, it would not be usable in
the context above; instead, @racket[let-values] would report an the context above; instead, @racket[let-values] would report an
invalid binding list. invalid binding list.
} }
@(close-eval the-eval)

View File

@ -6,6 +6,8 @@
"parse-common.rkt" "parse-common.rkt"
(for-label (only-in syntax/parse ...+))) (for-label (only-in syntax/parse ...+)))
@(define the-eval (make-sp-eval #f))
@(define-syntax-rule (defdummy id) @(define-syntax-rule (defdummy id)
(defidentifier (quote-syntax id) (defidentifier (quote-syntax id)
#:form? #t #:index? #f #:show-libs? #f)) #:form? #t #:index? #f #:show-libs? #f))
@ -36,7 +38,7 @@ the second case later in the introduction.
The macro can be implemented very simply using The macro can be implemented very simply using
@racket[define-syntax-rule]: @racket[define-syntax-rule]:
@myinteraction[ @interaction[#:eval the-eval
(define-syntax-rule (mylet ([var rhs] ...) body ...) (define-syntax-rule (mylet ([var rhs] ...) body ...)
((lambda (var ...) body ...) rhs ...)) ((lambda (var ...) body ...) rhs ...))
] ]
@ -47,7 +49,7 @@ uninformative error message; in others, it blithely accepts illegal
syntax and passes it along to @racket[lambda], with strange syntax and passes it along to @racket[lambda], with strange
consequences: consequences:
@myinteraction[ @interaction[#:eval the-eval
(mylet ([a 1] [b 2]) (+ a b)) (mylet ([a 1] [b 2]) (+ a b))
(mylet (b 2) (sub1 b)) (mylet (b 2) (sub1 b))
(mylet ([1 a]) (add1 a)) (mylet ([1 a]) (add1 a))
@ -70,13 +72,15 @@ We can improve the error behavior of the macro by using
"scribblings/reference/reference.scrbl")]{transformer environment}, "scribblings/reference/reference.scrbl")]{transformer environment},
since we will use it to implement a macro transformer. since we will use it to implement a macro transformer.
@myinteraction[(require (for-syntax syntax/parse))] @interaction[#:eval the-eval
(require (for-syntax syntax/parse))
]
The following is the syntax specification above transliterated into a The following is the syntax specification above transliterated into a
@racket[syntax-parse] macro definition. It behaves no better than the @racket[syntax-parse] macro definition. It behaves no better than the
version using @racket[define-syntax-rule] above. version using @racket[define-syntax-rule] above.
@myinteraction[ @interaction[#:eval the-eval
(define-syntax (mylet stx) (define-syntax (mylet stx)
(syntax-parse stx (syntax-parse stx
[(_ ([var-id rhs-expr] ...) body ...+) [(_ ([var-id rhs-expr] ...) body ...+)
@ -98,7 +102,7 @@ pattern variable name, a colon character, and the syntax class
name.@margin-note*{For an alternative to the ``colon'' syntax, see the name.@margin-note*{For an alternative to the ``colon'' syntax, see the
@racket[~var] pattern form.} @racket[~var] pattern form.}
@myinteraction[ @interaction[#:eval the-eval
(define-syntax (mylet stx) (define-syntax (mylet stx)
(syntax-parse stx (syntax-parse stx
[(_ ((var:id rhs:expr) ...) body ...+) [(_ ((var:id rhs:expr) ...) body ...+)
@ -108,24 +112,24 @@ Note that the syntax class annotations do not appear in the template
(i.e., @racket[var], not @racket[var:id]). (i.e., @racket[var], not @racket[var:id]).
The syntax class annotations are checked when we use the macro. The syntax class annotations are checked when we use the macro.
@myinteraction[ @interaction[#:eval the-eval
(mylet ([a 1] [b 2]) (+ a b)) (mylet ([a 1] [b 2]) (+ a b))
(mylet (["a" 1]) (add1 a)) (mylet (["a" 1]) (add1 a))
] ]
The @racket[expr] syntax class does not actually check that the term The @racket[expr] syntax class does not actually check that the term
it matches is a valid expression---that would require calling that it matches is a valid expression---that would require calling that
macro expander. Instead, @racket[expr] just means not a keyword. macro expander. Instead, @racket[expr] just means not a keyword.
@myinteraction[ @interaction[#:eval the-eval
(mylet ([a #:whoops]) 1) (mylet ([a #:whoops]) 1)
] ]
Also, @racket[syntax-parse] knows how to report a few kinds of errors Also, @racket[syntax-parse] knows how to report a few kinds of errors
without any help: without any help:
@myinteraction[ @interaction[#:eval the-eval
(mylet ([a 1 2]) (* a a)) (mylet ([a 1 2]) (* a a))
] ]
There are other kinds of errors, however, that this macro does not There are other kinds of errors, however, that this macro does not
handle gracefully: handle gracefully:
@myinteraction[ @interaction[#:eval the-eval
(mylet (a 1) (+ a 2)) (mylet (a 1) (+ a 2))
] ]
It's too much to ask for the macro to respond, ``This expression is It's too much to ask for the macro to respond, ``This expression is
@ -140,7 +144,7 @@ syntactic categories. One way of doing that is by defining new syntax
classes:@margin-note*{Another way is the @racket[~describe] pattern classes:@margin-note*{Another way is the @racket[~describe] pattern
form.} form.}
@myinteraction[ @interaction[#:eval the-eval
(define-syntax (mylet stx) (define-syntax (mylet stx)
(define-syntax-class binding (define-syntax-class binding
@ -158,11 +162,11 @@ Note that we write @racket[b.var] and @racket[b.rhs] now. They are the
syntax class @racket[binding]. syntax class @racket[binding].
Now the error messages can talk about ``binding pairs.'' Now the error messages can talk about ``binding pairs.''
@myinteraction[ @interaction[#:eval the-eval
(mylet (a 1) (+ a 2)) (mylet (a 1) (+ a 2))
] ]
Errors are still reported in more specific terms when possible: Errors are still reported in more specific terms when possible:
@myinteraction[ @interaction[#:eval the-eval
(mylet (["a" 1]) (+ a 2)) (mylet (["a" 1]) (+ a 2))
] ]
@ -170,13 +174,13 @@ There is one other constraint on the legal syntax of
@racket[mylet]. The variables bound by the different binding pairs @racket[mylet]. The variables bound by the different binding pairs
must be distinct. Otherwise the macro creates an illegal must be distinct. Otherwise the macro creates an illegal
@racket[lambda] form: @racket[lambda] form:
@myinteraction[ @interaction[#:eval the-eval
(mylet ([a 1] [a 2]) (+ a a)) (mylet ([a 1] [a 2]) (+ a a))
] ]
Constraints such as the distinctness requirement are expressed as side Constraints such as the distinctness requirement are expressed as side
conditions, thus: conditions, thus:
@myinteraction[ @interaction[#:eval the-eval
(define-syntax (mylet stx) (define-syntax (mylet stx)
(define-syntax-class binding (define-syntax-class binding
@ -190,7 +194,7 @@ conditions, thus:
"duplicate variable name" "duplicate variable name"
#'((lambda (b.var ...) body ...) b.rhs ...)])) #'((lambda (b.var ...) body ...) b.rhs ...)]))
] ]
@myinteraction[ @interaction[#:eval the-eval
(mylet ([a 1] [a 2]) (+ a a)) (mylet ([a 1] [a 2]) (+ a a))
] ]
The @racket[#:fail-when] keyword is followed by two expressions: the The @racket[#:fail-when] keyword is followed by two expressions: the
@ -202,7 +206,7 @@ pinpoint the cause of the failure.
Syntax classes can have side conditions, too. Here is the macro Syntax classes can have side conditions, too. Here is the macro
rewritten to include another syntax class representing a ``sequence of rewritten to include another syntax class representing a ``sequence of
distinct binding pairs.'' distinct binding pairs.''
@myinteraction[ @interaction[#:eval the-eval
(define-syntax (mylet stx) (define-syntax (mylet stx)
(define-syntax-class binding (define-syntax-class binding
@ -238,7 +242,7 @@ offered by Racket's @racket[let]. We must add the
``named-@racket[let]'' form. That turns out to be as simple as adding ``named-@racket[let]'' form. That turns out to be as simple as adding
a new clause: a new clause:
@myinteraction[ @interaction[#:eval the-eval
(define-syntax (mylet stx) (define-syntax (mylet stx)
(define-syntax-class binding (define-syntax-class binding
@ -267,7 +271,7 @@ lines.
But does adding this new case affect @racket[syntax-parse]'s ability But does adding this new case affect @racket[syntax-parse]'s ability
to pinpoint and report errors? to pinpoint and report errors?
@myinteraction[ @interaction[#:eval the-eval
(mylet ([a 1] [b 2]) (+ a b)) (mylet ([a 1] [b 2]) (+ a b))
(mylet (["a" 1]) (add1 a)) (mylet (["a" 1]) (add1 a))
(mylet ([a #:whoops]) 1) (mylet ([a #:whoops]) 1)
@ -278,7 +282,7 @@ to pinpoint and report errors?
The error reporting for the original syntax seems intact. We should The error reporting for the original syntax seems intact. We should
verify that the named-@racket[let] syntax is working, that verify that the named-@racket[let] syntax is working, that
@racket[syntax-parse] is not simply ignoring that clause. @racket[syntax-parse] is not simply ignoring that clause.
@myinteraction[ @interaction[#:eval the-eval
(mylet loop ([a 1] [b 2]) (+ a b)) (mylet loop ([a 1] [b 2]) (+ a b))
(mylet loop (["a" 1]) (add1 a)) (mylet loop (["a" 1]) (add1 a))
(mylet loop ([a #:whoops]) 1) (mylet loop ([a #:whoops]) 1)
@ -300,7 +304,7 @@ potential errors (including ones like @racket[loop] not matching
each error. Only the error with the most progress is reported. each error. Only the error with the most progress is reported.
For example, in this bad use of the macro, For example, in this bad use of the macro,
@myinteraction[ @interaction[#:eval the-eval
(mylet loop (["a" 1]) (add1 a)) (mylet loop (["a" 1]) (add1 a))
] ]
there are two potential errors: expected @racket[distinct-bindings] at there are two potential errors: expected @racket[distinct-bindings] at
@ -309,7 +313,7 @@ second error occurs further in the term than the first, so it is
reported. reported.
For another example, consider this term: For another example, consider this term:
@myinteraction[ @interaction[#:eval the-eval
(mylet (["a" 1]) (add1 a)) (mylet (["a" 1]) (add1 a))
] ]
Again, there are two potential errors: expected @racket[identifier] at Again, there are two potential errors: expected @racket[identifier] at
@ -319,7 +323,7 @@ if you prefer), but the second error occurs deeper in the
term. Progress is based on a left-to-right traversal of the syntax. term. Progress is based on a left-to-right traversal of the syntax.
A final example: consider the following: A final example: consider the following:
@myinteraction[ @interaction[#:eval the-eval
(mylet ([a 1] [a 2]) (+ a a)) (mylet ([a 1] [a 2]) (+ a a))
] ]
There are two errors again: duplicate variable name at @racket[([a 1] There are two errors again: duplicate variable name at @racket[([a 1]
@ -339,7 +343,7 @@ the term.
It is, however, possible for multiple potential errors to occur with It is, however, possible for multiple potential errors to occur with
the same progress. Here's one example: the same progress. Here's one example:
@myinteraction[ @interaction[#:eval the-eval
(mylet "not-even-close") (mylet "not-even-close")
] ]
In this case @racket[syntax-parse] reports both errors. In this case @racket[syntax-parse] reports both errors.
@ -347,7 +351,7 @@ In this case @racket[syntax-parse] reports both errors.
Even with all of the annotations we have added to our macro, there are Even with all of the annotations we have added to our macro, there are
still some misuses that defy @racket[syntax-parse]'s error reporting still some misuses that defy @racket[syntax-parse]'s error reporting
capabilities, such as this example: capabilities, such as this example:
@myinteraction[ @interaction[#:eval the-eval
(mylet) (mylet)
] ]
The philosophy behind @racket[syntax-parse] is that in these The philosophy behind @racket[syntax-parse] is that in these
@ -363,3 +367,5 @@ conditions, and progress-ordered error reporting. But
@secref{stxparse-examples} section for samples of other features in @secref{stxparse-examples} section for samples of other features in
working code, or skip to the subsequent sections for the complete working code, or skip to the subsequent sections for the complete
reference documentation. reference documentation.
@(close-eval the-eval)

View File

@ -5,6 +5,8 @@
scribble/eval scribble/eval
"parse-common.rkt") "parse-common.rkt")
@(define the-eval (make-sp-eval))
@title{Literal Sets and Conventions} @title{Literal Sets and Conventions}
Sometimes the same literals are recognized in a number of different Sometimes the same literals are recognized in a number of different
@ -38,7 +40,7 @@ identifiers the literal matches. If the @racket[#:literal-sets] option
is present, the contents of the given @racket[imported-litset-id]s are is present, the contents of the given @racket[imported-litset-id]s are
included. included.
@myexamples[ @examples[#:eval the-eval
(define-literal-set def-litset (define-literal-set def-litset
(define-values define-syntaxes)) (define-values define-syntaxes))
(syntax-parse #'(define-syntaxes (x) 12) (syntax-parse #'(define-syntaxes (x) 12)
@ -56,7 +58,7 @@ given, then @racket[phase-level] is @racket[0].
For example: For example:
@myexamples[ @interaction[#:eval the-eval
(module common racket/base (module common racket/base
(define x 'something) (define x 'something)
(provide x)) (provide x))
@ -74,7 +76,7 @@ module @racketmodname['common].
The following module defines an equivalent literal set, but imports The following module defines an equivalent literal set, but imports
the @racket['common] module for-template instead: the @racket['common] module for-template instead:
@myexamples[ @interaction[#:eval the-eval
(module lits racket/base (module lits racket/base
(require syntax/parse (for-template 'common)) (require syntax/parse (for-template 'common))
(define-literal-set common-lits #:for-template (x)) (define-literal-set common-lits #:for-template (x))
@ -85,7 +87,7 @@ When a literal set is @emph{used} with the @racket[#:phase phase-expr]
option, the literals' fixed bindings are compared against the binding of option, the literals' fixed bindings are compared against the binding of
the input literal at the specified phase. Continuing the example: the input literal at the specified phase. Continuing the example:
@myexamples[ @interaction[#:eval the-eval
(require syntax/parse 'lits (for-syntax 'common)) (require syntax/parse 'lits (for-syntax 'common))
(syntax-parse #'x #:literal-sets ([common-lits #:phase 1]) (syntax-parse #'x #:literal-sets ([common-lits #:phase 1])
[x 'yes] [x 'yes]
@ -106,7 +108,7 @@ phase @racket[_phase] at which to examine the binding of @racket[_id];
the @racket[_phase] argument defaults to the @racket[_phase] argument defaults to
@racket[(syntax-local-phase-level)]. @racket[(syntax-local-phase-level)].
@myexamples[ @examples[#:eval the-eval
(define kernel? (literal-set->predicate kernel-literals)) (define kernel? (literal-set->predicate kernel-literals))
(kernel? #'lambda) (kernel? #'lambda)
(kernel? #'#%plain-lambda) (kernel? #'#%plain-lambda)
@ -130,7 +132,7 @@ that matches determines the syntax class for the pattern. If no
@racket[name-pattern] matches, then the pattern variable has no syntax @racket[name-pattern] matches, then the pattern variable has no syntax
class. class.
@myexamples[ @examples[#:eval the-eval
(define-conventions xyz-as-ids (define-conventions xyz-as-ids
[x id] [y id] [z id]) [x id] [y id] [z id])
(syntax-parse #'(a b c 1 2 3) (syntax-parse #'(a b c 1 2 3)
@ -149,7 +151,7 @@ Local conventions, introduced with the @racket[#:local-conventions]
keyword argument of @racket[syntax-parse] and syntax class keyword argument of @racket[syntax-parse] and syntax class
definitions, may refer to local bindings: definitions, may refer to local bindings:
@myexamples[ @examples[#:eval the-eval
(define-syntax-class (nat> bound) (define-syntax-class (nat> bound)
(pattern n:nat (pattern n:nat
#:fail-unless (> (syntax-e #'n) bound) #:fail-unless (> (syntax-e #'n) bound)
@ -168,3 +170,5 @@ definitions, may refer to local bindings:
] ]
} }
@(close-eval the-eval)

View File

@ -1,16 +1,14 @@
#lang racket/base #lang racket/base
(require scribble/manual (require scribble/manual
scribble/eval scribble/eval
racket/string
racket/sandbox) racket/sandbox)
(provide ellipses (provide ellipses
the-eval make-sp-eval)
myexamples
myinteraction)
(define ellipses (racket ...)) (define ellipses (racket ...))
(define (fixup exn) (define (fixup/short exn)
(let ([src (ormap values (exn:fail:syntax-exprs exn))]) (let ([src (ormap values (exn:fail:syntax-exprs exn))])
(if src (if src
(make-exn:fail:syntax (make-exn:fail:syntax
@ -21,7 +19,21 @@
(exn-continuation-marks exn) (exn-continuation-marks exn)
(exn:fail:syntax-exprs exn)) (exn:fail:syntax-exprs exn))
exn))) exn)))
(define the-eval
(define (fixup/long exn)
(let ([src (ormap values (exn:fail:syntax-exprs exn))])
(if src
(make-exn:fail:syntax
(string-trim (exn-message exn)
#rx"[^ ]*[ ]"
#:left? #t #:right? #f)
(exn-continuation-marks exn)
(exn:fail:syntax-exprs exn))
exn)))
(define (make-sp-eval [short? #f])
(define fixup (if short? fixup/short fixup/long))
(define the-eval
(call-with-trusted-sandbox-configuration (call-with-trusted-sandbox-configuration
(lambda () (lambda ()
(parameterize ([sandbox-output 'string] (parameterize ([sandbox-output 'string]
@ -45,13 +57,8 @@
syntax/parse/experimental/eh)]) syntax/parse/experimental/eh)])
`((for-syntax racket/base ,@mods) `((for-syntax racket/base ,@mods)
,@mods))))))) ,@mods)))))))
(the-eval '(error-print-source-location #f)) (when short? (the-eval '(error-print-source-location #f)))
the-eval)
(define-syntax-rule (myexamples e ...)
(examples #:eval the-eval e ...))
(define-syntax-rule (myinteraction e ...)
(interaction #:eval the-eval e ...))
;; ---- ;; ----

View File

@ -6,6 +6,8 @@
"parse-common.rkt" "parse-common.rkt"
(for-label racket/syntax)) (for-label racket/syntax))
@(define the-eval (make-sp-eval))
@title{Parsing Syntax} @title{Parsing Syntax}
This section describes @racket[syntax-parse], the This section describes @racket[syntax-parse], the
@ -79,15 +81,16 @@ is inferred as with @racket[raise-syntax-error].
The @racket[current-syntax-context] parameter is also set to the The @racket[current-syntax-context] parameter is also set to the
syntax object @racket[_context-stx]. syntax object @racket[_context-stx].
@(myexamples @examples[#:eval the-eval
(syntax-parse #'(a b 3) (syntax-parse #'(a b 3)
[(x:id ...) 'ok]) [(x:id ...) 'ok])
(syntax-parse #'(a b 3) (syntax-parse #'(a b 3)
#:context #'(lambda (a b 3) (+ a b)) #:context #'(lambda (a b 3) (+ a b))
[(x:id ...) 'ok]) [(x:id ...) 'ok])
(syntax-parse #'(a b 3) (syntax-parse #'(a b 3)
#:context 'check-id-list #:context 'check-id-list
[(x:id ...) 'ok])) [(x:id ...) 'ok])
]
} }
@specsubform[(code:line #:literals (literal ...)) @specsubform[(code:line #:literals (literal ...))
@ -172,7 +175,7 @@ bindings. See the section on @tech{conventions} for examples.
Suppresses the ``colon notation'' for annotated pattern variables. Suppresses the ``colon notation'' for annotated pattern variables.
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(a b c) (syntax-parse #'(a b c)
[(x:y ...) 'ok]) [(x:y ...) 'ok])
(syntax-parse #'(a b c) #:disable-colon-notation (syntax-parse #'(a b c) #:disable-colon-notation
@ -195,7 +198,7 @@ syntax object result of @racket[stx-expr] against
@racket[syntax-pattern] and creates pattern variable definitions for @racket[syntax-pattern] and creates pattern variable definitions for
the attributes of @racket[syntax-pattern]. the attributes of @racket[syntax-pattern].
@myexamples[ @examples[#:eval the-eval
(define/syntax-parse ((~seq kw:keyword arg:expr) ...) (define/syntax-parse ((~seq kw:keyword arg:expr) ...)
#'(#:a 1 #:b 2 #:c 3)) #'(#:a 1 #:b 2 #:c 3))
#'(kw ...) #'(kw ...)
@ -204,3 +207,5 @@ the attributes of @racket[syntax-pattern].
Compare with @racket[define/with-syntax], a similar definition form Compare with @racket[define/with-syntax], a similar definition form
that uses the simpler @racket[syntax-case] patterns. that uses the simpler @racket[syntax-case] patterns.
} }
@(close-eval the-eval)

View File

@ -5,6 +5,8 @@
scribble/eval scribble/eval
"parse-common.rkt") "parse-common.rkt")
@(define the-eval (make-sp-eval))
@(define-syntax-rule (define-dotsplus-names dotsplus def-dotsplus) @(define-syntax-rule (define-dotsplus-names dotsplus def-dotsplus)
(begin (require (for-label (only-in syntax/parse ...+))) (begin (require (for-label (only-in syntax/parse ...+)))
(define dotsplus (racket ...+)) (define dotsplus (racket ...+))
@ -200,7 +202,7 @@ An identifier can be either a @tech{pattern variable}, an
literals list, it is a @tech{literal} pattern that behaves literals list, it is a @tech{literal} pattern that behaves
like @racket[(~literal id)]. like @racket[(~literal id)].
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(define x 12) (syntax-parse #'(define x 12)
#:literals (define) #:literals (define)
[(define var:id body:expr) 'ok]) [(define var:id body:expr) 'ok])
@ -221,7 +223,7 @@ An identifier can be either a @tech{pattern variable}, an
@tech{annotated pattern variable}, and the pattern is equivalent to @tech{annotated pattern variable}, and the pattern is equivalent to
@racket[(~var _pvar-id _syntax-class-id)]. @racket[(~var _pvar-id _syntax-class-id)].
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'a (syntax-parse #'a
[var:id (syntax-e #'var)]) [var:id (syntax-e #'var)])
(syntax-parse #'12 (syntax-parse #'12
@ -246,7 +248,7 @@ An identifier can be either a @tech{pattern variable}, an
where @racket[_literal-id] is in the literals list, then it is where @racket[_literal-id] is in the literals list, then it is
equivalent to @racket[(~and (~var _pvar-id) literal-id)]. equivalent to @racket[(~and (~var _pvar-id) literal-id)].
@myexamples[ @examples[#:eval the-eval
(require (only-in racket/base [define def])) (require (only-in racket/base [define def]))
(syntax-parse #'(def x 7) (syntax-parse #'(def x 7)
#:literals (define) #:literals (define)
@ -299,7 +301,7 @@ If @svar[pvar-id] is @racket[_], no attributes are bound. If
If @racket[role-expr] is given and evaluates to a string, it is If @racket[role-expr] is given and evaluates to a string, it is
combined with the syntax class's description in error messages. combined with the syntax class's description in error messages.
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'a (syntax-parse #'a
[(~var var id) (syntax-e #'var)]) [(~var var id) (syntax-e #'var)])
(syntax-parse #'12 (syntax-parse #'12
@ -327,7 +329,7 @@ combined with the syntax class's description in error messages.
A @deftech{literal} identifier pattern. Matches any identifier A @deftech{literal} identifier pattern. Matches any identifier
@racket[free-identifier=?] to @racket[literal-id]. @racket[free-identifier=?] to @racket[literal-id].
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(define x 12) (syntax-parse #'(define x 12)
[((~literal define) var:id body:expr) 'ok]) [((~literal define) var:id body:expr) 'ok])
(syntax-parse #'(lambda x 12) (syntax-parse #'(lambda x 12)
@ -344,7 +346,7 @@ The identifiers are compared at the phase given by
Numbers, strings, booleans, keywords, and the empty list match as Numbers, strings, booleans, keywords, and the empty list match as
literals. literals.
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(a #:foo bar) (syntax-parse #'(a #:foo bar)
[(x #:foo y) (syntax->datum #'y)]) [(x #:foo y) (syntax->datum #'y)])
(syntax-parse #'(a foo bar) (syntax-parse #'(a foo bar)
@ -358,7 +360,7 @@ Matches syntax whose S-expression contents (obtained by
@racket[syntax->datum]) is @racket[equal?] to the given @racket[syntax->datum]) is @racket[equal?] to the given
@racket[datum]. @racket[datum].
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(a #:foo bar) (syntax-parse #'(a #:foo bar)
[(x (~datum #:foo) y) (syntax->datum #'y)]) [(x (~datum #:foo) y) (syntax->datum #'y)])
(syntax-parse #'(a foo bar) (syntax-parse #'(a foo bar)
@ -369,7 +371,7 @@ The @racket[~datum] form is useful for recognizing identifiers
symbolically, in contrast to the @racket[~literal] form, which symbolically, in contrast to the @racket[~literal] form, which
recognizes them by binding. recognizes them by binding.
@myexamples[ @examples[#:eval the-eval
(syntax-parse (let ([define 'something-else]) #'(define x y)) (syntax-parse (let ([define 'something-else]) #'(define x y))
[((~datum define) var:id e:expr) 'yes] [((~datum define) var:id e:expr) 'yes]
[_ 'no]) [_ 'no])
@ -435,7 +437,7 @@ That is, the following patterns are equivalent:
@item[@racket[((~between H 1 +inf.0) ... . S)]] @item[@racket[((~between H 1 +inf.0) ... . S)]]
] ]
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(1 2 3) (syntax-parse #'(1 2 3)
[(n:nat ...+) 'ok]) [(n:nat ...+) 'ok])
(syntax-parse #'() (syntax-parse #'()
@ -461,7 +463,7 @@ term (including its lexical context, source location, etc) while also
examining its structure. Syntax classes are useful for the same examining its structure. Syntax classes are useful for the same
purpose, but @racket[~and] can be lighter weight. purpose, but @racket[~and] can be lighter weight.
@myexamples[ @examples[#:eval the-eval
(define-syntax (import stx) (define-syntax (import stx)
(raise-syntax-error #f "illegal use of import" stx)) (raise-syntax-error #f "illegal use of import" stx))
(eval:alts (eval:alts
@ -490,7 +492,7 @@ of @racket[#f]. The same attribute may be bound by multiple
subpatterns, and if it is bound by all of the subpatterns, it is sure subpatterns, and if it is bound by all of the subpatterns, it is sure
to have a value if the whole pattern matches. to have a value if the whole pattern matches.
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'a (syntax-parse #'a
[(~or x:id y:nat) (values (attribute x) (attribute y))]) [(~or x:id y:nat) (values (attribute x) (attribute y))])
(syntax-parse #'(a 1) (syntax-parse #'(a 1)
@ -506,7 +508,7 @@ Matches any term that does not match the subpattern. None of the
subpattern's attributes are bound outside of the subpattern's attributes are bound outside of the
@racket[~not]-pattern. @racket[~not]-pattern.
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(x y z => u v) (syntax-parse #'(x y z => u v)
#:literals (=>) #:literals (=>)
[((~and before (~not =>)) ... => after ...) [((~and before (~not =>)) ... => after ...)
@ -520,7 +522,7 @@ Matches a term that is a vector whose elements, when considered as a
list, match the @tech{@Spattern} corresponding to list, match the @tech{@Spattern} corresponding to
@racket[(pattern-part ...)]. @racket[(pattern-part ...)].
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'#(1 2 3) (syntax-parse #'#(1 2 3)
[#(x y z) (syntax->datum #'z)]) [#(x y z) (syntax->datum #'z)])
(syntax-parse #'#(1 2 3) (syntax-parse #'#(1 2 3)
@ -536,7 +538,7 @@ Matches a term that is a prefab struct whose key is exactly the given
key and whose sequence of fields, when considered as a list, match the key and whose sequence of fields, when considered as a list, match the
@tech{@Spattern} corresponding to @racket[(pattern-part ...)]. @tech{@Spattern} corresponding to @racket[(pattern-part ...)].
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'#s(point 1 2 3) (syntax-parse #'#s(point 1 2 3)
[#s(point x y z) 'ok]) [#s(point x y z) 'ok])
(syntax-parse #'#s(point 1 2 3) (syntax-parse #'#s(point 1 2 3)
@ -551,7 +553,7 @@ key and whose sequence of fields, when considered as a list, match the
Matches a term that is a box whose contents matches the inner Matches a term that is a box whose contents matches the inner
@tech{@Spattern}. @tech{@Spattern}.
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'#&5 (syntax-parse #'#&5
[#&n:nat 'ok]) [#&n:nat 'ok])
] ]
@ -564,7 +566,7 @@ is useful in positions where improper (``dotted'') lists are not
allowed by the reader, such as vector and structure patterns (see allowed by the reader, such as vector and structure patterns (see
above). above).
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(1 2 3) (syntax-parse #'(1 2 3)
[(x ~rest y) (syntax->datum #'y)]) [(x ~rest y) (syntax->datum #'y)])
(syntax-parse #'#(1 2 3) (syntax-parse #'#(1 2 3)
@ -594,7 +596,7 @@ terms of the description given.
If @racket[role-expr] is given and produces a string, its value is If @racket[role-expr] is given and produces a string, its value is
combined with the description in error messages. combined with the description in error messages.
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(m 1) (syntax-parse #'(m 1)
[(_ (~describe "id pair" (x:id y:id))) 'ok]) [(_ (~describe "id pair" (x:id y:id))) 'ok])
(syntax-parse #'(m (a 2)) (syntax-parse #'(m (a 2))
@ -681,7 +683,7 @@ matches a head pattern.
Matches a sequence of terms whose elements, if put in a list, would Matches a sequence of terms whose elements, if put in a list, would
match @racket[L-pattern]. match @racket[L-pattern].
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(1 2 3 4) (syntax-parse #'(1 2 3 4)
[((~seq 1 2 3) 4) 'ok]) [((~seq 1 2 3) 4) 'ok])
] ]
@ -695,7 +697,7 @@ examples of @racket[~seq].
Like the @Spattern version, @ref[~and s], but matches a sequence of Like the @Spattern version, @ref[~and s], but matches a sequence of
terms instead. terms instead.
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(#:a 1 #:b 2 3 4 5) (syntax-parse #'(#:a 1 #:b 2 3 4 5)
[((~and (~seq (~seq k:keyword e:expr) ...) [((~and (~seq (~seq k:keyword e:expr) ...)
(~seq keyword-stuff ...)) (~seq keyword-stuff ...))
@ -708,7 +710,7 @@ subpatterns be @tech{proper @Hpatterns} (not @tech{@Spatterns}). This
is to prevent typos like the following, a variant of the previous is to prevent typos like the following, a variant of the previous
example with the second @racket[~seq] omitted: example with the second @racket[~seq] omitted:
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(#:a 1 #:b 2 3 4 5) (syntax-parse #'(#:a 1 #:b 2 3 4 5)
[((~and (~seq (~seq k:keyword e:expr) ...) [((~and (~seq (~seq k:keyword e:expr) ...)
(keyword-stuff ...)) (keyword-stuff ...))
@ -728,7 +730,7 @@ example with the second @racket[~seq] omitted:
Like the @Spattern version, @ref[~or s], but matches a sequence of Like the @Spattern version, @ref[~or s], but matches a sequence of
terms instead. terms instead.
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(m #:foo 2 a b c) (syntax-parse #'(m #:foo 2 a b c)
[(_ (~or (~seq #:foo x) (~seq)) y:id ...) [(_ (~or (~seq #:foo x) (~seq)) y:id ...)
(attribute x)]) (attribute x)])
@ -752,7 +754,7 @@ terms. If the @racket[#:defaults] option is given, the subsequent
attribute bindings are used if the subpattern does not match. The attribute bindings are used if the subpattern does not match. The
default attributes must be a subset of the subpattern's attributes. default attributes must be a subset of the subpattern's attributes.
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(m #:foo 2 a b c) (syntax-parse #'(m #:foo 2 a b c)
[(_ (~optional (~seq #:foo x) #:defaults ([x #'#f])) y:id ...) [(_ (~optional (~seq #:foo x) #:defaults ([x #'#f])) y:id ...)
(attribute x)]) (attribute x)])
@ -812,7 +814,7 @@ matching position, so the pattern consumes no input. Used to look
ahead in a sequence. None of the subpattern's attributes are bound ahead in a sequence. None of the subpattern's attributes are bound
outside of the @racket[~peek-not]-pattern. outside of the @racket[~peek-not]-pattern.
@myexamples[ @examples[#:eval the-eval
(define-splicing-syntax-class final (code:comment "final term") (define-splicing-syntax-class final (code:comment "final term")
(pattern (~seq x (~peek-not _)))) (pattern (~seq x (~peek-not _))))
@ -841,7 +843,7 @@ repetition. They are useful for matching, for example, keyword
arguments where the keywords may come in any order. Multiple arguments where the keywords may come in any order. Multiple
alternatives are grouped together via @ref[~or eh]. alternatives are grouped together via @ref[~or eh].
@myexamples[ @examples[#:eval the-eval
(define parser1 (define parser1
(syntax-parser (syntax-parser
[((~or (~once (~seq #:a x) #:name "#:a keyword") [((~or (~once (~seq #:a x) #:name "#:a keyword")
@ -1041,7 +1043,7 @@ There is currently no way to bind attributes using a @racket[~do]
pattern. It is an error to shadow an attribute binding with a pattern. It is an error to shadow an attribute binding with a
definition in a @racket[~do] block. definition in a @racket[~do] block.
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(1 2 3) (syntax-parse #'(1 2 3)
[(a b (~do (printf "a was ~s\n" #'a)) c:id) 'ok]) [(a b (~do (printf "a was ~s\n" #'a)) c:id) 'ok])
] ]
@ -1065,7 +1067,7 @@ forms by rewriting them into existing pattern forms.
Returns a @tech{pattern expander} that uses @racket[proc] to transform the pattern. Returns a @tech{pattern expander} that uses @racket[proc] to transform the pattern.
@myexamples[ @examples[#:eval the-eval
(define-syntax ~maybe (define-syntax ~maybe
(pattern-expander (pattern-expander
(syntax-rules () (syntax-rules ()
@ -1100,3 +1102,5 @@ Returns @racket[#t] if @racket[v] is a @tech{pattern expander},
Like @racket[syntax-local-introduce], but for @tech{pattern expanders}. Like @racket[syntax-local-introduce], but for @tech{pattern expanders}.
} }
@(close-eval the-eval)

View File

@ -5,6 +5,8 @@
scribble/eval scribble/eval
"parse-common.rkt") "parse-common.rkt")
@(define the-eval (make-sp-eval))
@title[#:tag "stxparse-specifying"]{Specifying Syntax with Syntax Classes} @title[#:tag "stxparse-specifying"]{Specifying Syntax with Syntax Classes}
@declare-exporting[syntax/parse] @declare-exporting[syntax/parse]
@ -204,7 +206,7 @@ If a @racket[#:with] directive appears between the main pattern (e.g., in a
@racket[#:declare], then only pattern variables from the @racket[#:with] @racket[#:declare], then only pattern variables from the @racket[#:with]
pattern may be declared. pattern may be declared.
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'P (syntax-parse #'P
[x [x
#:declare x id #:declare x id
@ -322,7 +324,7 @@ subterm. A non-syntax-valued attribute should be bound using the
and @racket[~parse] will convert the right-hand side to a (possibly and @racket[~parse] will convert the right-hand side to a (possibly
3D) syntax object. 3D) syntax object.
@myexamples[ @examples[#:eval the-eval
(define-syntax-class table (define-syntax-class table
(pattern ((key value) ...) (pattern ((key value) ...)
#:attr hashtable #:attr hashtable
@ -347,7 +349,7 @@ used in a syntax template.
Syntax-valued attributes can be used in syntax templates: Syntax-valued attributes can be used in syntax templates:
@myinteraction[ @interaction[#:eval the-eval
(syntax-parse #'((a 3) (b 2) (c 1)) (syntax-parse #'((a 3) (b 2) (c 1))
[t:table [t:table
#'(t.key ...)]) #'(t.key ...)])
@ -357,7 +359,7 @@ Syntax-valued attributes can be used in syntax templates:
But non-syntax-valued attributes cannot: But non-syntax-valued attributes cannot:
@myinteraction[ @interaction[#:eval the-eval
(syntax-parse #'((a 3) (b 2) (c 1)) (syntax-parse #'((a 3) (b 2) (c 1))
[t:table [t:table
#'t.hashtable]) #'t.hashtable])
@ -366,7 +368,7 @@ But non-syntax-valued attributes cannot:
Use the @racket[attribute] form to get the value of an attribute Use the @racket[attribute] form to get the value of an attribute
(syntax-valued or not). (syntax-valued or not).
@myinteraction[ @interaction[#:eval the-eval
(syntax-parse #'((a 1) (b 2) (c 3)) (syntax-parse #'((a 1) (b 2) (c 3))
[t:table [t:table
(attribute t.hashtable)]) (attribute t.hashtable)])
@ -409,7 +411,7 @@ it is syntax-valued. In particular, @racket[~or] and
expected levels of list nesting, and @racket[#:attr] and expected levels of list nesting, and @racket[#:attr] and
@racket[~bind] can be used to bind attributes to arbitrary values. @racket[~bind] can be used to bind attributes to arbitrary values.
@myexamples[ @examples[#:eval the-eval
(syntax-parse #'(a b 3) (syntax-parse #'(a b 3)
[(~or (x:id ...) _) [(~or (x:id ...) _)
(attribute x)]) (attribute x)])
@ -421,3 +423,5 @@ Returns the value associated with the @tech{attribute} named
@racket[attr-id]. If @racket[attr-id] is not bound as an attribute, an @racket[attr-id]. If @racket[attr-id] is not bound as an attribute, an
error is raised. error is raised.
} }
@(close-eval the-eval)