Source of Nothingness - Common Lisp : 文字列中のエスケープシーケンスを解釈する

* Common Lisp : 文字列中のエスケープシーケンスを解釈する

とりあえずできた。REPL では動作確認できた。
要 cl-interpol。
SANO さんの情報がなかったらどうにか interpol-reader を使えないか、悩んでいたかも。サンクスです。

(in-package #:cl-user)

(defpackage #:decode-escape-sequence
  (:use #:cl #:cl-interpol)
  (:export #:enable-escape-sequence
           #:disable-escape-sequence)
  (:import-from #:cl-interpol
                #:*stream*
                #:*start-char*
                #:*term-char*
                #:*pair-level*
                #:*inner-delimiters*
                #:*saw-backslash*
                #:*readtable-copy*
                #:inner-reader
                #:read-char*
                #:*previous-readtables*))

(in-package :decode-escape-sequence)

;; /* (set-macro-character #\"
;;    #'(lambda (stream char)
;;        (let ((buffer (make-array 50 :element-type 'character
;;                                     :adjustable t :fill-pointer 0)))
;;          (loop
;;            (multiple-value-bind (ch sy) (read-char-syntax stream)
;;              (cond ((eq sy 'eof-code)
;;                     (error "~S: inputstream ~S ends within a String."
;;                            'read stream))
;;                    ((eql ch char) (return (coerce buffer 'simple-string)))
;;                    ((eq sy 'single-escape)
;;                     (multiple-value-setq (ch sy) (read-char-syntax stream))
;;                     (when (eq sy 'eof-code) (error ...))
;;                     (vector-push-extend ch buffer))
;;                    (t (vector-push-extend ch buffer)))))
;;          (if *read-suppress* nil (coerce buffer 'simple-string))))) */

(defun string-reader (stream char)
  (let ((*stream* stream)
        (*start-char* char)
        (*term-char* char)
        (*pair-level* 0)
        (*inner-delimitoers* nil)
        *saw-backslash*
        *readtable-copy*)
    (prog1 
        (inner-reader nil nil nil nil)
      (read-char*))))

(defun %enable-escape-sequence ()
  (push *readtable*
        *previous-readtables*)
  (setq *readtable* (copy-readtable))
  (set-macro-character #\" #'string-reader)
  (values))

(defun %disable-escape-sequence ()
  (if *previous-readtables*
    (setq *readtable* (pop *previous-readtables*))
    (setq *readtable* (copy-readtable nil)))
  (values))

(defmacro enable-escape-sequence ()
  `(eval-when (:compile-toplevel :load-toplevel :execute)
     (%enable-escape-sequence)))

(defmacro disable-escape-sequence ()
  `(eval-when (:compile-toplevel :load-toplevel :execute)
     (%disable-escape-sequence)))

update : 2008-03-04 (Tue) 23:57:26