899 lines
32 KiB
Racket
899 lines
32 KiB
Racket
#lang scribble/doc
|
|
@(require scribble/manual
|
|
scribble/struct
|
|
scribble/decode
|
|
scribble/eval
|
|
scheme/sandbox
|
|
(for-label scheme/base
|
|
scheme/contract
|
|
(except-in syntax/parse ...+)
|
|
syntax/kerncase))
|
|
|
|
@(define ellipses @scheme[...])
|
|
|
|
@(begin
|
|
(define (fixup exn)
|
|
(let ([src (ormap values (exn:fail:syntax-exprs exn))])
|
|
(if src
|
|
(make-exn:fail:syntax
|
|
(format "~a at: ~a" (exn-message exn) (syntax->datum src))
|
|
(exn-continuation-marks exn)
|
|
(exn:fail:syntax-exprs exn))
|
|
exn)))
|
|
(define the-eval
|
|
(parameterize ((sandbox-output 'string)
|
|
(sandbox-error-output 'string)
|
|
(sandbox-make-code-inspector current-code-inspector)
|
|
(sandbox-eval-handlers
|
|
(list #f
|
|
(lambda (thunk)
|
|
(with-handlers ([exn:fail:syntax?
|
|
(lambda (e) (raise (fixup e)))])
|
|
(thunk))))))
|
|
(make-evaluator 'scheme/base
|
|
#:requires '(syntax/parse (for-syntax scheme/base)))))
|
|
(the-eval '(error-print-source-location #f))
|
|
(define-syntax-rule (myexamples e ...)
|
|
(examples #:eval the-eval e ...)))
|
|
|
|
@title[#:tag "stxparse" #:style '(toc)]{Parsing and classifying syntax}
|
|
|
|
The @schememodname[syntax/parse] library provides a framework for
|
|
describing and parsing syntax. Using @schememodname[syntax/parse],
|
|
macro writers can define new syntactic categories, specify their legal
|
|
syntax, and use them to write clear, concise, and robust macros. The
|
|
library also provides a pattern-matching form, @scheme[syntax-parse],
|
|
which offers many improvements over @scheme[syntax-case].
|
|
|
|
@defmodule[syntax/parse]
|
|
|
|
@local-table-of-contents[]
|
|
|
|
@;{----------}
|
|
|
|
@section{Quick Start}
|
|
|
|
This section provides a rapid introduction to the
|
|
@schememodname[syntax/parse] library for the macro programmer.
|
|
|
|
To use @scheme[syntax-parse] to write a macro transformer, import it
|
|
@scheme[for-syntax]:
|
|
|
|
@schemeblock[(require (for-syntax syntax/parse))]
|
|
|
|
For example, here is is a module that defines
|
|
@schemekeywordfont{mylet}, a macro that has the same behavior as the
|
|
standard @scheme[let] form (including ``named @scheme[let]''):
|
|
|
|
@schemeblock[
|
|
(module example racket/base
|
|
(require (for-syntax scheme/base syntax/parse))
|
|
(define-syntax (mylet stx)
|
|
(syntax-parse stx
|
|
[(_ loop:id ((x:id e:expr) ...) . body)
|
|
#'(letrec ([loop (lambda (x ...) . body)])
|
|
(loop e ...))]
|
|
[(_ ((x:id e:expr) ...) . body)
|
|
#'((lambda (x ...) . body) e ...)])))
|
|
]
|
|
|
|
The macro is defined as a procedure that takes one argument,
|
|
@scheme[stx]. The @scheme[syntax-parse] form is similar to
|
|
@scheme[syntax-case], except that there is no literals list between
|
|
the syntax argument and the sequence of clauses.
|
|
|
|
@bold{Note: } Remember not to put a @scheme[syntax-case] style
|
|
literals list between the syntax argument and the clauses!
|
|
|
|
The patterns contain identifiers consisting of two parts separated by
|
|
a colon character, such as @scheme[loop:id] or @scheme[e:expr]. These
|
|
are pattern variables annotated with syntax classes. For example,
|
|
@scheme[loop:id] is a pattern variable named @scheme[loop] with the
|
|
syntax class @scheme[id] (identifier). Note that only the pattern
|
|
variable part is used in the syntax template.
|
|
|
|
Syntax classes restrict what a pattern variable can match. Above,
|
|
@scheme[loop] only matches an identifier, so the first clause only
|
|
matches the ``named-let'' syntax. Syntax classes replace some uses of
|
|
@scheme[syntax-case]'s ``fenders'' or guard expressions. They also
|
|
enable @scheme[syntax-parse] to automatically give specific error
|
|
messages.
|
|
|
|
The @schememodname[syntax/parse] library provides several built-in
|
|
syntax classes (see @secref{lib} for a list). Programmers can also
|
|
define their own using @scheme[define-syntax-class]:
|
|
|
|
@schemeblock[
|
|
(module example-syntax racket/base
|
|
(require syntax/parse)
|
|
(provide binding)
|
|
(define-syntax-class binding
|
|
#:attributes (x e)
|
|
(pattern (x:id e:expr))))
|
|
|
|
(module example racket/base
|
|
(require (for-syntax racket/base
|
|
syntax/parse
|
|
'example-syntax))
|
|
(define-syntax (mylet stx)
|
|
(syntax-parse stx
|
|
[(_ loop:id (b:binding ...) . body)
|
|
#'(letrec ([loop (lambda (b.x ...) . body)])
|
|
(loop b.e ...))]
|
|
[(_ (b:binding ...) . body)
|
|
#'((lambda (b.x ...) . body) b.e ...)])))
|
|
]
|
|
|
|
@bold{Note:} Syntax classes must be defined in the same phase as the
|
|
@scheme[syntax-parse] expression they're used in. The right-hand side
|
|
of a macro is at phase 1, so syntax classes it uses must be defined in
|
|
a separate module and required @scheme[for-syntax]. Since the
|
|
auxiliary module uses @scheme[define-syntax-class] at phase 0, it has
|
|
@scheme[(require syntax/parse)], with no @scheme[for-syntax].
|
|
|
|
Alternatively, the syntax class could be made a local definition,
|
|
thus:
|
|
|
|
@schemeblock[
|
|
(module example racket/base
|
|
(require (for-syntax scheme/base
|
|
syntax/parse))
|
|
(define-syntax (mylet stx)
|
|
(define-syntax-class binding
|
|
#:attributes (x e)
|
|
(pattern (x:id e:expr)))
|
|
(syntax-parse stx
|
|
[(_ loop:id (b:binding ...) . body)
|
|
#'(letrec ([loop (lambda (b.x ...) . body)])
|
|
(loop b.e ...))]
|
|
[(_ (b:binding ...) . body)
|
|
#'((lambda (b.x ...) . body) b.e ...)])))
|
|
]
|
|
|
|
A syntax class is an abstraction of a syntax pattern. The syntax class
|
|
@scheme[binding] gives a name to the repeated pattern fragment
|
|
@scheme[(x:id e:expr)]. The components of the fragment, @scheme[x] and
|
|
@scheme[e], become @tech{attributes} of the syntax class. When
|
|
@scheme[b:binding] matches, @scheme[b] gets bound to the whole binding
|
|
pair, and @scheme[b.x] and @scheme[b.e] get bound to the variable name
|
|
and expression, respectively. Actually, all of them are bound to
|
|
sequences, because of the ellipses.
|
|
|
|
Syntax classes can have multiple alternative patterns. Suppose we
|
|
wanted to extend @schemekeywordfont{mylet} to allow a simple
|
|
identifier as a binding, in which case it would get the value
|
|
@scheme[#f]:
|
|
|
|
@schemeblock[
|
|
(mylet ([a 1] b [c 'foo]) ....)
|
|
]
|
|
|
|
Here's how the syntax class would change:
|
|
|
|
@margin-note{The @scheme[(require (for-template scheme/base))] is
|
|
needed for the @scheme[quote] expression. If the syntax class
|
|
definition were a local definition in the same module, the
|
|
@scheme[for-template] would be unnecessary.}
|
|
@;
|
|
@SCHEMEBLOCK[
|
|
(module example-syntax scheme/base
|
|
(require syntax/parse)
|
|
(require (for-template scheme/base))
|
|
(provide binding)
|
|
(define-syntax-class binding
|
|
#:attributes (x e)
|
|
(pattern (x:id e:expr))
|
|
(pattern x:id
|
|
#:with e #'(quote #f))))
|
|
]
|
|
|
|
The second pattern matches unparenthesized identifiers. The @scheme[e]
|
|
attribute is bound using a @scheme[#:with] clause, which matches the
|
|
pattern @scheme[e] against the syntax from evaluating @scheme[#'#f].
|
|
|
|
Optional keyword arguments are supported via @tech{head
|
|
patterns}. Unlike normal patterns, which match one term, head patterns
|
|
can match a variable number of subterms in a list.
|
|
|
|
Suppose @schemekeywordfont{mylet} accepted an optional
|
|
@scheme[#:check] keyword with one argument, a procedure that would be
|
|
applied to every variable's value. Here's one way to write it
|
|
(dropping the named-let variant for simplicity):
|
|
|
|
@SCHEMEBLOCK[
|
|
(define-syntax (mylet stx)
|
|
(syntax-parse stx
|
|
[(_ (~optional (~seq #:check pred)) (b:binding ...) . body)
|
|
#`((lambda (b.x ...)
|
|
#,(if (attribute pred)
|
|
#'(unless (and (pred b.x) ...) (error 'check))
|
|
#'(void))
|
|
. body)
|
|
b.e ...)]))
|
|
]
|
|
|
|
An optional subpattern might not match, so attributes within an
|
|
@scheme[~optional] form might not be bound to syntax. Such
|
|
non-syntax-valued attributes may not be used within syntax
|
|
templates. The @scheme[attribute] special form is used to get the
|
|
value of an attribute; if the attribute didn't get matched, the value
|
|
is @scheme[#f].
|
|
|
|
Here's another way write it, using @scheme[#:defaults] to give the
|
|
@scheme[pred] attribute a default value:
|
|
|
|
@schemeblock[
|
|
(define-syntax (mylet stx)
|
|
(syntax-parse stx
|
|
[(_ (~optional (~seq #:check pred)
|
|
#:defaults ([pred #'(lambda (x) #t)]))
|
|
(b:binding ...) . body)
|
|
#`((lambda (b.x ...)
|
|
(unless (and (pred b.x) ...) (error 'check))
|
|
. body)
|
|
b.e ...)]))
|
|
]
|
|
|
|
Programmers can also create abstractions over head patterns, using
|
|
@scheme[define-splicing-syntax-class]. Here it is, rewritten to use
|
|
multiple alternatives instead of @scheme[~optional]:
|
|
|
|
@schemeblock[
|
|
(define-splicing-syntax-class optional-check
|
|
#:attributes (pred)
|
|
(pattern (~seq #:check pred))
|
|
(pattern (~seq)
|
|
#:with pred #'(lambda (x) #t)))
|
|
]
|
|
|
|
@bold{Note: } When defining a splicing syntax class, remember to
|
|
include @scheme[~seq] in the pattern!
|
|
|
|
Here is the corresponding macro:
|
|
|
|
@schemeblock[
|
|
(define-syntax (mylet stx)
|
|
(syntax-parse stx
|
|
[(_ c:optional-check (b:binding ...) . body)
|
|
#'((lambda (b.x ...)
|
|
(unless (and (c.pred b.x) ...) (error 'check))
|
|
. body)
|
|
b.e ...)]))
|
|
]
|
|
|
|
The documentation in the following sections contains additional
|
|
examples of @schememodname[syntax/parse] features.
|
|
|
|
|
|
@;{----------}
|
|
|
|
@section{Parsing and classifying syntax}
|
|
|
|
This section describes @schememodname[syntax/parse]'s facilities for
|
|
parsing and classifying syntax. These facilities use a common language
|
|
of @tech{syntax patterns}, which is described in detail in the next
|
|
section, @secref{syntax-patterns}.
|
|
|
|
@subsection{Parsing syntax}
|
|
|
|
Two parsing forms are provided: @scheme[syntax-parse] and
|
|
@scheme[syntax-parser].
|
|
|
|
@defform/subs[(syntax-parse stx-expr parse-option ... clause ...+)
|
|
([parse-option (code:line #:context context-expr)
|
|
(code:line #:literals (literal ...))
|
|
(code:line #:literal-sets (literal-set ...))
|
|
(code:line #:conventions (convention-id ...))
|
|
(code:line #:local-conventions (convention-rule ...))]
|
|
[literal literal-id
|
|
(pattern-id literal-id)
|
|
(pattern-id literal-id #:phase phase-expr)]
|
|
[literal-set literal-set-id
|
|
(literal-set-id literal-set-option ...)]
|
|
[literal-set-option (code:line #:at context-id)
|
|
(code:line #:phase phase-expr)]
|
|
[clause (syntax-pattern pattern-directive ... expr ...+)])
|
|
#:contracts ([stx-expr syntax?])]{
|
|
|
|
Evaluates @scheme[stx-expr], which should produce a syntax object, and
|
|
matches it against the @scheme[clause]s in order. If some clause's
|
|
pattern matches, its attributes are bound to the corresponding
|
|
subterms of the syntax object and that clause's side conditions and
|
|
@scheme[expr] is evaluated. The result is the result of @scheme[expr].
|
|
|
|
If the syntax object fails to match any of the patterns (or all
|
|
matches fail the corresponding clauses' side conditions), a syntax
|
|
error is raised.
|
|
|
|
The following options are supported:
|
|
|
|
@specsubform[(code:line #:context context-expr)
|
|
#:contracts ([context-expr syntax?])]{
|
|
|
|
When present, @scheme[context-expr] is used in reporting parse
|
|
failures; otherwise @scheme[stx-expr] is used.
|
|
|
|
@(myexamples
|
|
(syntax-parse #'(a b 3)
|
|
[(x:id ...) 'ok])
|
|
(syntax-parse #'(a b 3)
|
|
#:context #'(lambda (a b 3) (+ a b))
|
|
[(x:id ...) 'ok]))
|
|
}
|
|
|
|
@specsubform/subs[(code:line #:literals (literal ...))
|
|
([literal literal-id
|
|
(pattern-id literal-id)
|
|
(pattern-id literal-id #:phase phase-expr)])]{
|
|
@margin-note{
|
|
Unlike @scheme[syntax-case], @scheme[syntax-parse] requires all
|
|
literals to have a binding. To match identifiers by their symbolic
|
|
names, use the @scheme[~datum] pattern form instead.
|
|
}
|
|
@;
|
|
The @scheme[#:literals] option specifies identifiers that should be
|
|
treated as @tech{literals} rather than @tech{pattern variables}. An
|
|
entry in the literals list has two components: the identifier used
|
|
within the pattern to signify the positions to be matched
|
|
(@scheme[pattern-id]), and the identifier expected to occur in those
|
|
positions (@scheme[literal-id]). If the entry is a single identifier,
|
|
that identifier is used for both purposes.
|
|
|
|
If the @scheme[#:phase] option is given, then the literal is compared
|
|
at phase @scheme[phase-expr]. Specifically, the binding of the
|
|
@scheme[literal-id] at phase @scheme[phase-expr] must match the
|
|
input's binding at phase @scheme[phase-expr].
|
|
}
|
|
|
|
@specsubform/subs[(code:line #:literal-sets (literal-set ...))
|
|
([literal-set literal-set-id
|
|
(literal-set-id literal-set-option ...)]
|
|
[literal-set-option (code:line #:at context-id)
|
|
(code:line #:phase phase-expr)])]{
|
|
|
|
Many literals can be declared at once via one or more @tech{literal
|
|
sets}, imported with the @scheme[#:literal-sets] option. See
|
|
@tech{literal sets} for more information.
|
|
}
|
|
|
|
@specsubform[(code:line #:conventions (conventions-id ...))]{
|
|
|
|
Imports @tech{convention}s that give default syntax classes to pattern
|
|
variables that do not explicitly specify a syntax class.
|
|
}
|
|
|
|
@specsubform[(code:line #:local-conventions (convention-rule ...))]{
|
|
|
|
Uses the @tech{conventions} specified. The advantage of
|
|
@scheme[#:local-conventions] over @scheme[#:conventions] is that local
|
|
conventions can be in the scope of syntax-class parameter
|
|
bindings. See the section on @tech{conventions} for examples.
|
|
}
|
|
|
|
Each clause consists of a @tech{syntax pattern}, an optional sequence
|
|
of @tech{pattern directives}, and a non-empty sequence of body
|
|
expressions.
|
|
}
|
|
|
|
@defform[(syntax-parser parse-option ... clause ...+)]{
|
|
|
|
Like @scheme[syntax-parse], but produces a matching procedure. The
|
|
procedure accepts a single argument, which should be a syntax object.
|
|
}
|
|
|
|
@;{----------}
|
|
|
|
@subsection{Classifying syntax}
|
|
|
|
Syntax classes provide an abstraction mechanism for @tech{syntax
|
|
patterns}. Built-in syntax classes are supplied that recognize basic
|
|
classes such as @scheme[identifier] and @scheme[keyword]. Programmers
|
|
can compose basic syntax classes to build specifications of more
|
|
complex syntax, such as lists of distinct identifiers and formal
|
|
arguments with keywords. Macros that manipulate the same syntactic
|
|
structures can share syntax class definitions.
|
|
|
|
@defform*/subs[#:literals (pattern)
|
|
[(define-syntax-class name-id stxclass-option ...
|
|
stxclass-variant ...+)
|
|
(define-syntax-class (name-id arg-id ...) stxclass-option ...
|
|
stxclass-variant ...+)]
|
|
([stxclass-option
|
|
(code:line #:attributes (attr-arity-decl ...))
|
|
(code:line #:description description-expr)
|
|
(code:line #:opaque)
|
|
(code:line #:literals (literal-entry ...))
|
|
(code:line #:literal-sets (literal-set ...))
|
|
(code:line #:conventions (convention-id ...))
|
|
(code:line #:local-conventions (convention-rule ...))]
|
|
[attr-arity-decl
|
|
attr-name-id
|
|
(attr-name-id depth)]
|
|
[stxclass-variant
|
|
(pattern syntax-pattern pattern-directive ...)])]{
|
|
|
|
Defines @scheme[name-id] as a @deftech{syntax class}, which
|
|
encapsulates one or more @tech{single-term patterns}.
|
|
|
|
When the @scheme[arg-id]s are present, they are bound as variables in
|
|
the body. The body of the syntax-class definition contains a non-empty
|
|
sequence of @scheme[pattern] variants.
|
|
|
|
The following options are supported:
|
|
|
|
@specsubform/subs[(code:line #:attributes (attr-arity-decl ...))
|
|
([attr-arity-decl attr-id
|
|
(attr-id depth)])]{
|
|
|
|
Declares the attributes of the syntax class. An attribute arity
|
|
declaration consists of the attribute name and optionally its ellipsis
|
|
depth (zero if not explicitly specified).
|
|
|
|
If the attributes are not explicitly listed, they are inferred as the
|
|
set of all @tech{pattern variables} occurring in every variant of the
|
|
syntax class. Pattern variables that occur at different ellipsis
|
|
depths are not included, nor are nested attributes from
|
|
@tech{annotated pattern variables}.
|
|
}
|
|
|
|
@specsubform[(code:line #:description description-expr)]{
|
|
|
|
The @scheme[description] argument is an expression (evaluated in a
|
|
scope containing the syntax class's parameters) that should evaluate
|
|
to a string. It is used in error messages involving the syntax
|
|
class. For example, if a term is rejected by the syntax class, an
|
|
error of the form @schemevalfont{"expected @scheme[description]"} may
|
|
be synthesized.
|
|
|
|
If absent, the name of the syntax class is used instead.
|
|
}
|
|
|
|
@specsubform[#:opaque]{
|
|
|
|
Indicates that errors should not be reported with respect to the
|
|
internal structure of the syntax class.
|
|
}
|
|
|
|
@specsubform[(code:line #:literals (literal-entry))]
|
|
@specsubform[(code:line #:literal-sets (literal-set ...))]
|
|
@specsubform[(code:line #:conventions (convention-id ...))]{
|
|
|
|
Declares the literals and conventions that apply to the syntax class's
|
|
variant patterns and their immediate @scheme[#:with] clauses. Patterns
|
|
occuring within subexpressions of the syntax class (for example, on
|
|
the right-hand side of a @scheme[#:fail-when] clause) are not
|
|
affected.
|
|
|
|
These options have the same meaning as in @scheme[syntax-parse].
|
|
}
|
|
|
|
Each variant of a syntax class is specified as a separate
|
|
@scheme[pattern]-form whose syntax pattern is a @tech{single-term
|
|
pattern}.
|
|
}
|
|
|
|
@defform*[#:literals (pattern)
|
|
[(define-splicing-syntax-class name-id stxclass-option ...
|
|
stxclass-variant ...+)
|
|
(define-splicing-syntax-class (name-id arg-id ...) stxclass-option ...
|
|
stxclass-variant ...+)]]{
|
|
|
|
Defines @scheme[name-id] as a @deftech{splicing syntax class},
|
|
analogous to a @tech{syntax class} but encapsulating @tech{head
|
|
patterns} rather than @tech{single-term patterns}.
|
|
|
|
The options are the same as for @scheme[define-syntax-class].
|
|
|
|
Each variant of a splicing syntax class is specified as a separate
|
|
@scheme[pattern]-form whose syntax pattern is a @tech{head pattern}.
|
|
}
|
|
|
|
@defform[#:literals (pattern)
|
|
(pattern syntax-pattern pattern-directive ...)]{
|
|
|
|
Used to indicate a variant of a syntax class or splicing syntax
|
|
class. The variant accepts syntax matching the given syntax pattern
|
|
with the accompanying @tech{pattern directives}.
|
|
|
|
When used within @scheme[define-syntax-class], @scheme[syntax-pattern]
|
|
should be a @tech{single-term pattern}; within
|
|
@scheme[define-splicing-syntax-class], it should be a @tech{head
|
|
pattern}.
|
|
|
|
The attributes of the variant are the attributes of the pattern
|
|
together with all attributes bound by @scheme[#:with] clauses,
|
|
including nested attributes produced by syntax classes associated with
|
|
the pattern variables.
|
|
}
|
|
|
|
@;{--------}
|
|
|
|
@subsection{Pattern directives}
|
|
|
|
Both the parsing forms and syntax class definition forms support
|
|
@deftech{pattern directives} for annotating syntax patterns and
|
|
specifying side conditions. The grammar for pattern directives
|
|
follows:
|
|
|
|
@schemegrammar[pattern-directive
|
|
(code:line #:declare pattern-id syntax-class-id)
|
|
(code:line #:declare pattern-id (syntax-class-id expr ...))
|
|
(code:line #:with syntax-pattern expr)
|
|
(code:line #:attr attr-id expr)
|
|
(code:line #:fail-when condition-expr message-expr)
|
|
(code:line #:fail-unless condition-expr message-expr)
|
|
(code:line #:when condition-expr)]
|
|
|
|
@specsubform[(code:line #:declare pvar-id syntax-class-id)]
|
|
@specsubform[(code:line #:declare pvar-id (syntax-class-id expr ...))]{
|
|
|
|
The first form is equivalent to using the
|
|
@svar[pvar-id:syntax-class-id] form in the pattern (but it is illegal
|
|
to use both for the same pattern variable).
|
|
|
|
The second form allows the use of parameterized syntax classes, which
|
|
cannot be expressed using the ``colon'' notation. The @scheme[expr]s
|
|
are evaluated outside the scope of any of the attribute bindings from
|
|
pattern that the @scheme[#:declare] directive applies to.
|
|
|
|
}
|
|
|
|
@specsubform[(code:line #:with syntax-pattern stx-expr)]{
|
|
|
|
Evaluates the @scheme[stx-expr] in the context of all previous
|
|
attribute bindings and matches it against the pattern. If the match
|
|
succeeds, the pattern's attributes are added to environment for the
|
|
evaluation of subsequent side conditions. If the @scheme[#:with] match
|
|
fails, the matching process backtracks. Since a syntax object may
|
|
match a pattern in several ways, backtracking may cause the same
|
|
clause to be tried multiple times before the next clause is reached.
|
|
}
|
|
|
|
@specsubform[(code:line #:attr attr-id expr)]{
|
|
|
|
Evaluates the @scheme[expr] in the context of all previous attribute
|
|
bindings and binds it to the attribute named by @scheme[attr-id]. The
|
|
value of @scheme[expr] need not be syntax.
|
|
}
|
|
|
|
@specsubform[(code:line #:fail-when condition-expr message-expr)]{
|
|
|
|
Evaluates the @scheme[condition-expr] in the context of all previous
|
|
attribute bindings. If the value is any true value (not @scheme[#f]),
|
|
the matching process backtracks (with the given message); otherwise,
|
|
it continues. If the value of the condition expression is a syntax
|
|
object, it is indicated as the cause of the error.
|
|
}
|
|
|
|
@specsubform[(code:line #:fail-unless condition-expr message-expr)]{
|
|
|
|
Like @scheme[#:fail-when] with the condition negated.
|
|
}
|
|
|
|
@specsubform[(code:line #:when condition-expr)]{
|
|
|
|
Evaluates the @scheme[condition-expr] in the context of all previous
|
|
attribute bindings. If the value is @scheme[#f], the matching process
|
|
backtracks. In other words, @scheme[#:when] is like
|
|
@scheme[#:fail-unless] without the message argument.
|
|
|
|
}
|
|
|
|
|
|
@;{----------}
|
|
|
|
@subsection{Pattern variables and attributes}
|
|
|
|
An @deftech{attribute} is a name bound by a syntax pattern. An
|
|
attribute can be a @tech{pattern variable} itself, or it can be a
|
|
@tech{nested attribute} bound by an @tech{annotated pattern
|
|
variable}. The name of a nested attribute is computed by concatenating
|
|
the pattern variable name with the syntax class's exported attribute's
|
|
name, separated by a dot (see the example below).
|
|
|
|
Attribute names cannot be used directly as expressions; that is,
|
|
attributes are not variables. Instead, an attribute's value can be
|
|
gotten using the @scheme[attribute] special form.
|
|
|
|
@defform[(attribute attr-id)]{
|
|
|
|
Returns the value associated with the attribute named
|
|
@scheme[attr-id]. If @scheme[attr-id] is not bound as an attribute, an
|
|
error is raised.
|
|
}
|
|
|
|
The value of an attribute need not be syntax. Non-syntax-valued
|
|
attributes can be used to return a parsed representation of a subterm
|
|
or the results of an analysis on the subterm. A non-syntax-valued
|
|
attribute should be bound using the @scheme[#:attr] directive or a
|
|
@scheme[~bind] pattern.
|
|
|
|
@myexamples[
|
|
(define-syntax-class table
|
|
(pattern ((key value) ...)
|
|
#:attr hash
|
|
(for/hash ([k (syntax->datum #'(key ...))]
|
|
[v (syntax->datum #'(value ...))])
|
|
(values k v))))
|
|
(syntax-parse #'((a 1) (b 2) (c 3))
|
|
[t:table
|
|
(attribute t.hash)])
|
|
]
|
|
|
|
A syntax-valued attribute is an attribute whose value is a syntax
|
|
object or a syntax list of the appropriate @tech{ellipsis
|
|
depth}. Syntax-valued attributes can be used within @scheme[syntax],
|
|
@scheme[quasisyntax], etc as part of a syntax template. If a
|
|
non-syntax-valued attribute is used in a syntax template, a runtime
|
|
error is signalled.
|
|
|
|
@myexamples[
|
|
(syntax-parse #'((a 1) (b 2) (c 3))
|
|
[t:table
|
|
#'(t.key ...)])
|
|
(syntax-parse #'((a 1) (b 2) (c 3))
|
|
[t:table
|
|
#'t.hash])
|
|
]
|
|
|
|
Every attribute has an associated @deftech{ellipsis depth} that
|
|
determines how it can be used in a syntax template (see the discussion
|
|
of ellipses in @scheme[syntax]). For a pattern variable, the ellipsis
|
|
depth is the number of ellipses the pattern variable ``occurs under''
|
|
in the pattern. For a nested attribute the depth is the sum of the
|
|
pattern variable's depth and the depth of the attribute in the syntax
|
|
class. Consider the following code:
|
|
|
|
@schemeblock[
|
|
(define-syntax-class quark
|
|
(pattern (a b ...)))
|
|
(syntax-parse some-term
|
|
[(x (y:quark ...) ... z:quark)
|
|
some-code])
|
|
]
|
|
|
|
The syntax class @scheme[quark] exports two attributes: @scheme[a] at
|
|
depth 0 and @scheme[b] at depth 1. The @scheme[syntax-parse] pattern
|
|
has three pattern variables: @scheme[x] at depth 0, @scheme[y] at
|
|
depth 2, and @scheme[z] at depth 0. Since @scheme[x] and @scheme[y]
|
|
are annotated with the @scheme[quark] syntax class, the pattern also
|
|
binds the following nested attributes: @scheme[y.a] at depth 2,
|
|
@scheme[y.b] at depth 3, @scheme[z.a] at depth 0, and @scheme[z.b] at
|
|
depth 1.
|
|
|
|
An attribute's ellipsis nesting depth is @emph{not} a guarantee that
|
|
its value has that level of list nesting. In particular, @scheme[~or]
|
|
and @scheme[~optional] patterns may result in attributes with fewer
|
|
than expected levels of list nesting.
|
|
|
|
@(myexamples
|
|
(syntax-parse #'(1 2 3)
|
|
[(~or (x:id ...) _)
|
|
(attribute x)]))
|
|
|
|
|
|
@;{--------}
|
|
|
|
@subsection{Inspection tools}
|
|
|
|
The following special forms are for debugging syntax classes.
|
|
|
|
@defform[(syntax-class-attributes syntax-class-id)]{
|
|
|
|
Returns a list of the syntax class's attributes. Each attribute is
|
|
listed by its name and ellipsis depth.
|
|
}
|
|
|
|
@defform[(syntax-class-parse syntax-class-id stx-expr arg-expr ...)]{
|
|
|
|
Runs the parser for the syntax class (parameterized by the
|
|
@scheme[arg-expr]s) on the syntax object produced by
|
|
@scheme[stx-expr]. On success, the result is a list of vectors
|
|
representing the attribute bindings of the syntax class. Each vector
|
|
contains the attribute name, depth, and associated value. On failure,
|
|
the result is some internal representation of the failure.
|
|
}
|
|
|
|
|
|
@;{----------}
|
|
|
|
@include-section["parse-patterns.scrbl"]
|
|
|
|
|
|
@;{----------}
|
|
|
|
@section{Literal sets and Conventions}
|
|
|
|
Sometimes the same literals are recognized in a number of different
|
|
places. The most common example is the literals for fully expanded
|
|
programs, which are used in many analysis and transformation
|
|
tools. Specifying literals individually is burdensome and error-prone.
|
|
As a remedy, @schememodname[syntax/parse] offers @deftech{literal
|
|
sets}. A literal set is defined via @scheme[define-literal-set] and
|
|
used via the @scheme[#:literal-set] option of @scheme[syntax-parse].
|
|
|
|
@defform/subs[(define-literal-set name-id (literal ...))
|
|
([literal literal-id
|
|
(pattern-id literal-id)])]{
|
|
|
|
Defines @scheme[name] as a @tech{literal set}. Each @scheme[literal]
|
|
can have a separate @scheme[pattern-id] and @scheme[literal-id]. The
|
|
@scheme[pattern-id] determines what identifiers in the pattern are
|
|
treated as literals. The @scheme[literal-id] determines what
|
|
identifiers the literal matches.
|
|
|
|
@myexamples[
|
|
(define-literal-set def-litset
|
|
(define-values define-syntaxes))
|
|
(syntax-parse #'(define-syntaxes (x) 12)
|
|
#:literal-sets (def-litset)
|
|
[(define-values (x:id ...) e:expr) 'v]
|
|
[(define-syntaxes (x:id ...) e:expr) 's])
|
|
]
|
|
|
|
The literals in a literal set always refer to the phase-0 bindings of
|
|
the enclosing module. For example:
|
|
|
|
@myexamples[
|
|
(module common racket/base
|
|
(define x 'something)
|
|
(provide x))
|
|
|
|
(module lits racket/base
|
|
(require syntax/parse 'common)
|
|
(define-literal-set common-lits (x))
|
|
(provide common-lits))
|
|
]
|
|
|
|
In the literal set @scheme[common-lits], the literal @scheme[x] always
|
|
recognizes identifiers bound to the variable @scheme[x] defined in
|
|
module @schememodname['common].
|
|
|
|
When a literal set is used with the @scheme[#: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[
|
|
(require syntax/parse 'lits (for-syntax 'common))
|
|
(syntax-parse #'x #:literal-sets ([common-lits #:phase 1])
|
|
[x 'yes]
|
|
[_ 'no])
|
|
]
|
|
|
|
The occurrence of @scheme[x] in the pattern matches any identifier
|
|
whose binding at phase 1 is the @scheme[x] from module
|
|
@schememodname['common].
|
|
}
|
|
|
|
@defform/subs[(define-conventions name-id convention-rule ...)
|
|
([convention-rule (name-pattern syntax-class)]
|
|
[name-pattern exact-id
|
|
name-rx]
|
|
[syntax-class syntax-class-id
|
|
(syntax-class-id expr ...)])]{
|
|
|
|
Defines @deftech{conventions} that supply default syntax classes for
|
|
pattern variables. A pattern variable that has no explicit syntax
|
|
class is checked against each @scheme[id-pattern], and the first one
|
|
that matches determines the syntax class for the pattern. If no
|
|
@scheme[id-pattern] matches, then the pattern variable has no syntax
|
|
class.
|
|
|
|
@myexamples[
|
|
(define-conventions xyz-as-ids
|
|
[x id] [y id] [z id])
|
|
(syntax-parse #'(a b c 1 2 3)
|
|
#:conventions (xyz-as-ids)
|
|
[(x ... n ...) (syntax->datum #'(x ...))])
|
|
(define-conventions xn-prefixes
|
|
[#rx"^x" id]
|
|
[#rx"^n" nat])
|
|
(syntax-parse #'(a b c 1 2 3)
|
|
#:conventions (xn-prefixes)
|
|
[(x0 x ... n0 n ...)
|
|
(syntax->datum #'(x0 (x ...) n0 (n ...)))])
|
|
]
|
|
|
|
Local conventions, introduced with the @scheme[#:local-conventions]
|
|
keyword argument of @scheme[syntax-parse] and syntax class
|
|
definitions, may refer to local bindings:
|
|
|
|
@myexamples[
|
|
(define-syntax-class (nat> bound)
|
|
(pattern n:nat
|
|
#:fail-unless (> (syntax-e #'n) bound)
|
|
(format "expected number > ~s" bound)))
|
|
|
|
(define-syntax-class (natlist> bound)
|
|
#:local-conventions ([N (nat> bound)])
|
|
(pattern (N ...)))
|
|
|
|
(define (parse-natlist> bound x)
|
|
(syntax-parse x
|
|
#:local-conventions ([NS (natlist> bound)])
|
|
[NS 'ok]))
|
|
(parse-natlist> 0 #'(1 2 3))
|
|
(parse-natlist> 5 #'(8 6 4 2))
|
|
]
|
|
|
|
}
|
|
|
|
@;{----------}
|
|
|
|
@section[#:tag "lib"]{Library syntax classes and literal sets}
|
|
|
|
@subsection{Syntax classes}
|
|
|
|
@(begin
|
|
(define-syntax-rule (defstxclass name . pre-flows)
|
|
(defidform name . pre-flows))
|
|
(define-syntax-rule (defstxclass* (name arg ...) . pre-flows)
|
|
(defform (name arg ...) . pre-flows)))
|
|
|
|
@defstxclass[expr]{
|
|
|
|
Matches anything except a keyword literal (to distinguish expressions
|
|
from the start of a keyword argument sequence). The term is not
|
|
otherwise inspected, and no guarantee is made that the term is
|
|
actually a valid expression.
|
|
|
|
}
|
|
|
|
@deftogether[(
|
|
@defstxclass[identifier]
|
|
@defstxclass[boolean]
|
|
@defstxclass[str]
|
|
@defstxclass[char]
|
|
@defstxclass[keyword]
|
|
@defstxclass[number]
|
|
@defstxclass[integer]
|
|
@defstxclass[exact-integer]
|
|
@defstxclass[exact-nonnegative-integer]
|
|
@defstxclass[exact-positive-integer])]{
|
|
|
|
Match syntax satisfying the corresponding predicates.
|
|
|
|
}
|
|
|
|
@defstxclass[id]{ Alias for @scheme[identifier]. }
|
|
@defstxclass[nat]{ Alias for @scheme[exact-nonnegative-integer]. }
|
|
|
|
@defform[(static predicate description)]{
|
|
|
|
Matches an identifier that is bound in the syntactic environment to
|
|
static information (see @scheme[syntax-local-value]) satisfying the
|
|
given @scheme[predicate]. If the term does not match, the
|
|
@scheme[description] argument is used to describe the expected syntax.
|
|
|
|
When used outside of the dynamic extent of a macro transformer (see
|
|
@scheme[syntax-transforming?]), matching fails.
|
|
|
|
The attribute @var[value] contains the value the name is bound to.
|
|
}
|
|
|
|
@defform[(atom-in-list atoms description)]{
|
|
|
|
Matches a syntax object whose inner datum is @scheme[eqv?] to some
|
|
atom in the given list.
|
|
|
|
Use @scheme[atom-in-list] instead of a literals list when recognizing
|
|
identifier based on their symbolic names rather than their bindings.
|
|
|
|
}
|
|
|
|
|
|
@subsection{Literal sets}
|
|
|
|
@defidform[kernel-literals]{
|
|
|
|
Literal set containing the identifiers for fully-expanded code
|
|
(@secref[#:doc '(lib "scribblings/reference/reference.scrbl")
|
|
"fully-expanded"]). The set contains all of the forms listed by
|
|
@scheme[kernel-form-identifier-list], plus @scheme[module],
|
|
@scheme[#%plain-module-begin], @scheme[#%require], and
|
|
@scheme[#%provide].
|
|
|
|
Note that the literal-set uses the names @scheme[#%plain-lambda] and
|
|
@scheme[#%plain-app], not @scheme[lambda] and @scheme[#%app].
|
|
}
|