extend syntax/module-reader to avoid ugly hack in scribble/doc/reader
svn: r11517
This commit is contained in:
parent
8ed6a0c00f
commit
eaa5a69fa5
|
@ -2,22 +2,9 @@
|
||||||
|
|
||||||
scribble/doclang
|
scribble/doclang
|
||||||
|
|
||||||
;; `read-inside' reads the whole body, so make wrapper1 return null so
|
#:read scribble:read-inside
|
||||||
;; we get the right syntax, and then make wrapper2 do the actual
|
#:read-syntax scribble:read-syntax-inside
|
||||||
;; reading. This might seem extreme, but I think that it's still
|
#:whole-body-readers? #t
|
||||||
;; better to use module-reader for the subtleties it deals with.
|
#:wrapper1 (lambda (t) (list* 'doc '() (t)))
|
||||||
|
|
||||||
#:wrapper1 (lambda (t) '())
|
|
||||||
|
|
||||||
#:wrapper2
|
|
||||||
(lambda (in read stx?)
|
|
||||||
(let* ([skeleton (read in)]
|
|
||||||
[skeleton (if stx? (syntax->list skeleton) skeleton)]
|
|
||||||
[body (if stx?
|
|
||||||
(scribble:read-syntax-inside (object-name in) in)
|
|
||||||
(scribble:read-inside in))]
|
|
||||||
[mod `(,(car skeleton) ,(cadr skeleton) ,(caddr skeleton)
|
|
||||||
(#%module-begin doc () . ,body))])
|
|
||||||
(if stx? (datum->syntax #f mod) mod)))
|
|
||||||
|
|
||||||
(require (prefix-in scribble: "../reader.ss"))
|
(require (prefix-in scribble: "../reader.ss"))
|
||||||
|
|
|
@ -9,72 +9,68 @@
|
||||||
(define-syntax (provide-module-reader stx)
|
(define-syntax (provide-module-reader stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_ lib body ...)
|
[(_ lib body ...)
|
||||||
(let ([-read #f]
|
(let ([key-args '()])
|
||||||
[-read-syntax #f]
|
(define (err str [sub #f])
|
||||||
[-wrapper1 #f]
|
(raise-syntax-error 'syntax/module-reader str sub))
|
||||||
[-wrapper2 #f])
|
|
||||||
(define -body
|
(define -body
|
||||||
(let loop ([body #'(body ...)])
|
(let loop ([body (syntax->list #'(body ...))])
|
||||||
(define (err str)
|
(if (not (and (pair? body)
|
||||||
(raise-syntax-error 'syntax/module-reader str
|
(pair? (cdr body))
|
||||||
(car (syntax->list body))))
|
(not (keyword? (car body)))))
|
||||||
(syntax-case body ()
|
(datum->syntax stx body stx)
|
||||||
[(#:read r body ...)
|
(let* ([k (car body)] [k* (syntax-e k)] [v (cadr body)])
|
||||||
(if -read
|
(cond
|
||||||
(err "got two #:read keywords")
|
[(assq k* key-args) (err (format "got two ~s keywords" k*) k)]
|
||||||
(begin (set! -read #'r) (loop #'(body ...))))]
|
[(not (memq k* '(#:read #:read-syntax #:wrapper1 #:wrapper2
|
||||||
[(#:read-syntax r body ...)
|
#:whole-body-readers?)))
|
||||||
(if -read-syntax
|
(err "got an unknown keyword" (car body))]
|
||||||
(err "got two #:read-syntax keywords")
|
[else (set! key-args (cons (cons k* v) key-args))
|
||||||
(begin (set! -read-syntax #'r) (loop #'(body ...))))]
|
(loop (cddr body))])))))
|
||||||
[(#:wrapper1 w body ...)
|
(define (get kwd [dflt #f])
|
||||||
(if -wrapper1
|
(cond [(assq kwd key-args) => cdr] [else dflt]))
|
||||||
(err "got two #:wrapper1 keywords")
|
(unless (equal? (and (assq '#:read key-args) #t)
|
||||||
(begin (set! -wrapper1 #'w) (loop #'(body ...))))]
|
(and (assq '#:read-syntax key-args) #t))
|
||||||
[(#:wrapper2 w body ...)
|
(err "must specify either both #:read and #:read-syntax, or none"))
|
||||||
(if -wrapper2
|
(when (and (assq '#:whole-body-readers? key-args)
|
||||||
(err "got two #:wrapper2 keywords")
|
(not (assq '#:read key-args)))
|
||||||
(begin (set! -wrapper2 #'w) (loop #'(body ...))))]
|
(err "got a #:whole-body-readers? without #:read and #:read-syntax"))
|
||||||
[(k . b) (keyword? (syntax-e #'k))
|
(quasisyntax/loc stx
|
||||||
(err "got an unknown keyword")]
|
|
||||||
[_ body])))
|
|
||||||
(with-syntax ([-read (or -read #'read)]
|
|
||||||
[-read-syntax (or -read-syntax #'read-syntax)]
|
|
||||||
[-wrapper1 (or -wrapper1 #'#f)]
|
|
||||||
[-wrapper2 (or -wrapper2 #'#f)]
|
|
||||||
[(body ...) -body])
|
|
||||||
(syntax/loc stx
|
|
||||||
(#%module-begin
|
(#%module-begin
|
||||||
body ...
|
#,@-body
|
||||||
(#%provide (rename *read read) (rename *read-syntax read-syntax))
|
(#%provide (rename *read read) (rename *read-syntax read-syntax))
|
||||||
(define-values (*read *read-syntax)
|
(define-values (*read *read-syntax)
|
||||||
(let ([rd -read]
|
(let* ([rd #,(get '#:read #'read)]
|
||||||
[rds -read-syntax]
|
[rds #,(get '#:read-syntax #'read-syntax)]
|
||||||
[w1 -wrapper1]
|
[w1 #,(get '#:wrapper1 #'#f)]
|
||||||
[w2 (let ([w -wrapper2])
|
[w2 #,(get '#:wrapper2 #'#f)]
|
||||||
(cond [(not w) (lambda (in r _) (r in))]
|
[w2 (cond [(not w2) (lambda (in r _) (r in))]
|
||||||
[(procedure-arity-includes? w 3) w]
|
[(procedure-arity-includes? w2 3) w2]
|
||||||
[else (lambda (in r _) (w in r))]))])
|
[else (lambda (in r _) (w2 in r))])]
|
||||||
|
[base 'lib]
|
||||||
|
[whole? #,(get '#:whole-body-readers? #'#f)])
|
||||||
(values
|
(values
|
||||||
(lambda (in modpath line col pos)
|
(lambda (in modpath line col pos)
|
||||||
(w2 in
|
(w2 in
|
||||||
(lambda (in)
|
(lambda (in)
|
||||||
(wrap-internal 'lib in rd w1 #f modpath #f
|
(wrap-internal base in rd whole?
|
||||||
line col pos))
|
w1 #f modpath #f line col pos))
|
||||||
#f))
|
#f))
|
||||||
(lambda (src in modpath line col pos)
|
(lambda (src in modpath line col pos)
|
||||||
(w2 in
|
(w2 in
|
||||||
(lambda (in)
|
(lambda (in)
|
||||||
(wrap-internal 'lib in (lambda (in) (rds src in))
|
(wrap-internal
|
||||||
w1 #t modpath src
|
base in (lambda (in) (rds src in)) whole?
|
||||||
line col pos))
|
w1 #t modpath src line col pos))
|
||||||
#t)))))))))]))
|
#t))))))))]))
|
||||||
|
|
||||||
(define (wrap-internal lib port read wrapper stx? modpath src line col pos)
|
(define-syntax-rule (wrap-internal lib port read whole? wrapper stx?
|
||||||
|
modpath src line col pos)
|
||||||
(let* ([body (lambda ()
|
(let* ([body (lambda ()
|
||||||
|
(if whole?
|
||||||
|
(read port)
|
||||||
(let loop ([a null])
|
(let loop ([a null])
|
||||||
(let ([v (read port)])
|
(let ([v (read port)])
|
||||||
(if (eof-object? v) (reverse a) (loop (cons v a))))))]
|
(if (eof-object? v) (reverse a) (loop (cons v a)))))))]
|
||||||
[body (cond [(not wrapper) (body)]
|
[body (cond [(not wrapper) (body)]
|
||||||
[(procedure-arity-includes? wrapper 2) (wrapper body stx?)]
|
[(procedure-arity-includes? wrapper 2) (wrapper body stx?)]
|
||||||
[else (wrapper body)])]
|
[else (wrapper body)])]
|
||||||
|
@ -96,6 +92,6 @@
|
||||||
(if stx? (datum->syntax #f r) r)))
|
(if stx? (datum->syntax #f r) r)))
|
||||||
|
|
||||||
(define (wrap lib port read modpath src line col pos)
|
(define (wrap lib port read modpath src line col pos)
|
||||||
(wrap-internal lib port read #f #f modpath src line col pos))
|
(wrap-internal lib port read #f #f #f modpath src line col pos))
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#lang scribble/doc
|
#lang scribble/doc
|
||||||
@(require "common.ss")
|
@(require "common.ss")
|
||||||
|
|
||||||
@(require (for-label syntax/module-reader))
|
@(require (for-label syntax/module-reader
|
||||||
|
(only-in scribble/reader read-syntax-inside read-inside)))
|
||||||
|
|
||||||
@title[#:tag "module-reader"]{Module Reader}
|
@title[#:tag "module-reader"]{Module Reader}
|
||||||
|
|
||||||
|
@ -19,7 +20,8 @@ customized in a number of ways.
|
||||||
([reader-option (code:line #:read read-expr)
|
([reader-option (code:line #:read read-expr)
|
||||||
(code:line #:read-syntax read-syntax-expr)
|
(code:line #:read-syntax read-syntax-expr)
|
||||||
(code:line #:wrapper1 wrapper1-expr)
|
(code:line #:wrapper1 wrapper1-expr)
|
||||||
(code:line #:wrapper2 wrapper2-expr)])]{
|
(code:line #:wrapper2 wrapper2-expr)
|
||||||
|
(code:line #:whole-body-readers? whole?-expr)])]{
|
||||||
|
|
||||||
Causes a module written in the @schememodname[syntax/module-reader]
|
Causes a module written in the @schememodname[syntax/module-reader]
|
||||||
language to define and provide @schemeidfont{read} and
|
language to define and provide @schemeidfont{read} and
|
||||||
|
@ -119,6 +121,12 @@ using this option:
|
||||||
(r in))))
|
(r in))))
|
||||||
]
|
]
|
||||||
|
|
||||||
|
In some cases, the reader functions read the whole file, so there is
|
||||||
|
no need to iterate them (e.g., @scheme[read-inside] and
|
||||||
|
@scheme[read-syntax-inside]). In these cases you can specify
|
||||||
|
@scheme[#:whole-body-readers?] as @scheme[#t] --- the readers are
|
||||||
|
expected to return a list of expressions in this case.
|
||||||
|
|
||||||
Finally, note that the two wrappers can return a different value than
|
Finally, note that the two wrappers can return a different value than
|
||||||
the wrapped function. This introduces two more customization points
|
the wrapped function. This introduces two more customization points
|
||||||
for the resulting readers:
|
for the resulting readers:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user