syntax/parse: worked on docs, fixed error reporting bug

svn: r15834
This commit is contained in:
Ryan Culpepper 2009-08-30 04:20:29 +00:00
parent 19de92f5fd
commit 93b6f59264
2 changed files with 99 additions and 82 deletions

View File

@ -144,7 +144,7 @@
#:no-duplicates? #t))
(define context
(let ([c (options-select-one chunks '#:context #:default #f)])
(if c (car c) #'#f)))
(if c (car c) #'x)))
(define-values (decls0 defs) (get-decls+defs chunks))
(define (for-clause clause)
(syntax-case clause ()
@ -162,7 +162,7 @@
(convert-sides x #,sides
(clause-success () (let () . rest)))))))]))
(unless (and (stx-list? clauses-stx) (stx-pair? clauses-stx))
(wrong-syntax clauses-stx "expected non-empty sequence of clauses"))
(raise-syntax-error #f "expected non-empty sequence of clauses" stx))
(with-syntax ([(def ...) defs]
[(alternative ...)
(map for-clause (stx->list clauses-stx))])
@ -177,22 +177,6 @@
(define-for-syntax (wash-literals stx)
(wash-list wash-literal stx))
#|
;; (parse:clause id ([id id] ...) Clause) : expr
(define-syntax (parse:clause stx)
(syntax-case stx ()
[(parse:clause x literals [p . rest])
(let-values ([(rest decls sides)
(parse-pattern-directives
#'rest #:decls (new-declenv (wash-literals #'literals)))])
(with-syntax ([rest rest]
[fc (empty-frontier #'x)]
[pattern (parse-whole-pattern #'p decls)])
#`(parse:S x fc pattern
(convert-sides x #,sides
(clause-success () (let () . rest))))))]))
|#
;; (clause-success (IAttr ...) expr) : expr
(define-syntax (clause-success stx)
(syntax-case stx ()

View File

@ -15,7 +15,8 @@
(define the-eval
(parameterize ((sandbox-output 'string)
(sandbox-error-output 'string))
(make-evaluator 'scheme/base #:requires '(syntax/parse))))
(make-evaluator 'scheme/base
#:requires '(syntax/parse (for-syntax scheme/base)))))
(define-syntax-rule (myexamples e ...)
(parameterize ((error-print-source-location #f))
(examples #:eval the-eval e ...))))
@ -81,7 +82,7 @@ default syntax classes to pattern variables that do not explicitly
specify a syntax class.
}
@defform[(syntax-parser maybe-literals clause ...)]{
@defform[(syntax-parser parse-option ... clause ...+)]{
Like @scheme[syntax-parse], but produces a matching procedure. The
procedure accepts a single argument, which should be a syntax object.
@ -152,9 +153,10 @@ Here are the variants of @tech{S-pattern}:
@specsubform[pvar-id]{
If @scheme[pvar-id] has no syntax class (by @scheme[#:declare] or
@scheme[#:convention]), the pattern matches anything. The pattern
variable is bound to the matched subterm, unless the pattern variable
is the wildcard (@scheme[_]), in which case no binding occurs.
@scheme[#:convention]), the pattern matches anything. The
@deftech{pattern variable} is bound to the matched subterm, unless the
pattern variable is the wildcard (@scheme[_]), in which case no
binding occurs.
If @scheme[pvar-id] does have an associated syntax class, it behaves
like the following form.
@ -261,7 +263,7 @@ See @tech{EH-patterns} for more information.
@specsubform[#:literals (~and) (~and S-pattern ...)]{
Matches any syntax that matches all of the included patterns.
Matches any term that matches all of the subpatterns.
Attributes bound in subpatterns are available to subsequent
subpatterns. The whole pattern binds all of the subpatterns'
@ -272,11 +274,12 @@ term (including its lexical context, source location, etc) while also
examining its structure. Syntax classes are useful for the same
purpose, but @scheme[~and] can be lighter weight.
@(interaction-eval #:eval the-eval
(begin (define import #f)
(define (check-imports . _) #f)))
@myexamples[
(define-syntax (import stx)
(raise-syntax-error #f "illegal use of import" stx))
(eval:alts
(define (check-imports stx) ....)
(define (check-imports . _) #f))
(syntax-parse #'(m (import one two))
#:literals (import)
[(_ (~and import-clause (import i ...)))
@ -292,7 +295,8 @@ purpose, but @scheme[~and] can be lighter weight.
@specsubform[#:literals (~or) (~or S-pattern ...)]{
Matches any term that matches one of the included patterns.
Matches any term that matches one of the included patterns. The
alternatives are tried in order.
The whole pattern binds @emph{all} of the subpatterns' attributes. An
attribute that is not bound by the ``chosen'' subpattern has a value
@ -462,6 +466,10 @@ Matches a head whose elements, if put in a list, would match the given
(syntax-parse #'(1 2 3 4)
[((~seq 1 2 3) 4) 'ok])
]
See also the section on @tech{EH-patterns} for more interesting
examples of @scheme[~seq].
}
@specsubform[#:literals (~or) (~or H-pattern ...)]{
@ -607,16 +615,6 @@ given message); otherwise, it continues.
}
@specsubform[(code:line #:attr attr-id expr)]{
Evaluates the @scheme[expr] in the context of all previous attribute
bindings and binds the result to the attribute @scheme[attr-id]. The
result need not be a syntax object; attributes can be bound to any
kind of value.
}
@deftogether[[
@defidform[~or]
@defidform[~and]
@ -637,42 +635,16 @@ Syntax pattern keywords, recognized by @scheme[syntax-parse].
@section{Pattern Variables and Attributes}
@;{
An @deftech{attribute} is either a @tech{pattern variable}, a
@tech{nested attribute}, or a @tech{computed attribute}.
An @deftech{attribute} is a name bound by a syntax pattern. An
attribute can be a @tech{pattern variable} itself, or it can be a
@deftech{nested attribute} coming from the syntax class of some
pattern variable. The name of a nested attribute is computed by
concatenating the pattern variable name with the syntax class's
exported attribute's name, separated by a dot (see the example below).
A pattern consisting of an identifier not in the literals list is a
@deftech{pattern variable}. Pattern variables cannot be used as
ordinary variables; instead, they are used within @scheme[syntax],
@scheme[quasisyntax], etc as part of a syntax template.
Pattern variables have an @deftech{ellipsis depth} based on the number
of ellipses the pattern variable occurs in front of in the
pattern. For example, in the @tech{S-pattern} @scheme[(a (b c ...) ... d)],
the pattern variable @scheme[a] has depth 0, @scheme[b] has
depth 1, @scheme[c] has depth 2, and @scheme[d] has depth 0. The
ellipsis depth of a pattern variable in a pattern determines what
ellipsis depths it may be used at in a template.
Pattern variables annotated with syntax classes also bind
@deftech{nested attributes}, one for each attribute exported by the
syntax class. The names of the nested attributes are computed by
combining the pattern variable name with the syntax class attributes'
names. The ellipsis depth of a nested attribute is the sum of the
pattern variable's depth and the depth of the attribute in the syntax
class. @deftech{Computed attributes} are bound by @scheme[#:attr]
clauses and @scheme[~bind] patterns.
An attribute's ellipsis nesting depth is @emph{not} a guarantee that
its value has that level of list nesting. In particular, @scheme[~or]
and @scheme[~optional] patterns may result in attributes with fewer
than expected levels of list nesting.
@(myexamples
(syntax-parse #'(a b c)
[(~or (x:nat ...) _)
(attribute x)]))
}
Attribute names cannot be used directly as expressions (that is,
attributes are not variables). Instead, an attribute's value can be
gotten using the @scheme[attribute] special form.
@defform[(attribute attr-id)]{
@ -682,14 +654,77 @@ error is raised. If @scheme[attr-id] is an attribute with a nonzero
ellipsis depth, then the result has the corresponding level of list
nesting.
The values returned by @scheme[attribute] never undergo additional
wrapping as syntax objects, unlike values produced by some uses of
@scheme[syntax], @scheme[quasisyntax], etc. Therefore, use
@scheme[attribute] when the attribute value is used as data, not
placed in a syntax object.
}
The value of an attribute need not be syntax. Non-syntax-valued
attributes can be used to return a parsed representation of a subterm
or the results of an analysis on the subterm. A non-syntax-valued
attribute should be bound using the @scheme[#:attr] directive or a
@scheme[~bind] pattern.
@myexamples[
(define-syntax-class table
(pattern ((key value) ...)
#:attr hash
(for/hash ([k (syntax->datum #'(key ...))]
[v (syntax->datum #'(value ...))])
(values k v))))
(syntax-parse #'((a 1) (b 2) (c 3))
[t:table
(attribute t.hash)])
]
A syntax-valued attribute is an attribute whose value is a syntax
object or a syntax list of the appropriate @tech{ellipsis
depth}. Syntax-valued attributes can be used within @scheme[syntax],
@scheme[quasisyntax], etc as part of a syntax template. If a
non-syntax-valued attribute is used in a syntax template, a runtime
error is signalled.
@myexamples[
(syntax-parse #'((a 1) (b 2) (c 3))
[t:table
#'(t.key ...)])
(syntax-parse #'((a 1) (b 2) (c 3))
[t:table
#'t.hash])
]
Every attribute has an associated @deftech{ellipsis depth} that
determines how it can be used in a syntax template (see the discussion
of ellipses in @scheme[syntax]). For a pattern variable, the ellipsis
depth is the number of ellipses the pattern variable ``occurs under''
in the pattern. For a nested attribute the depth is the sum of the
pattern variable's depth and the depth of the attribute in the syntax
class. Consider the following code:
@schemeblock[
(define-syntax-class quark
(pattern (a b ...)))
(syntax-parse some-term
[(x (y:quark ...) ... z:quark)
some-code])
]
The syntax class @scheme[quark] exports two attributes: @scheme[a] at
depth 0 and @scheme[b] at depth 1. The @scheme[syntax-parse] pattern
has three pattern variables: @scheme[x] at depth 0, @scheme[y] at
depth 2, and @scheme[z] at depth 0. Since @scheme[x] and @scheme[y]
are annotated with the @scheme[quark] syntax class, the pattern also
binds the following nested attributes: @scheme[y.a] at depth 2,
@scheme[y.b] at depth 3, @scheme[z.a] at depth 0, and @scheme[z.b] at
depth 1.
An attribute's ellipsis nesting depth is @emph{not} a guarantee that
its value has that level of list nesting. In particular, @scheme[~or]
and @scheme[~optional] patterns may result in attributes with fewer
than expected levels of list nesting.
@(myexamples
(syntax-parse #'(1 2 3)
[(~or (x:id ...) _)
(attribute x)]))
@;{----------}
@section{Syntax Classes}
@ -993,8 +1028,6 @@ Literal set containing the identifiers for fully-expanded code
@scheme[#%plain-module-begin], @scheme[#%require], and
@scheme[#%provide].
@;{See @secref[#:doc '(lib "scribblings/reference/reference.scrbl") "fully-expanded"].}
Note that the literal-set uses the names @scheme[#%plain-lambda] and
@scheme[#%plain-app], not @scheme[lambda] and @scheme[#%app].
}