antlr實踐

對於寫一個本身的解析器這回事,我之前歷來沒有想過的,畢竟我學渣,並且還沒學過編譯原理。
可是沒想到到新公司居然這等美差還能落到我頭上,真是要好好感謝下大佬們。html

言歸
鄭傳java

雖然之前沒有寫過解析器,可是作過相關的事情。在之前的一家公司時曾經寫過規則,就是那種業務開始複雜後,邏輯很差寫死在程序中,須要根據業務改變,而動態配置規則。這個東西是在odoo下作的,用的它提供的asteval。python

簡而言之,就是用odoo 封裝過得eval 來執行一段 python code 而返回結果。git

而如今公司的業務需求是風控部門定義本身的風控規則,而咱們去解析這些規則。 這個就跟之前是倒過來。這裏以前沒明白爲何不用python的解釋器去解析這些規則,後面作實際作了事後才知道,這樣更面向風控規則,且能夠高於python之上。也就是說咱們能夠根據風控規則的形式,自定義一些規範,而後解析器去解析這些既定規範就好。感受高端了不少。github

比較

PLY(lexer/yacc) 是入門簡單,可是實現一些東西有難度。好比實現一個if條件判斷,須要多作一點事情。否則就會獲得錯誤的結果。好比算法

a=1; if("a") a=2 else a=4

最開始獲得的結果是4,由於ply是自下向上解析,每一個字符都會被執行到,而後你的邏輯須要單獨寫算法實現。curl

而antlr是入門困難,用起來很方便。個人比喻是ply像彙編語言,antlr是高級語言優化

安裝(OS X)

要使用antlr,須要先準備 antlr 的編譯環境。antlr 的規則是寫好詞法規則語法規則,而後用antlr去編譯生成對應語言的應用,而後再去作相應的實現就行。ui

$ cd /usr/local/lib
$ curl -O http://www.antlr.org/download/antlr-4.7-complete.jar
$ export CLASSPATH=".:/usr/local/lib/antlr-4.7-complete.jar:$CLASSPATH"
$ alias antlr4='java -jar /usr/local/lib/antlr-4.7-complete.jar'
$ alias grun='java org.antlr.v4.gui.TestRig'

語言執行環境

這裏我使用python 來實現antlr,因此我須要安裝antlr 的pyhon執行環境url

pip install antlr4-python3-runtime

or

pip install antlr4-python2-runtime

實現

異常/錯誤

詞法異常

若是你故意寫錯一個詞法, antlr 默認的詞法解析錯誤會報錯,可是會盡可能去按照正確的角度解析,結果仍是正確的!

這種咱們須要重寫它的錯誤處理,解析錯誤就扔出異常。

public class HyperRuleBailLexer extends HyperRuleLexer {
    public HyperRuleBailLexer(CharStream input) {
        super(input);
    }

    public void recover(LexerNoViableAltException e) {
        throw new RuntimeException(e);
    }
}

用HyperRuleBailLexer去實例化一個 lexer 對象

語法異常

java 跟Python 版本的語法錯誤都會拋異常,在the-definitive-antlr-4-reference書中提到了優化異常處理。在antlr4不須要咱們再去實現 BailErrorStrategy, antlr的依賴中有這個類,只須要給解析器注入下錯誤處理

HyperRuleParser parser = new HyperRuleParser(tokenStream);
parser.setErrorHandler(new BailErrorStrategy());

使用

HyperRuleParser parser = new HyperRuleParser(tokenStream);
    parser.setErrorHandler(new BailErrorStrategy());

注意:以上代碼只有在java中,python 沒有setErrorHandler 方法

參考連接

相關文章
相關標籤/搜索