语法解析器生成工具

有很多生成解析器/编译器的工具,帮你来实现自定义的语言(DSL)。

  • yacc Yet Another Compiler Compiler
  • jacc just another compiler compiler fro Java,
  • ANTLR ANother Tool for Language Recognition

下面主要介绍的是Antlr。

Anltr简介

Antlr的作者是 Terence Parr ,关于他的介绍见Anltr之父 (很励志的成长经历)。他说这个命名是在看了平头哥(蜜獾,话说马云也很赞赏这种勇猛的动物)的视频后想到的,无所畏惧,逮啥吃啥。无论你给啥语法来,都不在话下。

ANTLR v4 is named the “Honey Badger” release after the fearless hero of the YouTube sensation, “The Crazy Nastyass Honey Badger,” It takes whatever grammar you give it; it doesn’t give damn!

参考资料:

  • ANTLR 官方网址 http://www.antlr.org/
  • ANTLR 官方 Github https://github.com/antlr/antlr4
  • 大量语法文件例子 https://github.com/antlr/grammars-v4

Antlr是有很多编辑开发的工具,包括常用的IDE插件都有。

简单介绍下使用,主要有两部分工作,先是用antlr的语法来描述解析规则,用antlr的工具来生成解析器的代码;第二步就看通过扩展生成的解析器代码调用这个解析器了。

解析过程简单来说,就是词法解析Lexer,把输入字符解析成tokens,再通过语法解析Parser得到语法树。如下图:

简单体验一下Antlr的使用

就用最朴素的例子来体验一下

1、下载antlr工具包

目前版本是 antlr-4.7.1-complete.jar,地址如下:

https://www.antlr.org/download/antlr-4.7.1-complete.jar

2、编写语法的描述文件

描述文件一般是以.g4为后缀的。

注意这里例子是一个整数加减法的计算器,Calc.g4

我只做了一些简单注解。

grammar Calc;   //名称需要和文件名一致s : expr EOF;   //解决问题: no viable alternative at input '<EOF>'expr: expr '+' expr     #add   //标签会生成对应访问方法方便我们实现调用逻辑编写| expr '-' expr     #sub| INT               #int;INT : [0-9]+                   //定义整数;WS : [ \r\n\t]+ -> skip      //跳过空白类字符;

3、用Antlr的工具来生成类

$ java -cp antlr-4.7.1-complete.jar org.antlr.v4.Tool Calc.g4

当然你可以配置别名(unix下)或批处理脚本(win下)来简化执行命令,详见其入门文档

执行完生成,目录下会多出以下文件

Calc.interp
Calc.tokens
CalcBaseListener.java
CalcLexer.interp
CalcLexer.java
CalcLexer.tokens
CalcListener.java
CalcParser.java

运行时只需要java文件,编译成class

$ javac -cp antlr-4.7.1-complete.jar Calc*.java

这时我们可以通过工具看看我们的解析器代码是否能正常工作了。

$ java -cp antlr-4.7.1-complete.jar:. org.antlr.v4.gui.TestRig Calc expr -tree

注意windows下的classpath的分隔符是;而unix的是:

-cp antlr-4.7.1-complete.jar;.

接下来输入一个表达式,回车换行,然后输入一个EOF,在win下是^Z,在unix下是^D,会输出解析后的表达式。

$ java -cp antlr-4.7.1-complete.jar:. org.antlr.v4.gui.TestRig Calc expr -tree
1+2
(expr (expr 1) + (expr 2))

当然你可以把 -tree 参数换成 -gui,会在你输入EOF后弹出一个GUI的窗口展示解析的树,非常直观。

4、编写访问逻辑

这里需要创建一个java工程或使用IDE工具(如:eclipse)比较方便,当然也可以仍在命令行终端搞定这一切。

要运行执行解析器,只需要antlr4-runtime的jar即可。如果你在IDE工程中,只需要加入POM中这个依赖就行;然后把生成的.java文件拷贝到工程当中即可。

<dependency><groupId>org.antlr</groupId><artifactId>antlr4-runtime</artifactId><version>4.7.1</version>
</dependency>

如果需要生成的代码有包路径,在生成命令中可以通过-package来指定。
我这里使用默认包,也就是没有指定包名。

继续回到命令行环境,我们需要编写一个CalcExecuteListener类,继承CalcBaseListener类,通过覆盖(或者说实现)几个访问方法来达到访问我们解析表达式生成的语法树(AST)。

注意,Antlr对语法树访问提供两种模式Visitor和Listener。默认是生成Listener模式代码。这种模式实现了事件访问机制的调用。

其实也可以直接修改生成的CalcBaseListener类,实现其中的需要的方法,但是在修改的表达式定义后,重新生成代码会需要重新修改。所以一般不直接修改生成的代码,而是继承。

CalcExecuteListener.java 如下:

import java.util.Stack;public class CalcExecuteListener extends CalcBaseListener {Stack<Integer> stack = new Stack<>();@Overridepublic void exitInt(CalcParser.IntContext ctx) {stack.add(Integer.parseInt(ctx.INT().getText()));}@Overridepublic void exitAdd(CalcParser.AddContext ctx) {int r = stack.pop();int l = stack.pop();stack.add(l + r);}@Overridepublic void exitSub(CalcParser.SubContext ctx) {int r = stack.pop();int l = stack.pop();stack.add(l - r);}public int result() {return stack.pop();}
}

然后我们写一个测试类,来调用一下

T.java

