Skip to content

Commit dee6265

Browse files
authored
Add option for splitting generated Java parser into 3 files (#4764)
* Fi failing tests * generates a <grammar>ParserContexts.java file Signed-off-by: Eric Vergnaud <[email protected]> * rename tests Signed-off-by: Eric Vergnaud <[email protected]> * generates DFA in dedicated class * generates context classes in dedicated class * check that generated files compile * Bump GH action * Bump GH action Signed-off-by: Eric Vergnaud <[email protected]> * bump macos in github * rename option * reduce # of generated lines * fix issues * fix issue when no package * make parserDFA class abstract * drop static imports that are not scala friendly * drop ST warning * missed a few --------- Signed-off-by: Eric Vergnaud <[email protected]>
1 parent 9031d84 commit dee6265

17 files changed

+409
-155
lines changed

tool-testsuite/test/org/antlr/v4/test/tool/TestActionTranslation.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.antlr.v4.automata.LexerATNFactory;
1212
import org.antlr.v4.automata.ParserATNFactory;
1313
import org.antlr.v4.codegen.CodeGenerator;
14+
import org.antlr.v4.codegen.SourceType;
1415
import org.antlr.v4.semantics.SemanticPipeline;
1516
import org.antlr.v4.test.runtime.ErrorQueue;
1617
import org.antlr.v4.tool.Grammar;
@@ -244,7 +245,7 @@ private static void testActions(String templates, String actionName, String acti
244245
anal.process();
245246

246247
CodeGenerator gen = CodeGenerator.create(g);
247-
ST outputFileST = gen.generateParser(false);
248+
ST outputFileST = gen.generateParser(SourceType.SOURCE);
248249
String output = outputFileST.render();
249250
//System.out.println(output);
250251
String b = "#" + actionName + "#";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
package org.antlr.v4.test.tool;
2+
3+
import org.antlr.v4.Tool;
4+
import org.junit.jupiter.api.BeforeEach;
5+
import org.junit.jupiter.api.Test;
6+
7+
import javax.tools.JavaCompiler;
8+
import javax.tools.JavaFileObject;
9+
import javax.tools.StandardJavaFileManager;
10+
import javax.tools.ToolProvider;
11+
import java.io.File;
12+
import java.io.IOException;
13+
import java.net.URL;
14+
import java.net.URLClassLoader;
15+
import java.nio.file.Files;
16+
import java.nio.file.Path;
17+
import java.util.ArrayList;
18+
import java.util.Arrays;
19+
import java.util.List;
20+
import java.util.Set;
21+
import java.util.stream.Collectors;
22+
23+
import static org.antlr.v4.test.runtime.RuntimeTestUtils.PathSeparator;
24+
25+
26+
public class TestSplitParser {
27+
28+
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
29+
Path outDir = null;
30+
31+
@BeforeEach
32+
public void beforeEach() throws IOException {
33+
outDir = Files.createTempDirectory("antlr4-tool-test-").toAbsolutePath();
34+
}
35+
36+
@Test
37+
public void testGeneratesDefaultFiles() throws Exception {
38+
Set<String> created = generate();
39+
assert created.size() == 4;
40+
assert created.contains("JavaLRLexer.java");
41+
assert created.contains("JavaLRParser.java");
42+
assert created.contains("JavaLRBaseListener.java");
43+
assert created.contains("JavaLRListener.java");
44+
checkCompiles(created);
45+
}
46+
47+
@Test
48+
public void testGeneratesNoListenerFiles() throws Exception {
49+
Set<String> created = generate("-no-listener");
50+
assert created.size() == 2;
51+
assert created.contains("JavaLRLexer.java");
52+
assert created.contains("JavaLRParser.java");
53+
checkCompiles(created);
54+
}
55+
56+
@Test
57+
public void testGeneratesVisitorFiles() throws Exception {
58+
Set<String> created = generate("-visitor");
59+
assert created.size() == 6;
60+
assert created.contains("JavaLRLexer.java");
61+
assert created.contains("JavaLRParser.java");
62+
assert created.contains("JavaLRBaseListener.java");
63+
assert created.contains("JavaLRListener.java");
64+
assert created.contains("JavaLRBaseVisitor.java");
65+
assert created.contains("JavaLRVisitor.java");
66+
checkCompiles(created);
67+
}
68+
69+
@Test
70+
public void testGeneratesSplitFiles() throws Exception {
71+
Set<String> created = generate("-split-parser", "-visitor");
72+
assert created.size() == 8;
73+
assert created.contains("JavaLRLexer.java");
74+
assert created.contains("JavaLRParser.java");
75+
assert created.contains("JavaLRParserContexts.java");
76+
assert created.contains("JavaLRParserDFA.java");
77+
assert created.contains("JavaLRBaseListener.java");
78+
assert created.contains("JavaLRListener.java");
79+
assert created.contains("JavaLRBaseVisitor.java");
80+
assert created.contains("JavaLRVisitor.java");
81+
String content = Files.readString(Path.of(outDir.toString(), "JavaLRParser.java"));
82+
assert !content.contains("ATNDeserializer()");
83+
assert !content.contains("extends ParserRuleContext");
84+
content = Files.readString(Path.of(outDir.toString(), "JavaLRParserContexts.java"));
85+
assert !content.contains("ATNDeserializer()");
86+
assert content.contains("extends ParserRuleContext");
87+
content = Files.readString(Path.of(outDir.toString(), "JavaLRParserDFA.java"));
88+
assert content.contains("ATNDeserializer()");
89+
assert !content.contains("extends ParserRuleContext");
90+
checkCompiles(created);
91+
}
92+
93+
Set<String> generate(String ... args) throws IOException {
94+
List<String> options = new ArrayList<>(Arrays.asList(args));
95+
String grammar = getClass().getPackageName().replace(".", "/") + "/JavaLR.g4";
96+
URL url = Thread.currentThread().getContextClassLoader().getResource(grammar);
97+
assert url!=null;
98+
String path = url.getPath();
99+
options.add("-o");
100+
options.add(outDir.toString());
101+
options.add("-package");
102+
options.add("antlr4.split");
103+
options.add(path);
104+
Tool antlr = new Tool(options.toArray(new String[] {}));
105+
antlr.processGrammarsOnCommandLine();
106+
return Files.list(outDir)
107+
.map(Path::getFileName)
108+
.map(Object::toString)
109+
.filter(name -> name.endsWith(".java"))
110+
.collect(Collectors.toSet());
111+
112+
}
113+
114+
void checkCompiles(Set<String> generated) throws Exception, ClassNotFoundException {
115+
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
116+
List<File> files = generated.stream()
117+
.map(name -> Path.of(outDir.toString(), name))
118+
.map(Path::toFile)
119+
.collect(Collectors.toList());
120+
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(files);
121+
Iterable<String> compileOptions =
122+
Arrays.asList("-g", "-source", "1.8", "-target", "1.8", "-implicit:class", "-Xlint:-options", "-d",
123+
outDir.toString(), "-cp", outDir + PathSeparator + System.getProperty("java.class.path"));
124+
JavaCompiler.CompilationTask task =
125+
compiler.getTask(null, fileManager, null, compileOptions, null,
126+
compilationUnits);
127+
task.call();
128+
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
129+
ClassLoader loader = new URLClassLoader(new URL[]{outDir.toUri().toURL()}, systemClassLoader);
130+
for (String name : generated) {
131+
name = "antlr4.split." + name.substring(0, name.indexOf(".java"));
132+
Class<?> klass = loader.loadClass(name);
133+
assert klass != null;
134+
}
135+
}
136+
}

0 commit comments

Comments
 (0)