2018-01-15 Antlr4: 修改语法规则更接近普通BNF格式
经 @沈默 在上文Antlr4添加中文变量赋求值,括号,各种问题评论中指出, 语法规则描述依赖于Antlr4生成的语法分析器的默认分析方法, 比如运算符的左联系, 以及优先级处理等等. 于是将语法修改为下面(源码版本号: program-in-chinese/quan5):
表达式: 求积表达式 (('+'|'-') 求积表达式)*;
求积表达式: 最小表达式 (('*'|'/'|'×'|'÷') 最小表达式)*;
最小表达式
: 字面量
| '(' 表达式 ')'
;
字面量
: T数
| T变量名
;
这样做的结果是, Antlr4会分析生成一个多叉树. 比如 1+2-3, 生成树如下:

于是在生成抽象语法树时手动转换为二叉树. 代码如下:
private 节点 构建二叉树(List<ParseTree> 子节点) {
if (子节点.isEmpty()) {
return null;
} else if (子节点.size() == 1) {
return visit(子节点.get(0));
} else {
ParseTree 最后运算符节点 = 子节点.get(子节点.size() - 2);
运算符号 运算符 = ((TerminalNodeImpl)最后运算符节点).symbol.getType() == 圈5Parser.T加 ? 运算符号.加 : 运算符号.減;
运算式节点 节点 = new 运算式节点();
节点.运算符 = 运算符;
节点.左子节点 = 构建二叉树(子节点.subList(0, 子节点.size() - 2));
节点.右子节点 = visit(子节点.get(子节点.size() - 1));
return 节点;
}
}
开发过程中发现一些坑(如果是小白错误请指出). 一个比较费解的是, 不能省去"字面量"规则如下:
最小表达式
: T数
| T变量名
| '(' 表达式 ')'
;
不然生成的分析器会有编译错误:
com/中文编程/圈5/分析器/圈5Parser.java:403: error: unreachable statement
enterOuterAlt(_localctx, 3);
Antlr4有个github库汇集了社区维护的各种语言的语法规则文件, 其中有Java8, 根据注释说明它的语法规则描述"极度"接近Java标准, 于是参考了它的实现. 其中看到这样的模式(已转成中文):
求和表达式
: 求积表达式
| 求和表达式 '+' 求积表达式
| 求和表达式 '-' 求积表达式
;
求积表达式
: 最小表达式
| 求积表达式 '*' 最小表达式
| 求积表达式 '/' 最小表达式
;
感觉这样会让语法树转换这一步的实现更加方便(应该可以省去多叉树转换成二叉树的那个递归算法). 在添加新功能之前, 打算尝试修改成这样.
已完成:
表达式
: 求积表达式
| 表达式 '+' 求积表达式
| 表达式 '-' 求积表达式;
求积表达式
: 最小表达式
| 求积表达式 '*' 最小表达式
| 求积表达式 '/' 最小表达式
| 求积表达式 '×' 最小表达式
| 求积表达式 '÷' 最小表达式;
的确省去了多叉树转换. 代码整理完毕(program-in-chinese/quan5). 接下去, 是条件判断还是函数定义?
补记
Antlr4自带的语法分析可视化工具, 以antlr/grammars-v4为例:
$ alias grun='java -cp "{PATH_TO_antlr-4.7-complete.jar}:$CLASSPATH" org.antlr.v4.runtime.misc.TestRig'
$ java -cp "{PATH_TO_antlr-4.7-complete.jar}:$CLASSPATH" org.antlr.v4.Tool -visitor -no-listener Java8.g4
$ javac -cp "{PATH_TO_antlr-4.7-complete.jar}:$CLASSPATH" Java8*.java
$ grun Java8 expression -tree <--- 将输入字符串进行语法解析, 生成树结构
Warning: TestRig moved to org.antlr.v4.gui.TestRig; calling automatically
a>1
(expression (assignmentExpression (conditionalExpression (conditionalOrExpression (conditionalAndExpression (inclusiveOrExpression (exclusiveOrExpression (andExpression (equalityExpression (relationalExpression (relationalExpression (shiftExpression (additiveExpression (multiplicativeExpression (unaryExpression (unaryExpressionNotPlusMinus (postfixExpression (expressionName a)))))))) > (shiftExpression (additiveExpression (multiplicativeExpression (unaryExpression (unaryExpressionNotPlusMinus (postfixExpression (primary (primaryNoNewArray_lfno_primary (literal 1)))))))))))))))))))
$ grun Java8 expression -gui <--- 图形化
Warning: TestRig moved to org.antlr.v4.gui.TestRig; calling automatically
2>1
^D

