Talk about compiler and parser
會注意到 LLVM 是剛開始在學 XCode 時, 在 build settings 裡出現 Apple LLVM 6.0, 裡面有很多項目, 像是 Code Generation, Language, Modules, Preprocessing, Warning, … etc, 其實不是很了解他的明白. 不過後來在看 台灣軟體產業的失落十年 這本書時, 作者也提到 LLVM, 找了一些資料來讀, 像是 LLVM 總是打開你的心:從電玩模擬器看編譯器應用實例, 我才意會到這東西是了不起的概念.
- LLVM 實作最成功的就是 clang, 它是 Mac OS 上預設的 C/C++/Objective-C compiler.
- FreeBSD 10 預設 compiler 改用 clang
土法煉鋼
以前做過一個 product 有一段功能是需要 convert COBOL to Java. Code 有一段用 yacc 產生 COBOL parser, 每次看到這段都不知道在做啥 … 只知道 yacc 以前修 unix 時老師有提過 … 反正大概就是 parser 的東西. 那時候 code 的架構很大, 抽象了很多層, 就是練功的過程.
後來自己在寫 test framework 時, 為了讓 test case 的配置檔,也就是 config 更靈活、更有彈性,設計、實作類似 java annotation 的 “語法”, 然後用 python 實作了一個小 parser, 這個 parser 實作以下功能:
- config 的資料結構定義,基本上是
key
/value
概念,也支援 list,但可讀性沒有 json or yaml 那麼好。 - config 包還繼承功能,實際應用是 testcase config 會繼承 testsuite config.
- config 繼承包含 overwrite 概念
- config 支援 annnotation ,也就是 AOP
- annotation 支援 key value, attributes 等概念
- config 本身在 test framework 裡面是 DI/IOC 的實作概念。
過程中遇到很多問題, 像是 syntax scanner (LLVM: Implementing a Language ch1 提到的 Lexer), 也就是要檢查整個 code 的語法正確性 / 合法性, 當使用者 code 寫錯了, 要跟使用者說, 錯在哪一行, 錯誤是什麼. 下圖是當時設計時寫的部分 design, 主要是在定義 syntax 的部分:
實作的過程, 想很多很多東西, 整個語法應該是有個結構性 / 相依性 / 參考點, 像 XML Schema 那樣的 meta 定義, 後來才知道有 AST (Abstract Syntax Tree, ch2) 這種概念.
- Eclipse 有一個 plugin, 就叫做 AST, 用來分析 Java 語法結構. 吃一個 java code, 就會產生 AST tree
- 這段實作的目的與設計參閱 Designing Test Architecture and Framework 的說明。
後來前面兩個都做完, 想到應該要可以擴充, 除了 pre-defined 的 keyword, 也要讓使用者可以自訂, 就像 java 只要宣告 @interface
就可以了. 所以整個 parser 又砍掉重練好幾次 (四到五次有吧), 最後因為換工作關係, 沒有繼續完成它.
這是一個有趣的經驗, 雖然是土法煉鋼, 但是過程中也讓我一直在思考, 如何真的做一個有用的東西, 更有效率的解決問題, 另外就是原來 compiler / parser 的背後, 有這麼多學問在.
後記
後來有發現一些工具可以做類似的事情, 像是 DSL, Domain-specific language, Eclipse 3.7 開始有的 xtext, JVM language: groovy 的 DSL (gradle 就是應用案例之一). 這些應用其實就是我當時在做 test framework 時, 後來可以用來改善的工具與方法.
延伸閱讀 (站內)
推薦閱讀
- LLVM: Implementing a Language
- The Architecutre of Open Source Applications
- LLVM 總是打開你的心:從電玩模擬器看編譯器應用實例
- How A Compiler Works: GNU Toolchain