定义语法
Calc.g4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| grammar Calc;
prog: stat+;
stat: expr NEWLINE # printExpr | NEWLINE # blank ;
expr: expr MUL expr # Mul | expr DIV expr # Div | expr ADD expr # Add | expr SUB expr # Sub | INT # int | '(' expr ')' # parens ;
MUL : '*' ; DIV : '/' ; ADD : '+' ; SUB : '-' ; INT : [0-9]+ ; NEWLINE:'\r'? '\n' ; WS : [ \t]+ -> skip;
|
生成代码
使用插件或者 jar 根据语法生成代码。
安装 idea 插件

生成词法分析和语法分析的代码

编写程序代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| package io.github.lmikoto.calc;
import io.github.lmikoto.calc.gen.CalcBaseVisitor; import io.github.lmikoto.calc.gen.CalcParser;
public class CalcEvalVisitor extends CalcBaseVisitor<Integer> {
@Override public Integer visitPrintExpr(CalcParser.PrintExprContext ctx) { return visit(ctx.expr()); }
@Override public Integer visitInt(CalcParser.IntContext ctx) { return Integer.valueOf(ctx.INT().getText()); }
@Override public Integer visitMul(CalcParser.MulContext ctx) { Integer left = visit(ctx.expr(0)); Integer right = visit(ctx.expr(1)); return left * right; }
@Override public Integer visitDiv(CalcParser.DivContext ctx) { Integer left = visit(ctx.expr(0)); Integer right = visit(ctx.expr(1)); return left / right; }
@Override public Integer visitAdd(CalcParser.AddContext ctx) { Integer left = visit(ctx.expr(0)); Integer right = visit(ctx.expr(1)); return left + right; }
@Override public Integer visitSub(CalcParser.SubContext ctx) { Integer left = visit(ctx.expr(0)); Integer right = visit(ctx.expr(1)); return left - right; }
@Override public Integer visitParens(CalcParser.ParensContext ctx) { return visit(ctx.expr()); } }
|
编写 main 方法执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package io.github.lmikoto.calc;
import io.github.lmikoto.calc.gen.CalcLexer; import io.github.lmikoto.calc.gen.CalcParser; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CodePointCharStream; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTree;
public class Calc {
public static void main(String[] args) {
CodePointCharStream inputStream = CharStreams.fromString("6 + (1 + 5) * 4+ 6 / 2 \n"); CalcLexer lexer = new CalcLexer(inputStream);
CommonTokenStream tokenStream = new CommonTokenStream(lexer); CalcParser parser = new CalcParser(tokenStream); ParseTree parseTree = parser.prog(); CalcEvalVisitor visitor = new CalcEvalVisitor(); Integer rtn = visitor.visit(parseTree); System.out.println(rtn); } }
|