[Clojure]
HtmlTemplate
Clojure版のHTML::Template実装を作りたい
HTML::Templateの仕様
- HTML::Templateの仕様はここを見ればよい
- ソースコード
- 仕様
タグ | 概要 |
---|---|
TMPL_VAR | 単純な文字列補間(string interpolation) |
TMPL_LOOP | 配列で文字列補間 |
TMPL_INCLUDE | ファイルから読み取った文字列で置換する |
TMPL_IF | 条件付きの文字列補間 |
TMPL_ELSE | 条件付きの文字列補間 |
TMPL_UNLESS | 条件付きの文字列補間 |
実装方法検討
まずHTMLソースをantlrに食わせてAST(Abstract Syntax Tree)を得る
- antlerのプロジェクト内にいろいろな言語用のパーサジェネレータの元がある
- Clojureのantlerラッパーもある
- aphyr/clj-antlr ← これは実行時に文法ファイルを読めるが、単一ファイルしか処理できない
- Leiningen用のプラグインを使用してみた
HTML用の文法ファイルを使ってみる
サンプルコード
(ns html-template.core (:gen-class) (:import [org.antlr.v4.runtime ANTLRInputStream CommonTokenStream] [html_template.core HTMLParser HTMLLexer]) (:require [clojure.java.io :as io])) (defn stream [input] (new ANTLRInputStream input)) (defn html-parser [tokens] (new HTMLParser tokens)) (defn html-lexer [stream] (new HTMLLexer stream)) (defn tokens [lexer] (new CommonTokenStream lexer)) (defn -main "I don't do a whole lot ... yet." [& args] (let [stream (stream "<html>Hello,World</html>") lexer (html-lexer stream) tok (tokens lexer) parser (html-parser tok) ctx (.htmlDocument parser)] (println (.toStringTree ctx))))
出力
$ lein run ([] ([61] ([73 61] < ([81 73 61] html) > ([89 73 61] ([120 89 73 61] Hello,World)) < / ([92 73 61] html) >)))
とりあえずこれでそれっぽいものは得られた。
ASTを走査して条件にあったノードを改変する
antlrをそのまま使う?
意外に難しいようだ。まあ一度作った木構造を改変するのだからそれは難しいだろう。
Clojureのライブラリを使う?
- 最初はinstaparseのtransformを使用していたが、パターンマッチングを書くのがしんどい
その他
探してたらそれっぽいのはいろいろある
- https://github.com/hugoduncan/muir
- A Clojure AST transformation library -> muir0.1.1-SNAPSHOT library for clojure source code translation via AST
- タグではなくノードを検索対象にできそう