« HTML + CSS で数式組版 (その4) | トップページ | HTML + CSS で数式組版 (その6) »

2009年3月20日 (金)

HTML + CSS で数式組版 (その5)

引数解析で、色々ハマりました^^)

変更箇所

(setf *match-argbegin* "{")
(setf *match-argend* "}")
(setf *match-text* "[^ \\{}]+")


(defun parse-string (str elems se)
  (if (> (length str) 0)
      (let ((m (match-token str)))
        (let ((mb (car m))
              (me (cadr m))
              (spec (caddr m)))
        (if mb
            (let ((se2 (+ se me)))
              (cond
               ((eq spec 'keyargs)
                (cons (parse-keyword (substring str mb me) se2)
                      (parse-string (substring str me) elems se2)))
               ((eq spec 'argbegin)
                (let ((args (parse-args (substring str me) se2)))
                  (let ((se3 (parse-end args)))
                    (cons args
                          (parse-string
                           (substring str (+ (- se3 se2) 1))
                           elems se3)))))
               ((eq spec 'argend)
                (cons (list spec se2 (substring str mb me)) nil))
               ((eq spec 'text)
                (cons (list spec se2 (substring str mb me))
                      (parse-string (substring str me) elems se2)))))
          (parse-string (substring str 1) elems (+ se 1)))))))

引数解析を行なう関係で、 parse-string 関数を色々と書き換えました。トークンの種類別に処理を行なう、というのと、解析対象の文字列をどこまで読んだか判るように、引数・戻り値にそれぞれ文字位置を追加しました。

追加箇所

(defun parse-end (ast)
  (cond ((atom ast) 0)
        ((atom (car ast)) (max (cadr ast) (parse-end (caddr ast))))
        (t (max (parse-end (car ast)) (parse-end (cdr ast))))))

(defun parse-args (str se)
  (let ((succ (parse-string str nil se)))
    (if (eq succ nil)
        (list 'argbegin se (list (+ se 1) nil))
      (list 'argbegin se succ))))

parse-end 関数は、解析結果を受け取って、文字列からどこまでトークンを読み込んだか、その最後の文字位置を返します。

ここは、 グローバル変数を使おうかと 悩みました。単に文字位置を取るためにリストを走査するっていうのがね。作り方間違ったかな? ま、とりあえずこうしておいて、後でまた考えるということで。

parse-args 関数は、 parse-string 関数が、引数のカッコを見つけたときに呼ばれる関数です。

こうなりました:

(parse-string "{a}{b}" nil 0)
=>
((argbegin
  1 ((text 2 "a") (argend 3 "}")))
 (argbegin
  4 ((text 5 "b") (argend 6 "}"))))

(parse-string "{a{b}}{c}" nil 0)
=>
((argbegin
  1 ((text 2 "a")
     (argbegin 3 ((text 4 "b") (argend 5 "}")))
     (argend 6 "}")))
 (argbegin 7 ((text 8 "c") (argend 9 "}"))))

(parse-string "{a{b{c}}}{d{e}}" nil 0)
=>
((argbegin
  1
  ((text 2 "a")
   (argbegin
    3
    ((text 4 "b")
     (argbegin 5 ((text 6 "c") (argend 7 "}")))
     (argend 8 "}")))
   (argend 9 "}")))
 (argbegin
  10
  ((text 11 "d")
   (argbegin 12 ((text 13 "e") (argend 14 "}")))
   (argend 15 "}"))))

|

« HTML + CSS で数式組版 (その4) | トップページ | HTML + CSS で数式組版 (その6) »

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/80472/28719086

この記事へのトラックバック一覧です: HTML + CSS で数式組版 (その5):

« HTML + CSS で数式組版 (その4) | トップページ | HTML + CSS で数式組版 (その6) »