Merge branch 'model-updates-for-new-targets' of github.com:parrt/antlr4 into reduce-model-changes

This commit is contained in:
parrt 2016-11-05 09:29:25 -07:00
commit abdb0b6a46
5 changed files with 119 additions and 86 deletions

View File

@ -2,6 +2,7 @@
* [The "BSD license"] * [The "BSD license"]
* Copyright (c) 2012 Terence Parr * Copyright (c) 2012 Terence Parr
* Copyright (c) 2012 Sam Harwell * Copyright (c) 2012 Sam Harwell
* Copyright (c) 2016 Mike Lischke
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -27,7 +28,6 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package org.antlr.v4.codegen; package org.antlr.v4.codegen;
import org.antlr.v4.parse.ANTLRParser; import org.antlr.v4.parse.ANTLRParser;
@ -59,8 +59,8 @@ public class CodeGenPipeline {
for (GrammarAST idNode : idNodes) { for (GrammarAST idNode : idNodes) {
if ( gen.getTarget().grammarSymbolCausesIssueInGeneratedCode(idNode) ) { if ( gen.getTarget().grammarSymbolCausesIssueInGeneratedCode(idNode) ) {
g.tool.errMgr.grammarError(ErrorType.USE_OF_BAD_WORD, g.tool.errMgr.grammarError(ErrorType.USE_OF_BAD_WORD,
g.fileName, idNode.getToken(), g.fileName, idNode.getToken(),
idNode.getText()); idNode.getText());
} }
} }
@ -70,46 +70,84 @@ public class CodeGenPipeline {
int errorCount = g.tool.errMgr.getNumErrors(); int errorCount = g.tool.errMgr.getNumErrors();
if ( g.isLexer() ) { if ( g.isLexer() ) {
ST lexer = gen.generateLexer(); if (gen.getTarget().needsHeader()) {
ST lexer = gen.generateLexer(true); // Header file if needed.
if (g.tool.errMgr.getNumErrors() == errorCount) {
writeRecognizer(lexer, gen, true);
}
}
ST lexer = gen.generateLexer(false);
if (g.tool.errMgr.getNumErrors() == errorCount) { if (g.tool.errMgr.getNumErrors() == errorCount) {
writeRecognizer(lexer, gen); writeRecognizer(lexer, gen, false);
} }
} }
else { else {
ST parser = gen.generateParser(); if (gen.getTarget().needsHeader()) {
if (g.tool.errMgr.getNumErrors() == errorCount) { ST parser = gen.generateParser(true);
writeRecognizer(parser, gen);
}
if ( g.tool.gen_listener ) {
ST listener = gen.generateListener();
if (g.tool.errMgr.getNumErrors() == errorCount) { if (g.tool.errMgr.getNumErrors() == errorCount) {
gen.writeListener(listener); writeRecognizer(parser, gen, true);
}
}
ST parser = gen.generateParser(false);
if (g.tool.errMgr.getNumErrors() == errorCount) {
writeRecognizer(parser, gen, false);
}
if ( g.tool.gen_listener ) {
if (gen.getTarget().needsHeader()) {
ST listener = gen.generateListener(true);
if (g.tool.errMgr.getNumErrors() == errorCount) {
gen.writeListener(listener, true);
}
}
ST listener = gen.generateListener(false);
if (g.tool.errMgr.getNumErrors() == errorCount) {
gen.writeListener(listener, false);
}
if (gen.getTarget().needsHeader()) {
ST baseListener = gen.generateBaseListener(true);
if (g.tool.errMgr.getNumErrors() == errorCount) {
gen.writeBaseListener(baseListener, true);
}
} }
if (gen.getTarget().wantsBaseListener()) { if (gen.getTarget().wantsBaseListener()) {
ST baseListener = gen.generateBaseListener(); ST baseListener = gen.generateBaseListener(false);
if (g.tool.errMgr.getNumErrors() == errorCount) { if ( g.tool.errMgr.getNumErrors()==errorCount ) {
gen.writeBaseListener(baseListener); gen.writeBaseListener(baseListener, false);
} }
} }
} }
if ( g.tool.gen_visitor ) { if ( g.tool.gen_visitor ) {
ST visitor = gen.generateVisitor(); if (gen.getTarget().needsHeader()) {
ST visitor = gen.generateVisitor(true);
if (g.tool.errMgr.getNumErrors() == errorCount) {
gen.writeVisitor(visitor, true);
}
}
ST visitor = gen.generateVisitor(false);
if (g.tool.errMgr.getNumErrors() == errorCount) { if (g.tool.errMgr.getNumErrors() == errorCount) {
gen.writeVisitor(visitor); gen.writeVisitor(visitor, false);
}
if (gen.getTarget().needsHeader()) {
ST baseVisitor = gen.generateBaseVisitor(true);
if (g.tool.errMgr.getNumErrors() == errorCount) {
gen.writeBaseVisitor(baseVisitor, true);
}
} }
if (gen.getTarget().wantsBaseVisitor()) { if (gen.getTarget().wantsBaseVisitor()) {
ST baseVisitor = gen.generateBaseVisitor(); ST baseVisitor = gen.generateBaseVisitor(false);
if (g.tool.errMgr.getNumErrors() == errorCount) { if ( g.tool.errMgr.getNumErrors()==errorCount ) {
gen.writeBaseVisitor(baseVisitor); gen.writeBaseVisitor(baseVisitor, false);
} }
} }
} }
gen.writeHeaderFile();
} }
gen.writeVocabFile(); gen.writeVocabFile();
} }
protected void writeRecognizer(ST template, CodeGenerator gen) { protected void writeRecognizer(ST template, CodeGenerator gen, boolean header) {
if ( g.tool.launch_ST_inspector ) { if ( g.tool.launch_ST_inspector ) {
STViz viz = template.inspect(); STViz viz = template.inspect();
if (g.tool.ST_inspector_wait_for_close) { if (g.tool.ST_inspector_wait_for_close) {
@ -122,6 +160,6 @@ public class CodeGenPipeline {
} }
} }
gen.writeRecognizer(template); gen.writeRecognizer(template, header);
} }
} }

