文章目录

  • 前言
  • 一、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.运行结果

  1. 执行java Calc calc.txt
  2. 执行grun Calc prog -gui calc.txt

  1. 3+6*8-9/(7-4)
  2. 2*3-6+4
  3. 9/3+(6/2)
  4. 5*4+((6*7)-(3*2))/4

总结

以上就是Antlr计算器入门案例,本文仅仅简单介绍了Antlr最基本的使用方法,而Antlr提供的大量功能还需继续学习。 愿这篇博客能帮助到你ヾ(≧▽≦*)o

快速上手ANTLR--在Windows环境下解析计算器指令语法相关推荐

  1. java 内存映射文件进程间通讯_[转]Windows环境下利用“共享内存”实现进程间通信的C/C++代码---利用CreateFileMapping和MapViewOfFile...

    进程间的通信方式有很多种, 上次我们说了最傻瓜的"共享外存/文件"的方法. 那么, 在本文中, 我们即将学习"共享内存"的方式实现进程间的通信, 这是IPC最快 ...

  2. Android 开发之Windows环境下Android Studio安装和使用教程(图文详细步骤)

    鉴于谷歌最新推出的Android Studio备受开发者的推崇,所以也跟着体验一下. 一.介绍Android Studio  Android Studio 是一个Android开发环境,基于Intel ...

  3. windows 环境下mysql的操作浅析

    windows 环境下mysql的操作 一,MYSQL 的连接 在下载安装好mysql后,访问数据控之前我们需要先连接数据库: 建立一个connect.php 的文件: (面向过程) <?php ...

  4. Windows环境下Android Studio系列5—日志调试

    为什么80%的码农都做不了架构师?>>>    1. 定制Logcat调试日志字体颜色 Logcat是Android开发调试中最常用的一个工具,Android Studio 1.2. ...

  5. windows环境下C语言socket编程

    最近由于实验需要,要求写一个c程序与java程序通信的软件,为了测试首先写了一个windows环境下c语言的socket(tcp)通信程序. 首先socket通信的步骤:    图一     sock ...

  6. windows下编译c语言文件路径,解决JNI在Windows环境下因长路径导致编译失败问题

    之前听一个朋友反馈LuaScriptoCore在Windows下编译会报错,今天特意跑到Windows环境下测试了一番,果然是存在问题.得到了下面的编译报错信息: Build command fail ...

  7. [原创]python MySQLdb在windows环境下的安装、出错问题以及解决办法

    版权声明:本文为博主原创文章,未经博主允许不得转载. 问题:windows下安装MySQLdb的方法 解析:python没有php那种集成环境,比如wamp那种集成软件直接把所有需要的东西全部一次性搭 ...

  8. Vue快速上手笔记2 - 开发环境的搭建

    Vue快速上手笔记2 - 开发环境的搭建 CSDN:JcLee95 邮箱:291148484@163.com 专题目录:https://blog.csdn.net/qq_28550263/articl ...

  9. windows环境下Eclipse开发MapReduce程序遇到的四个问题及解决办法

    按此文章<Hadoop集群(第7期)_Eclipse开发环境设置>进行MapReduce开发环境搭建的过程中遇到一些问题,饶了一些弯路,解决办法记录在此: 文档目的: 记录windows环 ...

最新文章

  1. Spring整合Struts2
  2. 前端学习(1751):前端调试值之编辑源并同步到本地文件
  3. 与云原生及开源大神们的第二次亲密接触 | 全议程重磅发布
  4. Eclipse配置svn
  5. ORACLE11g R2下载地址
  6. 计算机类毕业设计源码大全
  7. Yaml读写--SnakeYaml
  8. Ingenuous Cubrency UVA - 11137(完全背包)
  9. html超链接地址隐藏,如何在Excel中隐藏超链接地址?
  10. 小程序swiper制作分门别类的轮播
  11. a-table及相关组件的使用
  12. Sentinel SuperPro加密锁编程开发指南
  13. cad2010背景怎么调成黑色_iOS14桌面怎么布局好看-热点资讯-
  14. XXXX is not in the sudoers file. This incident will be reported解决方法
  15. 基于javaweb+SSM农产品水果店销售管理系统
  16. 安卓中为了获取context的方法和区别(getContext,getActivity,this,mainActivity.this等)
  17. 基于微信小程序的流动人口管理移动APP设计与实现-计算机毕业设计源码+LW文档
  18. 1003. 我要通过!
  19. 正负数的二进制(转)
  20. 互联网上的单点登录研究

热门文章

  1. 位移运算符(7个)之第一个: 左移
  2. 529. Minesweeper
  3. 93. Restore IP Addresses 复原IP地址
  4. 信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1095:数1的个数
  5. Netty实战 IM即时通讯系统(三)Netty环境配置
  6. windows 下终止指定端口的进程
  7. 【MFC】工具栏按钮的热点效果
  8. k8s灰度更新_通过rancher部署k8s过程实战分享
  9. linux task进程跟踪,如何对Hadoop作业的某个task进行debug单步跟踪
  10. C++代码片段(三)过滤可变模板参数中某些类型的变量