2018-01-15 Antlr4: 修改语法规则更接近普通BNF格式的更多相关文章
- XML 树结构,语法规则,元素,属性,验证及其解析
XML 文档形成了一种树结构,它从"根部"开始,然后扩展到"枝叶". 一个 XML 文档实例 XML 文档使用简单的具有自我描述性的语法: <?xml v ...
- SQL SERVER修改排序规则——脚本篇
在上篇MS SQL 排序规则总结中,大致就数据库服务器排序规则(或者叫数据库实例排序规则).数据库排序规则.列的排序规则粗浅的叙说了一遍,重点讲述了修改数据库服务器排序规则(数据库实例排序规则),其中 ...
- Django模板语言(常用语法规则)
Django模板语言 The Django template language 模板中常用的语法规则 {最新版本的Django语法可能有改变,不支持的操作可能支持了.[HTML教程 - 基本元素/标签 ...
- Java基础-正则表达式(Regular Expression)语法规则简介
Java基础-正则表达式(Regular Expression)语法规则简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.正则表达式的概念 正则表达式(Regular Exp ...
- Windbg命令的语法规则系列(一)
本文介绍使用调试器命令必须遵循的语法规则.使用Windbg调试时,应遵守以下一般语法规则: 您可以在命令和参数中使用大小写字母的任意组合,除非在本节的主题中特别指出. 可以用一个或多个空格或逗号(,) ...
- Emmet语法规则
HTML速写之Emmet语法规则 Emmet-写HTML/CSS快到飞起 在前端开发的过程中,最费时间的工作就是写 HTML.CSS 代码.一堆的标签.属性.括号等,头疼.这里推荐一个Emmet语法规 ...
- JSON 语法规则详解
JSON 的语法规则十分简单,无论用何种方法总结都只有数条而已,它参考了 C 语言家族的一些习惯,学习起来并不会感到陌生. 回顾JSON 的五点语法 1)- 数组(Array)用方括号("[ ...
- Jenkins 定时构建语法规则
1.Jenkins自由风格任务定时构建 2.语法规则 定时构建语法 * * * * * 第一个*表示分钟,取值0~59 第二个*表示小时,取值0~23 第三个*表示一个月的第几天,取值1~31 第四个 ...
- 良好的JavaScript编码风格(语法规则)
编码风格 1.概述 "编程风格"(programming style)指的是编写代码的样式规则.不同的程序员,往往有不同的编程风格. 有人说,编译器的规范叫做"语法规则& ...
随机推荐
- iOS调用QQ发起临时会话
iOS调用QQ发起临时会话 iOS调用qq前先判断是否安装qq, 之后通过OpenURL打开对用的qq NSURL *url = [NSURL URLWithString:@"mqq://& ...
- 常用 Linux 命令使用说明
Linux 如果不知道某个命令的意思,通过 "man 命令" 可以查看它的使用方式及详细信息. 操作tomcat用到的相关命令 1.Enter 执行命令 2.Tab 自动补全命令 ...
- HTTP请求时间参数设置
1. JSON 2019-01-18 18:36:35 2. Postman 2019/01/18 18:36:35
- Linux 定位网络不通问题
[参考文章]:ping命令入门详解 1. ipconfig / ifconfig 1. 作用: 检查本地的网络配置是否正确 2. ping 1. 作用: 一个十分好用的TCP/IP工具.它主要的功能是 ...
- Angular使用总结 --- 通过指令动态添加组件
之前自己写的公共组件,都是会先引入,需要调起的时候再通过service控制公共组件状态.值.回调函数什么的.但是有一些场景不适合这种方式,还是动态添加组件更加好.通过写过的一个小组件来总结下. 创建组 ...
- 1 认识Jquery
一 代码风格和变量风格 1 链式操作风格 : (1)对同一对象不超三个操作的可以写在一行 (2)对于同一个对象的较多操作,建议每行写一个操作 (3)对于多个对象的少量操作,可以每个对象写一行,涉及子元 ...
- kafka shutdown停止关闭很慢问题的解决方案
kafka shutdown停止很慢问题 在数据量大的时候,consumer一次抓取数据的数据很多,进入到业务处理的数据可能有很多, 假设一次poll有1万条数据进入业务程序,而且业务程序是和poll ...
- keras中的mini-batch gradient descent (转)
深度学习的优化算法,说白了就是梯度下降.每次的参数更新有两种方式. 一. 第一种,遍历全部数据集算一次损失函数,然后算函数对各个参数的梯度,更新梯度.这种方法每更新一次参数都要把数据集里的所有样本都看 ...
- python常用库 - NumPy 和 sklearn入门
Numpy 和 scikit-learn 都是python常用的第三方库.numpy库可以用来存储和处理大型矩阵,并且在一定程度上弥补了python在运算效率上的不足,正是因为numpy的存在使得py ...
- Redis主从同步原理-SYNC【转】
和MySQL主从复制的原因一样,Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况.为了分担读压力,Redis支持主从复制,Redis的主从结构可以采用一主多从或者级联结构,下图为级 ...