racket/collects/syntax/scribblings/parse/parsing.scrbl

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.
}