/*
* Copyright (c) 2014 Sam Harwell, Tunnel Vision Laboratories LLC
* All rights reserved.
*
* The source code of this document is proprietary work, and is not licensed for
* distribution. For information about licensing, contact Sam Harwell at:
* sam@tunnelvisionlabs.com
*/
package org.antlr.works.editor.grammar.debugger;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.antlr.netbeans.editor.parsing.SyntaxError;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.atn.LexerATNSimulator;
import org.antlr.v4.runtime.atn.ParserATNSimulator;
import org.antlr.v4.runtime.atn.Transition;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.misc.Nullable;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeListener;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.antlr.works.editor.grammar.debugger.ParserDebuggerReferenceAnchorsParserTask.TracingParserInterpreter;
/**
*
* @author Sam Harwell
*/
public class FileParseResult {
public final String sourceName;
public final int checksum;
public final ParseTree parseTree;
public final Map<ParseTree, Transition> associatedTransitions;
public final int tokenCount;
public final long startTime;
public final long endTime;
public final int lexerDFASize;
public final long lexerTotalTransitions;
public final long lexerComputedTransitions;
public final int parserDFASize;
public final long[] decisionInvocations;
public final long[] fullContextFallback;
public final long[] nonSll;
public final long[] ambiguousResult;
public final long[] parserTotalTransitions;
public final long[] parserComputedTransitions;
public final long[] parserFullContextTransitions;
public final long[] totalLookaheadSll;
public final long[] totalLookaheadLl;
public final long[] minLookaheadSll;
public final long[] maxLookaheadSll;
public final long[] minLookaheadLl;
public final long[] maxLookaheadLl;
private final List<? extends SyntaxError> syntaxErrors;
public FileParseResult(String sourceName, int checksum, @Nullable ParseTree parseTree, List<? extends SyntaxError> syntaxErrors, int tokenCount, long startTime, Lexer lexer, Parser parser) {
this.sourceName = sourceName;
this.checksum = checksum;
this.parseTree = parseTree;
this.syntaxErrors = syntaxErrors;
this.tokenCount = tokenCount;
this.startTime = startTime;
this.endTime = System.nanoTime();
if (lexer != null) {
LexerATNSimulator interpreter = lexer.getInterpreter();
if (interpreter instanceof StatisticsLexerATNSimulator) {
lexerTotalTransitions = ((StatisticsLexerATNSimulator)interpreter).totalTransitions;
lexerComputedTransitions = ((StatisticsLexerATNSimulator)interpreter).computedTransitions;
} else {
lexerTotalTransitions = 0;
lexerComputedTransitions = 0;
}
int dfaSize = 0;
for (DFA dfa : interpreter.atn.decisionToDFA) {
if (dfa != null) {
dfaSize += dfa.states.size();
}
}
lexerDFASize = dfaSize;
} else {
lexerDFASize = 0;
lexerTotalTransitions = 0;
lexerComputedTransitions = 0;
}
if (parser != null) {
if (parser instanceof TracingParserInterpreter) {
associatedTransitions = ((TracingParserInterpreter)parser).associatedTransitions;
} else {
associatedTransitions = null;
}
ParserATNSimulator interpreter = parser.getInterpreter();
if (interpreter instanceof StatisticsParserATNSimulator) {
decisionInvocations = ((StatisticsParserATNSimulator)interpreter).decisionInvocations;
fullContextFallback = ((StatisticsParserATNSimulator)interpreter).fullContextFallback;
nonSll = ((StatisticsParserATNSimulator)interpreter).nonSll;
ambiguousResult = ((StatisticsParserATNSimulator)interpreter).ambiguousResult;
parserTotalTransitions = ((StatisticsParserATNSimulator)interpreter).totalTransitions;
parserComputedTransitions = ((StatisticsParserATNSimulator)interpreter).computedTransitions;
parserFullContextTransitions = ((StatisticsParserATNSimulator)interpreter).fullContextTransitions;
totalLookaheadSll = ((StatisticsParserATNSimulator)interpreter).totalLookaheadSll;
totalLookaheadLl = ((StatisticsParserATNSimulator)interpreter).totalLookaheadLl;
minLookaheadSll = ((StatisticsParserATNSimulator)interpreter).minLookaheadSll;
maxLookaheadSll = ((StatisticsParserATNSimulator)interpreter).maxLookaheadSll;
minLookaheadLl = ((StatisticsParserATNSimulator)interpreter).minLookaheadLl;
maxLookaheadLl = ((StatisticsParserATNSimulator)interpreter).maxLookaheadLl;
} else {
decisionInvocations = new long[0];
fullContextFallback = new long[0];
nonSll = new long[0];
ambiguousResult = new long[0];
parserTotalTransitions = new long[0];
parserComputedTransitions = new long[0];
parserFullContextTransitions = new long[0];
totalLookaheadSll = new long[0];
totalLookaheadLl = new long[0];
minLookaheadSll = new long[0];
maxLookaheadSll = new long[0];
minLookaheadLl = new long[0];
maxLookaheadLl = new long[0];
}
int dfaSize = 0;
for (DFA dfa : interpreter.atn.decisionToDFA) {
if (dfa != null) {
dfaSize += dfa.states.size();
}
}
parserDFASize = dfaSize;
} else {
associatedTransitions = null;
parserDFASize = 0;
decisionInvocations = new long[0];
fullContextFallback = new long[0];
nonSll = new long[0];
ambiguousResult = new long[0];
parserTotalTransitions = new long[0];
parserComputedTransitions = new long[0];
parserFullContextTransitions = new long[0];
totalLookaheadSll = new long[0];
totalLookaheadLl = new long[0];
minLookaheadSll = new long[0];
maxLookaheadSll = new long[0];
minLookaheadLl = new long[0];
maxLookaheadLl = new long[0];
}
}
public List<? extends SyntaxError> getSyntaxErrors() {
return syntaxErrors;
}
public Set<ParseTree> getErrorNodes() {
ErrorNodeAnalyzer analyzer = new ErrorNodeAnalyzer();
return analyzer.analyzeTree(parseTree, syntaxErrors);
}
private static class ErrorNodeAnalyzer {
public ErrorNodeAnalyzer() {
}
public Set<ParseTree> analyzeTree(ParseTree tree, List<? extends SyntaxError> syntaxErrors) {
// eventually check syntax errors in case skipped nodes from errors were omitted from the tree
Set<ParseTree> result = new HashSet<>();
ErrorNodeListener listener = new ErrorNodeListener(result);
ParseTreeWalker.DEFAULT.walk(listener, tree);
return result;
}
private static class ErrorNodeListener implements ParseTreeListener {
private final Set<ParseTree> result;
private ErrorNodeListener(Set<ParseTree> result) {
this.result = result;
}
@Override
public void visitTerminal(TerminalNode node) {
}
@Override
public void visitErrorNode(ErrorNode node) {
result.add(node);
}
@Override
public void enterEveryRule(ParserRuleContext ctx) {
if (ctx.exception != null) {
result.add(ctx);
}
}
@Override
public void exitEveryRule(ParserRuleContext ctx) {
if (result.contains(ctx) && ctx.getParent() != null) {
result.add(ctx.getParent());
}
}
}
}
}