inline ayrıştırma

This commit is contained in:
riton
2025-03-23 20:29:26 +03:00
parent 9a09f1577c
commit d6bc48718d

274
okur.lisp
View File

@@ -19,6 +19,10 @@
:documentation "Metin indeksi") :documentation "Metin indeksi")
(uzunluk :initarg :uzunluk :accessor uzunluk (uzunluk :initarg :uzunluk :accessor uzunluk
:documentation "Metin uzunluğu") :documentation "Metin uzunluğu")
(blok-baş :accessor blok-baş :initform 0
:documentation "Bloğun başının indexi")
(blok-son :accessor blok-son :initform 0
:documentation "Bloğun sonunun indexi")
(dosya-ismi :initarg :dosya-ismi (dosya-ismi :initarg :dosya-ismi
:documentation "Okunan markdown dosyasının ismi"))) :documentation "Okunan markdown dosyasının ismi")))
@@ -27,105 +31,201 @@
(dosya-metni-oku dosya-ismi) (dosya-metni-oku dosya-ismi)
(make-instance 'okur :metin metin :uzunluk uzunluk :dosya-ismi dosya-ismi))) (make-instance 'okur :metin metin :uzunluk uzunluk :dosya-ismi dosya-ismi)))
(defmethod son? ((okur okur)) (defmethod son? ((okur okur) index)
(>= (i okur) (>= index
(uzunluk okur))) (uzunluk okur)))
(defmethod index-reset ((okur okur)) (defmethod index-reset ((okur okur))
(setf (i oo) 0)) (setf (i okur) 0
(blok-son okur) 0))
(defmethod blok-reset ((okur okur))
(setf (i okur) (blok-baş okur)))
(let ((blok-sonu (format nil "~%~%"))) (let ((blok-sonu (format nil "~%~%")))
(defmethod sonraki-blok ((okur okur)) (defmethod sonraki-blok ((okur okur))
(unless (son? okur) "blok-baş ve blok-son indexlerinin atamasını yapar. Başka blok kalmadıysa nil döndürür."
(with-slots (i uzunluk metin) okur (unless (son? okur (blok-son okur))
(let ((son (or (search blok-sonu metin :start2 i) (with-slots (i uzunluk metin blok-son blok-baş) okur
uzunluk))) (let ((önceki-son blok-son)
(prog1 (make-array (- son i) (yeni-son (search blok-sonu metin :start2 blok-son)))
:element-type 'character (setf blok-son (if (numberp yeni-son)
:displaced-to metin (+ 2 yeni-son)
:displaced-index-offset i) uzunluk)
(setf i (+ son 2)))))))) blok-baş önceki-son
i blok-baş))))))
(defmethod okur-blok-listesi ((okur okur)) (defmethod boşluk-yut ((okur okur))
(let ((blok (sonraki-blok okur))) (with-slots (i metin) okur
(if (null blok) (loop :while (char= #\Space (char metin i))
nil :do (incf i))))
(cons blok (okur-blok-listesi okur)))))
(defgeneric ayrıştır (tag blok baş) (defmethod metin-parçası ((okur okur) uzunluk baş)
(make-array uzunluk
:element-type 'character
:displaced-to (metin okur)
:displaced-index-offset baş))
(defgeneric ayrıştır (okur tag)
(:documentation "Tag'a göre bloktaki elementleri belirler.")) (:documentation "Tag'a göre bloktaki elementleri belirler."))
(defmethod ayrıştır ((tag (eql :h)) blok baş) (defmethod ayrıştır ((okur okur) (tag (eql :h)))
(let ((i baş) (with-slots (i blok-son metin) okur
(son (length blok)) (let ((h-sayı 0))
(h-sayı 0)) (loop :while (char= #\# (char metin i))
(loop :while (char= #\# (char blok i)) :do (incf i)
:do (incf i) (incf h-sayı))
(incf h-sayı)) (assert (char= #\Space (char metin i)))
(assert (char= #\Space (char blok i))) (assert (< h-sayı 7))
(assert (< h-sayı 7)) (boşluk-yut okur)
(incf i) (çocuk-node! (intern (format nil "H~D" h-sayı) "KEYWORD")
(values (make-array (- son i) (metin-parçası okur
:element-type 'character (- (or (position #\Newline metin :start i)
:displaced-to blok blok-son)
:displaced-index-offset i) i)
h-sayı))) i)))))
(defmethod ayrıştır ((tag (eql :ul)) blok baş) (defmethod ayrıştır ((okur okur) (tag (eql :ul)))
(let ((i baş) (with-slots (i blok-son metin) okur
(son (length blok))) (let ((itemler (loop :while (and (< i blok-son)
(loop :while (< i son) (not (char= #\Newline (char metin i))))
:do (assert (string= "- " blok :start2 i :end2 (+ i 2))) :do (assert (string= "- " metin :start2 i :end2 (+ i 2)))
(incf i 2) (incf i 2)
:collect (let ((yeni (or (position #\Newline blok :start i) :collect (let ((yeni (or (position #\Newline metin :start i)
son))) blok-son)))
(prog1 (make-array (- yeni i) (prog1 (metin-parçası okur (- yeni i) i)
:element-type 'character (setf i (+ yeni 1)))))))
:displaced-to blok (ebeveyn-node! :ul
:displaced-index-offset i) (mapcar (lambda (item)
(setf i (+ yeni 1))))))) (çocuk-node! :li item))
itemler)))))
(defmethod ayrıştır ((tag (eql :ol)) blok baş) (defmethod ayrıştır ((okur okur) (tag (eql :ol)))
(let ((i baş) (with-slots (i blok-son metin) okur
(son (length blok)) (let ((item-sayısı 1))
(item-sayısı 1)) (let ((itemler
(loop :while (< i son) (loop :while (and (< i blok-son)
:do (let ((i2 i)) (not (char= #\Newline (char metin i))))
(loop :while (char<= #\0 (char blok i2) #\9) :do (let ((i2 i))
:do (incf i2)) (loop :while (char<= #\0 (char metin i2) #\9)
(assert (string= ". " blok :start2 i2 :end2 (+ i2 2))) :do (incf i2))
(assert (= item-sayısı (parse-integer blok :start i :end i2))) (assert (string= ". " metin :start2 i2 :end2 (+ i2 2)))
(incf item-sayısı) (assert (= item-sayısı (parse-integer metin :start i :end i2)))
(setf i (+ i2 2))) (incf item-sayısı)
:collect (let ((yeni (or (position #\Newline blok :start i) (setf i (+ i2 2)))
son))) :collect (let ((yeni (or (position #\Newline metin :start i)
(prog1 (make-array (- yeni i) blok-son)))
:element-type 'character (prog1 (metin-parçası okur (- yeni i) i)
:displaced-to blok (setf i (+ yeni 1)))))))
:displaced-index-offset i) (ebeveyn-node! :ol
(setf i (+ yeni 1))))))) (mapcar (lambda (item)
(çocuk-node! :li item))
itemler))))))
(defmethod ayrıştır ((tag (eql :code)) blok baş) (defmethod ayrıştır ((okur okur) (tag (eql :code)))
(let ((son (length blok)) (with-slots (i metin blok-son blok-baş) okur
(kod-baş (+ baş 3)) (let ((kod-baş (+ blok-baş 3)))
(kod-son (- (length blok) 3))) (assert (string= "```" metin :start2 blok-baş :end2 kod-baş))
(assert (string= "```" blok :start2 baş :end2 kod-baş)) (let ((kod (metin-parçası okur
(assert (string= "```" blok :start2 kod-son :end2 son)) (- (search "```" metin :start2 kod-baş)
(make-array (- kod-son kod-baş) kod-baş)
kod-baş)))
(ebeveyn-node! :pre
(list (çocuk-node! :code
kod)))))))
(defgeneric inline-ayrıştır (okur tag son)
(:documentation "Paragraf içindeki elementleri ayrıştırır"))
(defmethod inline-ayrıştır ((okur okur) tag str)
(with-slots (i metin blok-son) okur
(let ((son (search str metin
:start2 i
:end2 blok-son)))
(prog1 (çocuk-node! tag (metin-parçası okur (- son i) i))
(setf i (+ son (length str)))))))
(defmethod link-ayrıştır ((okur okur))
(with-slots (i metin blok-son) okur
(let* ((son (search "]" metin
:start2 i
:end2 blok-son))
(link-metni (metin-parçası okur (- son i) i)))
(setf i (+ son 1))
(assert (char= #\( (char metin i)))
(incf i)
(let ((son (search ")" metin
:start2 i
:end2 blok-son)))
(prog1 (çocuk-node! :a (metin-parçası okur (- son i) i)
(list :href link-metni))
(setf i (+ 1 son)))))))
(defmethod paragraf-ayrıştır ((okur okur))
(with-slots (i blok-son metin) okur
(let ((elementler (list))
(baş i))
(labels ((pushla-ve-ayrıştır (tag str)
(push (metin-parçası okur (- i baş) baş) elementler)
(incf i (length str))
(push (inline-ayrıştır okur tag str) elementler)
(setf baş i)))
(loop :while (< i blok-son)
:do (case (char metin i)
(#\[ (if (char= #\( (char metin (+ 1 (position #\] metin :start i))))
(progn
(push (metin-parçası okur (- i baş) baş) elementler)
(incf i 1)
(push (link-ayrıştır okur) elementler)
(setf baş i))
(incf i)))
(#\` (pushla-ve-ayrıştır :code "`"))
(#\_ (pushla-ve-ayrıştır :i "_"))
(#\* (if (char= #\* (char metin (+ i 1)))
(pushla-ve-ayrıştır :b "**")
(pushla-ve-ayrıştır :i "*")))
(t (incf i)))
:finally (when (/= baş i)
(push (metin-parçası okur (- i baş) baş) elementler)))
(ebeveyn-node! :p (reverse elementler))))))
(defmethod blok-ayrıştır ((okur okur))
(when (sonraki-blok okur)
(with-slots (i metin) okur
(boşluk-yut okur)
(case (char metin i)
(#\# (ayrıştır okur :h))
(#\- (ayrıştır okur :ul))
(#\` (ayrıştır okur :code))
(#\> "")
(t (if (char<= #\0 (char metin i) #\9)
(ayrıştır okur :ol)
(paragraf-ayrıştır okur)))))))
(defmethod tümünü-ayrıştır ((okur okur))
(let ((blok-node (blok-ayrıştır okur)))
(if (null blok-node)
nil
(cons blok-node (tümünü-ayrıştır okur)))))
(defparameter *okur* (okur! "/home/riton/projects/html-jen/cheat.md"))
(defmethod blok-yazdır ((okur okur) &optional (stream *standard-output*))
(write-sequence (metin okur) stream
:start (blok-baş okur)
:end (blok-son okur))
(values))
(defmethod blok-metni ((okur okur))
(with-slots (blok-son blok-baş metin) okur
(make-array (- blok-son blok-baş)
:element-type 'character :element-type 'character
:displaced-to blok :displaced-to metin
:displaced-index-offset kod-baş))) :displaced-index-offset blok-baş)))
(defun blok-ayrıştır (blok) (defmethod okur-blok-listesi ((okur okur))
(let ((i 0)) (loop :while (sonraki-blok okur)
(loop :while (char= #\Space (char blok i)) :collect (blok-metni okur)))
:do (incf i))
(case (char blok i)
(#\# (ayrıştır :h blok i))
(#\- (ayrıştır :ul blok i))
(#\` (ayrıştır :code blok i))
;; (#\> :blockquote)
(t (if (char<= #\0 (char blok i) #\9)
(ayrıştır :ol blok i)
:p))
)))