antlr实践

对于写一个自己的解析器这回事,我以前从来没有想过的,毕竟我学渣,而且还没学过编译原理。
但是没想到到新公司竟然这等美差还能落到我头上,真是要好好感谢下大佬们。

言归
郑传

虽然以前没有写过解析器,但是做过相关的事情。在以前的一家公司时曾经写过规则,就是那种业务开始复杂后,逻辑不好写死在程序中,需要根据业务改变,而动态配置规则。这个东西是在odoo下做的,用的它提供的asteval。

简而言之,就是用odoo 封装过得eval 来执行一段 python code 而返回结果。

而现在公司的业务需求是风控部门定义自己的风控规则,而我们去解析这些规则。 这个就跟以前是倒过来。这里之前没明白为什么不用python的解释器去解析这些规则,后面做实际做了过后才知道,这样更面向风控规则,且可以高于python之上。也就是说我们可以根据风控规则的形式,自定义一些规范,然后解析器去解析这些既定规范就好。感觉高端了很多。

比较

PLY(lexer/yacc) 是入门简单,但是实现一些东西有难度。比如实现一个if条件判断,需要多做一点事情。不然就会得到错误的结果。比如

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

最开始得到的结果是4,因为ply是自下向上解析,每个字符都会被执行到,然后你的逻辑需要单独写算法实现。

而antlr是入门困难,用起来很方便。我的比喻是ply像汇编语言,antlr是高级语言

安装(OS X)

要使用antlr,需要先准备 antlr 的编译环境。antlr 的规则是写好词法规则语法规则,然后用antlr去编译生成对应语言的应用,然后再去做相应的实现就行。

$ 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执行环境

pip install antlr4-python3-runtime

or

pip install antlr4-python2-runtime

实现

  • 我的实现-python
  • ANTLR4: 实现一个表达式解析器 (java)

异常/错误

词法异常

如果你故意写错一个词法, 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 方法

参考链接

  • ANTLR4: 实现一个表达式解析器(java)
  • Download ANTLR

你可能感兴趣的:(antlr)