Got the visitor thing cleaned up enough for a small example

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 9059]
This commit is contained in:
parrt 2011-09-08 13:45:05 -08:00
parent da7e7c8813
commit 2d234ee28c
9 changed files with 96 additions and 76 deletions

View File

@ -29,10 +29,11 @@
package org.antlr.v4.runtime.tree;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
public interface ParseTreeListener {
void visitToken(Token token);
void discoverRule(ParserRuleContext ctx);
void finishRule(ParserRuleContext ctx);
void enterEveryRule(ParserRuleContext ctx);
void exitEveryRule(ParserRuleContext ctx);
}

View File

@ -57,55 +57,13 @@ public class ParseTreeVisitor {
*/
protected void enterRule(ParseTreeListener listener, ParseTree.RuleNode r) {
ParserRuleContext ctx = (ParserRuleContext)r.getRuleContext();
listener.discoverRule((ParserRuleContext)r.getRuleContext());
listener.enterEveryRule((ParserRuleContext) r.getRuleContext());
ctx.enterRule(listener);
}
protected void exitRule(ParseTreeListener listener, ParseTree.RuleNode r) {
ParserRuleContext ctx = (ParserRuleContext)r.getRuleContext();
ctx.exitRule(listener);
listener.finishRule(ctx);
listener.exitEveryRule(ctx);
}
/*
public static void main(String[] args) {
TListener listener = new TListener() {
public void discover_s(s_ctx ctx) {
}
public void finish_s(s_ctx ctx) {
}
public void discover_ifstat(ParserRuleContext ctx) {
}
public void finish_ifstat(ParserRuleContext ctx) {
}
public void visitToken(Token token) {
}
public void discoverRule(ParserRuleContext ctx) {
}
public void finishRule(ParserRuleContext ctx) {
}
};
ParserRuleContext ctx = new ParserRuleContext();
ParseTreeVisitor visitor = new ParseTreeVisitor();
visitor.visit(listener, ctx);
}
*/
}
/*
interface TListener extends ParseTreeListener {
void discover_s(s_ctx ctx);
void finish_s(s_ctx ctx);
void discover_ifstat(ParserRuleContext ctx); // no labels
void finish_ifstat(ParserRuleContext ctx); // no labels
}
class s_ctx extends ParserRuleContext {
public ParserRuleContext i;
public s_ctx(RuleContext parent, int state) {
super(parent, state);
}
public void discover(TListener listener) { listener.discover_s(this); }
public void finish(TListener listener) { listener.discover_s(this); }
}
*/

View File

