add a contract on the interaction between the module-lexer and the

lexers it defers to

also, remove the checks in color.rkt in the framework (they are not
all covered by the added contract, but they mostly are and when they
aren't, most of those times are using the heavily tested racket-lexer)
This commit is contained in:
Robby Findler 2013-02-23 14:33:08 -06:00
parent 4cc9eb0326
commit b0343aa9f0
2 changed files with 59 additions and 23 deletions

View File

@ -337,16 +337,6 @@ added get-regions
(set-lexer-state-up-to-date?! ls #t) (set-lexer-state-up-to-date?! ls #t)
(re-tokenize-move-to-next-ls start-time #t)] (re-tokenize-move-to-next-ls start-time #t)]
[else [else
(unless (exact-positive-integer? new-token-start)
(error 'color:text<%> "expected an exact nonnegative integer for the token start, got ~e" new-token-start))
(unless (exact-positive-integer? new-token-end)
(error 'color:text<%> "expected an exact nonnegative integer for the token end, got ~e" new-token-end))
(unless (exact-nonnegative-integer? backup-delta)
(error 'color:text<%> "expected an exact nonnegative integer for the backup delta, got ~e" backup-delta))
(unless (new-token-start . < . new-token-end)
(error 'color:text<%>
"expected the distance between the start and end position for each token to be positive, but start was ~e and end was ~e"
new-token-start new-token-end))
(unless (<= pos-before new-token-start pos-after) (unless (<= pos-before new-token-start pos-after)
(error 'color:text<%> (error 'color:text<%>
"expected the token start to be between ~s and ~s, got ~s" pos-before pos-after new-token-start)) "expected the token start to be between ~s and ~s, got ~s" pos-before pos-after new-token-start))

View File

@ -1,6 +1,7 @@
#lang scheme/base #lang racket/base
(require scheme/port (require racket/port
"scheme-lexer.rkt") "racket-lexer.rkt"
racket/contract)
(provide module-lexer) (provide module-lexer)
#| #|
@ -22,6 +23,32 @@ to delegate to the scheme-lexer (in the 'no-lang-line mode).
|# |#
(define lexer/c
(or/c (->i ([in input-port?])
(values [txt any/c]
[type symbol?]
[paren (or/c symbol? #f)]
[start (or/c exact-positive-integer? #f)]
[end (start)
(if start
(and/c exact-positive-integer?
(>=/c start))
#f)]))
(->i ([in input-port?]
[offset exact-nonnegative-integer?]
[mode any/c])
(values [txt any/c]
[type symbol?]
[paren (or/c symbol? #f)]
[start (or/c exact-positive-integer? #f)]
[end (start)
(if start
(and/c exact-positive-integer?
(>=/c start))
#f)]
[backup exact-nonnegative-integer?]
[new-mode any/c]))))
(define (module-lexer in offset mode) (define (module-lexer in offset mode)
(cond (cond
[(or (not mode) (eq? mode 'before-lang-line)) [(or (not mode) (eq? mode 'before-lang-line))
@ -30,7 +57,7 @@ to delegate to the scheme-lexer (in the 'no-lang-line mode).
(when line (when line
(port-count-lines! lexer-port))) (port-count-lines! lexer-port)))
(set-port-next-location-from in lexer-port) (set-port-next-location-from in lexer-port)
(define-values (lexeme type data new-token-start new-token-end) (scheme-lexer lexer-port)) (define-values (lexeme type data new-token-start new-token-end) (racket-lexer lexer-port))
(cond (cond
[(or (eq? type 'comment) (eq? type 'white-space)) [(or (eq? type 'comment) (eq? type 'white-space))
(define lexer-end (file-position lexer-port)) (define lexer-end (file-position lexer-port))
@ -41,32 +68,51 @@ to delegate to the scheme-lexer (in the 'no-lang-line mode).
[else [else
;; look for #lang: ;; look for #lang:
(define p (peeking-input-port in #:init-position (+ 1 (file-position in)))) (define p (peeking-input-port in #:init-position (+ 1 (file-position in))))
(define name-p (peeking-input-port in #:init-position (+ 1 (file-position in))))
(let-values ([(line col pos) (port-next-location in)]) (let-values ([(line col pos) (port-next-location in)])
(when line (when line
(port-count-lines! p))) (port-count-lines! p)
(port-count-lines! name-p)))
(set-port-next-location-from in p) (set-port-next-location-from in p)
(set-port-next-location-from in name-p)
(define-values (_1 _2 start-pos) (port-next-location p)) (define-values (_1 _2 start-pos) (port-next-location p))
(define get-info (with-handlers ([exn:fail? values]) (read-language p (λ () 'fail)))) (define get-info (with-handlers ([exn:fail? values]) (read-language p (λ () 'fail))))
(define-values (_3 _4 end-pos) (port-next-location p)) (define-values (_3 _4 end-pos) (port-next-location p))
(cond (cond
[(procedure? get-info) [(procedure? get-info)
(define lang-name
(apply string
(filter
char?
(for/list ([i (in-range (file-position in) (file-position p))])
(read-char name-p)))))
;; sync ports ;; sync ports
(for ([i (in-range (file-position in) (file-position p))]) (for ([i (in-range (file-position in) (file-position p))])
(read-byte-or-special in)) (read-byte-or-special in))
(define no-ctc-lexer (or (get-info 'color-lexer #f)
racket-lexer))
;; add the lexer contract
(define the-lexer (contract lexer/c
no-ctc-lexer
lang-name
'syntax-color/module-lexer
(or (object-name no-ctc-lexer)
(format "~a's lexer" lang-name))
#'here))
;; Produce language as first token: ;; Produce language as first token:
(values (values
"#lang" lang-name
'other 'other
#f #f
start-pos start-pos
end-pos end-pos
0 0
(or (let ([v (get-info 'color-lexer #f)]) (if (procedure-arity-includes? the-lexer 3)
(and v (cons the-lexer #f)
(if (procedure-arity-includes? v 3) the-lexer))]
(cons v #f)
v)))
scheme-lexer))]
[(and (eq? type 'other) [(and (eq? type 'other)
(string? lexeme) (string? lexeme)
@ -82,7 +128,7 @@ to delegate to the scheme-lexer (in the 'no-lang-line mode).
(values lexeme type data new-token-start new-token-end 0 'no-lang-line)])])] (values lexeme type data new-token-start new-token-end 0 'no-lang-line)])])]
[(eq? mode 'no-lang-line) [(eq? mode 'no-lang-line)
(let-values ([(lexeme type data new-token-start new-token-end) (let-values ([(lexeme type data new-token-start new-token-end)
(scheme-lexer in)]) (racket-lexer in)])
(values lexeme type data new-token-start new-token-end 0 'no-lang-line))] (values lexeme type data new-token-start new-token-end 0 'no-lang-line))]
[(pair? mode) [(pair? mode)
;; #lang-selected language consumes and produces a mode: ;; #lang-selected language consumes and produces a mode: