Antlr4实现数学四则运算
基本参考https://pragprog.com/book/tpantlr2/the-definitive-antlr-4-reference 一书"Building a Calculator Using a Visitor"一节, 仅添加了数学乘除法符号的支持(×÷). 比如下面的算式:
3×2+8÷4-2×4
相比上一版本语法文件去除了空格定义. 需要深究的是优先级问题. 是否因为"表达式 运算符=('*'|'/'|'×'|'÷') 表达式"写在了前面才使得乘除法的优先级在语法分析时更高.
至此, 感觉Antlr语法文件对中文命名的支持还是不错的. 唯一需要权宜之计的就是Token(词)规则必须要大写开头, 因此采用了前缀"T"):
grammar 圈5; 程序 : 表达式 ; 表达式 : 表达式 运算符=('*'|'/'|'×'|'÷') 表达式 #乘除 | 表达式 运算符=('+'|'-') 表达式 #加減 | T数 #数 ; T数 : [0-9]+ ; T加 : '+'; T減 : '-'; T乘 : '*'; T数乘: '×'; T除 : '/'; T数除: '÷';
第一次尝试#标号的辅助功能. 一个"表达式"语法规则生成了三个Visitor方法(如下), 访问器仍比较简单. 注: 语法规则中要么所有分支都有标号, 要么都没有. 不然生成分析器时报错:
public class 定制访问器 extends 圈5BaseVisitor<节点> { @Override public 节点 visit数(数Context 上下文) { TerminalNode 数 = 上下文.T数(); return 数 instanceof ErrorNode ? null : new 数节点(数.getText()); } @Override public 节点 visit加減(加減Context 上下文) { 表达式节点 节点 = new 表达式节点(); 节点.运算符 = 上下文.运算符.getType() == 圈5Parser.T加 ? 运算符号.加 : 运算符号.減; 节点.左子节点 = visit(上下文.表达式(0)); 节点.右子节点 = visit(上下文.表达式(1)); return 节点; } @Override public 节点 visit乘除(乘除Context 上下文) { 表达式节点 节点 = new 表达式节点(); int 运算符 = 上下文.运算符.getType(); 节点.运算符 = (运算符 == 圈5Parser.T乘 || 运算符 == 圈5Parser.T数乘) ? 运算符号.乘 : 运算符号.除; 节点.左子节点 = visit(上下文.表达式(0)); 节点.右子节点 = visit(上下文.表达式(1)); return 节点; } }
语法树中稍微复杂一点的"表达式"节点, 代码很冗余:
public class 表达式节点 extends 节点 { public 运算符号 运算符; @Override public Object 求值() { if (运算符.equals(运算符号.加)) { return (int)(左子节点.求值()) + ((int)右子节点.求值()); } else if (运算符.equals(运算符号.減)) { return (int)(左子节点.求值()) - ((int)右子节点.求值()); } else if (运算符.equals(运算符号.乘)) { return (int)(左子节点.求值()) * ((int)右子节点.求值()); } else if (运算符.equals(运算符号.除)) { return (int)(左子节点.求值()) / ((int)右子节点.求值()); } else { return null; } } }
已经要手动跑十个测试文件, 下面除了清理代码, 还需要加测试, 再加功能(应该是变量赋值).
2018-01-11
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
烂尾工程: Java实现的汇编语言编译器
在半年前的《中文编程的尝试历程小记》中简单介绍了这一项目. 由于短期内估计不会继续进行, 而且这个项目好像是至今个人在中文命名实践中的代码量最大的一个项目, 谨在此作一小结. 最新的源码库在program-in-chinese/assembler-in-chinese-experiment. 大致设计草图 以'mov rax 0x1122334455667788'指令示例如下: 当前进度 仅支持两个操作数的部分指令, 第二个操作数仅支持立即数 第一个操作数可以是寄存器,或者简单的内存寻址,如[0] 支持强制类型,如add ax,strict word 5 生成空可执行文件(PE), 尚未填入生成的二进制码 源码结构 下面是所有文件, 希望是一目了然? "分析器类"从单行汇编指令字符串分析生成"代码行类", "汇编器类"从"代码行类"生成二进制码. 其他主要是业务数据描述("模型"包)和功用(utils). 假如要重新继续这一项目, 下面是一些想法: 考虑使用Antlr4, 用类似antlr/grammars-v4的语法文件辅助生成分析器, 省去手动编写分析器 最好有汇编和x64指令背景...
- 下一篇
Antlr4的分析错误处理
(前文通用型的中文编程语言探讨之一: 高考, 即使是这"第一步", 即使一切顺利达到列出的功能恐怕也需要个人数年的业余时间. 看到不少乎友都远更有资本和实力更快速地完成这一工程. 希望随时告知类似项目, 省得在下作无用功) 初步打算用Antlr4生成Java实现的词语法分析器, 主要是出于减少工作量的考虑, 但相应的需要深入学习这个工具. 根据至今看到的相关文档以及Antlr项目本身, 感觉还蛮实用, 可持续性也不错, 这些学习应该不会白费. 之前没有实验过它对错误语法的处理. 本文实现了编程语言试验之Antlr4+Java实现"圈2"的Visitor版本. 再添加了定制的词法语法错误处理. 源码在program-in-chinese/quan5 语法最简单, 只包含一个数: grammar 圈5; 程序 : T数; T数 : [0-9]+ ; T空白 : [ \n\t]+ -> skip; 定制的语法错误处理器, 只有报告功能: public class 语法错误监听器 extends BaseErrorListener { @Override public void synt...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS关闭SELinux安全模块
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库