fix the source problem with placeholders
svn: r6697
This commit is contained in:
parent
61fab4d58d
commit
76988f2d90
|
@ -45,14 +45,67 @@
|
||||||
(let ([s (make-string n #\space)])
|
(let ([s (make-string n #\space)])
|
||||||
(hash-table-put! t n s) s))))))
|
(hash-table-put! t n s) s))))))
|
||||||
|
|
||||||
|
;; Skips whitespace characters, sensitive to the current readtable's
|
||||||
|
;; definition of whitespace; optimizes common spaces when possible
|
||||||
|
(define/kw skip-whitespace
|
||||||
|
(let* ([plain-readtables (make-hash-table 'weak)]
|
||||||
|
[plain-spaces '(#\space #\tab #\newline #\return #\page)]
|
||||||
|
[plain-spaces-re
|
||||||
|
(regexp (string-append "^["(apply string plain-spaces)"]*"))])
|
||||||
|
(define (skip-plain-spaces port)
|
||||||
|
;; hack: according to the specs, this might consume more characters
|
||||||
|
;; than needed, but it seems to work fine with a simple <ch>* regexp
|
||||||
|
(regexp-match-positions plain-spaces-re port))
|
||||||
|
(define (whitespace? ch rt)
|
||||||
|
(if rt
|
||||||
|
(let-values ([(like-ch/sym _1 _2) (readtable-mapping rt ch)])
|
||||||
|
;; if like-ch/sym is whitespace, then ch is whitespace
|
||||||
|
(and (char? like-ch/sym) (char-whitespace? like-ch/sym)))
|
||||||
|
;; `char-whitespace?' is fine for the default readtable
|
||||||
|
(char-whitespace? ch)))
|
||||||
|
(define (plain-readtable? rt)
|
||||||
|
(hash-table-get plain-readtables rt
|
||||||
|
(lambda ()
|
||||||
|
(let ([plain? (andmap (lambda (ch) (whitespace? ch rt))
|
||||||
|
plain-spaces)])
|
||||||
|
(hash-table-put! plain-readtables rt #t)
|
||||||
|
rt))))
|
||||||
|
(lambda/kw (#:optional [port (current-input-port)])
|
||||||
|
(let* ([rt (current-readtable)] [plain? (plain-readtable? rt)])
|
||||||
|
(let loop ()
|
||||||
|
(when plain? (skip-plain-spaces port))
|
||||||
|
(let ([ch (peek-char port)])
|
||||||
|
(unless (eof-object? ch)
|
||||||
|
(when (whitespace? ch rt) (read-char port) (loop)))))))))
|
||||||
|
|
||||||
|
;; Wrappers for placeholders, to keep source information for them. (MzScheme
|
||||||
|
;; provides nothing for them -- there's not even a predicate. Hopefully, if
|
||||||
|
;; something is added it will use the same name, so there's a compiler error
|
||||||
|
;; here and this code is adapted.)
|
||||||
|
(define-struct placeholder (p loc))
|
||||||
|
(define (syntax/placeholder-line sp)
|
||||||
|
(if (placeholder? sp) (cadr (placeholder-loc sp)) (syntax-line sp)))
|
||||||
|
(define (syntax/placeholder-column sp)
|
||||||
|
(if (placeholder? sp) (caddr (placeholder-loc sp)) (syntax-column sp)))
|
||||||
|
(define (syntax/placeholder-strip sp)
|
||||||
|
(if (placeholder? sp) (placeholder-p sp) sp))
|
||||||
|
(define (datum->syntax-object/placeholder sp d)
|
||||||
|
(if (placeholder? sp)
|
||||||
|
;; using the syntax for lexical context is not possible for placeholders,
|
||||||
|
;; but we don't need it since we're a reader
|
||||||
|
(datum->syntax-object #f d (placeholder-loc sp))
|
||||||
|
(datum->syntax-object sp d sp)))
|
||||||
|
|
||||||
(define ((dispatcher start-inside?)
|
(define ((dispatcher start-inside?)
|
||||||
char inp source-name line-num col-num position)
|
char inp source-name line-num col-num position)
|
||||||
(define/kw (next-syntax readtable #:optional plain?)
|
(define/kw (next-syntax readtable #:optional plain?)
|
||||||
(let ([read (if plain? read-syntax read-syntax/recursive)])
|
(let ([read (if plain? read-syntax read-syntax/recursive)])
|
||||||
(parameterize ([current-readtable readtable])
|
(parameterize ([current-readtable readtable])
|
||||||
(let loop ()
|
(if plain?
|
||||||
(let ([x (read source-name inp)])
|
(read source-name inp) ; read-syntax never returns special comments
|
||||||
(if (special-comment? x) (loop) x))))))
|
(let loop ()
|
||||||
|
(let ([x (read source-name inp)])
|
||||||
|
(if (special-comment? x) (loop) x)))))))
|
||||||
(define (cur-pos)
|
(define (cur-pos)
|
||||||
(let-values ([(line col pos) (port-next-location inp)])
|
(let-values ([(line col pos) (port-next-location inp)])
|
||||||
pos))
|
pos))
|
||||||
|
@ -119,7 +172,13 @@
|
||||||
(set-box! level (add1 (unbox level)))
|
(set-box! level (add1 (unbox level)))
|
||||||
(make-stx (car m)))]
|
(make-stx (car m)))]
|
||||||
[(regexp-match-peek-positions sub-start inp)
|
[(regexp-match-peek-positions sub-start inp)
|
||||||
(read-syntax source-name inp)] ; include comment objs
|
;; read the next value, include comment objs, keep source
|
||||||
|
;; location manually (see above)
|
||||||
|
(let ([x (read-syntax/recursive source-name inp)])
|
||||||
|
(if (or (syntax? x) (special-comment? x))
|
||||||
|
x
|
||||||
|
(make-placeholder x
|
||||||
|
(list source-name line col pos (span-from pos)))))]
|
||||||
[(regexp-match/fail-without-reading end-of-line inp)
|
[(regexp-match/fail-without-reading end-of-line inp)
|
||||||
=> (lambda (m)
|
=> (lambda (m)
|
||||||
(if (cadr m) ; backslashes?
|
(if (cadr m) ; backslashes?
|
||||||
|
@ -137,7 +196,7 @@
|
||||||
(make-stx (car m)))]
|
(make-stx (car m)))]
|
||||||
[(regexp-match/fail-without-reading #rx#"^$" inp)
|
[(regexp-match/fail-without-reading #rx#"^$" inp)
|
||||||
(if eof-ok? #f (read-error "missing `~a'" close))]
|
(if eof-ok? #f (read-error "missing `~a'" close))]
|
||||||
[else (read-error "internal error")])))
|
[else (read-error "internal error [get-line]")])))
|
||||||
;; adds stx (new syntax) to the list of stxs, merging it if both are
|
;; adds stx (new syntax) to the list of stxs, merging it if both are
|
||||||
;; strings, except for newline markers
|
;; strings, except for newline markers
|
||||||
(define (maybe-merge stx stxs)
|
(define (maybe-merge stx stxs)
|
||||||
|
@ -157,24 +216,27 @@
|
||||||
(cdr stxs)))
|
(cdr stxs)))
|
||||||
(cons stx stxs)))
|
(cons stx stxs)))
|
||||||
(define (add-indents stxs)
|
(define (add-indents stxs)
|
||||||
(if (or (not (read-insert-indents))
|
(unless (andmap (lambda (x)
|
||||||
(null? stxs)
|
(or (and (syntax? x) (syntax-line x) (syntax-column x))
|
||||||
(not (andmap (lambda (s) (and (syntax-line s) (syntax-column s)))
|
(placeholder? x)))
|
||||||
stxs)))
|
stxs)
|
||||||
|
(read-error "internal error [add-indents] ~s" stxs))
|
||||||
|
(if (or (not (read-insert-indents)) (null? stxs))
|
||||||
stxs
|
stxs
|
||||||
(let ([mincol (apply min (map syntax-column stxs))])
|
(let ([mincol (apply min (map syntax/placeholder-column stxs))])
|
||||||
(let loop ([curline line-num] [stxs stxs] [r '()])
|
(let loop ([curline line-num] [stxs stxs] [r '()])
|
||||||
(if (null? stxs)
|
(if (null? stxs)
|
||||||
(reverse! r)
|
(reverse! r)
|
||||||
(let* ([stx (car stxs)] [line (syntax-line stx)])
|
(let* ([stx (car stxs)] [line (syntax/placeholder-line stx)])
|
||||||
(loop line (cdr stxs)
|
(loop line (cdr stxs)
|
||||||
(if (and (< curline line) (< mincol (syntax-column stx)))
|
(let ([stxcol (syntax/placeholder-column stx)]
|
||||||
(list* stx
|
[stx* (syntax/placeholder-strip stx)])
|
||||||
(datum->syntax-object stx
|
(if (and (< curline line) (< mincol stxcol))
|
||||||
(make-spaces (- (syntax-column stx) mincol))
|
(list* stx*
|
||||||
stx)
|
(datum->syntax-object/placeholder stx*
|
||||||
r)
|
(make-spaces (- stxcol mincol)))
|
||||||
(cons stx r)))))))))
|
r)
|
||||||
|
(cons stx* r))))))))))
|
||||||
(define (get-lines inside?)
|
(define (get-lines inside?)
|
||||||
(define get
|
(define get
|
||||||
(cond [inside?
|
(cond [inside?
|
||||||
|
@ -229,9 +291,10 @@
|
||||||
[#"," unquote]
|
[#"," unquote]
|
||||||
[#",@" unquote-splicing]))
|
[#",@" unquote-splicing]))
|
||||||
=> cadr]
|
=> cadr]
|
||||||
[else (error "internal error")]))
|
[else (read-error
|
||||||
|
"internal error [rpfxs]")]))
|
||||||
r)))]
|
r)))]
|
||||||
[else (error "internal error")])))]
|
[else (read-error "internal error [rpfxs]")])))]
|
||||||
[else '()]))
|
[else '()]))
|
||||||
(define (get-command) ; #f means no command
|
(define (get-command) ; #f means no command
|
||||||
(let-values ([(line col pos) (port-next-location inp)])
|
(let-values ([(line col pos) (port-next-location inp)])
|
||||||
|
@ -266,7 +329,7 @@
|
||||||
cmd ; no attrs/lines => simple expression (no parens)
|
cmd ; no attrs/lines => simple expression (no parens)
|
||||||
;; impossible: either we saw []s or {}s, or we read a
|
;; impossible: either we saw []s or {}s, or we read a
|
||||||
;; scheme expression
|
;; scheme expression
|
||||||
(error "internal error"))]
|
(read-error "internal error [dispatcher]"))]
|
||||||
[stx (let loop ([pfx pfx] [stx stx])
|
[stx (let loop ([pfx pfx] [stx stx])
|
||||||
(if (null? pfx) stx
|
(if (null? pfx) stx
|
||||||
(loop (cdr pfx) (list (car pfx) stx))))])
|
(loop (cdr pfx) (list (car pfx) stx))))])
|
||||||
|
@ -281,7 +344,7 @@
|
||||||
(define cmd-readtable
|
(define cmd-readtable
|
||||||
(make-readtable at-readtable #\| 'terminating-macro
|
(make-readtable at-readtable #\| 'terminating-macro
|
||||||
(lambda (char inp source-name line-num col-num position)
|
(lambda (char inp source-name line-num col-num position)
|
||||||
(let ([m (regexp-match #rx#"^([^|]*)\\|" inp)])
|
(let ([m (regexp-match/fail-without-reading #rx#"^([^|]*)\\|" inp)])
|
||||||
(unless m
|
(unless m
|
||||||
(raise-read-error
|
(raise-read-error
|
||||||
"unbalanced `|'" source-name line-num col-num position #f))
|
"unbalanced `|'" source-name line-num col-num position #f))
|
||||||
|
|
|
@ -28,22 +28,22 @@ exec mzscheme -r "$0" "$@"
|
||||||
[@'foo{bar}
|
[@'foo{bar}
|
||||||
'(foo "bar")]
|
'(foo "bar")]
|
||||||
|
|
||||||
,'
|
,@'( ; <- avoid the above openning quasiquote for these
|
||||||
|
|
||||||
[@'`,foo{bar}
|
[@'`,foo{bar}
|
||||||
'`,(foo "bar")]
|
'`,(foo "bar")]
|
||||||
|
|
||||||
,' ; <- to avoid the above openning quasiquote
|
|
||||||
[@'`,@,foo{bar}
|
[@'`,@,foo{bar}
|
||||||
'`,@,(foo "bar")]
|
'`,@,(foo "bar")]
|
||||||
|
|
||||||
,'
|
|
||||||
[@`',@foo{blah}
|
[@`',@foo{blah}
|
||||||
`@',@foo{blah}]
|
`@',@foo{blah}]
|
||||||
|
|
||||||
,'
|
|
||||||
[@`',@foo{blah}
|
[@`',@foo{blah}
|
||||||
`',@@foo{blah}]
|
`',@@foo{blah}]
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
[@(lambda (x) x){blah}
|
[@(lambda (x) x){blah}
|
||||||
((lambda (x) x) "blah")]
|
((lambda (x) x) "blah")]
|
||||||
|
|
||||||
|
@ -102,13 +102,11 @@ exec mzscheme -r "$0" "$@"
|
||||||
[@foo{a @bar{b} c}
|
[@foo{a @bar{b} c}
|
||||||
(foo "a " (bar "b") " c")]
|
(foo "a " (bar "b") " c")]
|
||||||
|
|
||||||
;; !!! to be fixed
|
[@foo{a @bar c}
|
||||||
|
(foo "a " bar " c")]
|
||||||
|
|
||||||
;; [@foo{a @bar c}
|
[@foo{a @(bar 2) c}
|
||||||
;; (foo "a " bar " c")]
|
(foo "a " (bar 2) " c")]
|
||||||
|
|
||||||
;; [@foo{a @(bar 2) c}
|
|
||||||
;; (foo "a " (bar 2) " c")]
|
|
||||||
|
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user