快速上手ANTLR--在Windows环境下解析计算器指令语法
文章目录
- 前言
- 一、antlr是什么?
- 二、使用步骤
- 1.引入库
- 2.写一个EvalVisitor.java类
- 3.写一个Calc.java类(主类)
- 4.写一个自定义的calc.txt文件
- 4.执行命令
- 5.运行结果
- 总结
前言
提示:网上讲述ANTLR入门的教程太多了,本文是在Windows X86 64位机器下配置运行的,仅供参考使用。这里感谢@一棵树和一枝猪的博客!
提示:以下是本篇文章正文内容,下面案例可供参考
一、antlr是什么?
antlr是一个非常强大的语法分析生成工具,可用于读取、处理、执行和翻译结构化的文本或二进制文件。它被广泛应用于学术领域和工业生产领域,是众多语言、工具和框架的基石。
二、使用步骤
声明:这里假设已经在电脑上配置好Java和ANTLR环境了。
具体配置可参考这个链接
1.引入库
自建一个Calc.g4文件代码如下:
grammar Calc;prog : stat+;stat : expr # printExpr| ID '=' expr # assign| 'print(' ID ')' # print;expr : <assoc=right> expr '^' expr # power| expr op=(MUL|DIV) expr # MulDiv| expr op=(ADD|SUB) expr # AddSub| sign=(ADD|SUB)?NUMBER # number| ID # id| '(' expr ')' # parens;ID : [a-zA-Z]+;
NUMBER : [0-9]+('.'([0-9]+)?)?| [0-9]+;
COMMENT : '/*' .*? '*/' -> skip;
LINE_COMMENT : '//' .*? '\r'? '\n' -> skip;
WS : [ \t\r\n]+ -> skip;
MUL : '*';
DIV : '/';
ADD : '+';
SUB : '-';
2.写一个EvalVisitor.java类
代码如下(示例):
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;public class EvalVisitor extends CalcBaseVisitor<Double> {Map<String, Double> memory = new HashMap<String, Double>();//id = expr@Overridepublic Double visitAssign(CalcParser.AssignContext ctx){String id = ctx.ID().getText();Double value = visit(ctx.expr());memory.put(id, value);return value;}// expr@Overridepublic Double visitPrintExpr(CalcParser.PrintExprContext ctx) {Double value = visit(ctx.expr());//保留两位有数字的方法DecimalFormat df = new DecimalFormat("#.##");String s_value = df.format(value);System.out.println(s_value);return 0.0;}//print@Overridepublic Double visitPrint(CalcParser.PrintContext ctx){String id = ctx.ID().getText();Double value=0.0;if(memory.containsKey(id)) value = memory.get(id);DecimalFormat df = new DecimalFormat("#.##");String s_value = df.format(value);System.out.println(s_value);return value;}//Number@Overridepublic Double visitNumber(CalcParser.NumberContext ctx){int size = ctx.getChildCount();if(size == 2){if(ctx.sign.getType() == CalcParser.SUB){return -1 * Double.valueOf(ctx.getChild(1).getText());}else{return Double.valueOf(ctx.getChild(1).getText());}}else{return Double.valueOf(ctx.getChild(0).getText());}}//ID@Overridepublic Double visitId(CalcParser.IdContext ctx){String id = ctx.ID().getText();if(memory.containsKey(id)) return memory.get(id);return 0.0;}//expr op=('*'|'/') expr@Overridepublic Double visitMulDiv(CalcParser.MulDivContext ctx) {Double left = visit(ctx.expr(0));Double right = visit(ctx.expr(1));if(ctx.op.getType() == CalcParser.MUL){return left * right;}else{if(right == 0 || right == 0.0){System.out.println("Divisor can not be zero");return 0.0;}else{return left / right;}}}//expr op=('+'|'-') expr@Overridepublic Double visitAddSub(CalcParser.AddSubContext ctx){Double left = visit(ctx.expr(0));Double right = visit(ctx.expr(1));if(ctx.op.getType() == CalcParser.ADD)return left + right;return left - right;}// '(' expr ')'@Overridepublic Double visitParens(CalcParser.ParensContext ctx){return visit(ctx.expr());}// '^'@Overridepublic Double visitPower(CalcParser.PowerContext ctx){Double base = visit(ctx.expr(0));Double exponet = visit(ctx.expr(1));return Math.pow(base, exponet);}
}
3.写一个Calc.java类(主类)
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;import java.io.InputStream;public class Calc {public static void main(String[] args) throws Exception {CharStream input;if(args.length == 1) {String fileName = String.valueOf(args[0]);input = CharStreams.fromFileName(fileName);}else if(args.length > 1 || args.length < 0){throw new Exception("the number of arguments is false, Please only give the source file or nothing and then you input your text");}else {InputStream is = System.in;input = CharStreams.fromStream(is);}CalcLexer lexer = new CalcLexer(input);CommonTokenStream tokens = new CommonTokenStream(lexer);CalcParser parser = new CalcParser(tokens);ParseTree tree = parser.prog();EvalVisitor eval = new EvalVisitor();eval.visit(tree);System.out.println(tree.toStringTree(parser));}
}
4.写一个自定义的calc.txt文件
3+6*8-9/(7-4)
2*3-6+4
9/3+(6/2)
5*4+((6*7)-(3*2))/4
4.执行命令
antlr4 -no-listener -visitor Calc.g4
javac *.java
java Calc 或 java Calc calc.txt
grun Calc prog -gui calc.txt #可看生成树
5.运行结果
- 执行
java Calc calc.txt
- 执行
grun Calc prog -gui calc.txt
3+6*8-9/(7-4)
2*3-6+4
9/3+(6/2)
5*4+((6*7)-(3*2))/4
总结
以上就是Antlr计算器入门案例,本文仅仅简单介绍了Antlr最基本的使用方法,而Antlr提供的大量功能还需继续学习。 愿这篇博客能帮助到你ヾ(≧▽≦*)o
快速上手ANTLR--在Windows环境下解析计算器指令语法相关推荐
- java 内存映射文件进程间通讯_[转]Windows环境下利用“共享内存”实现进程间通信的C/C++代码---利用CreateFileMapping和MapViewOfFile...
进程间的通信方式有很多种, 上次我们说了最傻瓜的"共享外存/文件"的方法. 那么, 在本文中, 我们即将学习"共享内存"的方式实现进程间的通信, 这是IPC最快 ...
- Android 开发之Windows环境下Android Studio安装和使用教程(图文详细步骤)
鉴于谷歌最新推出的Android Studio备受开发者的推崇,所以也跟着体验一下. 一.介绍Android Studio Android Studio 是一个Android开发环境,基于Intel ...
- windows 环境下mysql的操作浅析
windows 环境下mysql的操作 一,MYSQL 的连接 在下载安装好mysql后,访问数据控之前我们需要先连接数据库: 建立一个connect.php 的文件: (面向过程) <?php ...
- Windows环境下Android Studio系列5—日志调试
为什么80%的码农都做不了架构师?>>> 1. 定制Logcat调试日志字体颜色 Logcat是Android开发调试中最常用的一个工具,Android Studio 1.2. ...
- windows环境下C语言socket编程
最近由于实验需要,要求写一个c程序与java程序通信的软件,为了测试首先写了一个windows环境下c语言的socket(tcp)通信程序. 首先socket通信的步骤: 图一 sock ...
- windows下编译c语言文件路径,解决JNI在Windows环境下因长路径导致编译失败问题
之前听一个朋友反馈LuaScriptoCore在Windows下编译会报错,今天特意跑到Windows环境下测试了一番,果然是存在问题.得到了下面的编译报错信息: Build command fail ...
- [原创]python MySQLdb在windows环境下的安装、出错问题以及解决办法
版权声明:本文为博主原创文章,未经博主允许不得转载. 问题:windows下安装MySQLdb的方法 解析:python没有php那种集成环境,比如wamp那种集成软件直接把所有需要的东西全部一次性搭 ...
- Vue快速上手笔记2 - 开发环境的搭建
Vue快速上手笔记2 - 开发环境的搭建 CSDN:JcLee95 邮箱:291148484@163.com 专题目录:https://blog.csdn.net/qq_28550263/articl ...
- windows环境下Eclipse开发MapReduce程序遇到的四个问题及解决办法
按此文章<Hadoop集群(第7期)_Eclipse开发环境设置>进行MapReduce开发环境搭建的过程中遇到一些问题,饶了一些弯路,解决办法记录在此: 文档目的: 记录windows环 ...
最新文章
- Spring整合Struts2
- 前端学习(1751):前端调试值之编辑源并同步到本地文件
- 与云原生及开源大神们的第二次亲密接触 | 全议程重磅发布
- Eclipse配置svn
- ORACLE11g R2下载地址
- 计算机类毕业设计源码大全
- Yaml读写--SnakeYaml
- Ingenuous Cubrency UVA - 11137(完全背包)
- html超链接地址隐藏,如何在Excel中隐藏超链接地址?
- 小程序swiper制作分门别类的轮播
- a-table及相关组件的使用
- Sentinel SuperPro加密锁编程开发指南
- cad2010背景怎么调成黑色_iOS14桌面怎么布局好看-热点资讯-
- XXXX is not in the sudoers file. This incident will be reported解决方法
- 基于javaweb+SSM农产品水果店销售管理系统
- 安卓中为了获取context的方法和区别(getContext,getActivity,this,mainActivity.this等)
- 基于微信小程序的流动人口管理移动APP设计与实现-计算机毕业设计源码+LW文档
- 1003. 我要通过!
- 正负数的二进制(转)
- 互联网上的单点登录研究
热门文章
- 位移运算符(7个)之第一个: 左移
- 529. Minesweeper
- 93. Restore IP Addresses 复原IP地址
- 信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1095:数1的个数
- Netty实战 IM即时通讯系统(三)Netty环境配置
- windows 下终止指定端口的进程
- 【MFC】工具栏按钮的热点效果
- k8s灰度更新_通过rancher部署k8s过程实战分享
- linux task进程跟踪,如何对Hadoop作业的某个task进行debug单步跟踪
- C++代码片段(三)过滤可变模板参数中某些类型的变量