On this page:
syntax_  class
syntax_  class.together
fields
root_  swap
description
error_  mode
kind
field
match_  def
match_  when
match_  unless
Term
Identifier
Operator
Name
Identifier  Name
Keyword
String
Int
Group
Multi
Block
8.12

6.53 Syntax Classes🔗ℹ

definition

syntax_class id maybe_args:

  class_clause

  ...

| pattern_case

| ...

 

maybe_args

 = 

(id_bind, ...)

 | 

(id_bind, ..., & rest_id)

 | 

ϵ

 

class_clause

 = 

description desc_rhs

 | 

error_mode error_mode_rhs

 | 

kind kind_rhs

 | 

fields: field_decl

 | 

root_swap: id id

 

pattern_case

 = 

syntax_pattern

 | 

syntax_pattern: pattern_body; ...

 

pattern_body

 = 

field field_decl

 | 

match_def also_decl

 | 

match_when when_rhs

 | 

match_unless unless_rhs

 | 

body

Defines a syntax class that can be used in syntax patterns with ::. A syntax class can optionally have arguments, in which case every use of the syntax class with :: must supply arguments; an id_bind is like a bind_maybe_kw_opt for fun, but each binding must be a plain id (i.e., annotations and general pattern matching are not supported). Identifiers bound as arguments are visible in class_clause bodies. Use syntax_class.together to define a syntax class that refers to itself or a group of mutually referential syntax classes.

Syntax forms matched by the syntax class are described by pattern_case alternatives. Each kind of class_clause alternative can be supplied at most once.

An optional description clause provides a description of the syntax class, which is used to produce clearer error messages when a term is rejected by the syntax class. The result of the block block must be a string or #false, where #false is equivalent to not specifying a description. When error_mode is declared as ~opaque, then parsing error messages will not refer to the interior details of the pattern cases; insteda, messages will use the decsription string.

An optional kind declaration indicates the context within a pattern where a syntax class can be used, and it determines the kind of match that each pattern specifies. See kind for details. The default is inferred from the shapes for pattern_cases as either ~term, ~sequence, or ~multi.

A fields declaration limits the set of pattern variables that are accessible from the class, where variables used in all pattern_cases are otherwise available (as described next). Each identifier in fields must be a field name that would be made available. A fields declaration can also specify the repetition depth and context kind of a field, in which case pattern_cases must be consistent with the declaration; see fields for more information. A root_swap class moves the value of one of the would-be fields to the root while moving the root to a fresh feild; see root_swap for more information.

The pattern_case alternatives are the main content of a syntax class. After the class name is defined, then when a variable id is bound through a syntax pattern with $(id :: name), it matches a syntax object that matches any of the pattern_cases in the definition of stx_class_id, where the pattern_cases are tried first to last. A pattern variable that is included in all of the pattern_cases is a field of the syntax class, which is accessed from a binding id using dot notation. For example, if the pattern variable is var, its value is accessed from id using id.var.

A pattern_case matches when

Every pattern variable in the initial syntax_pattern of a pattern_case as well as evey variable in every match_def is a candiate field name, as long as it is also a candiate in all other syntax_patterns within the syntax class. In addition, names declared with field are also candidates. A field must have the same repetition depth across all pattern cases, unless it is excluded from the syntax class’s result through a fields declaration that does not list the field.

The body of a pattern_case can include other definitions and expressions. Those definitions and expressions can use pattern variables bound in the main syntax_pattern of the case as well as any preceding match_def clause or a field declared by a preceding field. Consecutive definitions and expressions within a pattern_case form a definition context, but separated sets of definitions and expressions can refer only to definitions in earlier sets.

A variable bound with a syntax class (within a syntax pattern) can be used without dot notation. The variable is bound to a syntax object corresponding to the entire match of a syntax_pattern.

> meta syntax_class Arithmetic

  | '$x + $y'

  | '$x - $y'

> expr.macro 'doubled_operands $(a :: Arithmetic)':

    '$a.x * 2 + $a.y * 2'

> doubled_operands 3 + 5

16

> expr.macro 'add_one_to_expression $(a :: Arithmetic)':

    '$a + 1'

> add_one_to_expression 2 + 2

5

> meta syntax_class NTerms

  | '~one $a':

      field b = '0'

      field average = '$(a.unwrap() / 2)'

  | '~two $a $b':

      def sum = a.unwrap() + b.unwrap()

      field average = '$(sum / 2)'

> expr.macro 'second_term $(e :: NTerms)':

    e.b

> second_term ~two 1 2

2

> second_term ~one 3

0

> expr.macro 'average $(e :: NTerms)':

    e.average

> average ~two 24 42

33

definition

syntax_class.together:

  syntax_class stxclass_decl

  ...

Declares syntax classes that can refer to themselves and each other. Unlike a syntax_class form in other contexts, each syntax_class form within syntax_class.together is required to declare its fields with fields, otherwise no fields are available from the syntax class.

