最近在思考爲如何xsoup添加自定義函數支持,基於這個目的,想起了最經常使用的模板引擎freemarker。因而down了源碼下來,開始瀏覽一番。本文基於https://github.com/freemarker/freemarker上的2.3.20版本。java
看源碼前,先思考一下,一個模板引擎,到底須要哪些東西?一門模板引擎實際上是一個完整的語言,只不過它只具備單純的輸入/輸出,不須要考慮其餘的功能。node
語法解析,轉換爲AST(抽象語法樹)git
語義分析,爲AST附加上執行語義github
上下文環境的注入框架
內置函數及外部函數支持函數
其餘外圍機制(與框架/工具的集成等)工具
打開freemarker的代碼,core包裏110個類一字排開,還有如下劃線開頭的「建議不要看」的類,看的人眼花繚亂啊!這一切都是由於Java規範的大師們,設計了一個「包級可見「的概念,大概就是,我寫給本身用的代碼,不要讓你用!這一來,別人用是用不了了,好像看起來也變得很困難了…ui
還好如今的IDE都很強大,刷刷兩下就給重構了,把一些類按照類型挪到多個包裏,頓時清爽不少!惋惜好多類/方法/字段都是包級可見,爲了讓這個重構版freemarker沒那麼多紅叉,lz加了好幾百個public,寫到意識都模糊了…最後把本身的勞動成果共享出來吧:https://github.com/code4craft/freemarker-learning。主要是將freemarker.core包裏內容拆開了,語法樹相關的內容放到了freemarker.core.nodes包,異常放到了freemarker.core.exception包,一些模板內置功能放到了freemarker.core.buildin包,還有工具類放到了freemarker.core.util包。.net
順便將freemarker的流程整理了一下:設計
這是一個很經典的模板引擎的執行流程:
freemarker使用了JavaCC(Java Compiler Compiler)作parser。關於JavaCC,有一篇很好的入門帖,順帶複習一下編譯原理:LL(0)文法,消除左遞歸等東西。http://cs.lmu.edu/~ray/notes/javacc/
JavaCC的下載在這裏:http://javacc.java.net/,不知是我操做失誤仍是怎樣,下載JavaCC-6.0以後,bin目錄只有lib/javacc.jar文件。下載JavaCC-5.0src以後,才找到javacc腳本。難道就這麼幾百K的東西,還要搞增量更新?
總之下載成功以後,用javacc FTL.jj,便可生成一堆Parser文件。核心是FMParser,解析完的語法樹在FMParser.root()裏。