Grammarinator:基于ANTLR4语法自动生成语句

Posted cdai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Grammarinator:基于ANTLR4语法自动生成语句相关的知识,希望对你有一定的参考价值。

Grammarinator是一个基于ANTLR 4的grammar文件,自动生成语句的开源项目:https://github.com/renatahodovan/grammarinator。从语言的grammar生成语句或者所谓的Fuzzy Testing,对软件测试很帮助。就像Grammarinator的README里所说,它已经帮助一些项目发现了很多缺陷。本文通过一个简单例子,让大家先了解一下它是如何安装和使用,是用来做什么的。至于背后的理论,则还需要花时间深入学习。


1.安装

Grammarinator的安装不是很复杂,以下是我在Linux Mint 19上的安装过程,主要依赖是Python3。一开始尝试用pip3安装,GitHub上说这样比较简单。但不知道为什么会报错,没安装成功。没办法还是clone源码安装吧,最后终于成功。

#Install with pip3
$ sudo apt-get install -y python-setuptools
$ pip3 install grammarinator

#Install from source
$ git clone https://github.com/renatahodovan/grammarinator.git
$ cd grammarinator
$ sudo python3 setup.py install

安装成功后应该会有两个命令,grammarinator-processgrammarinator-generate,自动加到你的path里。我们会在下一部分使用这两个命令,来从ANTLR的grammar文件自动生成语句。


2.使用

下面已OpenDistro SQL项目为例,看看如何利用其中的ANTLR grammar自动生成合法的语句。注意:src/main/antlr/OpenDistroSqlParser.g4因为疏忽,没有在Lexer的g4文件中定义DATE。在ANTLR里不是问题,但Grammarinator不允许这种情况,所以先注释掉Parser.g4中使用DATE的那一行避免Grammarinator抛异常。

$ git clone https://github.com/opendistro-for-elasticsearch/sql.git
$ cd sql

$ grammarinator-process src/main/antlr/OpenDistroSqlLexer.g4 src/main/antlr/OpenDistroSqlParser.g4 -o unparser
$ grammarinator-generate -l unparser/OpenDistroSqlUnlexer.py -p unparser/OpenDistroSqlUnparser.py -r selectStatement -n 100 -d 20 -o tests/test_%d.txt -t grammarinator.runtime.simple_space_transformer

可以看到Grammarinator是分两步走的,第一步先生成所谓的Unlexer和Unparser。两者都是Python文件,包含了两个类,可以供我们自行扩展和修改。第二步才是真正的自动生成。我们需要通过命令行参数指定:

  • -l:第一步生成的Unlexer文件的位置
  • -p:第一步生成的Unparser文件的位置
  • -n:我们想生成的总的语句个数
  • -d:我们想在grammar这些rule里递归的深度。比如SQL因为可以自由组合Subquery,所以需要depth选项控制深度。
  • -o:我们想把语句生成到哪,文件名是什么样子。
  • -t:可以额外指定transformer,比如官方提供了一个必选的simple_space_transformer。它会自动加空格,否则Gramminator生成的文本不会用空格间隔。
cat tests/test_274439899472822055781341517707794922780.txt
SELECT * , NESTED ( .FEFB   . `?઄?`   . * )   FROM ( `ኊ??`  / MIN      )  , .WUMON   *  ""    NATURAL LEFT JOIN .CBG   / `?ᜀ?`     NATURAL JOIN ( ( `꣚??`  / `???᏾`   `?଺?¢`   )   )     WHERE \\N    LIKE NOT \\N     < =  ~  NULL      IS NOT TRUE  | |  NULL    IS MISSING ...

3.深入

别看Grammarinator在GitHub上的Star并不多,它本身是有扎实的理论基础的。因为从grammar生成合法语句这件事并不那么简单,比如:

  1. 左递归:grammar中经常会有left recursion,ANTLR和Grammarinator都会自动处理。如果要自己做的话,除了控制深度,左递归也是要考虑的一点。
  2. 收集语句:需要知道在哪一点是可以把当前的语法树作为合法语句保存起来,这不是简单的递归遍历语法的Token和Rule那样简单。

如果感兴趣想要深入学习的话,请看Grammarinator作者们写的这篇论文以及最后reference部分引用的其他论文:<Grammarinator: A Grammar-Based Open Source Fuzzer>。这部分资料貌似不是很多,自己搜索的话也基本就是这几篇论文了。

以上是关于Grammarinator:基于ANTLR4语法自动生成语句的主要内容,如果未能解决你的问题,请参考以下文章

ANTLR4 如何编写语法文件之语法词汇

ANTLR4 如何编写语法文件之语法词汇

ANTLR4入门:使用mave ANTLR4插件(antlr4-maven-plugin)执行语法解析生成器

ANTLR4入门:使用mave ANTLR4插件(antlr4-maven-plugin)执行语法解析生成器

Antlr4,如何报告特定的语法错误

使用Antlr4和neo4j解析sql生成数据地图