bcgreek.lisp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. ;;;; bcgreek.lisp
  2. (in-package #:bcgreek)
  3. (eval-when (:compile-toplevel :execute :load-toplevel)
  4. (defparameter *decoders* '(decode-misc decode-simple-small decode-small decode-sigma decode-capital decode-catchall)))
  5. (defmacro define-bcgreek-streams ()
  6. `(defun bcgreek-decode-stream (input-stream output-stream &key (auto-final-sigma t) (j-sigma t) (case :ignore))
  7. (check-type case (member :ignore :upper :lower))
  8. (with-bc-setup
  9. (loop while (or ,@(mapcar #'list *decoders*))))))
  10. (defmacro with-bc-setup (&body body)
  11. `(let ((*standard-input* input-stream)
  12. (*standard-output* output-stream)
  13. (*auto-final-sigma* auto-final-sigma)
  14. (*j-sigma* j-sigma)
  15. (*case* case))
  16. (with-mask
  17. (with-capital-buffer
  18. ,@body))))
  19. ;;;;;;
  20. (defmacro define-char-macros ()
  21. (let ((last-read-char-v (gensym "LAST-READ-CHAR-")))
  22. `(progn
  23. (defmacro get-char ()
  24. `(setf ,',last-read-char-v (read-char nil nil)))
  25. (defmacro unread ()
  26. `(when ,',last-read-char-v
  27. (unread-char ,',last-read-char-v)
  28. (setf ,',last-read-char-v nil)))
  29. (defmacro with-get-char (&body body)
  30. `(let (,',last-read-char-v)
  31. ,@body))
  32. )))
  33. (define-char-macros)
  34. ;;;;;;;
  35. (defmacro save-char (result)
  36. `(write-char ,result))
  37. (defmacro save-string (result)
  38. `(write-string ,result))
  39. (defmacro define-decoder (name (&key return-type) &body body)
  40. `(defmacro ,name ()
  41. (let ((result-v (gensym "RESULT-")))
  42. `(with-get-char
  43. (let ((,result-v (progn
  44. ,@',body)))
  45. (if ,result-v
  46. (,',(if (eq return-type 'string) 'save-string 'save-char) ,result-v)
  47. (unread)))))))
  48. (define-decoder decode-catchall (:return-type character)
  49. (get-char))
  50. (defmacro get-normalized-char ()
  51. '(let ((char (get-char)))
  52. (if (or (null char)
  53. (and (eq *case* :lower) (upper-case-p char))
  54. (and (eq *case* :upper) (lower-case-p char)))
  55. nil
  56. (char-downcase char))))
  57. (define-decoder decode-simple-small (:return-type char)
  58. (simple-small-to-greek (get-normalized-char)))
  59. (define-decoder decode-s-sigma (:return-type char)
  60. (when (eql (get-normalized-char) #\s)
  61. (let ((c (get-normalized-char)))
  62. (cond ((null c) (if *auto-final-sigma*
  63. +final-sigma+
  64. +medial-sigma+))
  65. ((char= c #\1) +medial-sigma+)
  66. ((char= c #\2) +final-sigma+)
  67. ((char= c #\3) +lunate-sigma+)
  68. (t
  69. (unread)
  70. (if (and *auto-final-sigma* (or (find c (bc-letter-base))
  71. (and *j-sigma* (char= c #\j))))
  72. +medial-sigma+
  73. +final-sigma+))))))
  74. (define-decoder decode-j-sigma (:return-type character)
  75. (when *j-sigma*
  76. (when (eql (get-normalized-char) #\j)
  77. +final-sigma+)))
  78. (defmacro decode-sigma ()
  79. '(or (decode-s-sigma)
  80. (decode-j-sigma)))
  81. (define-decoder decode-small ()
  82. (prog1
  83. (let ((base-char (get-normalized-char)))
  84. (when (and base-char
  85. (not (char= base-char #\s))
  86. (find base-char (bc-letter-base)))
  87. (reset-mask)
  88. (let (decoded)
  89. (loop for c = base-char then (get-char)
  90. do
  91. (add-to-mask c)
  92. (let ((current-decoded (decode-mask)))
  93. (when (null current-decoded)
  94. (return))
  95. (setf decoded current-decoded)))
  96. decoded)))
  97. (unread)))
  98. (defmacro define-capital-buffer-macros ()
  99. (let ((capital-buffer-v (gensym "CAPITAL-BUFFER-")))
  100. `(progn
  101. (defmacro with-capital-buffer (&body body)
  102. `(let ((,',capital-buffer-v (make-array (capital-buffer-length) :element-type 'base-char :fill-pointer 1)))
  103. ,@body))
  104. (defmacro reset-capital-buffer ()
  105. `(setf (fill-pointer ,',capital-buffer-v) 1
  106. (char ,',capital-buffer-v 0) +capital-mark+))
  107. (defmacro add-to-capital-buffer (char)
  108. `(vector-push-extend ,char ,',capital-buffer-v))
  109. (defmacro capital-buffer-string ()
  110. ',capital-buffer-v))))
  111. (define-capital-buffer-macros)
  112. (define-decoder decode-capital (:return-type string)
  113. (let ((c (get-char)))
  114. (when (eql c +capital-mark+)
  115. (reset-capital-buffer)
  116. (reset-mask)
  117. (add-to-mask +capital-mark+)
  118. (let ((result nil))
  119. (loop
  120. (let ((c (get-char)))
  121. (add-to-mask c)
  122. (let ((decoded (decode-mask)))
  123. (case decoded
  124. ((t) (add-to-capital-buffer c))
  125. ((nil) (unread) (return))
  126. (otherwise (setf result decoded) (return))))))
  127. (or result (capital-buffer-string))))))
  128. (define-decoder decode-misc (:return-type char)
  129. (misc-bc-to-greek (get-char)))
  130. (define-bcgreek-streams)
  131. (defun bcgreek-decode (string &key (start 0) end (auto-final-sigma t) (j-sigma t) (case :ignore))
  132. (check-type case (member :ignore :upper :lower))
  133. (with-input-from-string (in string :start start :end end)
  134. (with-output-to-string (out)
  135. (bcgreek-decode-stream in out :auto-final-sigma auto-final-sigma :j-sigma j-sigma :case case))))