This commit is contained in:
Terence Parr 2012-02-16 13:36:07 -08:00
parent 4a374dab60
commit 646b22b9ec
10 changed files with 79 additions and 21 deletions

View File

@ -8,7 +8,12 @@ public class ParseTreeVisitor<T> {
return ctx.accept(this);
}
/** Visit all rule, nonleaf children */
/** Visit all rule, nonleaf children. Not useful if you are using T as
* non-Void. This returns nothing, losing all computations from below.
* But handy if you are just walking the tree with a visitor and only
* care about some nodes. The ParserRuleContext.accept() method
* walks all children by default; i.e., calls this method.
*/
public <Symbol> void visitChildren(ParserRuleContext<Symbol> ctx) {
for (ParseTree c : ctx.children) {
if ( c instanceof ParseTree.RuleNode) {

View File

@ -1,11 +1,10 @@
import org.antlr.v4.runtime.tree.*;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
public class ABaseVisitor<T> extends ParseTreeVisitor<T> implements AVisitor<T> {
public T visit(AParser.MultContext ctx) { return null; }
public T visit(AParser.ParensContext ctx) { return null; }
public T visit(AParser.eContext ctx) { return null; }
public T visit(AParser.sContext ctx) { return null; }
public T visit(AParser.AddContext ctx) { return null; }
public T visit(AParser.IntContext ctx) { return null; }
public T visit(AParser.MultContext ctx) { visitChildren(ctx); return null; }
public T visit(AParser.ParensContext ctx) { visitChildren(ctx); return null; }
public T visit(AParser.sContext ctx) { visitChildren(ctx); return null; }
public T visit(AParser.AddContext ctx) { visitChildren(ctx); return null; }
public T visit(AParser.IntContext ctx) { visitChildren(ctx); return null; }
}

View File

@ -1,3 +1,6 @@
import org.antlr.v4.runtime.tree.*;
import org.antlr.v4.runtime.Token;
public interface AVisitor<T> {
T visit(AParser.MultContext ctx);
T visit(AParser.ParensContext ctx);

View File

@ -31,7 +31,7 @@ import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
public class TestVisitor {
public static class MyVisitor extends ParseTreeVisitor<Integer> implements AVisitor<Integer> {
public static class MyVisitor extends ABaseVisitor<Integer> implements AVisitor<Integer> {
@Override
public Integer visit(AParser.AddContext ctx) {
return ctx.e(0).accept(this) + ctx.e(1).accept(this);

View File

@ -67,6 +67,16 @@ T visit(<file.parserName>.<lname>Context ctx);}; separator="\n">
}
>>
BaseVisitorFile(file, header) ::= <<
<header>
import org.antlr.v4.runtime.tree.*;
import org.antlr.v4.runtime.Token;
public class <file.grammarName>BaseVisitor\<T> extends ParseTreeVisitor\<T> implements <file.grammarName>Visitor\<T> {
<file.visitorNames:{lname |
public T visit(<file.parserName>.<lname>Context ctx) { visitChildren(ctx); return null; \}}; separator="\n">
}
>>
Parser(parser, funcs, atn, sempredFuncs, superclass) ::= <<
<Parser_(ctor="parser_ctor", ...)>

View File

@ -48,8 +48,9 @@ public class CodeGenPipeline {
gen.writeRecognizer(gen.generateParser());
if ( g.tool.gen_listener) {
gen.writeListener(gen.generateListener());
gen.writeBaseListener(gen.generateBaseListener());
gen.writeVisitor(gen.generateVisitor());
gen.writeBlankListener(gen.generateBlankListener());
gen.writeBaseVisitor(gen.generateBaseVisitor());
}
gen.writeHeaderFile();
}

View File

@ -182,16 +182,29 @@ public class CodeGenerator {
return st;
}
public ST generateBlankListener() {
public ST generateBaseListener() {
OutputModelFactory factory = new ParserFactory(this);
OutputModelController controller = new OutputModelController(factory);
factory.setController(controller);
OutputModelObject blankModel = controller.buildBlankListenerOutputModel();
OutputModelObject baseModel = controller.buildBaseListenerOutputModel();
OutputModelWalker walker = new OutputModelWalker(tool, templates);
ST st = walker.walk(blankModel);
ST st = walker.walk(baseModel);
return st;
}
public ST generateBaseVisitor() {
OutputModelFactory factory = new ParserFactory(this);
OutputModelController controller = new OutputModelController(factory);
factory.setController(controller);
OutputModelObject baseModel = controller.buildBaseVisitorOutputModel();
OutputModelWalker walker = new OutputModelWalker(tool, templates);
ST st = walker.walk(baseModel);
return st;
}
@ -235,14 +248,18 @@ public class CodeGenerator {
target.genFile(g,outputFileST, getListenerFileName());
}
public void writeBlankListener(ST outputFileST) {
target.genFile(g,outputFileST, getBlankListenerFileName());
public void writeBaseListener(ST outputFileST) {
target.genFile(g,outputFileST, getBaseListenerFileName());
}
public void writeVisitor(ST outputFileST) {
target.genFile(g,outputFileST, getVisitorFileName());
}
public void writeBaseVisitor(ST outputFileST) {
target.genFile(g,outputFileST, getBaseVisitorFileName());
}
public void writeHeaderFile() {
String fileName = getHeaderFileName();
if ( fileName==null ) return;
@ -333,15 +350,25 @@ public class CodeGenerator {
}
/** A given grammar T, return a blank listener implementation
* such as BlankTListener.java, if we're using the Java target.
* such as TBaseListener.java, if we're using the Java target.
*/
public String getBlankListenerFileName() {
public String getBaseListenerFileName() {
assert g.name != null;
ST extST = templates.getInstanceOf("codeFileExtension");
String listenerName = g.name + "BaseListener";
return listenerName+extST.render();
}
/** A given grammar T, return a blank listener implementation
* such as TBaseListener.java, if we're using the Java target.
*/
public String getBaseVisitorFileName() {
assert g.name != null;
ST extST = templates.getInstanceOf("codeFileExtension");
String listenerName = g.name + "BaseVisitor";
return listenerName+extST.render();
}
/** What is the name of the vocab file generated for this grammar?
* Returns null if no .tokens file should be generated.
*/

View File

@ -108,9 +108,9 @@ public class OutputModelController {
return new ListenerFile(delegate, gen.getListenerFileName());
}
public OutputModelObject buildBlankListenerOutputModel() {
public OutputModelObject buildBaseListenerOutputModel() {
CodeGenerator gen = delegate.getGenerator();
return new BaseListenerFile(delegate, gen.getBlankListenerFileName());
return new BaseListenerFile(delegate, gen.getBaseListenerFileName());
}
public OutputModelObject buildVisitorOutputModel() {
@ -118,6 +118,11 @@ public class OutputModelController {
return new VisitorFile(delegate, gen.getVisitorFileName());
}
public OutputModelObject buildBaseVisitorOutputModel() {
CodeGenerator gen = delegate.getGenerator();
return new BaseVisitorFile(delegate, gen.getBaseVisitorFileName());
}
public ParserFile parserFile(String fileName) {
ParserFile f = delegate.parserFile(fileName);
for (CodeGeneratorExtension ext : extensions) f = ext.parserFile(f);

View File

@ -0,0 +1,9 @@
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;
public class BaseVisitorFile extends VisitorFile {
public BaseVisitorFile(OutputModelFactory factory, String fileName) {
super(factory, fileName);
}
}

View File

@ -14,7 +14,6 @@ public class ListenerFile extends OutputFile {
public String grammarName;
public String parserName;
public Set<String> listenerNames = new HashSet<String>();
// public List<String> ruleNames = new ArrayList<String>();
@ModelElement public Action header;