ANTLR
Пример калькулятора на ANTLR.
LabeledExpr.g4:
grammar LabeledExpr;
prog: stat+ ;
stat: expr NEWLINE # printExpr
| ID '=' expr NEWLINE # assign
| NEWLINE # blank
;
expr: expr op=('*'|'/') expr # MulDiv
| expr op=('+'|'-') expr # AddSub
| INT # int
| ID # id
| '(' expr ')' # parens
;
MUL : '*' ; // Назначение имен токенам
DIV : '/' ;
ADD : '+' ;
SUB : '-' ;
ID : [a-zA-Z]+ ;
INT : [0-9]+ ;
NEWLINE:'\r'? '\n' ;
WS : [ \t]+ -> skip ; // Пропуск пробельных символов
Calc.java:
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ParseTree;
import java.io.FileInputStream;
import java.io.InputStream;
public class Calc {
public static void main(String[] args) throws Exception {
InputStream is = System.in;
if ( args.length>0 ) is = new FileInputStream(args[0]);
ANTLRInputStream input = new ANTLRInputStream(is);
LabeledExprLexer lexer = new LabeledExprLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
LabeledExprParser parser = new LabeledExprParser(tokens);
ParseTree tree = parser.prog();
EvalVisitor eval = new EvalVisitor();
eval.visit(tree);
}
}
EvalVisitor.java:
import java.util.HashMap;
import java.util.Map;
public class EvalVisitor extends LabeledExprBaseVisitor<Integer> {
//
Map<String, Integer> memory = new HashMap<String, Integer>();
private Integer eval(Integer left, Integer op, Integer right)
{ switch(op) {
case LabeledExprParser.MUL: return left*right;
case LabeledExprParser.DIV: return left/right;
case LabeledExprParser.ADD: return left+right;
case LabeledExprParser.SUB: return left-right;
}
}
@Override //
public Integer visitAssign(LabeledExprParser.AssignContext ctx) {
memory.put(ctx.ID().getText(), visit(ctx.expr()));
return 0;
}
@Override //
public Integer visitPrintExpr(LabeledExprParser.PrintExprContext ctx) {
System.out.println(visit(ctx.expr()));
return 0;
}
@Override //
public Integer visitInt(LabeledExprParser.IntContext ctx) {
return Integer.valueOf(ctx.INT().getText());
}
@Override //
public Integer visitId(LabeledExprParser.IdContext ctx) {
String id = ctx.ID().getText();
if ( memory.containsKey(id) ) return memory.get(id);
return 0;
}
@Override //
public Integer visitMulDiv(LabeledExprParser.MulDivContext ctx) {
return eval(visit(ctx.expr(0)), ctx.op.getType(), visit(ctx.expr(1)));
}
@Override //
public Integer visitAddSub(LabeledExprParser.AddSubContext ctx) {
return eval(visit(ctx.expr(0)), ctx.op.getType(), visit(ctx.expr(1)));
}
@Override //
public Integer visitParens(LabeledExprParser.ParensContext ctx) {
return visit(ctx.expr());
}
}