2008年1月24日木曜日

Chapter 30 Practical: An HTML Generation Library, the Interpreter

気をとりなおして。
30章と31章については、各節のエッセンスをメモしていく形にします。


前説


  • Interpreter : FOOプログラムを受け取って、HTMLを生成する。
  • Compiler : FOOプログラム(CL埋め込みあり)を受け取って、CLのコードを生成する。



Designing a Domain-Specific Language

DSL設計は2段階。

  • DSLの構文というか書きぶりを決める。
  • それの処理系を実装する。


DSLの設計のポイントは、DSLによっていかに表現が「圧縮」されるかということ。


The FOO Language


  • Lisp objectsを基礎におく。
  • self-evaluating lisp objectsは、PRINC-TO-STRINGで変換したものをFOOでは出力する。このとき<>などのエスケープも行う。
  • HTMLの要素名をキーワードシンボルとする。キーワードシンボルを第一要素とするリストを、HTMLの要素に対応させる。
  • 属性は次の2つの表現が可能とする。
    表現1 (:p :id "x" "Foo")
    表現2 ((:p :id "x") "Foo")


Character Escaping


  • 要素と属性でエスケープ対象文字が異なる。
  • 対象文字を、*element-escape*, *attribute-escape*に格納する。
  • *escape*に場所場所でどちらかを割り当てるなどの運用をする。



Indenting Printer


  • indenting-printerというクラスに情報を格納してindentを制御する。
  • ただし、indenting-printerのindentation slotに入っている値に対応してindentするというだけの機構。
  • 文字列をindentして出力するための基本関数を定義。

    (defun emit (ip string) ...)
    (defun emit/no-newlines (ip string &key (start 0) end) ...)
    (defun indent-if-necessary (ip) ...)
    (defun emit-newline (ip) ...)
    (defun emit-freshline (ip) ...)




HTML Processor Interface


  • HTML Processorのインターフェイスは総称関数で定義する。
  • これはInterpreterとCompilerの両方に対応するため。
  • 総称関数は次の8つ。

    (defgeneric raw-string (processor string &optional newlines-p))
    (defgeneric newline (processor))
    (defgeneric freshline (processor))
    (defgeneric indent (processor))
    (defgeneric unindent (processor))
    (defgeneric toggle-indenting (processor))
    (defgeneric embed-value (processor value))
    (defgeneric embed-code (processor code))




The Pretty Printer Backend


  • html-pretty-printerというクラスを導入する。これは、slotにindenting-printerとtab-widthをもつ。
  • 前章の総称関数に対するメソッドの定義をする。そのとき、Indenting-printer節で定義した基本関数が使える。
  • embed-valueとembed-codeとは、Compilerのみで使用する。Interpreterではerrorとなるようにする。



The Basic Evaluation Rule


  • 評価としては、まずself-evaluatingならば、raw-string関数にわたす。
  • そうでなければ、それはFOO言語のcons-sexp形式となる。
  • process-cons-sexp-html関数を導入する。
  • この関数は、HTMLタグ出力、その中身の出力、インデントの管理、改行の管理を担当する。
  • これの振舞の観点から、HTML要素は3つに分類できる。

    (defparameter *block-elements* '(:body :colgroup ...))
    (defparameter *paragraph-elements* '(:area :base :blockquote ...))
    (defparameter *inline-elements* '(:a :abbr ...))

  • この他に2つの補足的分類がある。

    (defparameter *empty-elements* '(:area :base :br ...))
    (defparameter *preserve-whitespace-elements* '(:pre :script ...))

  • この分類を利用して、process-cons-sexp-htmlを実装する。
  • process関数を直に呼ぶのでは手間なので、emit-html関数を導入して省く。
  • *html-ouput*自身をAPIとして公開したくはないので、with-html-ouputマクロを導入して隠蔽する。



What's Next?

特になし。

0 件のコメント: