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 方法

参考连接

相关文章
相关标签/搜索