syntax_class.together:

  syntax_class ModPath:

    fields: [elem, ...]

  | '$head':

      field [elem, ...]: [head]

  | '$head / $(mp :: ModPath)':

      field [elem, ...] = [head, mp.elem, ...]

> match 'a / b / c'

  | '$(mp :: ModPath)':

      [mp.elem, ...]

['a', 'b', 'c']

syntax class clause

fields spec ...

 

syntax class clause

fields: spec ...; ...

 

spec

 = 

id_maybe_rep

 | 

id_maybe_rep: kind kind_decl

 

id_maybe_rep

 = 

id

 | 

[id_maybe_rep, ellipsis]

 

ellipsis

 = 

...

Limits the set of fields that are provided by a syntax class to the listed ids. See syntax_class. A field’s repetition depth is declared by wrapping it within [] with ... like a repetition binding. If no spec is present at all, no fields will be provided.

If a kind is not declared for a field identifier, then the context kind is inferred from patterns within the syntax class. If kind is declared, then it must match the context kind that would be inferred for the field from all patterns.

syntax class clause

root_swap: id id

Adjusts the match value and fields of a syntax class. The first id names a field that the syntax class would otherwise provide, but the field is removed, and its value instead becomes the main value of an identifier that is bound with the syntax class. Meanwhile, the matching terms that would otherwise be the variable’s value are associated instead with a fresh field named by the second id.

syntax_class Parenthesized:

  root_swap: content group

| '($content)'

> match '(1 2 3)'

  | '$(p :: Parenthesized)':

      [p, p.group]

['1 2 3', '(1 2 3)']

syntax class clause

description:

  body;

  ...

 

syntax class clause

description expr

Configures a syntax class’s description for error reporting. See syntax_class.

syntax class clause

error_mode: error_mode_keyword

 

syntax class clause

error_mode error_mode_keyword

 

error_mode_keyword

 = 

~opaque

 | 

~transparent

Configures the way that failures to match a syntax class are reported. See syntax_class.

syntax class clause

kind: kind_keyword

 

syntax class clause

kind kind_keyword

 

kind_keyword

 = 

~term

 | 

~sequence

 | 

~group

 | 

~multi

 | 

~block

Provided both normally and as meta.

Determines the contexts where a syntax class can be used and the kinds of matches that it produces:

With ~term, each pattern case must match only a single term, and with ~block, each pattern case must be a block pattern.

See also syntax_class.

pattern clause

field id_maybe_rep:

  body

  ...

 

pattern clause

field id_maybe_rep = expr

 

id_maybe_rep

 = 

id

 | 

[id_maybe_rep, ellipsis]

 

ellipsis

 = 

...

Similar to def, but restricted to defining a plain identifier or a simple list repetition within a syntax_class pattern case, and adds a field (or, at least, a cadndidate field) to the pattern case.

The result of the right-hand body sequence or expr is not required to be a syntax object or have syntax objects in nested lists. If the field is referenced so that it’s value is included in a syntax template, a non-sytax value is converted to syntax at that point. Otherwise, the field can be used directly to access non-syntax values.

See also syntax_class.

pattern clause

match_def 'pattern':

  body

  ...

 

pattern clause

match_def 'pattern' = expr

Constrains a pattern case to match only when the right-hand body or expr matches pattern, and adds the pattern variables of pattern to the set of (candidate) syntax class fields.

See syntax_class.

pattern clause

match_when:

  body

  ...

 

pattern clause

match_when expr

 

pattern clause

match_unless:

  body

  ...

 

pattern clause

match_unless expr

Constrains a pattern case to match only when a body or expr produces a true value in the case of match_when or a false value in the case of match_unless.

See syntax_class.

syntax class

syntax_class Term: kind: ~term

 

syntax class

syntax_class Identifier: kind: ~term

 

syntax class

syntax_class Operator: kind: ~term

 

syntax class

syntax_class Name: kind: ~sequence

 

syntax class

syntax_class IdentifierName: kind: ~sequence

 

syntax class

syntax_class Keyword: kind: ~term

 

syntax class

syntax_class String: kind: ~term

 

syntax class

syntax_class Int: kind: ~term

 

syntax class

syntax_class Group: kind: ~group

 

syntax class

syntax_class Multi: kind: ~multi

 

syntax class

syntax_class Block: kind: ~block

Provided both normally and as meta.

Syntax classes, all of which imply a single-term match except for Group, Multi, and Block.

The Group syntax class can be used only for a pattern identifier that is at the end of its group in a pattern. The identifier is bound to a match for the entire tail of the group as a group syntax object.

The Multi syntax class can be used only for a pattern identifier that is the sole term where a sequence of groups is allowed, such as in the body of a block. The identifier is bound to a match for the entire sequence of groups.

The Block syntax class can be used only for a pattern identifier that is the sole term of a block. The identifier is bound to a match for the entire block as a single term (i.e., as a single-term syntax object that has a block term, and not as a multi-group syntax object).

The Name syntax class is an extension of the union of Identifier and Operator that matches dotted sequences like an op_or_id_name form.

The IdentifierName syntax class is an extension of Identifier that matches dotted sequences like an id_name form.