快速上手ANTLR--在Windows环境下解析计算器指令语法
生活随笔
收集整理的這篇文章主要介紹了
快速上手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))/44.執行命令
antlr4 -no-listener -visitor Calc.g4 javac *.java java Calc 或 java Calc calc.txt grun Calc prog -gui calc.txt #可看生成樹5.運行結果
總結
以上就是Antlr計算器入門案例,本文僅僅簡單介紹了Antlr最基本的使用方法,而Antlr提供的大量功能還需繼續學習。 愿這篇博客能幫助到你ヾ(≧▽≦*)o
總結
以上是生活随笔為你收集整理的快速上手ANTLR--在Windows环境下解析计算器指令语法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浅析Java语言
- 下一篇: Windows平台下 vscode清理J