View File

@ -2,6 +2,7 @@
* [The "BSD license"] * [The "BSD license"]
* Copyright (c) 2012 Terence Parr * Copyright (c) 2012 Terence Parr
* Copyright (c) 2012 Sam Harwell * Copyright (c) 2012 Sam Harwell
* Copyright (c) 2016 Mike Lischke
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -134,17 +135,28 @@ public class CodeGenerator {
return controller; return controller;
} }
private ST walk(OutputModelObject outputModel) { private ST walk(OutputModelObject outputModel, boolean header) {
OutputModelWalker walker = new OutputModelWalker(tool, getTemplates()); OutputModelWalker walker = new OutputModelWalker(tool, getTemplates());
return walker.walk(outputModel); return walker.walk(outputModel, header);
} }
public ST generateLexer() { return walk(createController().buildLexerOutputModel()); } public ST generateLexer() { return generateLexer(false); }
public ST generateParser() { return walk(createController().buildParserOutputModel()); } public ST generateLexer(boolean header) { return walk(createController().buildLexerOutputModel(header), header); }
public ST generateListener() { return walk(createController().buildListenerOutputModel()); }
public ST generateBaseListener() { return walk(createController().buildBaseListenerOutputModel()); } public ST generateParser() { return generateParser(false); }
public ST generateVisitor() { return walk(createController().buildVisitorOutputModel()); } public ST generateParser(boolean header) { return walk(createController().buildParserOutputModel(header), header); }
public ST generateBaseVisitor() { return walk(createController().buildBaseVisitorOutputModel()); }
public ST generateListener() { return generateListener(false); }
public ST generateListener(boolean header) { return walk(createController().buildListenerOutputModel(header), header); }
public ST generateBaseListener() { return generateBaseListener(false); }
public ST generateBaseListener(boolean header) { return walk(createController().buildBaseListenerOutputModel(header), header); }
public ST generateVisitor() { return generateVisitor(false); }
public ST generateVisitor(boolean header) { return walk(createController().buildVisitorOutputModel(header), header); }
public ST generateBaseVisitor() { return generateBaseVisitor(false); }
public ST generateBaseVisitor(boolean header) { return walk(createController().buildBaseVisitorOutputModel(header), header); }
/** Generate a token vocab file with all the token names/types. For example: /** Generate a token vocab file with all the token names/types. For example:
* ID=7 * ID=7
@ -178,35 +190,24 @@ public class CodeGenerator {
return vocabFileST; return vocabFileST;
} }
public void writeRecognizer(ST outputFileST) { public void writeRecognizer(ST outputFileST, boolean header) {
getTarget().genFile(g, outputFileST, getRecognizerFileName()); getTarget().genFile(g, outputFileST, getRecognizerFileName(header));
} }
public void writeListener(ST outputFileST) { public void writeListener(ST outputFileST, boolean header) {
getTarget().genFile(g, outputFileST, getListenerFileName()); getTarget().genFile(g, outputFileST, getListenerFileName(header));
} }
public void writeBaseListener(ST outputFileST) { public void writeBaseListener(ST outputFileST, boolean header) {
getTarget().genFile(g, outputFileST, getBaseListenerFileName()); getTarget().genFile(g, outputFileST, getBaseListenerFileName(header));
} }
public void writeVisitor(ST outputFileST) { public void writeVisitor(ST outputFileST, boolean header) {
getTarget().genFile(g, outputFileST, getVisitorFileName()); getTarget().genFile(g, outputFileST, getVisitorFileName(header));
} }
public void writeBaseVisitor(ST outputFileST) { public void writeBaseVisitor(ST outputFileST, boolean header) {
getTarget().genFile(g, outputFileST, getBaseVisitorFileName()); getTarget().genFile(g, outputFileST, getBaseVisitorFileName(header));
}
public void writeHeaderFile() {
String fileName = getHeaderFileName();
if ( fileName==null ) return;
if ( getTemplates().isDefined("headerFile") ) {
ST extST = getTemplates().getInstanceOf("headerFileExtension");
ST headerFileST = null;
// TODO: don't hide this header file generation here!
getTarget().genRecognizerHeaderFile(g, headerFileST, extST.render(lineWidth));
}
} }
public void writeVocabFile() { public void writeVocabFile() {

View File

@ -2,6 +2,7 @@
* [The "BSD license"] * [The "BSD license"]
* Copyright (c) 2012 Terence Parr * Copyright (c) 2012 Terence Parr
* Copyright (c) 2012 Sam Harwell * Copyright (c) 2012 Sam Harwell
* Copyright (c) 2016 Mike Lischke
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -107,24 +108,23 @@ public class OutputModelController {
* controller as factory in SourceGenTriggers so it triggers codegen * controller as factory in SourceGenTriggers so it triggers codegen
* extensions too, not just the factory functions in this factory. * extensions too, not just the factory functions in this factory.
*/ */
public OutputModelObject buildParserOutputModel() { public OutputModelObject buildParserOutputModel(boolean header) {
Grammar g = delegate.getGrammar();
CodeGenerator gen = delegate.getGenerator(); CodeGenerator gen = delegate.getGenerator();
ParserFile file = parserFile(gen.getRecognizerFileName()); ParserFile file = parserFile(gen.getRecognizerFileName(header));
setRoot(file); setRoot(file);
Parser parser = parser(file); file.parser = parser(file);
file.parser = parser;
Grammar g = delegate.getGrammar();
for (Rule r : g.rules.values()) { for (Rule r : g.rules.values()) {
buildRuleFunction(parser, r); buildRuleFunction(file.parser, r);
} }
return file; return file;
} }
public OutputModelObject buildLexerOutputModel() { public OutputModelObject buildLexerOutputModel(boolean header) {
CodeGenerator gen = delegate.getGenerator(); CodeGenerator gen = delegate.getGenerator();
LexerFile file = lexerFile(gen.getRecognizerFileName()); LexerFile file = lexerFile(gen.getRecognizerFileName(header));
setRoot(file); setRoot(file);
file.lexer = lexer(file); file.lexer = lexer(file);
@ -136,24 +136,24 @@ public class OutputModelController {
return file; return file;
} }
public OutputModelObject buildListenerOutputModel() { public OutputModelObject buildListenerOutputModel(boolean header) {
CodeGenerator gen = delegate.getGenerator(); CodeGenerator gen = delegate.getGenerator();
return new ListenerFile(delegate, gen.getListenerFileName()); return new ListenerFile(delegate, gen.getListenerFileName(header));
} }
public OutputModelObject buildBaseListenerOutputModel() { public OutputModelObject buildBaseListenerOutputModel(boolean header) {
CodeGenerator gen = delegate.getGenerator(); CodeGenerator gen = delegate.getGenerator();
return new BaseListenerFile(delegate, gen.getBaseListenerFileName()); return new BaseListenerFile(delegate, gen.getBaseListenerFileName(header));
} }
public OutputModelObject buildVisitorOutputModel() { public OutputModelObject buildVisitorOutputModel(boolean header) {
CodeGenerator gen = delegate.getGenerator(); CodeGenerator gen = delegate.getGenerator();
return new VisitorFile(delegate, gen.getVisitorFileName()); return new VisitorFile(delegate, gen.getVisitorFileName(header));
} }
public OutputModelObject buildBaseVisitorOutputModel() { public OutputModelObject buildBaseVisitorOutputModel(boolean header) {
CodeGenerator gen = delegate.getGenerator(); CodeGenerator gen = delegate.getGenerator();
return new BaseVisitorFile(delegate, gen.getBaseVisitorFileName()); return new BaseVisitorFile(delegate, gen.getBaseVisitorFileName(header));
} }
public ParserFile parserFile(String fileName) { public ParserFile parserFile(String fileName) {

View File

@ -2,6 +2,7 @@
* [The "BSD license"] * [The "BSD license"]
* Copyright (c) 2012 Terence Parr * Copyright (c) 2012 Terence Parr
* Copyright (c) 2012 Sam Harwell * Copyright (c) 2012 Sam Harwell
* Copyright (c) 2016 Mike Lischke
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -75,7 +76,7 @@ public class OutputModelWalker {
this.templates = templates; this.templates = templates;
} }
public ST walk(OutputModelObject omo) { public ST walk(OutputModelObject omo, boolean header) {
// CREATE TEMPLATE FOR THIS OUTPUT OBJECT // CREATE TEMPLATE FOR THIS OUTPUT OBJECT
Class<? extends OutputModelObject> cl = omo.getClass(); Class<? extends OutputModelObject> cl = omo.getClass();
String templateName = cl.getSimpleName(); String templateName = cl.getSimpleName();
@ -83,6 +84,9 @@ public class OutputModelWalker {
tool.errMgr.toolError(ErrorType.NO_MODEL_TO_TEMPLATE_MAPPING, cl.getSimpleName()); tool.errMgr.toolError(ErrorType.NO_MODEL_TO_TEMPLATE_MAPPING, cl.getSimpleName());
return new ST("["+templateName+" invalid]"); return new ST("["+templateName+" invalid]");
} }
if (header) templateName += "Header";
ST st = templates.getInstanceOf(templateName); ST st = templates.getInstanceOf(templateName);
if ( st == null ) { if ( st == null ) {
tool.errMgr.toolError(ErrorType.CODE_GEN_TEMPLATES_INCOMPLETE, templateName); tool.errMgr.toolError(ErrorType.CODE_GEN_TEMPLATES_INCOMPLETE, templateName);
@ -124,7 +128,7 @@ public class OutputModelWalker {
Object o = fi.get(omo); Object o = fi.get(omo);
if ( o instanceof OutputModelObject ) { // SINGLE MODEL OBJECT? if ( o instanceof OutputModelObject ) { // SINGLE MODEL OBJECT?
OutputModelObject nestedOmo = (OutputModelObject)o; OutputModelObject nestedOmo = (OutputModelObject)o;
ST nestedST = walk(nestedOmo); ST nestedST = walk(nestedOmo, header);
// System.out.println("set ModelElement "+fieldName+"="+nestedST+" in "+templateName); // System.out.println("set ModelElement "+fieldName+"="+nestedST+" in "+templateName);
st.add(fieldName, nestedST); st.add(fieldName, nestedST);
} }
@ -136,7 +140,7 @@ public class OutputModelWalker {
Collection<?> nestedOmos = (Collection<?>)o; Collection<?> nestedOmos = (Collection<?>)o;
for (Object nestedOmo : nestedOmos) { for (Object nestedOmo : nestedOmos) {
if ( nestedOmo==null ) continue; if ( nestedOmo==null ) continue;
ST nestedST = walk((OutputModelObject)nestedOmo); ST nestedST = walk((OutputModelObject)nestedOmo, header);
// System.out.println("set ModelElement "+fieldName+"="+nestedST+" in "+templateName); // System.out.println("set ModelElement "+fieldName+"="+nestedST+" in "+templateName);
st.add(fieldName, nestedST); st.add(fieldName, nestedST);
} }
@ -145,7 +149,7 @@ public class OutputModelWalker {
Map<?, ?> nestedOmoMap = (Map<?, ?>)o; Map<?, ?> nestedOmoMap = (Map<?, ?>)o;
Map<Object, ST> m = new LinkedHashMap<Object, ST>(); Map<Object, ST> m = new LinkedHashMap<Object, ST>();
for (Map.Entry<?, ?> entry : nestedOmoMap.entrySet()) { for (Map.Entry<?, ?> entry : nestedOmoMap.entrySet()) {
ST nestedST = walk((OutputModelObject)entry.getValue()); ST nestedST = walk((OutputModelObject)entry.getValue(), header);
// System.out.println("set ModelElement "+fieldName+"="+nestedST+" in "+templateName); // System.out.println("set ModelElement "+fieldName+"="+nestedST+" in "+templateName);
m.put(entry.getKey(), nestedST); m.put(entry.getKey(), nestedST);
} }

View File

@ -2,6 +2,7 @@
* [The "BSD license"] * [The "BSD license"]
* Copyright (c) 2012 Terence Parr * Copyright (c) 2012 Terence Parr
* Copyright (c) 2012 Sam Harwell * Copyright (c) 2012 Sam Harwell
* Copyright (c) 2016 Mike Lischke
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -121,20 +122,6 @@ public abstract class Target {
getCodeGenerator().write(outputFileST, fileName); getCodeGenerator().write(outputFileST, fileName);
} }
protected void genListenerFile(Grammar g,
ST outputFileST)
{
String fileName = getCodeGenerator().getListenerFileName();
getCodeGenerator().write(outputFileST, fileName);
}
protected void genRecognizerHeaderFile(Grammar g,
ST headerFileST,
String extName) // e.g., ".h"
{
// no header file by default
}
/** Get a meaningful name for a token type useful during code generation. /** Get a meaningful name for a token type useful during code generation.
* Literals without associated names are converted to the string equivalent * Literals without associated names are converted to the string equivalent
* of their integer values. Used to generate x==ID and x==34 type comparisons * of their integer values. Used to generate x==ID and x==34 type comparisons
@ -573,4 +560,7 @@ public abstract class Target {
public boolean supportsOverloadedMethods() { public boolean supportsOverloadedMethods() {
return true; return true;
} }
/** @since 4.6 */
public boolean needsHeader() { return false; }; // Override in targets that need header files.
} }