Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
3f20db3
Remove final keyword from debug_list_atn_decisions and dfa_debug in J…
parrt Nov 11, 2022
ae62a39
no such thing as CompositeLexer
parrt Nov 11, 2022
b3ef896
Oops. Misunderstood Composite term.
parrt Nov 11, 2022
6559425
rename debug to be showDiagnosticErrors for test generation
parrt Nov 11, 2022
1f3b9d6
add traceATN flag to test descriptors.
parrt Nov 11, 2022
7210a4c
turn on debug and debug_list_atn_decisions for java.
parrt Nov 11, 2022
1e7f256
add some baseline tests that get no traceATN output.
parrt Nov 12, 2022
a273e76
Add command line tool TraceATN to process grammar and run in any targ…
parrt Nov 12, 2022
c38fa36
fix compile error
parrt Nov 12, 2022
2825dee
add simple LL(2) rule with ATN debug output.
parrt Nov 12, 2022
e8ce09a
Revert "add simple LL(2) rule with ATN debug output."
parrt Nov 12, 2022
384bff0
Revert "add some baseline tests that get no traceATN output."
parrt Nov 12, 2022
7d70eb1
make retry_debug also nonfinal.
parrt Nov 12, 2022
cc307d7
add script to run TraceATN
parrt Nov 12, 2022
9786278
update javadoc
parrt Nov 12, 2022
fccaa32
include command and test dir when compilation fails during runtime te…
parrt Nov 12, 2022
84d5086
update doc on target testing, added needed jars to script.
parrt Nov 12, 2022
14648bf
Include exit code if non-zero during command exec.
parrt Nov 12, 2022
e4c7e36
Allow debug flags to be set from command line
parrt Nov 12, 2022
3a2dbe6
1. add option to dump commands exec'd during testing.
parrt Nov 12, 2022
fb139a7
separate lexer from parser ATN tracing.
parrt Nov 12, 2022
e100f04
get C++ and Java trace output more similar.
parrt Nov 12, 2022
7da167c
remove ref to specific user in script.
parrt Nov 13, 2022
51c3d65
* rename debug_list_atn_decisions to be trace_atn_sim
parrt Nov 13, 2022
f55a648
increase amount/quality of ATN sim debugging
parrt Nov 13, 2022
9fc3935
C++ target printed too much stuff with ATNConfigSet string.
parrt Nov 13, 2022
cc53b88
bring C++ ATN trace up to Java
parrt Nov 13, 2022
367816d
Add trace info for mergeArrays
parrt Nov 14, 2022
32ea639
rm extra print in C++
parrt Nov 14, 2022
7519413
Fix an error I made in https://github.com/antlr/antlr4/issues/3845
parrt Nov 14, 2022
03231e3
Merge branch 'dev' into compare-ATN-sim-output
parrt Nov 14, 2022
1b21fb6
Merge branch 'dev' into compare-ATN-sim-output
parrt Nov 15, 2022
ade5812
another small tweak to C++ trace output
parrt Nov 18, 2022
7cef1c3
Add more mergeArrays output for Java/C++
parrt Nov 18, 2022
44abee7
Make Python[2|3] trace output look just like java's
parrt Nov 18, 2022
488b00b
Make Go trace output look just like java's
parrt Nov 18, 2022
40ce34b
make NodeRunner sit under `node` package for consistency else we got …
parrt Nov 18, 2022
1796af4
Make javascript trace sim like java.
parrt Nov 18, 2022
af528d8
Merge branch 'dev' into compare-ATN-sim-output
parrt Nov 19, 2022
d26c429
Merge branch 'dev' into compare-ATN-sim-output
parrt Nov 19, 2022
19344b8
Make C# trace ATN sim look like Java.
parrt Nov 19, 2022
1cfb962
Damn forgot to add this to the javascript update.
parrt Nov 19, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions doc/creating-a-language-target.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,26 @@ $ mvn compile
```

That should proceed with success. See [Building ANTLR](building-antlr.md) for more details.

## Comparing your target's parsing decisionmaking with Java's

ANTLR's power comes from it's dynamic parsing strategy, but that means each target
must implement that complicated algorithm. You should compare your target's debug
output for ParserATNSimulator with Java's.

Run this so we get right jars before trying this script:

```
cd ANTLR-ROOT-DIR
mvn install -DskipTests=true
cd runtime-tests
mvn install -DskipTests=true # yes do it again
```

Run the script from `runtime-tests` dir with

```
../scripts/traceatn.sh /tmp/JSON.g4 json -target Go /tmp/foo.json
```

or whatever your test grammar, start rule, target, test input are.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ int main(int argc, const char* argv[]) {
CommonTokenStream tokens(&lexer);
<if(parserName)>
<parserName> parser(&tokens);
<if(debug)>
<if(showDiagnosticErrors)>
DiagnosticErrorListener errorListener;
parser.addErrorListener(&errorListener);
<endif>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using Antlr4.Runtime;
using Antlr4.Runtime.Atn;
using Antlr4.Runtime.Tree;
using System.Text;

Expand All @@ -12,8 +13,11 @@ public class Test {
var tokens = new CommonTokenStream(lex);
<if(parserName)>
var parser = new <parserName>(tokens);
<if(debug)>
<if(showDiagnosticErrors)>
parser.AddErrorListener(new DiagnosticErrorListener());
<endif>
<if(traceATN)>
ParserATNSimulator.trace_atn_sim = true;
<endif>
parser.BuildParseTree = true;
var tree = parser.<parserStartRuleName>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ void main(List\<String> args) async {
final tokens = CommonTokenStream(lex);
<if(parserName)>
final parser = <parserName>(tokens);
<if(debug)>
<if(showDiagnosticErrors)>
parser.addErrorListener(new DiagnosticErrorListener());
<endif>
<if(profile)>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ func (this *TreeShapeListener) EnterEveryRule(ctx antlr.ParserRuleContext) {
<endif>

func main() {
<if(traceATN)>
antlr.ParserATNSimulatorTraceATNSim = true
<endif>
input, err := antlr.NewFileStream(os.Args[1])
if err != nil {
fmt.Printf("Failed to find file: %v", err)
Expand All @@ -36,7 +39,7 @@ func main() {
stream := antlr.NewCommonTokenStream(lexer,0)
<if(parserName)>
p := parser.New<parserName>(stream)
<if(debug)>
<if(showDiagnosticErrors)>
p.AddErrorListener(antlr.NewDiagnosticErrorListener(true))
<endif>
p.BuildParseTrees = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ public class Test {
parser.setOutStream(outStream);
parser.removeErrorListeners();
parser.addErrorListener(errorListener);
<if(debug)>
<if(showDiagnosticErrors)>
parser.addErrorListener(new DiagnosticErrorListener());
<endif>
<if(traceATN)>
ParserATNSimulator.trace_atn_sim = true;
<endif>
parser.setBuildParseTree(true);
<if(profile)>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function main(argv) {
var stream = new antlr4.CommonTokenStream(lexer);
<if(parserName)>
var parser = new <parserName>(stream);
<if(debug)>
<if(showDiagnosticErrors)>
parser.addErrorListener(new antlr4.error.DiagnosticErrorListener());
<endif>
parser.buildParseTrees = true;
Expand All @@ -38,6 +38,10 @@ function main(argv) {
return this;
};
parser.printer = new printer();
<if(traceATN)>
parser._interp.trace_atn_sim = true;
antlr4.context.PredictionContext.trace_atn_sim = true;
<endif>
var tree = parser.<parserStartRuleName>();
antlr4.tree.ParseTreeWalker.DEFAULT.walk(new TreeShapeListener(), tree);
<else>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ $lexer->addErrorListener(new ConsoleErrorListener());
$tokens = new CommonTokenStream($lexer);
<if(parserName)>
$parser = new <parserName>($tokens);
<if(debug)>
<if(showDiagnosticErrors)>
$parser->addErrorListener(new DiagnosticErrorListener());
<endif>
$parser->addErrorListener(new ConsoleErrorListener());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@ class TreeShapeListener(ParseTreeListener):
<endif>

def main(argv):
<if(traceATN)>
ParserATNSimulator.trace_atn_sim = True
PredictionContext._trace_atn_sim = True
<endif>
input = FileStream(argv[1], encoding='utf-8', errors='replace')
lexer = <lexerName>(input)
stream = CommonTokenStream(lexer)
<if(parserName)>
parser = <parserName>(stream)
<if(debug)>
<if(showDiagnosticErrors)>
parser.addErrorListener(DiagnosticErrorListener())
<endif>
parser.buildParseTrees = True
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ let lex = <lexerName>(input)
let tokens = CommonTokenStream(lex)
<if(parserName)>
let parser = try <parserName>(tokens)
<if(debug)>
<if(showDiagnosticErrors)>
parser.addErrorListener(DiagnosticErrorListener())
<endif>
parser.setBuildParseTree(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ private static RuntimeTestDescriptor getLineSeparatorLfDescriptor() {
"lexer grammar L;\n" +
"T: ~'\\n'+;\n" +
"SEPARATOR: '\\n';",
null, false, false, null, uri);
null, false, false, false, null, uri);
}

private static RuntimeTestDescriptor getLineSeparatorCrLfDescriptor() {
Expand All @@ -71,7 +71,7 @@ private static RuntimeTestDescriptor getLineSeparatorCrLfDescriptor() {
"lexer grammar L;\n" +
"T: ~'\\r'+;\n" +
"SEPARATOR: '\\r\\n';",
null, false, false, null, uri);
null, false, false, false, null, uri);
}

private static RuntimeTestDescriptor getLargeLexerDescriptor() {
Expand All @@ -98,7 +98,7 @@ private static RuntimeTestDescriptor getLargeLexerDescriptor() {
"",
grammarName,
grammar.toString(),
null, false, false, null, uri);
null, false, false, false, null, uri);
}

private static RuntimeTestDescriptor getAtnStatesSizeMoreThan65535Descriptor() {
Expand Down Expand Up @@ -147,7 +147,7 @@ private static RuntimeTestDescriptor getAtnStatesSizeMoreThan65535Descriptor() {
"",
grammarName,
grammar.toString(),
null, false, false,
null, false, false, false,
new String[] {"CSharp", "Python2", "Python3", "Go", "PHP", "Swift", "JavaScript", "Dart"}, uri);
}

Expand Down Expand Up @@ -192,6 +192,6 @@ private static RuntimeTestDescriptor getMultiTokenAlternativeDescriptor() {
"r",
"P",
grammar,
null, false, false, null, uri);
null, false, false, false, null, uri);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public ProcessorResult start() throws InterruptedException, IOException {
String output = stdoutReader.toString();
String errors = stderrReader.toString();
if (throwOnNonZeroErrorCode && process.exitValue() != 0) {
throw new InterruptedException(joinLines(output, errors));
throw new InterruptedException("Exit code "+process.exitValue()+" with output:\n"+joinLines(output, errors));
}
return new ProcessorResult(process.exitValue(), output, errors);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class RunOptions {
public final String input;
public final boolean profile;
public final boolean showDiagnosticErrors;
public final boolean traceATN;
public final boolean showDFA;
public final Stage endStage;
public final boolean returnObject;
Expand All @@ -26,7 +27,7 @@ public class RunOptions {
public RunOptions(String grammarFileName, String grammarStr, String parserName, String lexerName,
boolean useListener, boolean useVisitor, String startRuleName,
String input, boolean profile, boolean showDiagnosticErrors,
boolean showDFA, Stage endStage, boolean returnObject,
boolean traceATN, boolean showDFA, Stage endStage, boolean returnObject,
String language, String superClass) {
this.grammarFileName = grammarFileName;
this.grammarStr = grammarStr;
Expand Down Expand Up @@ -61,6 +62,7 @@ else if (lexerName != null) {
this.input = input;
this.profile = profile;
this.showDiagnosticErrors = showDiagnosticErrors;
this.traceATN = traceATN;
this.showDFA = showDFA;
this.endStage = endStage;
this.returnObject = returnObject;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@
import static org.antlr.v4.test.runtime.RuntimeTestUtils.*;

public abstract class RuntimeRunner implements AutoCloseable {
/** Turn this on to see output like:
* RUNNING cmake . -DCMAKE_BUILD_TYPE=Release in /Users/parrt/antlr/code/antlr4/runtime/Cpp
* RUNNING make -j 20 in /Users/parrt/antlr/code/antlr4/runtime/Cpp
* RUNNING ln -s /Users/parrt/antlr/code/antlr4/runtime/Cpp/dist/libantlr4-runtime.dylib in /var/folders/w1/_nr4stn13lq0rvjdkwh7q8cc0000gn/T/CppRunner-ForkJoinPool-1-worker-23-1668284191961
* RUNNING clang++ -std=c++17 -I /Users/parrt/antlr/code/antlr4/runtime/Cpp/runtime/src -L. -lantlr4-runtime -pthread -o Test.out Test.cpp TLexer.cpp TParser.cpp TListener.cpp TBaseListener.cpp TVisitor.cpp TBaseVisitor.cpp in /var/folders/w1/_nr4stn13lq0rvjdkwh7q8cc0000gn/T/CppRunner-ForkJoinPool-1-worker-23-1668284191961
*/
public static final boolean WATCH_COMMANDS_EXEC = false;

public abstract String getLanguage();

protected String getExtension() { return getLanguage().toLowerCase(); }
Expand Down Expand Up @@ -170,7 +178,7 @@ public State run(RunOptions runOptions) {
return generatedState;
}

if (!initAntlrRuntimeIfRequired()) {
if (!initAntlrRuntimeIfRequired(runOptions)) {
// Do not repeat ANTLR runtime initialization error
return new CompiledState(generatedState, new Exception(getTitleName() + " ANTLR runtime is not initialized"));
}
Expand Down Expand Up @@ -223,7 +231,8 @@ protected void writeRecognizerFile(RunOptions runOptions) {
outputFileST.add("lexerName", runOptions.lexerName);
outputFileST.add("parserName", runOptions.parserName);
outputFileST.add("parserStartRuleName", grammarParseRuleToRecognizerName(runOptions.startRuleName));
outputFileST.add("debug", runOptions.showDiagnosticErrors);
outputFileST.add("showDiagnosticErrors", runOptions.showDiagnosticErrors);
outputFileST.add("traceATN", runOptions.traceATN);
outputFileST.add("profile", runOptions.profile);
outputFileST.add("showDFA", runOptions.showDFA);
outputFileST.add("useListener", runOptions.useListener);
Expand All @@ -238,7 +247,7 @@ protected String grammarParseRuleToRecognizerName(String startRuleName) {

protected void addExtraRecognizerParameters(ST template) {}

private boolean initAntlrRuntimeIfRequired() {
private boolean initAntlrRuntimeIfRequired(RunOptions runOptions) {
String language = getLanguage();
InitializationStatus status;

Expand All @@ -260,7 +269,7 @@ private boolean initAntlrRuntimeIfRequired() {
if (status.isInitialized == null) {
Exception exception = null;
try {
initRuntime();
initRuntime(runOptions);
} catch (Exception e) {
exception = e;
e.printStackTrace();
Expand All @@ -272,7 +281,7 @@ private boolean initAntlrRuntimeIfRequired() {
return status.isInitialized;
}

protected void initRuntime() throws Exception {
protected void initRuntime(RunOptions runOptions) throws Exception {
}

protected CompiledState compile(RunOptions runOptions, GeneratedState generatedState) {
Expand All @@ -298,7 +307,8 @@ protected ExecutedState execute(RunOptions runOptions, CompiledState compiledSta
ProcessorResult result = Processor.run(args.toArray(new String[0]), getTempDirPath(), getExecEnvironment());
output = result.output;
errors = result.errors;
} catch (InterruptedException | IOException e) {
}
catch (InterruptedException | IOException e) {
exception = e;
}
return new ExecutedState(compiledState, output, errors, exception);
Expand All @@ -309,10 +319,19 @@ protected ProcessorResult runCommand(String[] command, String workPath) throws E
}

protected ProcessorResult runCommand(String[] command, String workPath, String description) throws Exception {
String cmd = String.join(" ", command);
if ( WATCH_COMMANDS_EXEC ) {
System.out.println("RUNNING "+cmd+" in "+workPath);
}
try {
return Processor.run(command, workPath);
} catch (InterruptedException | IOException e) {
throw description != null ? new Exception("can't " + description, e) : e;
}
catch (InterruptedException | IOException e) {
String msg = "command \""+cmd+"\"\n in "+workPath+" failed";
if ( description != null ) {
msg += ":\n can't "+description;
}
throw new Exception(msg, e);
}
}

Expand All @@ -322,7 +341,8 @@ private void removeTempTestDirIfRequired() {
if (dirFile.exists()) {
try {
deleteDirectory(dirFile);
} catch (IOException e) {
}
catch (IOException e) {
e.printStackTrace();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ public class RuntimeTestDescriptor {
/** For parsing, engage the DiagnosticErrorListener, dumping results to stderr */
public final boolean showDiagnosticErrors;

public final boolean traceATN;

public final String[] skipTargets;

public final URI uri;
Expand All @@ -59,7 +61,7 @@ public RuntimeTestDescriptor(GrammarType testType, String name, String notes,
String input, String output, String errors,
String startRule,
String grammarName, String grammar, List<Pair<String, String>> slaveGrammars,
boolean showDFA, boolean showDiagnosticErrors, String[] skipTargets,
boolean showDiagnosticErrors, boolean traceATN, boolean showDFA, String[] skipTargets,
URI uri) {
this.testType = testType;
this.name = name;
Expand All @@ -73,6 +75,7 @@ public RuntimeTestDescriptor(GrammarType testType, String name, String notes,
this.slaveGrammars = slaveGrammars;
this.showDFA = showDFA;
this.showDiagnosticErrors = showDiagnosticErrors;
this.traceATN = traceATN;
this.skipTargets = skipTargets != null ? skipTargets : new String[0];
this.uri = uri;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public static RuntimeTestDescriptor parse(String name, String text, URI uri) thr
String errors = "";
boolean showDFA = false;
boolean showDiagnosticErrors = false;
boolean traceATN = false;
String[] skipTargets = new String[0];
for (Pair<String,String> p : pairs) {
String section = p.a;
Expand Down Expand Up @@ -152,6 +153,9 @@ else if ( value.indexOf('\n')>=0 ) {
case "showDiagnosticErrors":
showDiagnosticErrors = true;
break;
case "traceATN":
traceATN = true;
break;
}
}
break;
Expand All @@ -163,7 +167,7 @@ else if ( value.indexOf('\n')>=0 ) {
}
}
return new RuntimeTestDescriptor(testType, name, notes, input, output, errors, startRule, grammarName, grammar,
slaveGrammars, showDFA, showDiagnosticErrors, skipTargets, uri);
slaveGrammars, showDiagnosticErrors, traceATN, showDFA, skipTargets, uri);
}

/** Get A, B, or C from:
Expand Down
Loading