快速上手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
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
