use of org.antlr.v4.runtime.dfa.DFAState in project antlr4 by tunnelvisionlabs.
the class TestPerformance method parseSources.
@SuppressWarnings("unused")
protected void parseSources(final int currentPass, final ParserFactory factory, Collection<InputDescriptor> sources, boolean shuffleSources) throws InterruptedException {
if (shuffleSources) {
List<InputDescriptor> sourcesList = new ArrayList<InputDescriptor>(sources);
synchronized (RANDOM) {
Collections.shuffle(sourcesList, RANDOM);
}
sources = sourcesList;
}
long startTime = System.nanoTime();
tokenCount.set(currentPass, 0);
int inputSize = 0;
int inputCount = 0;
Collection<Future<FileParseResult>> results = new ArrayList<Future<FileParseResult>>();
ExecutorService executorService;
if (FILE_GRANULARITY) {
executorService = Executors.newFixedThreadPool(FILE_GRANULARITY ? NUMBER_OF_THREADS : 1, new NumberedThreadFactory());
} else {
executorService = Executors.newSingleThreadExecutor(new FixedThreadNumberFactory(((NumberedThread) Thread.currentThread()).getThreadNumber()));
}
for (InputDescriptor inputDescriptor : sources) {
if (inputCount >= MAX_FILES_PER_PARSE_ITERATION) {
break;
}
final CharStream input = inputDescriptor.getInputStream();
input.seek(0);
inputSize += input.size();
inputCount++;
Future<FileParseResult> futureChecksum = executorService.submit(new Callable<FileParseResult>() {
@Override
public FileParseResult call() {
// System.out.format("Parsing file %s\n", input.getSourceName());
try {
return factory.parseFile(input, currentPass, ((NumberedThread) Thread.currentThread()).getThreadNumber());
} catch (IllegalStateException ex) {
ex.printStackTrace(System.err);
} catch (Throwable t) {
t.printStackTrace(System.err);
}
return null;
}
});
results.add(futureChecksum);
}
MurmurHashChecksum checksum = new MurmurHashChecksum();
int currentIndex = -1;
for (Future<FileParseResult> future : results) {
currentIndex++;
int fileChecksum = 0;
try {
FileParseResult fileResult = future.get();
if (COMPUTE_TRANSITION_STATS) {
totalTransitionsPerFile[currentPass][currentIndex] = sum(fileResult.parserTotalTransitions);
computedTransitionsPerFile[currentPass][currentIndex] = sum(fileResult.parserComputedTransitions);
if (DETAILED_DFA_STATE_STATS) {
decisionInvocationsPerFile[currentPass][currentIndex] = fileResult.decisionInvocations;
fullContextFallbackPerFile[currentPass][currentIndex] = fileResult.fullContextFallback;
nonSllPerFile[currentPass][currentIndex] = fileResult.nonSll;
totalTransitionsPerDecisionPerFile[currentPass][currentIndex] = fileResult.parserTotalTransitions;
computedTransitionsPerDecisionPerFile[currentPass][currentIndex] = fileResult.parserComputedTransitions;
fullContextTransitionsPerDecisionPerFile[currentPass][currentIndex] = fileResult.parserFullContextTransitions;
}
}
if (COMPUTE_TIMING_STATS) {
timePerFile[currentPass][currentIndex] = fileResult.endTime - fileResult.startTime;
tokensPerFile[currentPass][currentIndex] = fileResult.tokenCount;
}
fileChecksum = fileResult.checksum;
} catch (ExecutionException ex) {
Logger.getLogger(TestPerformance.class.getName()).log(Level.SEVERE, null, ex);
}
if (COMPUTE_CHECKSUM) {
updateChecksum(checksum, fileChecksum);
}
}
executorService.shutdown();
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
System.out.format("%d. Total parse time for %d files (%d KB, %d tokens%s): %.0fms%n", currentPass + 1, inputCount, inputSize / 1024, tokenCount.get(currentPass), COMPUTE_CHECKSUM ? String.format(", checksum 0x%8X", checksum.getValue()) : "", (double) (System.nanoTime() - startTime) / 1000000.0);
if (sharedLexers.length > 0) {
int index = FILE_GRANULARITY ? 0 : ((NumberedThread) Thread.currentThread()).getThreadNumber();
Lexer lexer = sharedLexers[index];
final LexerATNSimulator lexerInterpreter = lexer.getInterpreter();
final DFA[] modeToDFA = lexerInterpreter.atn.modeToDFA;
if (SHOW_DFA_STATE_STATS) {
int states = 0;
int configs = 0;
Set<ATNConfig> uniqueConfigs = new HashSet<ATNConfig>();
for (int i = 0; i < modeToDFA.length; i++) {
DFA dfa = modeToDFA[i];
if (dfa == null) {
continue;
}
states += dfa.states.size();
for (DFAState state : dfa.states.values()) {
configs += state.configs.size();
uniqueConfigs.addAll(state.configs);
}
}
System.out.format("There are %d lexer DFAState instances, %d configs (%d unique), %d prediction contexts.%n", states, configs, uniqueConfigs.size(), lexerInterpreter.atn.getContextCacheSize());
if (DETAILED_DFA_STATE_STATS) {
System.out.format("\tMode\tStates\tConfigs\tMode%n");
for (int i = 0; i < modeToDFA.length; i++) {
DFA dfa = modeToDFA[i];
if (dfa == null || dfa.states.isEmpty()) {
continue;
}
int modeConfigs = 0;
for (DFAState state : dfa.states.values()) {
modeConfigs += state.configs.size();
}
String modeName = lexer.getModeNames()[i];
System.out.format("\t%d\t%d\t%d\t%s%n", dfa.decision, dfa.states.size(), modeConfigs, modeName);
}
}
}
}
if (RUN_PARSER && sharedParsers.length > 0) {
int index = FILE_GRANULARITY ? 0 : ((NumberedThread) Thread.currentThread()).getThreadNumber();
Parser parser = sharedParsers[index];
// make sure the individual DFAState objects actually have unique ATNConfig arrays
final ParserATNSimulator interpreter = parser.getInterpreter();
final DFA[] decisionToDFA = interpreter.atn.decisionToDFA;
if (SHOW_DFA_STATE_STATS) {
int states = 0;
int configs = 0;
Set<ATNConfig> uniqueConfigs = new HashSet<ATNConfig>();
for (int i = 0; i < decisionToDFA.length; i++) {
DFA dfa = decisionToDFA[i];
if (dfa == null) {
continue;
}
states += dfa.states.size();
for (DFAState state : dfa.states.values()) {
configs += state.configs.size();
uniqueConfigs.addAll(state.configs);
}
}
System.out.format("There are %d parser DFAState instances, %d configs (%d unique), %d prediction contexts.%n", states, configs, uniqueConfigs.size(), interpreter.atn.getContextCacheSize());
if (DETAILED_DFA_STATE_STATS) {
if (COMPUTE_TRANSITION_STATS) {
System.out.format("\tDecision\tStates\tConfigs\tPredict (ALL)\tPredict (LL)\tNon-SLL\tTransitions\tTransitions (ATN)\tTransitions (LL)\tLA (SLL)\tLA (LL)\tRule%n");
} else {
System.out.format("\tDecision\tStates\tConfigs\tRule%n");
}
for (int i = 0; i < decisionToDFA.length; i++) {
DFA dfa = decisionToDFA[i];
if (dfa == null || dfa.states.isEmpty()) {
continue;
}
int decisionConfigs = 0;
for (DFAState state : dfa.states.values()) {
decisionConfigs += state.configs.size();
}
String ruleName = parser.getRuleNames()[parser.getATN().decisionToState.get(dfa.decision).ruleIndex];
long calls = 0;
long fullContextCalls = 0;
long nonSllCalls = 0;
long transitions = 0;
long computedTransitions = 0;
long fullContextTransitions = 0;
double lookahead = 0;
double fullContextLookahead = 0;
String formatString;
if (COMPUTE_TRANSITION_STATS) {
for (long[] data : decisionInvocationsPerFile[currentPass]) {
calls += data[i];
}
for (long[] data : fullContextFallbackPerFile[currentPass]) {
fullContextCalls += data[i];
}
for (long[] data : nonSllPerFile[currentPass]) {
nonSllCalls += data[i];
}
for (long[] data : totalTransitionsPerDecisionPerFile[currentPass]) {
transitions += data[i];
}
for (long[] data : computedTransitionsPerDecisionPerFile[currentPass]) {
computedTransitions += data[i];
}
for (long[] data : fullContextTransitionsPerDecisionPerFile[currentPass]) {
fullContextTransitions += data[i];
}
if (calls > 0) {
lookahead = (double) (transitions - fullContextTransitions) / (double) calls;
}
if (fullContextCalls > 0) {
fullContextLookahead = (double) fullContextTransitions / (double) fullContextCalls;
}
formatString = "\t%1$d\t%2$d\t%3$d\t%4$d\t%5$d\t%6$d\t%7$d\t%8$d\t%9$d\t%10$f\t%11$f\t%12$s%n";
} else {
calls = 0;
formatString = "\t%1$d\t%2$d\t%3$d\t%12$s%n";
}
System.out.format(formatString, dfa.decision, dfa.states.size(), decisionConfigs, calls, fullContextCalls, nonSllCalls, transitions, computedTransitions, fullContextTransitions, lookahead, fullContextLookahead, ruleName);
}
}
}
int localDfaCount = 0;
int globalDfaCount = 0;
int localConfigCount = 0;
int globalConfigCount = 0;
int[] contextsInDFAState = new int[0];
for (int i = 0; i < decisionToDFA.length; i++) {
DFA dfa = decisionToDFA[i];
if (dfa == null) {
continue;
}
if (SHOW_CONFIG_STATS) {
for (DFAState state : dfa.states.keySet()) {
if (state.configs.size() >= contextsInDFAState.length) {
contextsInDFAState = Arrays.copyOf(contextsInDFAState, state.configs.size() + 1);
}
if (state.isAcceptState()) {
boolean hasGlobal = false;
for (ATNConfig config : state.configs) {
if (config.getReachesIntoOuterContext()) {
globalConfigCount++;
hasGlobal = true;
} else {
localConfigCount++;
}
}
if (hasGlobal) {
globalDfaCount++;
} else {
localDfaCount++;
}
}
contextsInDFAState[state.configs.size()]++;
}
}
if (EXPORT_LARGEST_CONFIG_CONTEXTS) {
for (DFAState state : dfa.states.keySet()) {
for (ATNConfig config : state.configs) {
String configOutput = config.toDotString();
if (configOutput.length() <= configOutputSize) {
continue;
}
configOutputSize = configOutput.length();
writeFile(tmpdir, "d" + dfa.decision + ".s" + state.stateNumber + ".a" + config.getAlt() + ".config.dot", configOutput);
}
}
}
}
if (SHOW_CONFIG_STATS && currentPass == 0) {
System.out.format(" DFA accept states: %d total, %d with only local context, %d with a global context%n", localDfaCount + globalDfaCount, localDfaCount, globalDfaCount);
System.out.format(" Config stats: %d total, %d local, %d global%n", localConfigCount + globalConfigCount, localConfigCount, globalConfigCount);
if (SHOW_DFA_STATE_STATS) {
for (int i = 0; i < contextsInDFAState.length; i++) {
if (contextsInDFAState[i] != 0) {
System.out.format(" %d configs = %d%n", i, contextsInDFAState[i]);
}
}
}
}
}
if (COMPUTE_TIMING_STATS) {
System.out.format("File\tTokens\tTime%n");
for (int i = 0; i < timePerFile[currentPass].length; i++) {
System.out.format("%d\t%d\t%d%n", i + 1, tokensPerFile[currentPass][i], timePerFile[currentPass][i]);
}
}
}
use of org.antlr.v4.runtime.dfa.DFAState in project antlr4 by antlr.
the class ParserATNSimulator method execATN.
/**
* Performs ATN simulation to compute a predicted alternative based
* upon the remaining input, but also updates the DFA cache to avoid
* having to traverse the ATN again for the same input sequence.
*
* There are some key conditions we're looking for after computing a new
* set of ATN configs (proposed DFA state):
* if the set is empty, there is no viable alternative for current symbol
* does the state uniquely predict an alternative?
* does the state have a conflict that would prevent us from
* putting it on the work list?
*
* We also have some key operations to do:
* add an edge from previous DFA state to potentially new DFA state, D,
* upon current symbol but only if adding to work list, which means in all
* cases except no viable alternative (and possibly non-greedy decisions?)
* collecting predicates and adding semantic context to DFA accept states
* adding rule context to context-sensitive DFA accept states
* consuming an input symbol
* reporting a conflict
* reporting an ambiguity
* reporting a context sensitivity
* reporting insufficient predicates
*
* cover these cases:
* dead end
* single alt
* single alt + preds
* conflict
* conflict + preds
*/
protected int execATN(DFA dfa, DFAState s0, TokenStream input, int startIndex, ParserRuleContext outerContext) {
if (debug || debug_list_atn_decisions) {
System.out.println("execATN decision " + dfa.decision + " exec LA(1)==" + getLookaheadName(input) + " line " + input.LT(1).getLine() + ":" + input.LT(1).getCharPositionInLine());
}
DFAState previousD = s0;
if (debug)
System.out.println("s0 = " + s0);
int t = input.LA(1);
while (true) {
// while more work
DFAState D = getExistingTargetState(previousD, t);
if (D == null) {
D = computeTargetState(dfa, previousD, t);
}
if (D == ERROR) {
// if any configs in previous dipped into outer context, that
// means that input up to t actually finished entry rule
// at least for SLL decision. Full LL doesn't dip into outer
// so don't need special case.
// We will get an error no matter what so delay until after
// decision; better error message. Also, no reachable target
// ATN states in SLL implies LL will also get nowhere.
// If conflict in states that dip out, choose min since we
// will get error no matter what.
NoViableAltException e = noViableAlt(input, outerContext, previousD.configs, startIndex);
input.seek(startIndex);
int alt = getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previousD.configs, outerContext);
if (alt != ATN.INVALID_ALT_NUMBER) {
return alt;
}
throw e;
}
if (D.requiresFullContext && mode != PredictionMode.SLL) {
// IF PREDS, MIGHT RESOLVE TO SINGLE ALT => SLL (or syntax error)
BitSet conflictingAlts = D.configs.conflictingAlts;
if (D.predicates != null) {
if (debug)
System.out.println("DFA state has preds in DFA sim LL failover");
int conflictIndex = input.index();
if (conflictIndex != startIndex) {
input.seek(startIndex);
}
conflictingAlts = evalSemanticContext(D.predicates, outerContext, true);
if (conflictingAlts.cardinality() == 1) {
if (debug)
System.out.println("Full LL avoided");
return conflictingAlts.nextSetBit(0);
}
if (conflictIndex != startIndex) {
// restore the index so reporting the fallback to full
// context occurs with the index at the correct spot
input.seek(conflictIndex);
}
}
if (dfa_debug)
System.out.println("ctx sensitive state " + outerContext + " in " + D);
boolean fullCtx = true;
ATNConfigSet s0_closure = computeStartState(dfa.atnStartState, outerContext, fullCtx);
reportAttemptingFullContext(dfa, conflictingAlts, D.configs, startIndex, input.index());
int alt = execATNWithFullContext(dfa, D, s0_closure, input, startIndex, outerContext);
return alt;
}
if (D.isAcceptState) {
if (D.predicates == null) {
return D.prediction;
}
int stopIndex = input.index();
input.seek(startIndex);
BitSet alts = evalSemanticContext(D.predicates, outerContext, true);
switch(alts.cardinality()) {
case 0:
throw noViableAlt(input, outerContext, D.configs, startIndex);
case 1:
return alts.nextSetBit(0);
default:
// report ambiguity after predicate evaluation to make sure the correct
// set of ambig alts is reported.
reportAmbiguity(dfa, D, startIndex, stopIndex, false, alts, D.configs);
return alts.nextSetBit(0);
}
}
previousD = D;
if (t != IntStream.EOF) {
input.consume();
t = input.LA(1);
}
}
}
use of org.antlr.v4.runtime.dfa.DFAState in project antlr4 by antlr.
the class ParserATNSimulator method reportAmbiguity.
/**
* If context sensitive parsing, we know it's ambiguity not conflict
*/
protected void reportAmbiguity(DFA dfa, // the DFA state from execATN() that had SLL conflicts
DFAState D, int startIndex, int stopIndex, boolean exact, BitSet ambigAlts, // configs that LL not SLL considered conflicting
ATNConfigSet configs) {
if (debug || retry_debug) {
Interval interval = Interval.of(startIndex, stopIndex);
System.out.println("reportAmbiguity " + ambigAlts + ":" + configs + ", input=" + parser.getTokenStream().getText(interval));
}
if (parser != null)
parser.getErrorListenerDispatch().reportAmbiguity(parser, dfa, startIndex, stopIndex, exact, ambigAlts, configs);
}
use of org.antlr.v4.runtime.dfa.DFAState in project antlr4 by antlr.
the class ParserATNSimulator method adaptivePredict.
public int adaptivePredict(TokenStream input, int decision, ParserRuleContext outerContext) {
if (debug || debug_list_atn_decisions) {
System.out.println("adaptivePredict decision " + decision + " exec LA(1)==" + getLookaheadName(input) + " line " + input.LT(1).getLine() + ":" + input.LT(1).getCharPositionInLine());
}
_input = input;
_startIndex = input.index();
_outerContext = outerContext;
DFA dfa = decisionToDFA[decision];
_dfa = dfa;
int m = input.mark();
int index = _startIndex;
// But, do we still need an initial state?
try {
DFAState s0;
if (dfa.isPrecedenceDfa()) {
// the start state for a precedence DFA depends on the current
// parser precedence, and is provided by a DFA method.
s0 = dfa.getPrecedenceStartState(parser.getPrecedence());
} else {
// the start state for a "regular" DFA is just s0
s0 = dfa.s0;
}
if (s0 == null) {
if (outerContext == null)
outerContext = ParserRuleContext.EMPTY;
if (debug || debug_list_atn_decisions) {
System.out.println("predictATN decision " + dfa.decision + " exec LA(1)==" + getLookaheadName(input) + ", outerContext=" + outerContext.toString(parser));
}
boolean fullCtx = false;
ATNConfigSet s0_closure = computeStartState(dfa.atnStartState, ParserRuleContext.EMPTY, fullCtx);
if (dfa.isPrecedenceDfa()) {
/* If this is a precedence DFA, we use applyPrecedenceFilter
* to convert the computed start state to a precedence start
* state. We then use DFA.setPrecedenceStartState to set the
* appropriate start state for the precedence level rather
* than simply setting DFA.s0.
*/
// not used for prediction but useful to know start configs anyway
dfa.s0.configs = s0_closure;
s0_closure = applyPrecedenceFilter(s0_closure);
s0 = addDFAState(dfa, new DFAState(s0_closure));
dfa.setPrecedenceStartState(parser.getPrecedence(), s0);
} else {
s0 = addDFAState(dfa, new DFAState(s0_closure));
dfa.s0 = s0;
}
}
int alt = execATN(dfa, s0, input, index, outerContext);
if (debug)
System.out.println("DFA after predictATN: " + dfa.toString(parser.getVocabulary()));
return alt;
} finally {
// wack cache after each prediction
mergeCache = null;
_dfa = null;
input.seek(index);
input.release(m);
}
}
use of org.antlr.v4.runtime.dfa.DFAState in project antlr4 by antlr.
the class ParserATNSimulator method addDFAState.
/**
* Add state {@code D} to the DFA if it is not already present, and return
* the actual instance stored in the DFA. If a state equivalent to {@code D}
* is already in the DFA, the existing state is returned. Otherwise this
* method returns {@code D} after adding it to the DFA.
*
* <p>If {@code D} is {@link #ERROR}, this method returns {@link #ERROR} and
* does not change the DFA.</p>
*
* @param dfa The dfa
* @param D The DFA state to add
* @return The state stored in the DFA. This will be either the existing
* state if {@code D} is already in the DFA, or {@code D} itself if the
* state was not already present.
*/
protected DFAState addDFAState(DFA dfa, DFAState D) {
if (D == ERROR) {
return D;
}
synchronized (dfa.states) {
DFAState existing = dfa.states.get(D);
if (existing != null)
return existing;
D.stateNumber = dfa.states.size();
if (!D.configs.isReadonly()) {
D.configs.optimizeConfigs(this);
D.configs.setReadonly(true);
}
dfa.states.put(D, D);
if (debug)
System.out.println("adding new DFA state: " + D);
return D;
}
}
Aggregations