Merge branch 'model-updates-for-new-targets' of github.com:parrt/antlr4 into reduce-model-changes
This commit is contained in:
commit
abdb0b6a46
|
@ -2,6 +2,7 @@
|
|||
* [The "BSD license"]
|
||||
* Copyright (c) 2012 Terence Parr
|
||||
* Copyright (c) 2012 Sam Harwell
|
||||
* Copyright (c) 2016 Mike Lischke
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.antlr.v4.codegen;
|
||||
|
||||
import org.antlr.v4.parse.ANTLRParser;
|
||||
|
@ -59,8 +59,8 @@ public class CodeGenPipeline {
|
|||
for (GrammarAST idNode : idNodes) {
|
||||
if ( gen.getTarget().grammarSymbolCausesIssueInGeneratedCode(idNode) ) {
|
||||
g.tool.errMgr.grammarError(ErrorType.USE_OF_BAD_WORD,
|
||||
g.fileName, idNode.getToken(),
|
||||
idNode.getText());
|
||||
g.fileName, idNode.getToken(),
|
||||
idNode.getText());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,46 +70,84 @@ public class CodeGenPipeline {
|
|||
int errorCount = g.tool.errMgr.getNumErrors();
|
||||
|
||||
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) {
|
||||
writeRecognizer(lexer, gen);
|
||||
writeRecognizer(lexer, gen, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ST parser = gen.generateParser();
|
||||
if (g.tool.errMgr.getNumErrors() == errorCount) {
|
||||
writeRecognizer(parser, gen);
|
||||
}
|
||||
if ( g.tool.gen_listener ) {
|
||||
ST listener = gen.generateListener();
|
||||
if (gen.getTarget().needsHeader()) {
|
||||
ST parser = gen.generateParser(true);
|
||||
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()) {
|
||||
ST baseListener = gen.generateBaseListener();
|
||||
if (g.tool.errMgr.getNumErrors() == errorCount) {
|
||||
gen.writeBaseListener(baseListener);
|
||||
ST baseListener = gen.generateBaseListener(false);
|
||||
if ( g.tool.errMgr.getNumErrors()==errorCount ) {
|
||||
gen.writeBaseListener(baseListener, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
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()) {
|
||||
ST baseVisitor = gen.generateBaseVisitor();
|
||||
if (g.tool.errMgr.getNumErrors() == errorCount) {
|
||||
gen.writeBaseVisitor(baseVisitor);
|
||||
ST baseVisitor = gen.generateBaseVisitor(false);
|
||||
if ( g.tool.errMgr.getNumErrors()==errorCount ) {
|
||||
gen.writeBaseVisitor(baseVisitor, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
gen.writeHeaderFile();
|
||||
}
|
||||
gen.writeVocabFile();
|
||||
}
|
||||
|
||||
protected void writeRecognizer(ST template, CodeGenerator gen) {
|
||||
protected void writeRecognizer(ST template, CodeGenerator gen, boolean header) {
|
||||
if ( g.tool.launch_ST_inspector ) {
|
||||
STViz viz = template.inspect();
|
||||
if (g.tool.ST_inspector_wait_for_close) {
|
||||
|
@ -122,6 +160,6 @@ public class CodeGenPipeline {
|
|||
}
|
||||
}
|
||||
|
||||
gen.writeRecognizer(template);
|
||||
gen.writeRecognizer(template, header);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* [The "BSD license"]
|
||||
* Copyright (c) 2012 Terence Parr
|
||||
* Copyright (c) 2012 Sam Harwell
|
||||
* Copyright (c) 2016 Mike Lischke
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -134,17 +135,28 @@ public class CodeGenerator {
|
|||
return controller;
|
||||
}
|
||||
|
||||
private ST walk(OutputModelObject outputModel) {
|
||||
private ST walk(OutputModelObject outputModel, boolean header) {
|
||||
OutputModelWalker walker = new OutputModelWalker(tool, getTemplates());
|
||||
return walker.walk(outputModel);
|
||||
return walker.walk(outputModel, header);
|
||||
}
|
||||
|
||||
public ST generateLexer() { return walk(createController().buildLexerOutputModel()); }
|
||||
public ST generateParser() { return walk(createController().buildParserOutputModel()); }
|
||||
public ST generateListener() { return walk(createController().buildListenerOutputModel()); }
|
||||
public ST generateBaseListener() { return walk(createController().buildBaseListenerOutputModel()); }
|
||||
public ST generateVisitor() { return walk(createController().buildVisitorOutputModel()); }
|
||||
public ST generateBaseVisitor() { return walk(createController().buildBaseVisitorOutputModel()); }
|
||||
public ST generateLexer() { return generateLexer(false); }
|
||||
public ST generateLexer(boolean header) { return walk(createController().buildLexerOutputModel(header), header); }
|
||||
|
||||
public ST generateParser() { return generateParser(false); }
|
||||
public ST generateParser(boolean header) { return walk(createController().buildParserOutputModel(header), header); }
|
||||
|
||||
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:
|
||||
* ID=7
|
||||
|
@ -178,35 +190,24 @@ public class CodeGenerator {
|
|||
return vocabFileST;
|
||||
}
|
||||
|
||||
public void writeRecognizer(ST outputFileST) {
|
||||
getTarget().genFile(g, outputFileST, getRecognizerFileName());
|
||||
public void writeRecognizer(ST outputFileST, boolean header) {
|
||||
getTarget().genFile(g, outputFileST, getRecognizerFileName(header));
|
||||
}
|
||||
|
||||
public void writeListener(ST outputFileST) {
|
||||
getTarget().genFile(g, outputFileST, getListenerFileName());
|
||||
public void writeListener(ST outputFileST, boolean header) {
|
||||
getTarget().genFile(g, outputFileST, getListenerFileName(header));
|
||||
}
|
||||
|
||||
public void writeBaseListener(ST outputFileST) {
|
||||
getTarget().genFile(g, outputFileST, getBaseListenerFileName());
|
||||
public void writeBaseListener(ST outputFileST, boolean header) {
|
||||
getTarget().genFile(g, outputFileST, getBaseListenerFileName(header));
|
||||
}
|
||||
|
||||
public void writeVisitor(ST outputFileST) {
|
||||
getTarget().genFile(g, outputFileST, getVisitorFileName());
|
||||
public void writeVisitor(ST outputFileST, boolean header) {
|
||||
getTarget().genFile(g, outputFileST, getVisitorFileName(header));
|
||||
}
|
||||
|
||||
public void writeBaseVisitor(ST outputFileST) {
|
||||
getTarget().genFile(g, outputFileST, getBaseVisitorFileName());
|
||||
}
|
||||
|
||||
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 writeBaseVisitor(ST outputFileST, boolean header) {
|
||||
getTarget().genFile(g, outputFileST, getBaseVisitorFileName(header));
|
||||
}
|
||||
|
||||
public void writeVocabFile() {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* [The "BSD license"]
|
||||
* Copyright (c) 2012 Terence Parr
|
||||
* Copyright (c) 2012 Sam Harwell
|
||||
* Copyright (c) 2016 Mike Lischke
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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
|
||||
* extensions too, not just the factory functions in this factory.
|
||||
*/
|
||||
public OutputModelObject buildParserOutputModel() {
|
||||
Grammar g = delegate.getGrammar();
|
||||
public OutputModelObject buildParserOutputModel(boolean header) {
|
||||
CodeGenerator gen = delegate.getGenerator();
|
||||
ParserFile file = parserFile(gen.getRecognizerFileName());
|
||||
ParserFile file = parserFile(gen.getRecognizerFileName(header));
|
||||
setRoot(file);
|
||||
Parser parser = parser(file);
|
||||
file.parser = parser;
|
||||
file.parser = parser(file);
|
||||
|
||||
Grammar g = delegate.getGrammar();
|
||||
for (Rule r : g.rules.values()) {
|
||||
buildRuleFunction(parser, r);
|
||||
buildRuleFunction(file.parser, r);
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public OutputModelObject buildLexerOutputModel() {
|
||||
public OutputModelObject buildLexerOutputModel(boolean header) {
|
||||
CodeGenerator gen = delegate.getGenerator();
|
||||
LexerFile file = lexerFile(gen.getRecognizerFileName());
|
||||
LexerFile file = lexerFile(gen.getRecognizerFileName(header));
|
||||
setRoot(file);
|
||||
file.lexer = lexer(file);
|
||||
|
||||
|
@ -136,24 +136,24 @@ public class OutputModelController {
|
|||
return file;
|
||||
}
|
||||
|
||||
public OutputModelObject buildListenerOutputModel() {
|
||||
public OutputModelObject buildListenerOutputModel(boolean header) {
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
return new BaseVisitorFile(delegate, gen.getBaseVisitorFileName());
|
||||
return new BaseVisitorFile(delegate, gen.getBaseVisitorFileName(header));
|
||||
}
|
||||
|
||||
public ParserFile parserFile(String fileName) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* [The "BSD license"]
|
||||
* Copyright (c) 2012 Terence Parr
|
||||
* Copyright (c) 2012 Sam Harwell
|
||||
* Copyright (c) 2016 Mike Lischke
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -75,7 +76,7 @@ public class OutputModelWalker {
|
|||
this.templates = templates;
|
||||
}
|
||||
|
||||
public ST walk(OutputModelObject omo) {
|
||||
public ST walk(OutputModelObject omo, boolean header) {
|
||||
// CREATE TEMPLATE FOR THIS OUTPUT OBJECT
|
||||
Class<? extends OutputModelObject> cl = omo.getClass();
|
||||
String templateName = cl.getSimpleName();
|
||||
|
@ -83,6 +84,9 @@ public class OutputModelWalker {
|
|||
tool.errMgr.toolError(ErrorType.NO_MODEL_TO_TEMPLATE_MAPPING, cl.getSimpleName());
|
||||
return new ST("["+templateName+" invalid]");
|
||||
}
|
||||
|
||||
if (header) templateName += "Header";
|
||||
|
||||
ST st = templates.getInstanceOf(templateName);
|
||||
if ( st == null ) {
|
||||
tool.errMgr.toolError(ErrorType.CODE_GEN_TEMPLATES_INCOMPLETE, templateName);
|
||||
|
@ -124,7 +128,7 @@ public class OutputModelWalker {
|
|||
Object o = fi.get(omo);
|
||||
if ( o instanceof OutputModelObject ) { // SINGLE MODEL OBJECT?
|
||||
OutputModelObject nestedOmo = (OutputModelObject)o;
|
||||
ST nestedST = walk(nestedOmo);
|
||||
ST nestedST = walk(nestedOmo, header);
|
||||
// System.out.println("set ModelElement "+fieldName+"="+nestedST+" in "+templateName);
|
||||
st.add(fieldName, nestedST);
|
||||
}
|
||||
|
@ -136,7 +140,7 @@ public class OutputModelWalker {
|
|||
Collection<?> nestedOmos = (Collection<?>)o;
|
||||
for (Object nestedOmo : nestedOmos) {
|
||||
if ( nestedOmo==null ) continue;
|
||||
ST nestedST = walk((OutputModelObject)nestedOmo);
|
||||
ST nestedST = walk((OutputModelObject)nestedOmo, header);
|
||||
// System.out.println("set ModelElement "+fieldName+"="+nestedST+" in "+templateName);
|
||||
st.add(fieldName, nestedST);
|
||||
}
|
||||
|
@ -145,7 +149,7 @@ public class OutputModelWalker {
|
|||
Map<?, ?> nestedOmoMap = (Map<?, ?>)o;
|
||||
Map<Object, ST> m = new LinkedHashMap<Object, ST>();
|
||||
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);
|
||||
m.put(entry.getKey(), nestedST);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* [The "BSD license"]
|
||||
* Copyright (c) 2012 Terence Parr
|
||||
* Copyright (c) 2012 Sam Harwell
|
||||
* Copyright (c) 2016 Mike Lischke
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -121,20 +122,6 @@ public abstract class Target {
|
|||
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.
|
||||
* Literals without associated names are converted to the string equivalent
|
||||
* 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() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @since 4.6 */
|
||||
public boolean needsHeader() { return false; }; // Override in targets that need header files.
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue