188 lines
7.2 KiB
Racket
188 lines
7.2 KiB
Racket
#lang scribble/doc
|
|
@(require scribble/manual
|
|
scribble/struct
|
|
scribble/decode
|
|
scribble/eval
|
|
"parse-common.rkt"
|
|
(for-label racket/syntax))
|
|
|
|
@title{Parsing Syntax}
|
|
|
|
This section describes @racket[syntax-parse], the
|
|
@racketmodname[syntax/parse] library's facility for parsing
|
|
syntax. Both @racket[syntax-parse] and the specification facility,
|
|
@seclink["stxparse-specifying"]{syntax classes}, use a common language
|
|
of @tech{syntax patterns}, which is described in detail in
|
|
@secref{stxparse-patterns}.
|
|
|
|
@declare-exporting[syntax/parse]
|
|
|
|
Two parsing forms are provided: @racket[syntax-parse] and
|
|
@racket[syntax-parser].
|
|
|
|
@defform/subs[(syntax-parse stx-expr parse-option ... clause ...+)
|
|
([parse-option (code:line #:context context-expr)
|
|
(code:line #:literals (literal ...))
|
|
(code:line #:datum-literals (datum-literal ...))
|
|
(code:line #:literal-sets (literal-set ...))
|
|
(code:line #:conventions (convention-id ...))
|
|
(code:line #:local-conventions (convention-rule ...))
|
|
(code:line #:disable-colon-notation)]
|
|
[literal literal-id
|
|
(pattern-id literal-id)
|
|
(pattern-id literal-id #:phase phase-expr)]
|
|
[datum-literal literal-id
|
|
(pattern-id literal-id)]
|
|
[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 ... body ...+)])
|
|
#:contracts ([stx-expr syntax?]
|
|
[context-expr syntax?]
|
|
[phase-expr (or/c exact-integer? #f)])]{
|
|
|
|
Evaluates @racket[stx-expr], which should produce a syntax object, and
|
|
matches it against the @racket[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
|
|
@racket[expr] is evaluated. The result is the result of @racket[expr].
|
|
|
|
Each clause consists of a @tech{syntax pattern}, an optional sequence
|
|
of @tech{pattern directives}, and a non-empty sequence of body
|
|
forms.
|
|
|
|
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, @racket[context-expr] is used in reporting parse
|
|
failures; otherwise @racket[stx-expr] is used. The
|
|
@racket[current-syntax-context] parameter is also set to the value of
|
|
@racket[context-expr].
|
|
|
|
@(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)])
|
|
#:contracts ([phase-expr (or/c exact-integer? #f)])]{
|
|
|
|
@margin-note*{
|
|
Unlike @racket[syntax-case], @racket[syntax-parse] requires all
|
|
literals to have a binding. To match identifiers by their symbolic
|
|
names, use @racket[#:datum-literals] or the @racket[~datum] pattern
|
|
form instead.
|
|
}
|
|
@;
|
|
The @racket[#: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
|
|
(@racket[pattern-id]), and the identifier expected to occur in those
|
|
positions (@racket[literal-id]). If the entry is a single identifier,
|
|
that identifier is used for both purposes.
|
|
|
|
If the @racket[#:phase] option is given, then the literal is compared
|
|
at phase @racket[phase-expr]. Specifically, the binding of the
|
|
@racket[literal-id] at phase @racket[phase-expr] must match the
|
|
input's binding at phase @racket[phase-expr].
|
|
|
|
In other words, the @racket[syntax-pattern]s are interpreted as if each
|
|
occurrence of @racket[pattern-id] were replaced with the following pattern:
|
|
@racketblock[(~literal literal-id #:phase phase-expr)]
|
|
}
|
|
|
|
@specsubform/subs[(code:line #:datum-literals (datum-literal ...))
|
|
([datum-literal literal-id
|
|
(pattern-id literal-id)])]{
|
|
|
|
Like @racket[#:literals], but the literals are matched as symbols
|
|
instead of as identifiers.
|
|
|
|
In other words, the @racket[syntax-pattern]s are interpreted as if each
|
|
occurrence of @racket[pattern-id] were replaced with the following
|
|
pattern:
|
|
@racketblock[(~datum literal-id)]
|
|
}
|
|
|
|
@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 lctx)
|
|
(code:line #:phase phase-expr)])
|
|
#:contracts ([phase-expr (or/c exact-integer? #f)])]{
|
|
|
|
Many literals can be declared at once via one or more @tech{literal
|
|
sets}, imported with the @racket[#:literal-sets] option. See
|
|
@tech{literal sets} for more information.
|
|
|
|
If the @racket[#:at] keyword is given, the lexical context of the
|
|
@racket[lctx] term is used to determine which identifiers in the
|
|
patterns are treated as literals; this option is useful primarily for
|
|
macros that generate @racket[syntax-parse] expressions.
|
|
}
|
|
|
|
@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
|
|
@racket[#:local-conventions] over @racket[#:conventions] is that local
|
|
conventions can be in the scope of syntax-class parameter
|
|
bindings. See the section on @tech{conventions} for examples.
|
|
}
|
|
|
|
@specsubform[(code:line #:disable-colon-notation)]{
|
|
|
|
Suppresses the ``colon notation'' for annotated pattern variables.
|
|
|
|
@myexamples[
|
|
(syntax-parse #'(a b c)
|
|
[(x:y ...) 'ok])
|
|
(syntax-parse #'(a b c) #:disable-colon-notation
|
|
[(x:y ...) 'ok])
|
|
]
|
|
}
|
|
}
|
|
|
|
@defform[(syntax-parser parse-option ... clause ...+)]{
|
|
|
|
Like @racket[syntax-parse], but produces a matching procedure. The
|
|
procedure accepts a single argument, which should be a syntax object.
|
|
}
|
|
|
|
@defform[(define/syntax-parse syntax-pattern pattern-directive ... stx-expr)
|
|
#:contracts ([stx-expr syntax?])]{
|
|
|
|
Definition form of @racket[syntax-parse]. That is, it matches the
|
|
syntax object result of @racket[stx-expr] against
|
|
@racket[syntax-pattern] and creates pattern variable definitions for
|
|
the attributes of @racket[syntax-pattern].
|
|
|
|
@myexamples[
|
|
(define/syntax-parse ((~seq kw:keyword arg:expr) ...)
|
|
#'(#:a 1 #:b 2 #:c 3))
|
|
#'(kw ...)
|
|
]
|
|
|
|
Compare with @racket[define/with-syntax], a similar definition form
|
|
that uses the simpler @racket[syntax-case] patterns.
|
|
}
|