Skip to content

Commit 189476c

Browse files
committed
Refactored Tool a bit to have a method to get the results as a string via API + some other refactorings
Signed-off-by: KOLANICH <[email protected]>
1 parent 65bdc52 commit 189476c

File tree

9 files changed

+593
-79
lines changed

9 files changed

+593
-79
lines changed

tool/src/org/antlr/v4/Tool.java

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
import org.antlr.v4.automata.ParserATNFactory;
1919
import org.antlr.v4.codegen.CodeGenPipeline;
2020
import org.antlr.v4.codegen.CodeGenerator;
21+
import org.antlr.v4.codegen.InMemoryCodeGenerator;
22+
import org.antlr.v4.codegen.inMemoryResult.InMemoryCodeGenResult;
23+
import org.antlr.v4.codegen.inMemoryResult.InMemoryFile;
24+
import org.antlr.v4.codegen.inMemoryResult.DataFiles;
2125
import org.antlr.v4.misc.Graph;
2226
import org.antlr.v4.parse.ANTLRParser;
2327
import org.antlr.v4.parse.GrammarASTAdaptor;
@@ -320,13 +324,23 @@ else if (errMgr.getNumErrors() == 0) {
320324
}
321325
}
322326

327+
public void process(Grammar g, boolean gencode) {
328+
process(g, gencode, null);
329+
}
330+
331+
public InMemoryCodeGenResult processInMemory(Grammar g, boolean gencode) {
332+
InMemoryCodeGenResult res = new InMemoryCodeGenResult();
333+
process(g, gencode, res);
334+
return res;
335+
}
336+
323337
/** To process a grammar, we load all of its imported grammars into
324338
subordinate grammar objects. Then we merge the imported rules
325339
into the root grammar. If a root grammar is a combined grammar,
326340
we have to extract the implicit lexer. Once all this is done, we
327341
process the lexer first, if present, and then the parser grammar
328342
*/
329-
public void process(Grammar g, boolean gencode) {
343+
public void process(Grammar g, boolean gencode, InMemoryCodeGenResult res) {
330344
g.loadImportedGrammars();
331345

332346
GrammarTransformPipeline transform = new GrammarTransformPipeline(g, this);
@@ -348,50 +362,67 @@ public void process(Grammar g, boolean gencode) {
348362
lexerg.originalGrammar = g;
349363
g.implicitLexer = lexerg;
350364
lexerg.implicitLexerOwner = g;
351-
processNonCombinedGrammar(lexerg, gencode);
365+
processNonCombinedGrammar(lexerg, gencode, res);
352366
// System.out.println("lexer tokens="+lexerg.tokenNameToTypeMap);
353367
// System.out.println("lexer strings="+lexerg.stringLiteralToTypeMap);
354368
}
355369
}
356370
if ( g.implicitLexer!=null ) g.importVocab(g.implicitLexer);
357371
// System.out.println("tokens="+g.tokenNameToTypeMap);
358372
// System.out.println("strings="+g.stringLiteralToTypeMap);
359-
processNonCombinedGrammar(g, gencode);
373+
processNonCombinedGrammar(g, gencode, res);
360374
}
361375

