racket/collects/stxclass/scribblings/syntax-classes.scrbl
Ryan Culpepper 44efc7cb48 stxclass:
fixed scoping of attributes (wrt declare)
  added 'attribute' form
  added internal/external literals form

svn: r13574
2009-02-14 12:17:14 +00:00

226 lines
8.5 KiB
Racket

#lang scribble/doc
@(require scribble/manual
scribble/struct
scribble/decode
(for-label scheme/base
scheme/contract
stxclass
stxclass/util))
@(define ellipses @scheme[...])
@(define (TODO . pre-flow)
(make-splice
(cons (bold "TODO: ")
(decode-content pre-flow))))
@title{Syntax Classes}
@declare-exporting[stxclass]
Syntax classes provide an abstraction mechanism for the specification
of syntax. Basic syntax classes include @scheme[identifier] and
@scheme[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
@scheme[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.
@defform*/subs[#:literals (pattern basic-syntax-class)
[(define-syntax-class name-id stxclass-option ...
stxclass-body)
(define-syntax-class (name-id arg-id ...) stxclass-option ...
stxclass-body)]
([stxclass-options
(code:line #:attributes (attr-arity-decl ...))
(code:line #:description description)
(code:line #:transparent)
(code:line #:literals (literal-entry ...))]
[attr-arity-decl
attr-name-id
(attr-name-id depth)]
[stxclass-body
(code:line (pattern syntax-pattern stxclass-pattern-directive ...) ...+)
(code:line (basic-syntax-class parser-expr))])]{
Defines @scheme[name-id] as a syntax class. When the @scheme[arg-id]s
are present, they are bound as variables (not pattern variables) in
the body. The body of the syntax-class definition contains either one
@scheme[basic-syntax-class] clause or a non-empty sequence of
@scheme[pattern] clauses.
@specsubform[(code:line #: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
@techlink{attribute inference}.
}
@specsubform[(code:line #:description description)]{
The @scheme[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 @scheme["expected <description>"] may be generated.
If absent, the name of the syntax class is used instead.
}
@specsubform[#:transparent]{
Indicates that errors may be reported with respect to the internal
structure of the syntax class.
}
@specsubform[(code:line #:literals (literal-entry))]{
Declares the literal identifiers for the syntax class's main patterns
(immediately within @scheme[pattern] variants) and @scheme[#:with]
clauses. The literals list does not affect patterns that occur within
subexpressions inside the syntax class (for example, the condition of
a @scheme[#:when] clause or the right-hand side of a @scheme[#:with]
binding).
A literal can have separate internal and external names, as described
for @scheme[syntax-parse].
}
@specsubform/subs[#:literals (pattern)
(pattern syntax-pattern stxclass-pattern-directive ...)
([stxclass-pattern-directive
pattern-directive
(code:line #:rename internal-id external-id)])]{
Accepts syntax matching the given pattern with the accompanying
pattern directives as in @scheme[syntax-parse].
The attributes of the pattern are the pattern variables within the
@scheme[pattern] form together with all pattern variables bound by
@scheme[#: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 @scheme[#:rename]
clause.
@specsubform[(code:line #:rename internal-id external-id)]{
Exports the pattern variable binding named by @scheme[internal-id] as
the attribute named @scheme[external-id].
}
}
@specsubform[#:literals (basic-syntax-class)
(basic-syntax-class parser-expr)]{
The @scheme[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 @scheme[define-syntax-class] level are not bound within the
@scheme[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 @scheme[#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.}
}
}
@defidform[pattern]{
Keyword recognized by @scheme[define-syntax-class]. It may not be
used as an expression.
}
@defidform[basic-syntax-class]{
Keyword recognized by @scheme[define-syntax-class]. It may not be used
as an expression.
}
@section{Attributes}
A syntax class has a set of @deftech{attribute}s. 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 @scheme[p] is bound to an instance of
a syntax class with attribute @scheme[a], then the pattern variable
@scheme[p.a] is bound to the value of that attribute. The ellipsis
depth of @scheme[p.a] is the sum of the depths of @scheme[p] and
attribute @scheme[a].
If the attributes are not declared explicitly, they are computed via
@deftech{attribute inference}. For ``basic'' syntax classes, the
inferred attribute list is always empty. For compound syntax classes,
each @scheme[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 @scheme[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 @scheme[#: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.
@section{Inspection tools}
The following special forms are for debugging syntax classes.
@defform[(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.
}
@defform[(syntax-class-parse syntax-class-id stx-expr arg-expr ...)]{
Runs the parser for the syntax class (parameterized by the
@scheme[arg-expr]s) on the syntax object produced by
@scheme[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.
}