On this page:
define-syntax-class
pattern
basic-syntax-class
2.1 Attributes
2.2 Inspection tools
syntax-class-attributes
syntax-class-parse
Version: 4.1.5

2 Syntax Classes

Syntax classes provide an abstraction mechanism for the specification of syntax. Basic syntax classes include identifier and keyword. More generally, a programmer can define a “basic” syntax from an arbitrary predicate, although syntax classes thus defined lose some of the benefits of declarative specification of syntactic structure.

Programmers can also 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. The structure of syntax classes and patterns also allows syntax-parse to automatically generate error messages for syntax errors.

When a syntax class accepts (matches, includes) a syntax object, it computes and provides attributes based on the contents of the matched syntax. While the values of the attributes depend on the matched syntax, the set of attributes and each attribute’s ellipsis nesting depth is fixed for each syntax class.

(define-syntax-class name-id stxclass-option ...
  stxclass-body)
(define-syntax-class (name-id arg-id ...) stxclass-option ...
  stxclass-body)
 
stxclass-options = #:attributes (attr-arity-decl ...)
  | #:description description
  | #:transparent
  | #:literals (literal-entry ...)
     
attr-arity-decl = attr-name-id
  | (attr-name-id depth)
     
stxclass-body = (pattern syntax-pattern stxclass-pattern-directive ...) ...+
  | (basic-syntax-class parser-expr)

Defines name-id as a syntax class. When the arg-ids are present, they are bound as variables (not pattern variables) in the body. The body of the syntax-class definition contains either one basic-syntax-class clause or a non-empty sequence of pattern clauses.

#:attributes (attr-arity-decl ...)

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 computed using attribute inference.

#:description description

The description argument is an expression (with the syntax-class’s parameters in scope) 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 "expected <description>" may be generated.

If absent, the name of the syntax class is used instead.

#:transparent

Indicates that errors may be reported with respect to the internal structure of the syntax class.

#:literals (literal-entry)

Declares the literal identifiers for the syntax class’s main patterns (immediately within pattern variants) and #:with clauses. The literals list does not affect patterns that occur within subexpressions inside the syntax class (for example, the condition of a #:when clause or the right-hand side of a #:with binding).

A literal can have separate internal and external names, as described for syntax-parse.

(pattern syntax-pattern stxclass-pattern-directive ...)
 
stxclass-pattern-directive = pattern-directive
  | #:rename internal-id external-id

Accepts syntax matching the given pattern with the accompanying pattern directives as in syntax-parse.

The attributes of the pattern are the pattern variables within the pattern form together with all pattern variables bound by #:with clauses, including nested attributes produced by syntax classes associated with the pattern variables.

The name of an attribute is the symbolic name of the pattern variable, except when the name is explicitly given via a #:rename clause.

#:rename internal-id external-id

Exports the pattern variable binding named by internal-id as the attribute named external-id.

(basic-syntax-class parser-expr)

The parser-expr must evaluate to a procedure. This procedure is used to parse or reject syntax objects. The arguments to the parser procedure consist of the syntax object to parse followed by the syntax-class parameterization arguments (the parameter names given at the define-syntax-class level are not bound within the parser-expr). To indicate success, the parser should return a list of attribute values, one for each attribute listed. (For example, a parser for a syntax class that defines no attributes returns the empty list when it succeeds.) To indicate failure, the parser procedure should return #f.

The parser procedure should avoid side-effects, as they interfere with the parsing process’s backtracking and error reporting.

TODO: Add support for better error reporting within basic syntax class.

pattern

Keyword recognized by define-syntax-class. It may not be used as an expression.

basic-syntax-class

Keyword recognized by define-syntax-class. It may not be used as an expression.

2.1 Attributes

A syntax class has a set of attributes. Each attribute has a name, an ellipsis depth, and a set of nested attributes. When an instance of the syntax class is parsed and bound to a pattern variable, additional pattern variables are bound for each of the syntax class’s attributes. The name of these additional pattern variables is the dotted concatenation of the the primary pattern variable with the name of the attribute.

For example, if pattern variable p is bound to an instance of a syntax class with attribute a, then the pattern variable p.a is bound to the value of that attribute. The ellipsis depth of p.a is the sum of the depths of p and attribute a.

If the attributes are not declared explicitly, they are computed via attribute inference. For “basic” syntax classes, the inferred attribute list is always empty. For compound syntax classes, each pattern form is analyzed to determine its candiate attributes. The attributes of the syntax class are the attributes common to all of the variants (that is, the intersection of the candidate attributes). An attribute must have the same ellipsis-depth in each of the variants; otherwise, an error is raised.

The candidate attributes of a pattern variant are the pattern variables bound by the variant’s pattern (including nested attributes contributed by their associated syntax classes) together with the pattern variables (and nested attributes) from #:with clauses.

For the purpose of attribute inference, recursive references to the same syntax class and forward references to syntax classes not yet defined do not contribute any nested attributes. This avoids various problems in computing attributes, including infinitely nested attributes.

2.2 Inspection tools

The following special forms are for debugging syntax classes.

(syntax-class-attributes syntax-class-id)

Returns a list of the syntax class’s attributes in flattened form. Each attribute is listed by its name and ellipsis depth.

(syntax-class-parse syntax-class-id stx-expr arg-expr ...)

Runs the parser for the syntax class (parameterized by the arg-exprs) on the syntax object produced by 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.