lang/antlr/ SimplestExample
This just takes a list of arithmetical expressions and evaluates them.
Put this in e.g. test.txt
.
1 + (2 * 3) + 4
42 - (35 * 2) + 8 / 2
To compile the grammar
antlr4 Expr4.g4
Then write the files below, compile with
javac *.java
and run with
<test.txt java Test
The grammar Expr.g4
grammar Expr ;
file : line * ;
line : expr ENDL ;
expr : expr '+' term # Plus
| expr '-' term # Minus
| term # ExprTerm
;
term : term '*' factor # Mult
| term '/' factor # Div
| factor # TermFactor
;
factor : '(' expr ')' # FactorExpr
| NUM # Num
;
NUM : '-'?[1-9][0-9]* | '0' ;
ENDL : '\n' ;
WS : [ \r\t] -> skip ;
The test driver Test.java
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
public class Test {
public static void main(String[] args) throws Exception {
ANTLRInputStream input = new ANTLRInputStream(System.in);
ExprLexer lexer = new ExprLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ExprParser parser = new ExprParser(tokens);
ParseTree tree = parser.file();
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(new MyListener(),tree);
}
}
The listener MyListener.java
. To make this, (I use vim btw), copy the BaseListener java file, delete all lines containing a to clear out the comments (:g/\*/d
in vim). Replace the imports with the same ones used in the test driver (runtime. and runtime.tree.*) (in vim, use :r! head -n2 Test.java
). Delete all enter methods (in vim: :g/enter/d
). Add newlines between braces: (in vim: :%s/}$/\r /
} ). Then you have the barebones template you need to insert the code into.
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
public class MyListener extends ArithBaseListener {
ParseTreeProperty<Integer> values = new ParseTreeProperty<Integer>();
private void setValue(ParseTree node, Integer value)
{
values.put(node,value);
}
private Integer getValue(ParseTree node)
{
return values.get(node);
}
@Override public void exitLine(ArithParser.LineContext ctx) {
System.out.println(""+getValue(ctx.expr()));
}
@Override public void exitExprTerm(ArithParser.ExprTermContext ctx) {
setValue(ctx,getValue(ctx.term()));
}
@Override public void exitPlus(ArithParser.PlusContext ctx) {
setValue(ctx,getValue(ctx.expr())+getValue(ctx.term()));
}
@Override public void exitMinus(ArithParser.MinusContext ctx) {
setValue(ctx,getValue(ctx.expr())-getValue(ctx.term()));
}
@Override public void exitDiv(ArithParser.DivContext ctx) {
setValue(ctx,getValue(ctx.term())/getValue(ctx.factor()));
}
@Override public void exitMult(ArithParser.MultContext ctx) {
setValue(ctx,getValue(ctx.term())*getValue(ctx.factor()));
}
@Override public void exitTermFactor(ArithParser.TermFactorContext ctx) {
setValue(ctx,getValue(ctx.factor()));
}
@Override public void exitFactorExpr(ArithParser.FactorExprContext ctx) {
setValue(ctx,getValue(ctx.expr()));
}
@Override public void exitNum(ArithParser.NumContext ctx) {
setValue(ctx,Integer.valueOf(ctx.NUM().getText()));
}
}