362-
public void processNonCombinedGrammar(Grammar g, boolean gencode) {
363-
if ( g.ast==null || g.ast.hasErrors ) return;
376+
public boolean prepareProcessNonCombinedGrammar(Grammar g, boolean gencode) {
377+
if ( g.ast==null || g.ast.hasErrors ) return false;
364378

365379
boolean ruleFail = checkForRuleIssues(g);
366-
if ( ruleFail ) return;
380+
if ( ruleFail ) return false;
367381

368382
int prevErrors = errMgr.getNumErrors();
369383
// MAKE SURE GRAMMAR IS SEMANTICALLY CORRECT (FILL IN GRAMMAR OBJECT)
370384
SemanticPipeline sem = new SemanticPipeline(g);
371385
sem.process();
372386

373-
if ( errMgr.getNumErrors()>prevErrors ) return;
387+
if ( errMgr.getNumErrors()>prevErrors ) return false;
374388

375389
CodeGenerator codeGenerator = CodeGenerator.create(g);
376390
if (codeGenerator == null) {
377-
return;
391+
return false;
378392
}
379393

394+
if ( errMgr.getNumErrors()>prevErrors ) return false;
395+
380396
// BUILD ATN FROM AST
381397
ATNFactory factory;
382398
if ( g.isLexer() ) factory = new LexerATNFactory((LexerGrammar)g, codeGenerator);
383399
else factory = new ParserATNFactory(g);
384400
g.atn = factory.createATN();
385401

386402
if ( generate_ATN_dot ) generateATNs(g);
403+
return true;
404+
}
387405

388-
if (gencode && g.tool.getNumErrors()==0 ) {
389-
String interpFile = generateInterpreterData(g);
390-
try (Writer fw = getOutputFileWriter(g, getInterpFileName(g))) {
391-
fw.write(interpFile);
392-
}
393-
catch (IOException ioe) {
394-
errMgr.toolError(ErrorType.CANNOT_WRITE_FILE, ioe);
406+
public void processNonCombinedGrammar(Grammar g, boolean gencode) {
407+
processNonCombinedGrammar(g, gencode, null);
408+
}
409+
410+
public void processNonCombinedGrammar(Grammar g, boolean gencode, InMemoryCodeGenResult res) {
411+
if (!prepareProcessNonCombinedGrammar(g, gencode)) return;
412+
int prevErrors = errMgr.getNumErrors();
413+
414+
if (gencode && g.tool.getNumErrors()==0 ){
415+
if(res != null){
416+
DataFiles selectedDFiles = (g.isLexer()?res.lexerData:res.mainData);
417+
selectedDFiles.interp = new InMemoryFile(getInterpFileName(g), generateInterpreterData(g));
418+
}else{
419+
String interpFile = generateInterpreterData(g);
420+
try (Writer fw = getOutputFileWriter(g, g.name + ".interp")) {
421+
fw.write(interpFile);
422+
}
423+
catch (IOException ioe) {
424+
errMgr.toolError(ErrorType.CANNOT_WRITE_FILE, ioe);
425+
}
395426
}
396427
}
397428

@@ -405,11 +436,23 @@ public void processNonCombinedGrammar(Grammar g, boolean gencode) {
405436

406437
// GENERATE CODE
407438
if ( gencode ) {
439+
CodeGenerator codeGenerator = null;
440+
if(res != null){
441+
codeGenerator = InMemoryCodeGenerator.create(g, res);
442+
} else {
443+
codeGenerator = CodeGenerator.create(g);
444+
}
408445
CodeGenPipeline gen = new CodeGenPipeline(g, codeGenerator);
409-
gen.process();
446+
gen.process(res);
410447
}
411448
}
412449

450+
public InMemoryCodeGenResult processNonCombinedGrammarInMemory(Grammar g) {
451+
InMemoryCodeGenResult res = new InMemoryCodeGenResult();
452+
processNonCombinedGrammar(g, true, res);
453+
return res;
454+
}
455+
413456
// Don't inline: used in https://github.com/antlr/antlr4/issues/3874
414457
protected static String getInterpFileName(Grammar g){
415458
return g.name + ".interp";
@@ -691,7 +734,7 @@ public void generateATNs(Grammar g) {
691734
writeDOTFile(g, r, dot);
692735
}
693736
}
694-
catch (IOException ioe) {
737+
catch (IOException ioe) {
695738
errMgr.toolError(ErrorType.CANNOT_WRITE_FILE, ioe);
696739
}
697740
}
@@ -745,7 +788,6 @@ public static String generateInterpreterData(Grammar g) {
745788

746789
content.append("atn:\n");
747790
content.append(serializedATN.toString());
748-
749791
return content.toString();
750792
}
751793

@@ -767,7 +809,7 @@ public static String generateInterpreterData(Grammar g) {
767809
* If outputDirectory==null then write a String.
768810
*/
769811
public Writer getOutputFileWriter(Grammar g, String fileName) throws IOException {
770-
if (outputDirectory == null) {
812+
if (outputDirectory == null || fileName == null) {
771813
return new StringWriter();
772814
}
773815
// output directory is a function of where the grammar file lives

tool/src/org/antlr/v4/codegen/CodeGenPipeline.java

Lines changed: 79 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -10,100 +10,120 @@
1010
import org.antlr.v4.tool.Rule;
1111
import org.stringtemplate.v4.ST;
1212
import org.stringtemplate.v4.gui.STViz;
13+
import org.antlr.v4.codegen.inMemoryResult.InMemoryCodeGenResult;
14+
import org.antlr.v4.codegen.inMemoryResult.InMemoryFile;
1315

1416
public class CodeGenPipeline {
1517
final Grammar g;
1618
final CodeGenerator gen;
19+
int errorCount;
1720

1821
public CodeGenPipeline(Grammar g, CodeGenerator gen) {
1922
this.g = g;
2023
this.gen = gen;
2124
}
2225

23-
public void process() {
24-
// all templates are generated in memory to report the most complete
25-
// error information possible, but actually writing output files stops
26-
// after the first error is reported
27-
int errorCount = g.tool.errMgr.getNumErrors();
28-
29-
if ( g.isLexer() ) {
30-
if (gen.getTarget().needsHeader()) {
31-
ST lexer = gen.generateLexer(true); // Header file if needed.
32-
if (g.tool.errMgr.getNumErrors() == errorCount) {
33-
writeRecognizer(lexer, gen, true);
34-
}
26+
public void processLexer(CodeGenerator gen, Grammar g){
27+
if (gen.getTarget().needsHeader()) {
28+
ST lexer = gen.generateLexer(true); // Header file if needed.
29+
if (g.tool.errMgr.getNumErrors() == errorCount) {
30+
writeRecognizer(lexer, gen, true);
3531
}
36-
ST lexer = gen.generateLexer(false);
32+
}
33+
ST lexer = gen.generateLexer(false);
34+
if (g.tool.errMgr.getNumErrors() == errorCount) {
35+
writeRecognizer(lexer, gen, false);
36+
}
37+
}
38+
39+
public void processParser(CodeGenerator gen, Grammar g){
40+
if (gen.getTarget().needsHeader()) {
41+
ST parser = gen.generateParser(true);
3742
if (g.tool.errMgr.getNumErrors() == errorCount) {
38-
writeRecognizer(lexer, gen, false);
43+
writeRecognizer(parser, gen, true);
3944
}
4045
}
41-
else {
46+
ST parser = gen.generateParser(false);
47+
if (g.tool.errMgr.getNumErrors() == errorCount) {
48+
writeRecognizer(parser, gen, false);
49+
}
50+
51+
if ( g.tool.gen_listener ) {
4252
if (gen.getTarget().needsHeader()) {
43-
ST parser = gen.generateParser(true);
53+
ST listener = gen.generateListener(true);
4454
if (g.tool.errMgr.getNumErrors() == errorCount) {
45-
writeRecognizer(parser, gen, true);
55+
gen.writeListener(listener, true);
4656
}
4757
}
48-
ST parser = gen.generateParser(false);
58+
ST listener = gen.generateListener(false);
4959
if (g.tool.errMgr.getNumErrors() == errorCount) {
50-
writeRecognizer(parser, gen, false);
60+
gen.writeListener(listener, false);
5161
}
5262

53-
if ( g.tool.gen_listener ) {
54-
if (gen.getTarget().needsHeader()) {
55-
ST listener = gen.generateListener(true);
56-
if (g.tool.errMgr.getNumErrors() == errorCount) {
57-
gen.writeListener(listener, true);
58-
}
59-
}
60-
ST listener = gen.generateListener(false);
63+
if (gen.getTarget().needsHeader()) {
64+
ST baseListener = gen.generateBaseListener(true);
6165
if (g.tool.errMgr.getNumErrors() == errorCount) {
62-
gen.writeListener(listener, false);
63-
}
64-
65-
if (gen.getTarget().needsHeader()) {
66-
ST baseListener = gen.generateBaseListener(true);
67-
if (g.tool.errMgr.getNumErrors() == errorCount) {
68-
gen.writeBaseListener(baseListener, true);
69-
}
70-
}
71-
if (gen.getTarget().wantsBaseListener()) {
72-
ST baseListener = gen.generateBaseListener(false);
73-
if ( g.tool.errMgr.getNumErrors()==errorCount ) {
74-
gen.writeBaseListener(baseListener, false);
75-
}
66+
gen.writeBaseListener(baseListener, true);
7667
}
7768
}
78-
if ( g.tool.gen_visitor ) {
79-
if (gen.getTarget().needsHeader()) {
80-
ST visitor = gen.generateVisitor(true);
81-
if (g.tool.errMgr.getNumErrors() == errorCount) {
82-
gen.writeVisitor(visitor, true);
83-
}
69+
if (gen.getTarget().wantsBaseListener()) {
70+
ST baseListener = gen.generateBaseListener(false);
71+
if ( g.tool.errMgr.getNumErrors()==errorCount ) {
72+
gen.writeBaseListener(baseListener, false);
8473
}
85-
ST visitor = gen.generateVisitor(false);
74+
}
75+
}
76+
if ( g.tool.gen_visitor ) {
77+
if (gen.getTarget().needsHeader()) {
78+
ST visitor = gen.generateVisitor(true);
8679
if (g.tool.errMgr.getNumErrors() == errorCount) {
87-
gen.writeVisitor(visitor, false);
80+
gen.writeVisitor(visitor, true);
8881
}
82+
}
83+
ST visitor = gen.generateVisitor(false);
84+
if (g.tool.errMgr.getNumErrors() == errorCount) {
85+
gen.writeVisitor(visitor, false);
86+
}
8987

90-
if (gen.getTarget().needsHeader()) {
91-
ST baseVisitor = gen.generateBaseVisitor(true);
92-
if (g.tool.errMgr.getNumErrors() == errorCount) {
93-
gen.writeBaseVisitor(baseVisitor, true);
94-
}
88+
if (gen.getTarget().needsHeader()) {
89+
ST baseVisitor = gen.generateBaseVisitor(true);
90+
if (g.tool.errMgr.getNumErrors() == errorCount) {
91+
gen.writeBaseVisitor(baseVisitor, true);
9592
}
96-
if (gen.getTarget().wantsBaseVisitor()) {
97-
ST baseVisitor = gen.generateBaseVisitor(false);
98-
if ( g.tool.errMgr.getNumErrors()==errorCount ) {
99-
gen.writeBaseVisitor(baseVisitor, false);
100-
}
93+
}
94+
if (gen.getTarget().wantsBaseVisitor()) {
95+
ST baseVisitor = gen.generateBaseVisitor(false);
96+
if ( g.tool.errMgr.getNumErrors()==errorCount ) {
97+
gen.writeBaseVisitor(baseVisitor, false);
10198
}
10299
}
103100
}
101+
}
102+
103+
public void processWithCodeGen(CodeGenerator gen){
104+
// all templates are generated in memory to report the most complete
105+
// error information possible, but actually writing output files stops
106+
// after the first error is reported
107+
errorCount = g.tool.errMgr.getNumErrors();
108+
109+
if ( g.isLexer() ) {
110+
processLexer(gen, g);
111+
}
112+
else {
113+
processParser(gen, g);
114+
}
115+
}
116+
117+
public void process(InMemoryCodeGenResult res) {
118+
if ( g.getLanguage() == null ) return;
119+
120+
//CodeGenerator gen = new CodeGenerator(null, g); // TODO
121+
gen.result = res;
122+
processWithCodeGen(gen);
104123
gen.writeVocabFile();
105124
}
106125

126+
107127
protected void writeRecognizer(ST template, CodeGenerator gen, boolean header) {
108128
if ( g.tool.launch_ST_inspector ) {
109129
STViz viz = template.inspect();

tool/src/org/antlr/v4/codegen/CodeGenerator.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
import org.antlr.v4.Tool;
1010
import org.antlr.v4.codegen.model.OutputModelObject;
11+
import org.antlr.v4.codegen.InMemoryCodeGenerator;
12+
import org.antlr.v4.codegen.inMemoryResult.InMemoryCodeGenResult;
13+
import org.antlr.v4.codegen.inMemoryResult.InMemoryFile;
1114
import org.antlr.v4.runtime.Token;
1215
import org.antlr.v4.tool.ErrorType;
1316
import org.antlr.v4.tool.Grammar;
@@ -41,6 +44,8 @@ public class CodeGenerator {
4144

4245
public int lineWidth = 72;
4346

47+
public InMemoryCodeGenResult result = null;
48+
4449
public static CodeGenerator create(Grammar g) {
4550
return create(g.tool, g, g.getLanguage());
4651
}
@@ -220,5 +225,4 @@ public String getHeaderFileName() {
220225
String recognizerName = g.getRecognizerName();
221226
return recognizerName+extST.render();
222227
}
223-
224228
}

0 commit comments

Comments
 (0)