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

View File

@ -6,6 +6,8 @@
"parse-common.rkt"
(for-label racket/class))
@(define the-eval (make-sp-eval))
@title[#:tag "exprc"]{Contracts on Macro Sub-expressions}
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
the parameter expressions.
@myinteraction[
@interaction[#:eval the-eval
(define-syntax (myparameterize stx)
(syntax-parse stx
[(_ ((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
pattern variables are bound; it only computes an attribute that
represents the checked expression.
@(close-eval the-eval)

View File

@ -6,6 +6,8 @@
"parse-common.rkt"
(for-label racket/class))
@(define the-eval (make-sp-eval))
@title{Optional Keyword Arguments}
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:
@myinteraction[
@interaction[#:eval the-eval
(define-syntax (mycond stx)
(syntax-parse stx
[(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
attribute.
@myinteraction[
@interaction[#:eval the-eval
(mycond [(even? 13) 'blue]
[(odd? 4) 'red])
(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
is like an ordinary syntax class but for head patterns.
@myinteraction[
@interaction[#:eval the-eval
(define-syntax (mycond stx)
(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
convenient.) Splicing syntax classes also closely parallel the style
of grammars in macro documentation.
@(close-eval the-eval)

View File

@ -6,6 +6,8 @@
"parse-common.rkt"
(for-label racket/class))
@(define the-eval (make-sp-eval))
@title{More Keyword Arguments}
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
first.
@myinteraction[
@interaction[#:eval the-eval
(define-splicing-syntax-class maybe-super
(pattern (~seq super:id))
(pattern (~seq)))
@ -135,3 +137,5 @@ both @racket[#:guard] and @racket[#:property]. Repetition constraints
cannot express arbitrary incompatibility relations. The best way to
handle such constraints is with a side condition using
@racket[#:fail-when].
@(close-eval the-eval)

View File

@ -6,6 +6,8 @@
"parse-common.rkt"
(for-label racket/class))
@(define the-eval (make-sp-eval))
@title{Phases and Reusable Syntax Classes}
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
macros in the same module; it is defined at the wrong phase.
@myinteraction[
@interaction[#:eval the-eval
(module phase-mismatch-mod racket
(require syntax/parse (for-syntax syntax/parse))
(define-syntax-class foo
@ -37,7 +39,7 @@ phase level incompatibility.)
The phase level mismatch is easily remedied by putting the syntax
class definition within a @racket[begin-for-syntax] block:
@myinteraction[
@interaction[#:eval the-eval
(module phase-ok-mod racket
(require (for-syntax syntax/parse))
(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
@racket[for-syntax].
@myinteraction[
@interaction[#:eval the-eval
(module stxclass-mod racket
(require syntax/parse)
(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
referred to in the patterns and templates.
@myinteraction[
@interaction[#:eval the-eval
(module arith-keywords-mod racket
(define-syntax plus (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
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].
@(close-eval the-eval)

View File

@ -5,6 +5,8 @@
scribble/eval
"parse-common.rkt")
@(define the-eval (make-sp-eval))
@title{Experimental}
The following facilities are experimental.
@ -118,7 +120,7 @@ must be specified explicitly.
Like @racket[~reflect] but for reified splicing syntax classes.
}
@myexamples[
@examples[#:eval the-eval
(define-syntax-class (nat> x)
#:description (format "natural number greater than ~s" x)
#:attributes (diff)
@ -216,7 +218,7 @@ Includes the alternatives of @racket[eh-alternative-set-id], prefixing
their attributes with @racket[name].
}
@myexamples[
@examples[#:eval the-eval
(define-eh-alternative-set options
(pattern (~once (~seq #:a a:expr) #:name "#:a option"))
(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
invalid binding list.
}
@(close-eval the-eval)

View File

@ -6,6 +6,8 @@
"parse-common.rkt"
(for-label (only-in syntax/parse ...+)))
@(define the-eval (make-sp-eval #f))
@(define-syntax-rule (defdummy id)
(defidentifier (quote-syntax id)
#: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
@racket[define-syntax-rule]:
@myinteraction[
@interaction[#:eval the-eval
(define-syntax-rule (mylet ([var rhs] ...) body ...)
((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
consequences:
@myinteraction[
@interaction[#:eval the-eval
(mylet ([a 1] [b 2]) (+ a b))
(mylet (b 2) (sub1 b))
(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},
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
@racket[syntax-parse] macro definition. It behaves no better than the
version using @racket[define-syntax-rule] above.
@myinteraction[
@interaction[#:eval the-eval
(define-syntax (mylet stx)
(syntax-parse stx
[(_ ([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
@racket[~var] pattern form.}
@myinteraction[
@interaction[#:eval the-eval
(define-syntax (mylet stx)
(syntax-parse stx
[(_ ((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]).
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]) (add1 a))
]
The @racket[expr] syntax class does not actually check that the term
it matches is a valid expression---that would require calling that
macro expander. Instead, @racket[expr] just means not a keyword.
@myinteraction[
@interaction[#:eval the-eval
(mylet ([a #:whoops]) 1)
]
Also, @racket[syntax-parse] knows how to report a few kinds of errors
without any help:
@myinteraction[
@interaction[#:eval the-eval
(mylet ([a 1 2]) (* a a))
]
There are other kinds of errors, however, that this macro does not
handle gracefully:
@myinteraction[
@interaction[#:eval the-eval
(mylet (a 1) (+ a 2))
]
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
form.}
@myinteraction[
@interaction[#:eval the-eval
(define-syntax (mylet stx)
(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].
Now the error messages can talk about ``binding pairs.''
@myinteraction[
@interaction[#:eval the-eval
(mylet (a 1) (+ a 2))
]
Errors are still reported in more specific terms when possible:
@myinteraction[
@interaction[#:eval the-eval
(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
must be distinct. Otherwise the macro creates an illegal
@racket[lambda] form:
@myinteraction[
@interaction[#:eval the-eval
(mylet ([a 1] [a 2]) (+ a a))
]
Constraints such as the distinctness requirement are expressed as side
conditions, thus:
@myinteraction[
@interaction[#:eval the-eval
(define-syntax (mylet stx)
(define-syntax-class binding
@ -190,7 +194,7 @@ conditions, thus:
"duplicate variable name"
#'((lambda (b.var ...) body ...) b.rhs ...)]))
]
@myinteraction[
@interaction[#:eval the-eval
(mylet ([a 1] [a 2]) (+ a a))
]
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
rewritten to include another syntax class representing a ``sequence of
distinct binding pairs.''
@myinteraction[
@interaction[#:eval the-eval
(define-syntax (mylet stx)
(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
a new clause:
@myinteraction[
@interaction[#:eval the-eval
(define-syntax (mylet stx)
(define-syntax-class binding
@ -267,7 +271,7 @@ lines.
But does adding this new case affect @racket[syntax-parse]'s ability
to pinpoint and report errors?
@myinteraction[
@interaction[#:eval the-eval
(mylet ([a 1] [b 2]) (+ a b))
(mylet (["a" 1]) (add1 a))
(mylet ([a #:whoops]) 1)
@ -278,7 +282,7 @@ to pinpoint and report errors?
The error reporting for the original syntax seems intact. We should
verify that the named-@racket[let] syntax is working, that
@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]) (add1 a))
(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.
For example, in this bad use of the macro,
@myinteraction[
@interaction[#:eval the-eval
(mylet loop (["a" 1]) (add1 a))
]
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.
For another example, consider this term:
@myinteraction[
@interaction[#:eval the-eval
(mylet (["a" 1]) (add1 a))
]
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.
A final example: consider the following:
@myinteraction[
@interaction[#:eval the-eval
(mylet ([a 1] [a 2]) (+ a a))
]
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
the same progress. Here's one example:
@myinteraction[
@interaction[#:eval the-eval
(mylet "not-even-close")
]
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
still some misuses that defy @racket[syntax-parse]'s error reporting
capabilities, such as this example:
@myinteraction[
@interaction[#:eval the-eval
(mylet)
]
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
working code, or skip to the subsequent sections for the complete
reference documentation.
@(close-eval the-eval)

View File

@ -5,6 +5,8 @@
scribble/eval
"parse-common.rkt")
@(define the-eval (make-sp-eval))
@title{Literal Sets and Conventions}
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
included.
@myexamples[
@examples[#:eval the-eval
(define-literal-set def-litset
(define-values define-syntaxes))
(syntax-parse #'(define-syntaxes (x) 12)
@ -56,7 +58,7 @@ given, then @racket[phase-level] is @racket[0].
For example:
@myexamples[
@interaction[#:eval the-eval
(module common racket/base
(define x 'something)
(provide x))
@ -74,7 +76,7 @@ module @racketmodname['common].
The following module defines an equivalent literal set, but imports
the @racket['common] module for-template instead:
@myexamples[
@interaction[#:eval the-eval
(module lits racket/base
(require syntax/parse (for-template 'common))
(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
the input literal at the specified phase. Continuing the example:
@myexamples[
@interaction[#:eval the-eval
(require syntax/parse 'lits (for-syntax 'common))
(syntax-parse #'x #:literal-sets ([common-lits #:phase 1])
[x 'yes]
@ -106,7 +108,7 @@ phase @racket[_phase] at which to examine the binding of @racket[_id];
the @racket[_phase] argument defaults to
@racket[(syntax-local-phase-level)].
@myexamples[
@examples[#:eval the-eval
(define kernel? (literal-set->predicate kernel-literals))
(kernel? #'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
class.
@myexamples[
@examples[#:eval the-eval
(define-conventions xyz-as-ids
[x id] [y id] [z id])
(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
definitions, may refer to local bindings:
@myexamples[
@examples[#:eval the-eval
(define-syntax-class (nat> bound)
(pattern n:nat
#: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
(require scribble/manual
scribble/eval
racket/string
racket/sandbox)
(provide ellipses
the-eval
myexamples
myinteraction)
make-sp-eval)
(define ellipses (racket ...))
(define (fixup exn)
(define (fixup/short exn)
(let ([src (ormap values (exn:fail:syntax-exprs exn))])
(if src
(make-exn:fail:syntax
@ -21,37 +19,46 @@
(exn-continuation-marks exn)
(exn:fail:syntax-exprs exn))
exn)))
(define the-eval
(call-with-trusted-sandbox-configuration
(lambda ()
(parameterize ([sandbox-output 'string]
[sandbox-error-output 'string]
[sandbox-propagate-breaks #f]
[sandbox-eval-handlers
(list #f
(lambda (thunk)
(with-handlers ([exn:fail:syntax?
(lambda (e) (raise (fixup e)))])
(thunk))))])
(make-evaluator 'racket/base
#:requires (let ([mods '(racket/promise
syntax/parse
syntax/parse/debug
syntax/parse/experimental/splicing
syntax/parse/experimental/contract
syntax/parse/experimental/reflect
syntax/parse/experimental/specialize
syntax/parse/experimental/template
syntax/parse/experimental/eh)])
`((for-syntax racket/base ,@mods)
,@mods)))))))
(the-eval '(error-print-source-location #f))
(define-syntax-rule (myexamples e ...)
(examples #:eval the-eval e ...))
(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-syntax-rule (myinteraction e ...)
(interaction #:eval the-eval e ...))
(define (make-sp-eval [short? #f])
(define fixup (if short? fixup/short fixup/long))
(define the-eval
(call-with-trusted-sandbox-configuration
(lambda ()
(parameterize ([sandbox-output 'string]
[sandbox-error-output 'string]
[sandbox-propagate-breaks #f]
[sandbox-eval-handlers
(list #f
(lambda (thunk)
(with-handlers ([exn:fail:syntax?
(lambda (e) (raise (fixup e)))])
(thunk))))])
(make-evaluator 'racket/base
#:requires (let ([mods '(racket/promise
syntax/parse
syntax/parse/debug
syntax/parse/experimental/splicing
syntax/parse/experimental/contract
syntax/parse/experimental/reflect
syntax/parse/experimental/specialize
syntax/parse/experimental/template
syntax/parse/experimental/eh)])
`((for-syntax racket/base ,@mods)
,@mods)))))))
(when short? (the-eval '(error-print-source-location #f)))
the-eval)
;; ----

View File

@ -6,6 +6,8 @@
"parse-common.rkt"
(for-label racket/syntax))
@(define the-eval (make-sp-eval))
@title{Parsing Syntax}
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
syntax object @racket[_context-stx].
@(myexamples
(syntax-parse #'(a b 3)
[(x:id ...) 'ok])
(syntax-parse #'(a b 3)
#:context #'(lambda (a b 3) (+ a b))
[(x:id ...) 'ok])
(syntax-parse #'(a b 3)
#:context 'check-id-list
[(x:id ...) 'ok]))
@examples[#:eval the-eval
(syntax-parse #'(a b 3)
[(x:id ...) 'ok])
(syntax-parse #'(a b 3)
#:context #'(lambda (a b 3) (+ a b))
[(x:id ...) 'ok])
(syntax-parse #'(a b 3)
#:context 'check-id-list
[(x:id ...) 'ok])
]
}
@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.
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(a b c)
[(x:y ...) 'ok])
(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
the attributes of @racket[syntax-pattern].
@myexamples[
@examples[#:eval the-eval
(define/syntax-parse ((~seq kw:keyword arg:expr) ...)
#'(#:a 1 #:b 2 #:c 3))
#'(kw ...)
@ -204,3 +207,5 @@ the attributes of @racket[syntax-pattern].
Compare with @racket[define/with-syntax], a similar definition form
that uses the simpler @racket[syntax-case] patterns.
}
@(close-eval the-eval)

View File

@ -5,6 +5,8 @@
scribble/eval
"parse-common.rkt")
@(define the-eval (make-sp-eval))
@(define-syntax-rule (define-dotsplus-names dotsplus def-dotsplus)
(begin (require (for-label (only-in syntax/parse ...+)))
(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
like @racket[(~literal id)].
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(define x 12)
#:literals (define)
[(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
@racket[(~var _pvar-id _syntax-class-id)].
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'a
[var:id (syntax-e #'var)])
(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
equivalent to @racket[(~and (~var _pvar-id) literal-id)].
@myexamples[
@examples[#:eval the-eval
(require (only-in racket/base [define def]))
(syntax-parse #'(def x 7)
#: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
combined with the syntax class's description in error messages.
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'a
[(~var var id) (syntax-e #'var)])
(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
@racket[free-identifier=?] to @racket[literal-id].
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(define x 12)
[((~literal define) var:id body:expr) 'ok])
(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
literals.
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(a #:foo bar)
[(x #:foo y) (syntax->datum #'y)])
(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[datum].
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(a #:foo bar)
[(x (~datum #:foo) y) (syntax->datum #'y)])
(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
recognizes them by binding.
@myexamples[
@examples[#:eval the-eval
(syntax-parse (let ([define 'something-else]) #'(define x y))
[((~datum define) var:id e:expr) 'yes]
[_ 'no])
@ -435,7 +437,7 @@ That is, the following patterns are equivalent:
@item[@racket[((~between H 1 +inf.0) ... . S)]]
]
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(1 2 3)
[(n:nat ...+) 'ok])
(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
purpose, but @racket[~and] can be lighter weight.
@myexamples[
@examples[#:eval the-eval
(define-syntax (import stx)
(raise-syntax-error #f "illegal use of import" stx))
(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
to have a value if the whole pattern matches.
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'a
[(~or x:id y:nat) (values (attribute x) (attribute y))])
(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
@racket[~not]-pattern.
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(x y z => u v)
#:literals (=>)
[((~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
@racket[(pattern-part ...)].
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'#(1 2 3)
[#(x y z) (syntax->datum #'z)])
(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
@tech{@Spattern} corresponding to @racket[(pattern-part ...)].
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'#s(point 1 2 3)
[#s(point x y z) 'ok])
(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
@tech{@Spattern}.
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'#&5
[#&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
above).
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(1 2 3)
[(x ~rest y) (syntax->datum #'y)])
(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
combined with the description in error messages.
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(m 1)
[(_ (~describe "id pair" (x:id y:id))) 'ok])
(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
match @racket[L-pattern].
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(1 2 3 4)
[((~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
terms instead.
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(#:a 1 #:b 2 3 4 5)
[((~and (~seq (~seq k:keyword e:expr) ...)
(~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
example with the second @racket[~seq] omitted:
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(#:a 1 #:b 2 3 4 5)
[((~and (~seq (~seq k:keyword e:expr) ...)
(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
terms instead.
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(m #:foo 2 a b c)
[(_ (~or (~seq #:foo x) (~seq)) y:id ...)
(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
default attributes must be a subset of the subpattern's attributes.
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(m #:foo 2 a b c)
[(_ (~optional (~seq #:foo x) #:defaults ([x #'#f])) y:id ...)
(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
outside of the @racket[~peek-not]-pattern.
@myexamples[
@examples[#:eval the-eval
(define-splicing-syntax-class final (code:comment "final term")
(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
alternatives are grouped together via @ref[~or eh].
@myexamples[
@examples[#:eval the-eval
(define parser1
(syntax-parser
[((~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
definition in a @racket[~do] block.
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(1 2 3)
[(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.
@myexamples[
@examples[#:eval the-eval
(define-syntax ~maybe
(pattern-expander
(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}.
}
@(close-eval the-eval)

View File

@ -5,6 +5,8 @@
scribble/eval
"parse-common.rkt")
@(define the-eval (make-sp-eval))
@title[#:tag "stxparse-specifying"]{Specifying Syntax with Syntax Classes}
@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]
pattern may be declared.
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'P
[x
#: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
3D) syntax object.
@myexamples[
@examples[#:eval the-eval
(define-syntax-class table
(pattern ((key value) ...)
#:attr hashtable
@ -347,7 +349,7 @@ used in a syntax template.
Syntax-valued attributes can be used in syntax templates:
@myinteraction[
@interaction[#:eval the-eval
(syntax-parse #'((a 3) (b 2) (c 1))
[t:table
#'(t.key ...)])
@ -357,7 +359,7 @@ Syntax-valued attributes can be used in syntax templates:
But non-syntax-valued attributes cannot:
@myinteraction[
@interaction[#:eval the-eval
(syntax-parse #'((a 3) (b 2) (c 1))
[t:table
#'t.hashtable])
@ -366,7 +368,7 @@ But non-syntax-valued attributes cannot:
Use the @racket[attribute] form to get the value of an attribute
(syntax-valued or not).
@myinteraction[
@interaction[#:eval the-eval
(syntax-parse #'((a 1) (b 2) (c 3))
[t:table
(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
@racket[~bind] can be used to bind attributes to arbitrary values.
@myexamples[
@examples[#:eval the-eval
(syntax-parse #'(a b 3)
[(~or (x:id ...) _)
(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
error is raised.
}
@(close-eval the-eval)