got first draft of new "go/stop" algorithm.

This commit is contained in:
Terence Parr 2012-09-09 19:20:33 -07:00
parent 89656989e6
commit aa2d893a77
2 changed files with 58 additions and 23 deletions

View File

@ -38,8 +38,8 @@ import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenStream; import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.dfa.DFA; import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.dfa.DFAState; import org.antlr.v4.runtime.dfa.DFAState;
import org.antlr.v4.runtime.misc.Array2DHashSet;
import org.antlr.v4.runtime.misc.DoubleKeyMap; import org.antlr.v4.runtime.misc.DoubleKeyMap;
import org.antlr.v4.runtime.misc.FlexibleHashMap;
import org.antlr.v4.runtime.misc.Interval; import org.antlr.v4.runtime.misc.Interval;
import org.antlr.v4.runtime.misc.IntervalSet; import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.runtime.misc.NotNull; import org.antlr.v4.runtime.misc.NotNull;
@ -48,6 +48,7 @@ import org.stringtemplate.v4.misc.MultiMap;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -654,7 +655,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
D.prediction = predictedAlt; D.prediction = predictedAlt;
} }
else { else {
boolean cont = needMoreLookaheadSLL(reach); // boolean cont = needMoreLookaheadLL(reach);
D.configs.conflictingAlts = getConflictingAlts(reach); D.configs.conflictingAlts = getConflictingAlts(reach);
if ( D.configs.conflictingAlts!=null ) { if ( D.configs.conflictingAlts!=null ) {
if ( greedy ) { if ( greedy ) {
@ -826,6 +827,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
} }
reach.uniqueAlt = getUniqueAlt(reach); reach.uniqueAlt = getUniqueAlt(reach);
if ( reach.uniqueAlt!=ATN.INVALID_ALT_NUMBER ) break; if ( reach.uniqueAlt!=ATN.INVALID_ALT_NUMBER ) break;
// boolean cont = needMoreLookaheadLL(reach);
reach.conflictingAlts = getConflictingAlts(reach); reach.conflictingAlts = getConflictingAlts(reach);
if ( reach.conflictingAlts!=null ) break; if ( reach.conflictingAlts!=null ) break;
previous = reach; previous = reach;
@ -1492,31 +1494,54 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
return len(viable_alts)>1 return len(viable_alts)>1
*/ */
class AltAndContextMap extends FlexibleHashMap<ATNConfig,BitSet> {
/** Code is function of (s, _, ctx, _) */
@Override
public int hashCode(ATNConfig o) {
int hashCode = 7;
hashCode = 31 * hashCode + o.state.stateNumber;
hashCode = 31 * hashCode + o.context.hashCode();
return hashCode;
}
@Override
public boolean equals(ATNConfig a, ATNConfig b) {
if ( a==b ) return true;
if ( a==null || b==null ) return false;
if ( hashCode(a) != hashCode(b) ) return false;
return a.state.stateNumber==b.state.stateNumber
&& b.context.equals(b.context);
}
}
public boolean needMoreLookaheadLL(@NotNull ATNConfigSet configs) { public boolean needMoreLookaheadLL(@NotNull ATNConfigSet configs) {
class AltAndContextHashSet extends Array2DHashSet<ATNConfig> { // for c in configs:
public AltAndContextHashSet() { // map[c] U= c.alt # map hash/equals uses s and x, not alt and not pred
super(16,2); System.out.println(configs);
AltAndContextMap configToAlts = new AltAndContextMap();
for (ATNConfig c : configs) {
BitSet alts = configToAlts.get(c);
if ( alts==null ) {
alts = new BitSet();
configToAlts.put(c, alts);
} }
alts.set(c.alt);
/** Code is function of (s, _, ctx, _) */ }
@Override System.out.println(configToAlts);
public int hashCode(ATNConfig o) { BitSet viableAlts = new BitSet();
int hashCode = 7; for (BitSet alts : configToAlts.values()) {
hashCode = 31 * hashCode + o.state.stateNumber; int firstOnBit = alts.nextSetBit(0);
hashCode = 31 * hashCode + o.context.hashCode(); if ( alts.cardinality()==1 ) {
return hashCode; int singleton = firstOnBit;
viableAlts.set(singleton);
} }
else { // > 1
@Override int minAlt = firstOnBit;
public boolean equals(ATNConfig a, ATNConfig b) { viableAlts.set(minAlt);
if ( a==b ) return true;
if ( a==null || b==null ) return false;
if ( hashCode(a) != hashCode(b) ) return false;
return a.state.stateNumber==b.state.stateNumber
&& b.context.equals(b.context);
} }
} }
return false; boolean go = viableAlts.cardinality() > 1;
System.out.println("stop="+!go);
return go;
} }
/** /**

View File

@ -1,7 +1,9 @@
package org.antlr.v4.runtime.misc; package org.antlr.v4.runtime.misc;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -92,6 +94,7 @@ public class FlexibleHashMap<K,V> implements EquivalenceMap<K,V> {
} }
// not there // not there
bucket.add(new Entry(key, value)); bucket.add(new Entry(key, value));
n++;
return null; return null;
} }
@ -112,7 +115,14 @@ public class FlexibleHashMap<K,V> implements EquivalenceMap<K,V> {
@Override @Override
public Collection<V> values() { public Collection<V> values() {
throw new UnsupportedOperationException(); List<V> a = new ArrayList<V>(size());
for (LinkedList<Entry> bucket : buckets) {
if ( bucket==null ) continue;
for (Entry e : bucket) {
a.add(e.value);
}
}
return a;
} }
@Override @Override