import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CodePointCharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;public class T {public static int exec(String input) {CodePointCharStream cs  = CharStreams.fromString(input);CalcLexer lexer = new CalcLexer(cs);CommonTokenStream tokens = new CommonTokenStream(lexer);CalcParser parser = new CalcParser(tokens);ParseTree tree = parser.expr();ParseTreeWalker walker = new ParseTreeWalker();CalcExecuteListener listener = new CalcExecuteListener();walker.walk(listener, tree);return listener.result();}public static void main(String[] args) {String input = "1+2";System.out.println(exec(input));}}

编译一下,然后执行

$ javac -cp antlr-4.7.1-complete.jar:. CalcBaseListener.java T.java
$ java -cp antlr-4.7.1-complete.jar:. T

输出了结果,看起挺顺利。

3

你可以尝试修改input的值,比如: 1+2+3试试。

至此,一个简单的解释模式表达式解析器就完成了,感觉还不错吧。为了提高执行效率,我们还可以实现访问语法树时,生成一个调用栈,来实现编译模式。

只不过目前的例子里表达式都是常量。如果当一个表达式中包含执行上下文中带来的变量,这个表达式会多次执行的时候,我们就可以用提前编译,在后续执行时省去解析语法树过程,从而加速执行速度。

Antlr4的使用简介相关推荐

  1. Skywalking-07:OAL原理——解释器实现

    OAL 解释器实现 OAL 解释器是基于 Antlr4 实现的,我们先来了解下 Antlr4 Antlr4 基本介绍 Antlr4 使用案例 参考Antlr4的使用简介这篇文章,我们实现了一个简单的案 ...

  2. Spark-SQL解析

    文章目录 Spark-SQL解析 Antlr4 一.简介 1.词法分析阶段 (lexical analysis) 2.解析阶段 二.语法 三.编译 四.遍历模式 1.Listener(观察者模式) 2 ...

  3. 第一章:antlr4 简介

    antlr4 简介 ANTLR(全名:ANother Tool for Language Recognition)是基于LL(*)算法实现的语法解析器生成器(parser generator),用Ja ...

  4. anltr oracle,Antlr4官方参考手册

    [实例简介] Antlr4 文档 参考手册 官方 Early Praise for The Definitive ANTLR 4 Reference Parrs clear writing and l ...

  5. 使用antlr4及java实现snl语言的解释器

    对于antlr4的基础使用,请参考我的前一篇文章<用antlr4来实现<按编译原理的思路设计的一个计算器>中的计算器>. 其实我对于antlr4的理解也仅限于那篇文章的范围,但 ...

  6. ANTLR4基本语法

    原文地址:ANTLR4基本语法 ANTLR4简介 ANTLR4是一个用于构建语法解析器.编译器和其他语言处理工具的强大工具.ANTLR是"Another Tool for Language ...

  7. Antlr4入门(安装、配置、简单实例)

    Antlr4入门(安装.配置.简单实例) 2020.5.28 仅本人初次使用Antlr4的经历分享 目前所知有3种使用Antlr4的方式: 通过命令行使用: 在Eclipse中安装Antlr4插件:( ...

  8. antlr4 简单实用入门——(一)

    Antlr4 简介 简介 Antlr4 是一款强大的语法生成器工具,可用于读取.处理.执行和翻译结构化的文本或二进制文件.基本上是当前 Java 语言中使用最为广泛的语法生成器工具.Twitter搜索 ...

  9. antlr4 for linux,ANTLR v4 安装以及试用 For Linux

    ANTLR 简介 ANTLR-Another Tool for Language Recognition,Antlr 本身是使用 Java 开发的,它为包括Java,Python,C#在内的语言提供了 ...

最新文章

  1. 2017先知创新大会:有ZHI而来
  2. 从个人到团队:思维转变是关键
  3. 按指定格式拼接字符串
  4. c语言 增删查 案例,C语言实现单链表的增删查改
  5. Cgroup 好文集合
  6. Eric6最简单的应用(创建一个项目-窗体-编译-运行)
  7. qml 信号槽第二次才响应_QML中各种代理的用法
  8. 牛客网Java刷题知识点之调用线程类的start()方法和run()方法的区别
  9. 9月TIOBE编程语言排行榜出炉,这个语言或成最大赢家!
  10. html图表插入ppt
  11. Java:1加到100的算法
  12. C++实现简单数独游戏
  13. C++图书ISBN码校验
  14. MaratonIME plays Cîrokime
  15. 第四章(1.2)机器学习——在web攻击检测中的应用实践
  16. 数字逻辑复习(Wust)
  17. 怎么录制视频声音,什么录音软件好用
  18. java时间加30天_java实现,怎么在当前时间往后推三十天
  19. Nature子刊:AI技术从零开始设计具有生物活性的蛋白质
  20. 大夏天解渴,喝茶,喝凉白开

热门文章

  1. docker wireguard
  2. 要警惕眼睛有红血丝和黑点!
  3. android高德SDK,Marker的zIndex导致的遮罩层问题解决
  4. python程序设计教程 清华大学出版社下载-清华大学出版社-图书详情-《Python程序设计(第3版)》...
  5. Django:使用QuerySet删除和查询数据表
  6. win10计算机服务打不开,win10系统计算器打不开闪退的解决方法
  7. 树莓派安装系统详细步骤
  8. 腾讯云公网负载均衡技术实现详解
  9. 房产税费计算2022
  10. mysql数据迁移数据一致性检校验