/* [The "BSD license"] Copyright (c) 2011 Terence Parr All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ import org.antlr.v4.runtime.*; import java.io.*; public class TestA { /** An example listener that uses a stack to store return values * so that exit methods executed on notes further up the parse tree * can see the results of these computations. * * Because we are using only the exit routines, the same listener works * as a parse listener and is a parse tree listener. It generates * the following output from input 3+4*5: Int: 3 Int: 4 Int: 5 Mult: 20 Add: 23 tree = (s (e (e 3) + (e (e 4) * (e 5)))) Int: 3 Int: 4 Int: 5 Mult: 20 Add: 23 result from tree walk = 23 * The key things to notice are that there are no actions * and the labels in the grammar--it is completely language neutral. * Also, I have labeled each alternative so that we get a different * context object. That way we get a listener method for each * alternative. * * Compare this to A2.g4, which adds a field to the context objects * by using a "returns [int v]" on the expression rule. */ // public static class Do extends ABaseListener { // Stack results = new Stack(); // // @Override // public void exit(AParser.AddContext ctx) { // results.push( results.pop() + results.pop() ); // System.out.println("Add: " + results.peek()); // } // // @Override // public void exit(AParser.IntContext ctx) { // results.push( Integer.valueOf(ctx.INT().getText()) ); // System.out.println("Int: "+results.peek()); // } // // @Override // public void exit(AParser.MultContext ctx) { // results.push( results.pop() * results.pop() ); // System.out.println("Mult: " + results.peek()); // } // // @Override // public void exit(AParser.ParensContext ctx) { // // result already on stack // System.out.println("Parens: "+results.peek()); // } // } public static class Tracer extends ABaseListener { @Override public void enterAdd(AParser.AddContext ctx) { printMethodName(ctx); } @Override public void enterEveryRule(ParserRuleContext ctx) { printMethodName(ctx); } @Override public void enterMult(AParser.MultContext ctx) { printMethodName(ctx); } @Override public void enterParens(AParser.ParensContext ctx) { printMethodName(ctx); } @Override public void enterS(AParser.SContext ctx) { printMethodName(ctx); } @Override public void exitAdd(AParser.AddContext ctx) { printMethodName(ctx); } @Override public void exitMult(AParser.MultContext ctx) { printMethodName(ctx); } @Override public void exitParens(AParser.ParensContext ctx) { printMethodName(ctx); } @Override public void exitS(AParser.SContext ctx) { printMethodName(ctx); } @Override public void exitEveryRule(ParserRuleContext ctx) { printMethodName(ctx); } @Override public void visitTerminal(ParserRuleContext ctx, Token symbol) { printMethodName(ctx); } @Override public void enterPrimary(AParser.PrimaryContext ctx) { printMethodName(ctx); } @Override public void exitPrimary(AParser.PrimaryContext ctx) { printMethodName(ctx); } } public static class TraceDuringParse extends ABaseParseListener { @Override public void enterNonLRRule(ParserRuleContext ctx) { printMethodName(ctx); } @Override public void enterS(ParserRuleContext ctx) { printMethodName(ctx); } @Override public void exitAdd(AParser.AddContext ctx) { printMethodName(ctx); } @Override public void exitEveryRule(ParserRuleContext ctx) { printMethodName(ctx); } @Override public void exitMult(AParser.MultContext ctx) { printMethodName(ctx); } @Override public void exitParens(AParser.ParensContext ctx) { printMethodName(ctx); } @Override public void exitPrimary(AParser.PrimaryContext ctx) { printMethodName(ctx); } @Override public void exitS(AParser.SContext ctx) { printMethodName(ctx); } @Override public void visitTerminal(ParserRuleContext ctx, Token symbol) { printMethodName(ctx); System.out.println("visiting "+symbol); } } public static void printMethodName(ParserRuleContext ctx) { Throwable t = new Throwable(); StackTraceElement[] stack = t.getStackTrace(); String m = stack[1].getMethodName(); System.out.println(m+"("+ctx.getClass().getSimpleName()+")"); } public static void main(String[] args) throws Exception { InputStream is = System.in; if ( args.length>0 && args[0]!=null ) { is = new FileInputStream(args[0]); } ALexer lexer = new ALexer(new ANTLRInputStream(is)); CommonTokenStream tokens = new CommonTokenStream(lexer); AParser p = new AParser(tokens); p.setBuildParseTree(true); p.addParseListener(new TraceDuringParse()); ParserRuleContext t = p.s(); System.out.println("tree = "+t.toStringTree(p)); // ParseTreeWalker walker = new ParseTreeWalker(); // Do doer = new Do(); // walker.walk(doer, t); // System.out.println("result from tree walk = "+ doer.results.pop()); } }