forked from jasder/antlr
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:
parent
da7e7c8813
commit
2d234ee28c
|
@ -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);
|
||||
}
|
|
@ -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); }
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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); }
|
||||
}
|
||||
>>
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ public class CodeGenPipeline {
|
|||
else {
|
||||
gen.writeRecognizer(gen.generateParser());
|
||||
gen.writeListener(gen.generateListener());
|
||||
gen.writeBlankListener(gen.generateBlankListener());
|
||||
gen.writeHeaderFile();
|
||||
}
|
||||
gen.writeVocabFile();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -240,7 +234,11 @@ public class CodeGenerator {
|
|||
}
|
||||
|
||||
public void writeListener(ST outputFileST) {
|
||||
target.genFile(g,outputFileST,getListenerFileName());
|
||||
target.genFile(g,outputFileST, getListenerFileName());
|
||||
}
|
||||
|
||||
public void writeBlankListener(ST outputFileST) {
|
||||
target.genFile(g,outputFileST, getBlankListenerFileName());
|
||||
}
|
||||
|
||||
public void writeHeaderFile() {
|
||||
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue