From cd69a46154fcc567f7e458cf5bfd4318cfc20706 Mon Sep 17 00:00:00 2001 From: KOLANICH Date: Tue, 11 Oct 2022 16:58:36 +0300 Subject: [PATCH 1/6] Convert some members of `CodeGenerator` from `private` into `protected`. Signed-off-by: KOLANICH --- tool/src/org/antlr/v4/codegen/CodeGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tool/src/org/antlr/v4/codegen/CodeGenerator.java b/tool/src/org/antlr/v4/codegen/CodeGenerator.java index e065466337..43ce327ab9 100644 --- a/tool/src/org/antlr/v4/codegen/CodeGenerator.java +++ b/tool/src/org/antlr/v4/codegen/CodeGenerator.java @@ -37,7 +37,7 @@ public class CodeGenerator { public final String language; - private Target target; + protected Target target; public int lineWidth = 72; @@ -60,7 +60,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; From 879df148d763bf76d3c5229aa6d5095b7418f958 Mon Sep 17 00:00:00 2001 From: KOLANICH Date: Tue, 11 Oct 2022 16:58:22 +0300 Subject: [PATCH 2/6] Move a part of `CodeGenerator.write` into a separate reusable method `writeToWriter` to be able to reuse it later. Signed-off-by: KOLANICH --- tool/src/org/antlr/v4/codegen/CodeGenerator.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tool/src/org/antlr/v4/codegen/CodeGenerator.java b/tool/src/org/antlr/v4/codegen/CodeGenerator.java index e065466337..82db3e350c 100644 --- a/tool/src/org/antlr/v4/codegen/CodeGenerator.java +++ b/tool/src/org/antlr/v4/codegen/CodeGenerator.java @@ -168,13 +168,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(); } From 791b33019ecc817d3786134c49b6a89dcdb38697 Mon Sep 17 00:00:00 2001 From: KOLANICH Date: Tue, 11 Oct 2022 16:58:05 +0300 Subject: [PATCH 3/6] Refactor CodeGenerator a bit: move target initialization code into a separate method. Signed-off-by: KOLANICH --- tool/src/org/antlr/v4/codegen/CodeGenerator.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tool/src/org/antlr/v4/codegen/CodeGenerator.java b/tool/src/org/antlr/v4/codegen/CodeGenerator.java index e065466337..5d165690ef 100644 --- a/tool/src/org/antlr/v4/codegen/CodeGenerator.java +++ b/tool/src/org/antlr/v4/codegen/CodeGenerator.java @@ -45,13 +45,18 @@ 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) { From 4abbca2a318e8cd9c8b52b8b196b1ec87dc7f191 Mon Sep 17 00:00:00 2001 From: KOLANICH Date: Tue, 11 Oct 2022 16:58:52 +0300 Subject: [PATCH 4/6] Extracted getting the interp file name into a separate method `Tool::getInterpFileName`. Signed-off-by: KOLANICH --- tool/src/org/antlr/v4/Tool.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tool/src/org/antlr/v4/Tool.java b/tool/src/org/antlr/v4/Tool.java index 1b7eea7535..0484ddb9df 100644 --- a/tool/src/org/antlr/v4/Tool.java +++ b/tool/src/org/antlr/v4/Tool.java @@ -387,7 +387,7 @@ public void processNonCombinedGrammar(Grammar g, boolean gencode) { if (gencode && g.tool.getNumErrors()==0 ) { String interpFile = generateInterpreterData(g); - try (Writer fw = getOutputFileWriter(g, g.name + ".interp")) { + try (Writer fw = getOutputFileWriter(g, getInterpFileName(g))) { fw.write(interpFile); } catch (IOException ioe) { @@ -410,6 +410,11 @@ public void processNonCombinedGrammar(Grammar g, boolean gencode) { } } + // 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 From 63f7edeb5179c13eb83acfd298dac1d417dbdc36 Mon Sep 17 00:00:00 2001 From: KOLANICH Date: Thu, 12 Mar 2020 12:53:31 +0300 Subject: [PATCH 5/6] Refactored Tool a bit to have a method to get the results as a string via API + some other refactorings Signed-off-by: KOLANICH --- tool/src/org/antlr/v4/Tool.java | 80 +++++++--- .../org/antlr/v4/codegen/CodeGenPipeline.java | 138 ++++++++++-------- .../org/antlr/v4/codegen/CodeGenerator.java | 6 +- .../v4/codegen/InMemoryCodeGenerator.java | 126 ++++++++++++++++ .../v4/codegen/inMemoryResult/DataFiles.java | 85 +++++++++++ .../inMemoryResult/InMemoryCodeGenResult.java | 120 +++++++++++++++ .../codegen/inMemoryResult/InMemoryFile.java | 37 +++++ .../inMemoryResult/InMemoryFilesWithRole.java | 39 +++++ .../antlr/v4/codegen/inMemoryResult/Role.java | 41 ++++++ 9 files changed, 593 insertions(+), 79 deletions(-) create mode 100644 tool/src/org/antlr/v4/codegen/InMemoryCodeGenerator.java create mode 100644 tool/src/org/antlr/v4/codegen/inMemoryResult/DataFiles.java create mode 100644 tool/src/org/antlr/v4/codegen/inMemoryResult/InMemoryCodeGenResult.java create mode 100644 tool/src/org/antlr/v4/codegen/inMemoryResult/InMemoryFile.java create mode 100644 tool/src/org/antlr/v4/codegen/inMemoryResult/InMemoryFilesWithRole.java create mode 100644 tool/src/org/antlr/v4/codegen/inMemoryResult/Role.java diff --git a/tool/src/org/antlr/v4/Tool.java b/tool/src/org/antlr/v4/Tool.java index 0484ddb9df..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, getInterpFileName(g))) { - 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,23 @@ 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"; @@ -691,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); } } @@ -745,7 +788,6 @@ public static String generateInterpreterData(Grammar g) { content.append("atn:\n"); content.append(serializedATN.toString()); - return content.toString(); } @@ -767,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 a096b1cfd4..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; @@ -41,6 +44,8 @@ public class CodeGenerator { public int lineWidth = 72; + public InMemoryCodeGenResult result = null; + public static CodeGenerator create(Grammar g) { return create(g.tool, g, g.getLanguage()); } @@ -220,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 +}; From 238d7c83cbfebde26ed59ca50f7abfa19b59610d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 7 Jan 2023 07:04:59 +0000 Subject: [PATCH 6/6] Bump json5 from 2.2.1 to 2.2.3 in /runtime/JavaScript Bumps [json5](https://github.com/json5/json5) from 2.2.1 to 2.2.3. - [Release notes](https://github.com/json5/json5/releases) - [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md) - [Commits](https://github.com/json5/json5/compare/v2.2.1...v2.2.3) --- updated-dependencies: - dependency-name: json5 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- runtime/JavaScript/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/runtime/JavaScript/package-lock.json b/runtime/JavaScript/package-lock.json index efaf7d610b..c1db00eef6 100644 --- a/runtime/JavaScript/package-lock.json +++ b/runtime/JavaScript/package-lock.json @@ -3591,9 +3591,9 @@ "peer": true }, "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "bin": { "json5": "lib/cli.js" @@ -7562,9 +7562,9 @@ "peer": true }, "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, "kind-of": {