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()));
  }
}