;*=====================================================================*/ ;* serrano/prgm/project/skribe/src/bigloo/read.scm */ ;* ------------------------------------------------------------- */ ;* Author : Manuel Serrano */ ;* Creation : Tue Dec 27 11:16:00 1994 */ ;* Last change : Mon Nov 8 13:30:32 2004 (serrano) */ ;* ------------------------------------------------------------- */ ;* Skribe's reader */ ;*=====================================================================*/ ;*---------------------------------------------------------------------*/ ;* Le module */ ;*---------------------------------------------------------------------*/ (module skribe_read (export (skribe-read . port))) ;*---------------------------------------------------------------------*/ ;* Global counteurs ... */ ;*---------------------------------------------------------------------*/ (define *par-open* 0) ;*---------------------------------------------------------------------*/ ;* Parenthesis mismatch (or unclosing) errors. */ ;*---------------------------------------------------------------------*/ (define *list-error-level* 20) (define *list-errors* (make-vector *list-error-level* #unspecified)) (define *vector-errors* (make-vector *list-error-level* #unspecified)) ;*---------------------------------------------------------------------*/ ;* Control variables. */ ;*---------------------------------------------------------------------*/ (define *end-of-list* (cons 0 0)) (define *dotted-mark* (cons 1 1)) ;*---------------------------------------------------------------------*/ ;* skribe-reader-reset! ... */ ;*---------------------------------------------------------------------*/ (define (skribe-reader-reset!) (set! *par-open* 0)) ;*---------------------------------------------------------------------*/ ;* read-error ... */ ;*---------------------------------------------------------------------*/ (define (read-error msg obj port) (let* ((obj-loc (if (epair? obj) (match-case (cer obj) ((at ?fname ?pos ?-) pos) (else #f)) #f)) (loc (if (number? obj-loc) obj-loc (cond ((>fx *par-open* 0) (let ((open-key (-fx *par-open* 1))) (if (char (string->integer (the-substring 2 5)))))) ((: "#\\" (or letter digit special (in "|#; []" quote paren))) (string-ref (the-string) 2)) ((: "#\\" (>= 2 letter)) (let ((char-name (string->symbol (string-upcase! (the-substring 2 (the-length)))))) (case char-name ((NEWLINE) #\Newline) ((TAB) #\tab) ((SPACE) #\space) ((RETURN) (integer->char 13)) (else (error/location "skribe-read" "Illegal character" (the-string) (input-port-name (the-port)) (input-port-position (the-port))))))) ;; ucs-2 characters ((: "#u" (= 4 xdigit)) (integer->ucs2 (string->integer (the-substring 2 6) 16))) ((: "\"" (* (or (out #a000 #\\ #\") (: #\\ all))) "\"") (let ((str (the-substring 1 (-fx (the-length) 1)))) (let ((str (the-substring 0 (-fx (the-length) 1)))) (escape-C-string str)))) ;; ucs2 strings ((: "#u\"" (* (or (out #a000 #\\ #\") (: #\\ all))) "\"") (let ((str (the-substring 3 (-fx (the-length) 1)))) (utf8-string->ucs2-string str))) ;; fixnums ((: (? (in "-+")) (+ digit)) (the-fixnum)) ((: "#o" (? (in "-+")) (+ (in ("07")))) (string->integer (the-substring 2 (the-length)) 8)) ((: "#d" (? (in "-+")) (+ (in ("09")))) (string->integer (the-substring 2 (the-length)) 10)) ((: "#x" (? (in "-+")) (+ (in (uncase (in ("09af")))))) (string->integer (the-substring 2 (the-length)) 16)) ((: "#e" (? (in "-+")) (+ digit)) (string->elong (the-substring 2 (the-length)) 10)) ((: "#l" (? (in "-+")) (+ digit)) (string->llong (the-substring 2 (the-length)) 10)) ;; flonum ((: (? (in "-+")) (or float (: (or float (+ digit)) (in "eE") (? (in "+-")) (+ digit)))) (the-flonum)) ;; doted pairs ("." (if (<=fx *par-open* 0) (error/location "read" "Illegal token" #\. (input-port-name (the-port)) (input-port-position (the-port))) *dotted-mark*)) ;; unspecified and eof-object ((: "#" (in "ue") (+ (in "nspecified-objt"))) (let ((symbol (string->symbol (string-upcase! (the-substring 1 (the-length)))))) (case symbol ((UNSPECIFIED) unspec) ((EOF-OBJECT) beof) (else (error/location "read" "Illegal identifier" symbol (input-port-name (the-port)) (input-port-position (the-port))))))) ;; booleans ((: "#" (uncase #\t)) #t) ((: "#" (uncase #\f)) #f) ;; keywords ((or (: ":" kid) (: kid ":")) ;; since the keyword expression is also matched by the id ;; rule, keyword rule has to be placed before the id rule. (the-keyword)) ;; identifiers (id ;; this rule has to be placed after the rule matching the `.' char (the-symbol)) ((: "|" (+ (or (out #a000 #\\ #\|) (: #\\ all))) "|") (if (=fx (the-length) 2) (the-symbol) (let ((str (the-substring 0 (-fx (the-length) 1)))) (string->symbol (escape-C-string str))))) ;; quotations ("'" (read-quote 'quote (the-port) ignore)) ("`" (read-quote 'quasiquote (the-port) ignore)) ("," (read-quote 'unquote (the-port) ignore)) (",@" (read-quote 'unquote-splicing (the-port) ignore)) ;; lists (#\( ;; if possible, we store the opening parenthesis. (if (and (vector? *list-errors*) (vector (reverse! (collect-up-to ignore "vector" (the-port))))) ;; error or eof (else (let ((port (the-port)) (char (the-failure))) (if (eof-object? char) (cond ((>fx *par-open* 0) (let ((open-key (-fx *par-open* 1))) (skribe-reader-reset!) (if (and (