@ -1,5 +1,7 @@
import org.antlr.v4.runtime.ANTLRFileStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
public class TestT {
public static void main(String[] args) throws Exception {
@ -11,7 +13,18 @@ public class TestT {
// }
TParser p = new TParser(tokens);
p.setBuildParseTrees(true);
TParser.sContext ret = p.s();
System.out.println(ret.toStringTree(p));
TParser.sContext tree = p.s();
System.out.println(tree.toStringTree(p));
ParseTreeVisitor visitor = new ParseTreeVisitor();
TListener listener = new BlankTListener() {
public void enterEveryRule(ParserRuleContext ctx) {
System.out.println("enter rule "+TParser.ruleNames[ctx.ruleIndex]);
}
public void exitRule(TParser.sContext ctx) { // specific to rule s
System.out.println("exit rule s");
}
};
visitor.visit(listener, tree);
}
}

View File

@ -35,15 +35,36 @@ import java.util.ArrayList;
<parser>
>>
ListenerFile(listener) ::= <<
ListenerFile(listener, header) ::= <<
<header>
import org.antlr.v4.runtime.tree.ParseTreeListener;
@SuppressWarnings({"all", "warnings", "unchecked", "unused"})
public interface <listener.grammarName>Listener {
public interface <listener.grammarName>Listener extends ParseTreeListener {
<listener.rules:{r |
void enterRule(<listener.parserName>.<r.name>Context ctx);
void exitRule(<listener.parserName>.<r.name>Context ctx);}; separator="\n">
}
>>
BlankListenerFile(listener, header) ::= <<
<header>
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
@SuppressWarnings({"all", "warnings", "unchecked", "unused"})
public class Blank<listener.grammarName>Listener implements <listener.grammarName>Listener {
<listener.rules:{r |
public void enterRule(<listener.parserName>.<r.name>Context ctx) { \}
public void exitRule(<listener.parserName>.<r.name>Context ctx) { \}}; separator="\n">
public void enterEveryRule(ParserRuleContext ctx) { }
public void exitEveryRule(ParserRuleContext ctx) { }
public void visitToken(Token token) { }
}
>>
Parser(parser, scopes, funcs, atn, sempredFuncs) ::= <<
@SuppressWarnings({"all", "warnings", "unchecked", "unused"})
public class <parser.name> extends Parser {
@ -429,8 +450,8 @@ public static class <s.name> extends ParserRuleContext {
super(parent, state);
<s.ctorAttrs:{a | this.<a.name> = <a.name>;}; separator="\n">
}
public void enterRule(<parser.grammarName>Listener listener) { listener.enterRule(this); }
public void exitRule(<parser.grammarName>Listener listener) { listener.exitRule(this); }
public void enterRule(ParseTreeListener listener) { ((<parser.grammarName>Listener)listener).enterRule(this); }
public void exitRule(ParseTreeListener listener) { ((<parser.grammarName>Listener)listener).exitRule(this); }
}
>>

View File

@ -47,6 +47,7 @@ public class CodeGenPipeline {
else {
gen.writeRecognizer(gen.generateParser());
gen.writeListener(gen.generateListener());
gen.writeBlankListener(gen.generateBlankListener());
gen.writeHeaderFile();
}
gen.writeVocabFile();

View File

@ -52,8 +52,6 @@ public class CodeGenerator {
"<tokens.keys:{t | <t>=<tokens.(t)>\n}>" +
"<literals.keys:{t | <t>=<literals.(t)>\n}>";
public OutputModelObject outputModel;
public Grammar g;
public Tool tool;
public Target target;
@ -118,9 +116,6 @@ public class CodeGenerator {
// OutputModelFactory factory;
// if ( g.isLexer() ) factory = new LexerFactory(this);
// else factory = new ParserFactory(this);
//
// // TODO: let someone add their own factory?
//
// // CREATE OUTPUT MODEL FROM GRAMMAR OBJ AND AST WITHIN RULES
// OutputModelController controller = new OutputModelController(factory);
// if ( g.hasASTOption() ) {
@ -140,7 +135,7 @@ public class CodeGenerator {
OutputModelController controller = new OutputModelController(factory);
factory.setController(controller);
outputModel = controller.buildLexerOutputModel();
OutputModelObject outputModel = controller.buildLexerOutputModel();
OutputModelWalker walker = new OutputModelWalker(tool, templates);
ST st = walker.walk(outputModel);
@ -156,8 +151,6 @@ public class CodeGenerator {
public ST generateParser() {
OutputModelFactory factory = new ParserFactory(this);
// TODO: let someone add their own factory?
// CREATE OUTPUT MODEL FROM GRAMMAR OBJ AND AST WITHIN RULES
OutputModelController controller = new OutputModelController(factory);
if ( g.hasASTOption() ) {
@ -165,7 +158,7 @@ public class CodeGenerator {
}
factory.setController(controller);
outputModel = controller.buildParserOutputModel();
OutputModelObject outputModel = controller.buildParserOutputModel();
OutputModelWalker walker = new OutputModelWalker(tool, templates);
ST st = walker.walk(outputModel);
@ -181,25 +174,26 @@ public class CodeGenerator {
public ST generateListener() {
OutputModelFactory factory = new ParserFactory(this);
// TODO: let someone add their own factory?
// CREATE OUTPUT MODEL FROM GRAMMAR OBJ AND AST WITHIN RULES
OutputModelController controller = new OutputModelController(factory);
if ( g.hasASTOption() ) {
controller.addExtension( new ParserASTExtension(factory) );
}
factory.setController(controller);
outputModel = controller.buildListenerOutputModel();
OutputModelObject listenerModel = controller.buildListenerOutputModel();
OutputModelWalker walker = new OutputModelWalker(tool, templates);
ST st = walker.walk(outputModel);
if ( tool.launch_ST_inspector ) {
st.inspect();
//if ( templates.isDefined("headerFile") ) headerFileST.inspect();
ST st = walker.walk(listenerModel);
return st;
}
public ST generateBlankListener() {
OutputModelFactory factory = new ParserFactory(this);
OutputModelController controller = new OutputModelController(factory);
factory.setController(controller);
OutputModelObject blankModel = controller.buildBlankListenerOutputModel();
OutputModelWalker walker = new OutputModelWalker(tool, templates);
ST st = walker.walk(blankModel);
return st;
}
@ -243,6 +237,10 @@ public class CodeGenerator {
target.genFile(g,outputFileST, getListenerFileName());
}
public void writeBlankListener(ST outputFileST) {
target.genFile(g,outputFileST, getBlankListenerFileName());
}
public void writeHeaderFile() {
String fileName = getHeaderFileName();
if ( fileName==null ) return;
@ -322,6 +320,15 @@ public class CodeGenerator {
return listenerName+extST.render();
}
/** A given grammar T, return a blank listener implementation
* such as BlankTListener.java, if we're using the Java target.
*/
public String getBlankListenerFileName() {
ST extST = templates.getInstanceOf("codeFileExtension");
String listenerName = "Blank" + g.name + "Listener";
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

@ -110,6 +110,11 @@ public class OutputModelController {
return new ListenerFile(delegate, gen.getListenerFileName());
}
public OutputModelObject buildBlankListenerOutputModel() {
CodeGenerator gen = delegate.getGenerator();
return new BlankListenerFile(delegate, gen.getBlankListenerFileName());
}
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 BlankListenerFile extends ListenerFile {
public BlankListenerFile(OutputModelFactory factory, String fileName) {
super(factory, fileName);
}
}

View File

@ -1,6 +1,7 @@
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.tool.ActionAST;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.Rule;
@ -15,6 +16,8 @@ public class ListenerFile extends OutputModelObject {
public String parserName;
public Collection<Rule> rules;
@ModelElement public Action header;
public ListenerFile(OutputModelFactory factory, String fileName) {
super(factory);
this.fileName = fileName;
@ -22,5 +25,7 @@ public class ListenerFile extends OutputModelObject {
parserName = g.getRecognizerName();
grammarName = g.name;
rules = g.rules.values();
ActionAST ast = g.namedActions.get("header");
if ( ast!=null ) header = new Action(factory, ast);
}
}