antlr/tool/playground/TestA.java

234 lines
6.3 KiB
Java

/*
[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<Integer> results = new Stack<Integer>();
//
// @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<Token> 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<Token> ctx) {
printMethodName(ctx);
}
@Override
public void visitTerminal(ParserRuleContext<Token> 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<Token> ctx) {
printMethodName(ctx);
}
@Override
public void enterS(ParserRuleContext<Token> ctx) {
printMethodName(ctx);
}
@Override
public void exitAdd(AParser.AddContext ctx) {
printMethodName(ctx);
}
@Override
public void exitEveryRule(ParserRuleContext<Token> 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<Token> 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<Token> 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());
}
}