Added syntax properties to mark @-form datum and body number of subexprs
svn: r6902 original commit: 108b23e491e7965939f6b80e0b13b19363afc499
This commit is contained in:
parent
b5928162f5
commit
6f39353a52
|
@ -570,34 +570,65 @@ matter, you can begin (or end) a line with a "@||".
|
|||
@|| bar @|| --reads-as--> (foo " bar " "\n" " baz")
|
||||
@|| baz}
|
||||
|
||||
Finally, you might be need a verbatim-like environment, where the
|
||||
parsed body matches exactly the textual source. To make this
|
||||
possible, the @-parser uses syntax properties on the resulting syntax
|
||||
values. All items that are not physically in the Scribble source --
|
||||
newlines and indentation-spaces -- have a 'scribble property. An
|
||||
indentation string will have 'indentation as the value of this
|
||||
property, and a newline will have a '(newline S) value where S is the
|
||||
original newline string including spaces that precede and follow it
|
||||
(which includes the indentation for the following item). To implement
|
||||
a verbatim environment you need to drop indentation strings, and use
|
||||
the original newline strings instead of the single-newline string.
|
||||
* Syntax Properties
|
||||
|
||||
The Scribble reader attaches properties to syntax objects. These
|
||||
properties might be useful in rare situations.
|
||||
|
||||
Forms that Scribble reads is marked with a 'scribble property, and a
|
||||
value of a list of three elements: the first is 'form, the second is
|
||||
the number of items that were read from the datum part, and the third
|
||||
is the number of items in the body part (strings, sub-forms, and
|
||||
escapes). In both cases, a 0 means an empty datum/body part, and #f
|
||||
means that the corresponding part was omitted. If the form has
|
||||
neither parts, the property is not attached to the result. This
|
||||
property can be used to give different meanings to expressions from
|
||||
the datum and the body parts, for example, implicitly quoted keywords:
|
||||
|
||||
(define-syntax (foo stx)
|
||||
(let ([p (syntax-property stx 'scribble)])
|
||||
(syntax-case stx ()
|
||||
[(_ x ...)
|
||||
(and (pair? p) (eq? (car p) 'form) (even? (cadr p)))
|
||||
(let loop ([n (/ (cadr p) 2)]
|
||||
[as '()]
|
||||
[xs (syntax->list #'(x ...))])
|
||||
(if (zero? n)
|
||||
#`(list 'foo `#,(reverse as) #,@xs)
|
||||
(loop (sub1 n)
|
||||
(cons #`(#,(car xs) ,#,(cadr xs)) as)
|
||||
(cddr xs))))])))
|
||||
@foo[x 1 y (* 2 3)]{blah}
|
||||
--> (foo ((x 1) (y 6)) "blah")
|
||||
|
||||
In addition, the Scribble parser uses syntax properties to mark syntax
|
||||
items that are not physically in the original source -- indentation
|
||||
spaces and newlines. Both of these will have a 'scribble property; an
|
||||
indentation string of spaces will have 'indentation as the value of
|
||||
the property, and a newline will have a '(newline S) value where S is
|
||||
the original newline string including spaces that precede and follow
|
||||
it (which includes the indentation for the following item). This can
|
||||
be used to implement a verbatim environment: drop indentation strings,
|
||||
and use the original source strings instead of single-newline string.
|
||||
Here is an example of this.
|
||||
|
||||
(define-syntax (verb stx)
|
||||
(syntax-case stx ()
|
||||
[(_ cmd item ...)
|
||||
#`(cmd .
|
||||
#,(let loop ([items (syntax->list #'(item ...))])
|
||||
(if (null? items)
|
||||
'()
|
||||
(let* ([fst (car items)]
|
||||
[prop (syntax-property fst 'scribble)]
|
||||
[rst (loop (cdr items))])
|
||||
(cond [(not prop) (cons fst rst)]
|
||||
[(eq? prop 'indentation) rst]
|
||||
[else (cons (datum->syntax-object
|
||||
fst (cadr prop) fst)
|
||||
rst)])))))]))
|
||||
#`(cmd
|
||||
#,@(let loop ([items (syntax->list #'(item ...))])
|
||||
(if (null? items)
|
||||
'()
|
||||
(let* ([fst (car items)]
|
||||
[prop (syntax-property fst 'scribble)]
|
||||
[rst (loop (cdr items))])
|
||||
(cond [(eq? prop 'indentation) rst]
|
||||
[(not (and (pair? prop)
|
||||
(eq? (car prop) 'newline)))
|
||||
(cons fst rst)]
|
||||
[else (cons (datum->syntax-object
|
||||
fst (cadr prop) fst)
|
||||
rst)])))))]))
|
||||
@verb[string-append]{
|
||||
foo
|
||||
bar
|
||||
|
|
|
@ -631,18 +631,59 @@ matter, you can begin (or end) a line with a "@||".
|
|||
@|| baz}
|
||||
}===|
|
||||
|
||||
Finally, you might be need a verbatim-like environment, where the
|
||||
parsed body matches exactly the textual source. To make this
|
||||
possible, the @"@"-parser uses syntax properties on the resulting
|
||||
syntax values. All items that are not physically in the Scribble
|
||||
source---newlines and indentation-spaces---have a 'scribble property.
|
||||
An indentation string will have @scheme['indentation] as the value of
|
||||
this property, and a newline will have a @scheme['(newline S)] value
|
||||
where S is the original newline string including spaces that precede
|
||||
and follow it (which includes the indentation for the following item).
|
||||
To implement a verbatim environment you need to drop indentation
|
||||
strings, and use the original newline strings instead of the
|
||||
single-newline string. Here is an example of this.
|
||||
@subsubsub*section{Syntax Properties}
|
||||
|
||||
The Scribble reader attaches properties to syntax objects. These
|
||||
properties might be useful in rare situations.
|
||||
|
||||
Forms that Scribble reads is marked with a @scheme['scribble]
|
||||
property, and a value of a list of three elements: the first is
|
||||
@scheme['form], the second is the number of items that were read from
|
||||
the datum part, and the third is the number of items in the body part
|
||||
(strings, sub-forms, and escapes). In both cases, a @scheme[0] means
|
||||
an empty datum/body part, and @scheme[#f] means that the corresponding
|
||||
part was omitted. If the form has neither parts, the property is not
|
||||
attached to the result. This property can be used to give different
|
||||
meanings to expressions from the datum and the body parts, for
|
||||
example, implicitly quoted keywords:
|
||||
|
||||
@; FIXME: a bit of code duplication here
|
||||
@def+int[
|
||||
(define-syntax (foo stx)
|
||||
(let ([p (syntax-property stx 'scribble)])
|
||||
(syntax-case stx ()
|
||||
[(_ x ...)
|
||||
(and (pair? p) (eq? (car p) 'form) (even? (cadr p)))
|
||||
(let loop ([n (/ (cadr p) 2)]
|
||||
[as '()]
|
||||
[xs (syntax->list #'(x ...))])
|
||||
(if (zero? n)
|
||||
(with-syntax ([attrs (reverse as)]
|
||||
[(x ...) xs])
|
||||
#'(list 'foo `attrs x ...))
|
||||
(loop (sub1 n)
|
||||
(cons (with-syntax ([key (car xs)]
|
||||
[val (cadr xs)])
|
||||
#'(key ,val))
|
||||
as)
|
||||
(cddr xs))))])))
|
||||
(eval:alts
|
||||
(code:line
|
||||
#, @tt["@foo[x 1 y (* 2 3)]{blah}"])
|
||||
@foo[x 1 y (* 2 3)]{blah})
|
||||
]
|
||||
|
||||
In addition, the Scribble parser uses syntax properties to mark syntax
|
||||
items that are not physically in the original source --- indentation
|
||||
spaces and newlines. Both of these will have a @scheme['scribble]
|
||||
property; an indentation string of spaces will have
|
||||
@scheme['indentation] as the value of the property, and a newline will
|
||||
have a @scheme['(newline S)] value where @scheme[S] is the original
|
||||
newline string including spaces that precede and follow it (which
|
||||
includes the indentation for the following item). This can be used to
|
||||
implement a verbatim environment: drop indentation strings, and use
|
||||
the original source strings instead of single-newline string. Here is
|
||||
an example of this.
|
||||
|
||||
@; FIXME: a bit of code duplication here
|
||||
@def+int[
|
||||
|
@ -656,21 +697,21 @@ single-newline string. Here is an example of this.
|
|||
(let* ([fst (car items)]
|
||||
[prop (syntax-property fst 'scribble)]
|
||||
[rst (loop (cdr items))])
|
||||
(cond [(not prop) (cons fst rst)]
|
||||
[(eq? prop 'indentation) rst]
|
||||
(cond [(eq? prop 'indentation) rst]
|
||||
[(not (and (pair? prop)
|
||||
(eq? (car prop) 'newline)))
|
||||
(cons fst rst)]
|
||||
[else (cons (datum->syntax-object
|
||||
fst (cadr prop) fst)
|
||||
rst)])))))]))
|
||||
(eval:alts
|
||||
|
||||
(code:line
|
||||
#, @tt["@verb[string-append]{"]
|
||||
#, @tt[" foo"]
|
||||
#, @tt[" bar"]
|
||||
#, @tt["}"])
|
||||
|
||||
@verb[string-append]{
|
||||
foo
|
||||
bar
|
||||
})
|
||||
@verb[string-append]{
|
||||
foo
|
||||
bar
|
||||
})
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue
Block a user