On this page:
syntax-parse
syntax-parser
define/  syntax-parse

1.3 Parsing Syntax

This section describes syntax-parse, the syntax/parse library’s facility for parsing syntax. Both syntax-parse and the specification facility, syntax classes, use a common language of syntax patterns, which is described in detail in Syntax Patterns.

Two parsing forms are provided: syntax-parse and syntax-parser.

syntax

(syntax-parse stx-expr parse-option ... clause ...+)

 
parse-option = #:context context-expr
  | #:literals (literal ...)
  | #:datum-literals (datum-literal ...)
  | #:literal-sets (literal-set ...)
  | #:track-literals
  | #:conventions (convention-id ...)
  | #:local-conventions (convention-rule ...)
  | #: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 = #:at context-id
  | #:phase phase-expr
     
clause = (syntax-pattern pattern-directive ... body ...+)
 
  stx-expr : syntax?
  context-expr : 
(or/c syntax? symbol? #f
      (list/c symbol? syntax?))
  phase-expr : (or/c exact-integer? #f)
Evaluates stx-expr, which should produce a syntax object, and matches it against the clauses 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 expr is evaluated. The result is the result of expr.

Each clause consists of a syntax pattern, an optional sequence of 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:

#:context context-expr
 
  context-expr : 
(or/c syntax? symbol? #f
      (list/c symbol? syntax?))

When present, context-expr is used in reporting parse failures; otherwise stx-expr is used. If context-expr evaluates to (list who context-stx), then who appears in the error message as the form raising the error, and context-stx is used as the term. If context-expr evaluates to a symbol, it is used as who and stx-expr (the syntax to be destructured) is used as context-stx. If context-expr evaluates to a syntax object, it is used as context-stx and who is inferred as with raise-syntax-error.

The current-syntax-context parameter is also set to the syntax object context-stx.

Examples:
> (syntax-parse #'(a b 3)
    [(x:id ...) 'ok])

a: expected identifier

  at: 3

  in: (a b 3)

> (syntax-parse #'(a b 3)
    #:context #'(lambda (a b 3) (+ a b))
    [(x:id ...) 'ok])

lambda: expected identifier

  at: 3

  in: (lambda (a b 3) (+ a b))

> (syntax-parse #'(a b 3)
    #:context 'check-id-list
    [(x:id ...) 'ok])

check-id-list: expected identifier

  at: 3

  in: (a b 3)

#:literals (literal ...)
 
literal = literal-id
  | (pattern-id literal-id)
  | (pattern-id literal-id #:phase phase-expr)
 
  phase-expr : (or/c exact-integer? #f)

Unlike syntax-case, syntax-parse requires all literals to have a binding. To match identifiers by their symbolic names, use #:datum-literals or the ~datum pattern form instead. The #:literals option specifies identifiers that should be treated as literals rather than pattern variables. An entry in the literals list has two components: the identifier used within the pattern to signify the positions to be matched (pattern-id), and the identifier expected to occur in those positions (literal-id). If the entry is a single identifier, that identifier is used for both purposes.

If the #:phase option is given, then the literal is compared at phase phase-expr. Specifically, the binding of the literal-id at phase phase-expr must match the input’s binding at phase phase-expr.

In other words, the syntax-patterns are interpreted as if each occurrence of pattern-id were replaced with the following pattern:

(~literal literal-id #:phase phase-expr)

#:datum-literals (datum-literal ...)
 
datum-literal = literal-id
  | (pattern-id literal-id)

Like #:literals, but the literals are matched as symbols instead of as identifiers.

In other words, the syntax-patterns are interpreted as if each occurrence of pattern-id were replaced with the following pattern:

(~datum literal-id)

#:literal-sets (literal-set ...)
 
literal-set = literal-set-id
  | (literal-set-id literal-set-option ...)
     
literal-set-option = #:at lctx
  | #:phase phase-expr
 
  phase-expr : (or/c exact-integer? #f)

Many literals can be declared at once via one or more literal sets, imported with the #:literal-sets option. See literal sets for more information.

If the #:at keyword is given, the lexical context of the lctx term is used to determine which identifiers in the patterns are treated as literals; this option is useful primarily for macros that generate syntax-parse expressions.

#:track-literals

If specified, each final body expression is further constrained to produce a single value, which must be a syntax object, and its 'disappeared-use syntax property is automatically extended to include literals matched as part of pattern-matching. Literals are automatically tracked from uses of #:literals, #:literal-sets, or ~literal, but they can also be manually tracked using syntax-parse-state-cons!. The property is added or extended in the same way as a property added by syntax-parse-track-literals.

Due to the way the body forms are wrapped, specifying this option means the final body form will no longer be in tail position with respect to the enclosing syntax-parse form.

Added in version 6.90.0.29 of package base.

#:conventions (conventions-id ...)

Imports conventions that give default syntax classes to pattern variables that do not explicitly specify a syntax class.

#:local-conventions (convention-rule ...)

Uses the conventions specified. The advantage of #:local-conventions over #:conventions is that local conventions can be in the scope of syntax-class parameter bindings. See the section on conventions for examples.

#:disable-colon-notation

Suppresses the “colon notation” for annotated pattern variables.

Examples:
> (syntax-parse #'(a b c)
    [(x:y ...) 'ok])

syntax-parse: not defined as syntax class

  at: y

  in: (syntax-parse (syntax (a b c)) ((x:y ...) (quote ok)))

> (syntax-parse #'(a b c) #:disable-colon-notation
    [(x:y ...) 'ok])

'ok

syntax

(syntax-parser parse-option ... clause ...+)

Like syntax-parse, but produces a matching procedure. The procedure accepts a single argument, which should be a syntax object.

syntax

(define/syntax-parse syntax-pattern pattern-directive ... stx-expr)

 
  stx-expr : syntax?
Definition form of syntax-parse. That is, it matches the syntax object result of stx-expr against syntax-pattern and creates pattern variable definitions for the attributes of syntax-pattern.

Examples:
> (define/syntax-parse ((~seq kw:keyword arg:expr) ...)
    #'(#:a 1 #:b 2 #:c 3))
> #'(kw ...)

#<syntax:eval:7:0 (#:a #:b #:c)>

Compare with define/with-syntax, a similar definition form that uses the simpler syntax-case patterns.