diff --git a/runtime/JavaScript/package-lock.json b/runtime/JavaScript/package-lock.json index ec8f67401b..0cfdc3cab4 100644 --- a/runtime/JavaScript/package-lock.json +++ b/runtime/JavaScript/package-lock.json @@ -4818,9 +4818,9 @@ } }, "node_modules/webpack": { - "version": "5.75.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz", - "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==", + "version": "5.76.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", + "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", @@ -8588,9 +8588,9 @@ } }, "webpack": { - "version": "5.75.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz", - "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==", + "version": "5.76.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", + "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.3", diff --git a/tool/src/org/antlr/v4/Tool.java b/tool/src/org/antlr/v4/Tool.java index 1b7eea7535..1e45dc44e0 100644 --- a/tool/src/org/antlr/v4/Tool.java +++ b/tool/src/org/antlr/v4/Tool.java @@ -18,6 +18,10 @@ import org.antlr.v4.automata.ParserATNFactory; import org.antlr.v4.codegen.CodeGenPipeline; import org.antlr.v4.codegen.CodeGenerator; +import org.antlr.v4.codegen.InMemoryCodeGenerator; +import org.antlr.v4.codegen.inMemoryResult.InMemoryCodeGenResult; +import org.antlr.v4.codegen.inMemoryResult.InMemoryFile; +import org.antlr.v4.codegen.inMemoryResult.DataFiles; import org.antlr.v4.misc.Graph; import org.antlr.v4.parse.ANTLRParser; import org.antlr.v4.parse.GrammarASTAdaptor; @@ -320,13 +324,23 @@ else if (errMgr.getNumErrors() == 0) { } } + public void process(Grammar g, boolean gencode) { + process(g, gencode, null); + } + + public InMemoryCodeGenResult processInMemory(Grammar g, boolean gencode) { + InMemoryCodeGenResult res = new InMemoryCodeGenResult(); + process(g, gencode, res); + return res; + } + /** To process a grammar, we load all of its imported grammars into subordinate grammar objects. Then we merge the imported rules into the root grammar. If a root grammar is a combined grammar, we have to extract the implicit lexer. Once all this is done, we process the lexer first, if present, and then the parser grammar */ - public void process(Grammar g, boolean gencode) { + public void process(Grammar g, boolean gencode, InMemoryCodeGenResult res) { g.loadImportedGrammars(); GrammarTransformPipeline transform = new GrammarTransformPipeline(g, this); @@ -348,7 +362,7 @@ public void process(Grammar g, boolean gencode) { lexerg.originalGrammar = g; g.implicitLexer = lexerg; lexerg.implicitLexerOwner = g; - processNonCombinedGrammar(lexerg, gencode); + processNonCombinedGrammar(lexerg, gencode, res); // System.out.println("lexer tokens="+lexerg.tokenNameToTypeMap); // System.out.println("lexer strings="+lexerg.stringLiteralToTypeMap); } @@ -356,27 +370,29 @@ public void process(Grammar g, boolean gencode) { if ( g.implicitLexer!=null ) g.importVocab(g.implicitLexer); // System.out.println("tokens="+g.tokenNameToTypeMap); // System.out.println("strings="+g.stringLiteralToTypeMap); - processNonCombinedGrammar(g, gencode); + processNonCombinedGrammar(g, gencode, res); } - public void processNonCombinedGrammar(Grammar g, boolean gencode) { - if ( g.ast==null || g.ast.hasErrors ) return; + public boolean prepareProcessNonCombinedGrammar(Grammar g, boolean gencode) { + if ( g.ast==null || g.ast.hasErrors ) return false; boolean ruleFail = checkForRuleIssues(g); - if ( ruleFail ) return; + if ( ruleFail ) return false; int prevErrors = errMgr.getNumErrors(); // MAKE SURE GRAMMAR IS SEMANTICALLY CORRECT (FILL IN GRAMMAR OBJECT) SemanticPipeline sem = new SemanticPipeline(g); sem.process(); - if ( errMgr.getNumErrors()>prevErrors ) return; + if ( errMgr.getNumErrors()>prevErrors ) return false; CodeGenerator codeGenerator = CodeGenerator.create(g); if (codeGenerator == null) { - return; + return false; } + if ( errMgr.getNumErrors()>prevErrors ) return false; + // BUILD ATN FROM AST ATNFactory factory; if ( g.isLexer() ) factory = new LexerATNFactory((LexerGrammar)g, codeGenerator); @@ -384,14 +400,29 @@ public void processNonCombinedGrammar(Grammar g, boolean gencode) { g.atn = factory.createATN(); if ( generate_ATN_dot ) generateATNs(g); + return true; + } - if (gencode && g.tool.getNumErrors()==0 ) { - String interpFile = generateInterpreterData(g); - try (Writer fw = getOutputFileWriter(g, g.name + ".interp")) { - fw.write(interpFile); - } - catch (IOException ioe) { - errMgr.toolError(ErrorType.CANNOT_WRITE_FILE, ioe); + public void processNonCombinedGrammar(Grammar g, boolean gencode) { + processNonCombinedGrammar(g, gencode, null); + } + + public void processNonCombinedGrammar(Grammar g, boolean gencode, InMemoryCodeGenResult res) { + if (!prepareProcessNonCombinedGrammar(g, gencode)) return; + int prevErrors = errMgr.getNumErrors(); + + if (gencode && g.tool.getNumErrors()==0 ){ + if(res != null){ + DataFiles selectedDFiles = (g.isLexer()?res.lexerData:res.mainData); + selectedDFiles.interp = new InMemoryFile(getInterpFileName(g), generateInterpreterData(g)); + }else{ + String interpFile = generateInterpreterData(g); + try (Writer fw = getOutputFileWriter(g, g.name + ".interp")) { + fw.write(interpFile); + } + catch (IOException ioe) { + errMgr.toolError(ErrorType.CANNOT_WRITE_FILE, ioe); + } } } @@ -405,11 +436,28 @@ public void processNonCombinedGrammar(Grammar g, boolean gencode) { // GENERATE CODE if ( gencode ) { + CodeGenerator codeGenerator = null; + if(res != null){ + codeGenerator = InMemoryCodeGenerator.create(g, res); + } else { + codeGenerator = CodeGenerator.create(g); + } CodeGenPipeline gen = new CodeGenPipeline(g, codeGenerator); - gen.process(); + gen.process(res); } } + public InMemoryCodeGenResult processNonCombinedGrammarInMemory(Grammar g) { + InMemoryCodeGenResult res = new InMemoryCodeGenResult(); + processNonCombinedGrammar(g, true, res); + return res; + } + + // Don't inline: used in https://github.com/antlr/antlr4/issues/3874 + protected static String getInterpFileName(Grammar g){ + return g.name + ".interp"; + } + /** * Important enough to avoid multiple definitions that we do very early, * right after AST construction. Also check for undefined rules in @@ -686,7 +734,7 @@ public void generateATNs(Grammar g) { writeDOTFile(g, r, dot); } } - catch (IOException ioe) { + catch (IOException ioe) { errMgr.toolError(ErrorType.CANNOT_WRITE_FILE, ioe); } } @@ -740,7 +788,6 @@ public static String generateInterpreterData(Grammar g) { content.append("atn:\n"); content.append(serializedATN.toString()); - return content.toString(); } @@ -762,7 +809,7 @@ public static String generateInterpreterData(Grammar g) { * If outputDirectory==null then write a String. */ public Writer getOutputFileWriter(Grammar g, String fileName) throws IOException { - if (outputDirectory == null) { + if (outputDirectory == null || fileName == null) { return new StringWriter(); } // output directory is a function of where the grammar file lives diff --git a/tool/src/org/antlr/v4/codegen/CodeGenPipeline.java b/tool/src/org/antlr/v4/codegen/CodeGenPipeline.java index fee35ef2a4..4557c7285a 100644 --- a/tool/src/org/antlr/v4/codegen/CodeGenPipeline.java +++ b/tool/src/org/antlr/v4/codegen/CodeGenPipeline.java @@ -10,100 +10,120 @@ import org.antlr.v4.tool.Rule; import org.stringtemplate.v4.ST; import org.stringtemplate.v4.gui.STViz; +import org.antlr.v4.codegen.inMemoryResult.InMemoryCodeGenResult; +import org.antlr.v4.codegen.inMemoryResult.InMemoryFile; public class CodeGenPipeline { final Grammar g; final CodeGenerator gen; + int errorCount; public CodeGenPipeline(Grammar g, CodeGenerator gen) { this.g = g; this.gen = gen; } - public void process() { - // all templates are generated in memory to report the most complete - // error information possible, but actually writing output files stops - // after the first error is reported - int errorCount = g.tool.errMgr.getNumErrors(); - - if ( g.isLexer() ) { - if (gen.getTarget().needsHeader()) { - ST lexer = gen.generateLexer(true); // Header file if needed. - if (g.tool.errMgr.getNumErrors() == errorCount) { - writeRecognizer(lexer, gen, true); - } + public void processLexer(CodeGenerator gen, Grammar g){ + 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); + } + ST lexer = gen.generateLexer(false); + if (g.tool.errMgr.getNumErrors() == errorCount) { + writeRecognizer(lexer, gen, false); + } + } + + public void processParser(CodeGenerator gen, Grammar g){ + if (gen.getTarget().needsHeader()) { + ST parser = gen.generateParser(true); if (g.tool.errMgr.getNumErrors() == errorCount) { - writeRecognizer(lexer, gen, false); + writeRecognizer(parser, gen, true); } } - else { + 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 parser = gen.generateParser(true); + ST listener = gen.generateListener(true); if (g.tool.errMgr.getNumErrors() == errorCount) { - writeRecognizer(parser, gen, true); + gen.writeListener(listener, true); } } - ST parser = gen.generateParser(false); + ST listener = gen.generateListener(false); if (g.tool.errMgr.getNumErrors() == errorCount) { - writeRecognizer(parser, gen, false); + gen.writeListener(listener, 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 (gen.getTarget().needsHeader()) { + ST baseListener = gen.generateBaseListener(true); 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(false); - if ( g.tool.errMgr.getNumErrors()==errorCount ) { - gen.writeBaseListener(baseListener, false); - } + gen.writeBaseListener(baseListener, true); } } - if ( g.tool.gen_visitor ) { - if (gen.getTarget().needsHeader()) { - ST visitor = gen.generateVisitor(true); - if (g.tool.errMgr.getNumErrors() == errorCount) { - gen.writeVisitor(visitor, true); - } + if (gen.getTarget().wantsBaseListener()) { + ST baseListener = gen.generateBaseListener(false); + if ( g.tool.errMgr.getNumErrors()==errorCount ) { + gen.writeBaseListener(baseListener, false); } - ST visitor = gen.generateVisitor(false); + } + } + if ( g.tool.gen_visitor ) { + if (gen.getTarget().needsHeader()) { + ST visitor = gen.generateVisitor(true); if (g.tool.errMgr.getNumErrors() == errorCount) { - gen.writeVisitor(visitor, false); + gen.writeVisitor(visitor, true); } + } + ST visitor = gen.generateVisitor(false); + if (g.tool.errMgr.getNumErrors() == errorCount) { + 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().needsHeader()) { + ST baseVisitor = gen.generateBaseVisitor(true); + if (g.tool.errMgr.getNumErrors() == errorCount) { + gen.writeBaseVisitor(baseVisitor, true); } - if (gen.getTarget().wantsBaseVisitor()) { - ST baseVisitor = gen.generateBaseVisitor(false); - if ( g.tool.errMgr.getNumErrors()==errorCount ) { - gen.writeBaseVisitor(baseVisitor, false); - } + } + if (gen.getTarget().wantsBaseVisitor()) { + ST baseVisitor = gen.generateBaseVisitor(false); + if ( g.tool.errMgr.getNumErrors()==errorCount ) { + gen.writeBaseVisitor(baseVisitor, false); } } } + } + + public void processWithCodeGen(CodeGenerator gen){ + // all templates are generated in memory to report the most complete + // error information possible, but actually writing output files stops + // after the first error is reported + errorCount = g.tool.errMgr.getNumErrors(); + + if ( g.isLexer() ) { + processLexer(gen, g); + } + else { + processParser(gen, g); + } + } + + public void process(InMemoryCodeGenResult res) { + if ( g.getLanguage() == null ) return; + + //CodeGenerator gen = new CodeGenerator(null, g); // TODO + gen.result = res; + processWithCodeGen(gen); gen.writeVocabFile(); } + protected void writeRecognizer(ST template, CodeGenerator gen, boolean header) { if ( g.tool.launch_ST_inspector ) { STViz viz = template.inspect(); diff --git a/tool/src/org/antlr/v4/codegen/CodeGenerator.java b/tool/src/org/antlr/v4/codegen/CodeGenerator.java index e065466337..d89ddb6dad 100644 --- a/tool/src/org/antlr/v4/codegen/CodeGenerator.java +++ b/tool/src/org/antlr/v4/codegen/CodeGenerator.java @@ -8,6 +8,9 @@ import org.antlr.v4.Tool; import org.antlr.v4.codegen.model.OutputModelObject; +import org.antlr.v4.codegen.InMemoryCodeGenerator; +import org.antlr.v4.codegen.inMemoryResult.InMemoryCodeGenResult; +import org.antlr.v4.codegen.inMemoryResult.InMemoryFile; import org.antlr.v4.runtime.Token; import org.antlr.v4.tool.ErrorType; import org.antlr.v4.tool.Grammar; @@ -37,21 +40,28 @@ public class CodeGenerator { public final String language; - private Target target; + protected Target target; public int lineWidth = 72; + public InMemoryCodeGenResult result = null; + public static CodeGenerator create(Grammar g) { return create(g.tool, g, g.getLanguage()); } - public static CodeGenerator create(Tool tool, Grammar g, String language) { + // Don't inline: used in https://github.com/antlr/antlr4/issues/3874 + public void initializeTarget() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, java.lang.reflect.InvocationTargetException { String targetName = "org.antlr.v4.codegen.target."+language+"Target"; + Class c = Class.forName(targetName).asSubclass(Target.class); + Constructor ctor = c.getConstructor(CodeGenerator.class); + this.target = ctor.newInstance(this); + } + + public static CodeGenerator create(Tool tool, Grammar g, String language) { try { - Class c = Class.forName(targetName).asSubclass(Target.class); - Constructor ctor = c.getConstructor(CodeGenerator.class); CodeGenerator codeGenerator = new CodeGenerator(tool, g, language); - codeGenerator.target = ctor.newInstance(codeGenerator); + codeGenerator.initializeTarget(); return codeGenerator; } catch (Exception e) { @@ -60,7 +70,7 @@ public static CodeGenerator create(Tool tool, Grammar g, String language) { } } - private CodeGenerator(Tool tool, Grammar g, String language) { + protected CodeGenerator(Tool tool, Grammar g, String language) { this.g = g; this.tool = tool; this.language = language; @@ -168,13 +178,18 @@ public void writeVocabFile() { } } + // Don't inline: used in https://github.com/antlr/antlr4/issues/3874 + protected void writeToWriter(ST code, Writer w) throws IOException{ + STWriter wr = new AutoIndentWriter(w); + wr.setLineWidth(lineWidth); + code.write(wr); + } + public void write(ST code, String fileName) { try { // long start = System.currentTimeMillis(); Writer w = tool.getOutputFileWriter(g, fileName); - STWriter wr = new AutoIndentWriter(w); - wr.setLineWidth(lineWidth); - code.write(wr); + writeToWriter(code, w); w.close(); // long stop = System.currentTimeMillis(); } @@ -210,5 +225,4 @@ public String getHeaderFileName() { String recognizerName = g.getRecognizerName(); return recognizerName+extST.render(); } - } diff --git a/tool/src/org/antlr/v4/codegen/InMemoryCodeGenerator.java b/tool/src/org/antlr/v4/codegen/InMemoryCodeGenerator.java new file mode 100644 index 0000000000..24e31a10b4 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/InMemoryCodeGenerator.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.codegen; + +import org.antlr.v4.Tool; +import org.antlr.v4.codegen.model.OutputModelObject; +import org.antlr.v4.codegen.inMemoryResult.InMemoryCodeGenResult; +import org.antlr.v4.codegen.inMemoryResult.InMemoryFile; +import org.antlr.v4.codegen.inMemoryResult.DataFiles; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.tool.ErrorType; +import org.antlr.v4.tool.Grammar; +import org.stringtemplate.v4.AutoIndentWriter; +import org.stringtemplate.v4.ST; +import org.stringtemplate.v4.STGroup; +import org.stringtemplate.v4.STWriter; + +import java.io.IOException; +import java.io.Writer; +import java.lang.reflect.Constructor; +import java.util.LinkedHashMap; +import java.util.ArrayList; +import java.util.Map; + +import org.antlr.v4.codegen.CodeGenerator; + +/** Generates files in-memory. + */ +public class InMemoryCodeGenerator extends CodeGenerator{ + protected InMemoryCodeGenerator(Tool tool, Grammar g, String language) { + super(tool, g, language); + } + + public static CodeGenerator create(Grammar g, InMemoryCodeGenResult res) { + InMemoryCodeGenerator gen = create(g.tool, g, g.getLanguage()); + gen.result = res; + return gen; + } + + public static InMemoryCodeGenerator create(Tool tool, Grammar g, String language) { + try { + InMemoryCodeGenerator codeGenerator = new InMemoryCodeGenerator(tool, g, language); + codeGenerator.initializeTarget(); + return codeGenerator; + } + catch (Exception e) { + g.tool.errMgr.toolError(ErrorType.CANNOT_CREATE_TARGET_GENERATOR, e, language); + return null; + } + } + + public void writeRecognizer(ST outputFileST, boolean header) { + String fn = getRecognizerFileName(header); + InMemoryFile res = new InMemoryFile(fn, this.writeToString(outputFileST)); + if(g.isLexer()){ + if(result.lexer == null) + result.lexer = new ArrayList(); + result.lexer.add(res); + } else { + if(result.parser == null) + result.parser = new ArrayList(); + result.parser.add(res); + } + } + + public void writeListener(ST outputFileST, boolean header) { + String fn = getListenerFileName(header); + if(result.listener == null) + result.listener = new ArrayList(); + result.listener.add(new InMemoryFile(fn, this.writeToString(outputFileST))); + } + + public void writeBaseListener(ST outputFileST, boolean header) { + String fn = getBaseListenerFileName(header); + if(result.baseListener == null) + result.baseListener = new ArrayList(); + result.baseListener.add(new InMemoryFile(fn, this.writeToString(outputFileST))); + } + + public void writeVisitor(ST outputFileST, boolean header) { + String fn = getVisitorFileName(header); + if(result.visitor == null) + result.visitor = new ArrayList(); + result.visitor.add(new InMemoryFile(fn, this.writeToString(outputFileST))); + } + + public void writeBaseVisitor(ST outputFileST, boolean header) { + Target t = getTarget(); + String fn = getBaseVisitorFileName(header); + if(result.baseVisitor == null) + result.baseVisitor = new ArrayList(); + result.baseVisitor.add(new InMemoryFile(fn, this.writeToString(outputFileST))); + } + + public void writeVocabFile() { + // write out the vocab interchange file; used by antlr, + // does not change per target + ST tokenVocabSerialization = getTokenVocabOutput(); + String fileName = getVocabFileName(); + if ( fileName!=null ) { + DataFiles selectedDFiles = (g.isLexer()?result.lexerData:result.mainData); + selectedDFiles.tokens = new InMemoryFile(fileName, this.writeToString(tokenVocabSerialization)); + } + } + + public String writeToString(ST code) { + try { +// long start = System.currentTimeMillis(); + Writer w = tool.getOutputFileWriter(g, null); + writeToWriter(code, w); + w.close(); + return w.toString(); +// long stop = System.currentTimeMillis(); + } + catch (IOException ioe) { + tool.errMgr.toolError(ErrorType.CANNOT_WRITE_FILE, + ioe, + ""); + return null; + } + } +} diff --git a/tool/src/org/antlr/v4/codegen/inMemoryResult/DataFiles.java b/tool/src/org/antlr/v4/codegen/inMemoryResult/DataFiles.java new file mode 100644 index 0000000000..abdb382028 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/inMemoryResult/DataFiles.java @@ -0,0 +1,85 @@ +/* + * This file is free and unencumbered software released into the public domain. + + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this file, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + + * In jurisdictions that recognize copyright laws, the author or authors + * of this file dedicate any and all copyright interest in the + * file to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * file under copyright law. + + * THE FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE FILE OR THE USE OR + * OTHER DEALINGS IN THE FILE. + + * For more information, please refer to + */ + +package org.antlr.v4.codegen.inMemoryResult; + +import java.util.Iterator; +import java.util.Collection; +import java.util.ArrayList; +import java.util.NoSuchElementException; + +public class DataFiles implements Iterable{ + public InMemoryFile interp, tokens; + + public class DataFilesResultIterator implements Iterator{ + int state = 0; + public static final int size = 2; + + private DataFiles parent; + + public DataFilesResultIterator(DataFiles parent){ + this.parent = parent; + } + + @Override + public boolean hasNext() { + return state < size; + } + + @Override + public InMemoryFile next() throws NoSuchElementException { + int prevState = state; + state += 1; + switch(prevState){ + case 0: + return parent.interp; + case 1: + return parent.tokens; + default: + state = prevState; + throw new NoSuchElementException(); + } + } + } + + public ArrayList toArrayList(){ + ArrayList res = new ArrayList(); + for (InMemoryFile el : this){ + res.add(el); + } + return res; + } + + @Override + public Iterator iterator(){ + return new DataFilesResultIterator(this); + } + + public void clear(){ + interp = tokens = null; + } +} diff --git a/tool/src/org/antlr/v4/codegen/inMemoryResult/InMemoryCodeGenResult.java b/tool/src/org/antlr/v4/codegen/inMemoryResult/InMemoryCodeGenResult.java new file mode 100644 index 0000000000..fbd4646ccc --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/inMemoryResult/InMemoryCodeGenResult.java @@ -0,0 +1,120 @@ +/* + * This file is free and unencumbered software released into the public domain. + + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this file, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + + * In jurisdictions that recognize copyright laws, the author or authors + * of this file dedicate any and all copyright interest in the + * file to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * file under copyright law. + + * THE FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE FILE OR THE USE OR + * OTHER DEALINGS IN THE FILE. + + * For more information, please refer to + */ + +package org.antlr.v4.codegen.inMemoryResult; + +import java.util.Iterator; +import java.util.Collection; +import java.util.ArrayList; +import java.util.NoSuchElementException; + + +/** Just a struct storing the results of code generation */ +public class InMemoryCodeGenResult implements Iterable{ + public ArrayList lexer, parser, listener, baseListener, visitor, baseVisitor, DFAGraph; + + public DataFiles mainData, lexerData; + public InMemoryCodeGenResult(){ + this.mainData = new DataFiles(); + this.lexerData = new DataFiles(); + } + + public class InMemoryCodeGenResultIterator implements Iterator{ + int curPropNo = 0; + int indexInCurProp = 0; + public static final int size = 8; // Role.STOP.ordinal(); + + private InMemoryCodeGenResult parent; + + public InMemoryCodeGenResultIterator(InMemoryCodeGenResult parent){ + this.parent = parent; + } + + @Override + public boolean hasNext() { + return curPropNo < size; + } + + public ArrayList dataFilesToArrayList(DataFiles df){ + if(df != null){ + return df.toArrayList(); + } else { + return null; + } + } + + @Override + public InMemoryFilesWithRole next() throws NoSuchElementException { + ArrayList curProp = null; + + Role role = Role.values()[curPropNo]; + switch(role){ + case lexer: + curProp = parent.lexer; + break; + case parser: + curProp = parent.parser; + break; + case listener: + curProp = parent.listener; + break; + case visitor: + curProp = parent.visitor; + break; + case baseListener: + curProp = parent.baseListener; + break; + case baseVisitor: + curProp = parent.baseVisitor; + break; + case DFAGraph: + curProp = parent.DFAGraph; + break; + case lexerData: + curProp = dataFilesToArrayList(parent.lexerData); + break; + case mainData: + curProp = dataFilesToArrayList(parent.mainData); + break; + default: + throw new NoSuchElementException(); + } + ++curPropNo; + return new InMemoryFilesWithRole(role, curProp); + } + } + + @Override + public Iterator iterator(){ + return new InMemoryCodeGenResultIterator(this); + } + + public void clear(){ + mainData = lexerData = null; + parser = lexer = listener = baseListener = visitor = baseVisitor = DFAGraph = null; + } +} diff --git a/tool/src/org/antlr/v4/codegen/inMemoryResult/InMemoryFile.java b/tool/src/org/antlr/v4/codegen/inMemoryResult/InMemoryFile.java new file mode 100644 index 0000000000..d0c7de64cc --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/inMemoryResult/InMemoryFile.java @@ -0,0 +1,37 @@ +/* + * This file is free and unencumbered software released into the public domain. + + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this file, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + + * In jurisdictions that recognize copyright laws, the author or authors + * of this file dedicate any and all copyright interest in the + * file to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * file under copyright law. + + * THE FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE FILE OR THE USE OR + * OTHER DEALINGS IN THE FILE. + + * For more information, please refer to + */ + +package org.antlr.v4.codegen.inMemoryResult; + +/** Just a pair - */ +public class InMemoryFile { + public String name, content; + public InMemoryFile(String name, String content) { + this.name = name; + this.content = content; + } +} diff --git a/tool/src/org/antlr/v4/codegen/inMemoryResult/InMemoryFilesWithRole.java b/tool/src/org/antlr/v4/codegen/inMemoryResult/InMemoryFilesWithRole.java new file mode 100644 index 0000000000..42fba95d61 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/inMemoryResult/InMemoryFilesWithRole.java @@ -0,0 +1,39 @@ +/* + * This file is free and unencumbered software released into the public domain. + + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this file, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + + * In jurisdictions that recognize copyright laws, the author or authors + * of this file dedicate any and all copyright interest in the + * file to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * file under copyright law. + + * THE FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE FILE OR THE USE OR + * OTHER DEALINGS IN THE FILE. + + * For more information, please refer to + */ + +package org.antlr.v4.codegen.inMemoryResult; +import java.util.ArrayList; + +public class InMemoryFilesWithRole{ + public ArrayList files; + public Role role; + + public InMemoryFilesWithRole(Role role, ArrayList files){ + this.role = role; + this.files = files; + } +}; diff --git a/tool/src/org/antlr/v4/codegen/inMemoryResult/Role.java b/tool/src/org/antlr/v4/codegen/inMemoryResult/Role.java new file mode 100644 index 0000000000..7f0f831b65 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/inMemoryResult/Role.java @@ -0,0 +1,41 @@ +/* + * This file is free and unencumbered software released into the public domain. + + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this file, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + + * In jurisdictions that recognize copyright laws, the author or authors + * of this file dedicate any and all copyright interest in the + * file to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * file under copyright law. + + * THE FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE FILE OR THE USE OR + * OTHER DEALINGS IN THE FILE. + + * For more information, please refer to + */ + +package org.antlr.v4.codegen.inMemoryResult; + +public enum Role { + lexer, + parser, + listener, + baseListener, + visitor, + baseVisitor, + DFAGraph, + lexerData, + mainData, + STOP +};