atnconfigsets can be readonly now. no copying to put into new DFA state, set readonly instead. made atnconfigset.equals() more accurate. add -notree option to test java lr

This commit is contained in:
Terence Parr 2012-07-27 10:34:59 -07:00
parent 093af0edce
commit 26165c5d54
4 changed files with 49 additions and 26 deletions

View File

@ -88,9 +88,10 @@ public class ATNConfigSet implements Set<ATNConfig> {
}
}
protected boolean readonly = false;
/** Track every config we add */
public final LinkedHashMap<Key,ATNConfig> configToContext =
new LinkedHashMap<Key, ATNConfig>();
public final LinkedHashMap<Key,ATNConfig> configToContext;
/** Track the elements as they are added to the set; supports get(i) */
// too hard to keep in sync
@ -111,11 +112,14 @@ public class ATNConfigSet implements Set<ATNConfig> {
*/
public final boolean fullCtx;
public ATNConfigSet(boolean fullCtx) { this.fullCtx = fullCtx; }
public ATNConfigSet() { this.fullCtx = true; }
public ATNConfigSet(boolean fullCtx) {
configToContext = new LinkedHashMap<Key, ATNConfig>();
this.fullCtx = fullCtx;
}
public ATNConfigSet() { this(true); }
public ATNConfigSet(ATNConfigSet old, PredictionContextCache contextCache) {
addAll(old, contextCache);
configToContext = new LinkedHashMap<Key, ATNConfig>(old.configToContext);
this.fullCtx = old.fullCtx;
this.uniqueAlt = old.uniqueAlt;
this.conflictingAlts = old.conflictingAlts;
@ -133,6 +137,7 @@ public class ATNConfigSet implements Set<ATNConfig> {
* We use (s,i,pi) as key
*/
public boolean add(ATNConfig config, @Nullable PredictionContextCache contextCache) {
if ( readonly ) throw new IllegalStateException("This set is readonly");
contextCache = null; // TODO: costs time to cache and saves essentially no RAM
if ( config.semanticContext!=SemanticContext.NONE ) {
hasSemanticContext = true;
@ -172,21 +177,24 @@ public class ATNConfigSet implements Set<ATNConfig> {
return states;
}
// TODO: very expensive, used in lexer to kill after wildcard config
public ATNConfig get(int i) {
int j = 0;
for (ATNConfig c : configToContext.values()) {
if ( j == i ) return c;
j++;
}
throw new IndexOutOfBoundsException();
throw new IndexOutOfBoundsException("config set index "+i+" not in 0.."+size());
}
public void remove(int i) {
if ( readonly ) throw new IllegalStateException("This set is readonly");
ATNConfig c = elements().get(i);
configToContext.remove(new Key(c));
}
public void optimizeConfigs(ATNSimulator interpreter) {
if ( readonly ) throw new IllegalStateException("This set is readonly");
if ( configToContext.isEmpty() ) return;
for (ATNConfig config : configToContext.values()) {
@ -214,8 +222,15 @@ public class ATNConfigSet implements Set<ATNConfig> {
@Override
public boolean equals(Object o) {
// System.out.print("equals " + this + ", " + o+" = ");
ATNConfigSet other = (ATNConfigSet)o;
boolean same = configToContext!=null &&
configToContext.equals(((ATNConfigSet)o).configToContext);
configToContext.equals(other.configToContext) &&
this.fullCtx == other.fullCtx &&
this.uniqueAlt == other.uniqueAlt &&
this.conflictingAlts == other.conflictingAlts &&
this.hasSemanticContext == other.hasSemanticContext &&
this.dipsIntoOuterContext == other.dipsIntoOuterContext;
// System.out.println(same);
return same;
}
@ -250,6 +265,7 @@ public class ATNConfigSet implements Set<ATNConfig> {
@Override
public void clear() {
if ( readonly ) throw new IllegalStateException("This set is readonly");
configToContext.clear();
}

View File

@ -322,7 +322,7 @@ public class LexerATNSimulator extends ATNSimulator {
}
// Did we hit a stop state during reach op?
processAcceptConfigs(input, reach);
reach = processAcceptConfigs(input, reach);
// Add an edge from s to target DFA found/created for reach
target = addDFAEdge(s, t, reach);
@ -390,7 +390,7 @@ public class LexerATNSimulator extends ATNSimulator {
}
}
protected void processAcceptConfigs(@NotNull CharStream input, @NotNull ATNConfigSet reach) {
protected ATNConfigSet processAcceptConfigs(@NotNull CharStream input, @NotNull ATNConfigSet reach) {
if ( debug ) {
System.out.format("processAcceptConfigs: reach=%s, prevAccept=%s, prevIndex=%d\n",
reach, prevAccept.config, prevAccept.index);
@ -422,12 +422,13 @@ public class LexerATNSimulator extends ATNSimulator {
// if we reach lexer accept state, toss out any configs in rest
// of configs work list associated with this rule (config.alt);
// that rule is done. this is how we cut off nongreedy .+ loops.
deleteWildcardConfigsForAlt(reach, ci, c.alt); // CAUSES INF LOOP if reach not closure
reach = deleteWildcardConfigsForAlt(reach, ci, c.alt);
// move to next char, looking for longer match
// (we continue processing if there are states in reach)
}
}
return reach;
}
protected void accept(@NotNull CharStream input, int ruleIndex, int actionIndex,
@ -488,21 +489,24 @@ public class LexerATNSimulator extends ATNSimulator {
return null;
}
public void deleteWildcardConfigsForAlt(@NotNull ATNConfigSet closure, int ci, int alt) {
/** Delete configs for alt following ci. Closure is unmodified; copy returned. */
public ATNConfigSet deleteWildcardConfigsForAlt(@NotNull ATNConfigSet closure, int ci, int alt) {
ATNConfigSet dup = new ATNConfigSet(closure, null);
int j=ci+1;
while ( j<closure.size() ) {
ATNConfig c = closure.get(j);
boolean isWildcard = c.state.getClass() == ATNState.class &&
c.state.transition(0).getClass() == WildcardTransition.class;
while ( j < dup.size() ) {
ATNConfig c = dup.get(j);
boolean isWildcard = c.state.getClass() == ATNState.class && // plain state only, not rulestop etc..
c.state.transition(0) instanceof WildcardTransition;
if ( c.alt == alt && isWildcard ) {
if ( debug ) {
System.out.format("deleteWildcardConfigsForAlt %s\n", c);
}
closure.remove(j);
dup.remove(j);
}
else j++;
}
return dup;
}
@NotNull
@ -730,8 +734,8 @@ public class LexerATNSimulator extends ATNSimulator {
}
newState.stateNumber = dfa[mode].states.size();
newState.configs = new ATNConfigSet();
newState.configs.addAll(configs);
configs.readonly = true;
newState.configs = configs;
dfa[mode].states.put(newState, newState);
return newState;
}

View File

@ -616,7 +616,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
if ( debug ) System.out.println("in computeReachSet, starting closure: " + closure);
ATNConfigSet reach = new ATNConfigSet(fullCtx);
Set<ATNConfig> closureBusy = new HashSet<ATNConfig>();
ATNConfigSet intermediate = new ATNConfigSet();
ATNConfigSet intermediate = new ATNConfigSet(fullCtx);
// First figure out where we can reach on input t
for (ATNConfig c : closure) {
if ( debug ) System.out.println("testing "+getTokenName(t)+" at "+c.toString());
@ -1394,8 +1394,8 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
configs.optimizeConfigs(this);
// System.out.println("After opt, cache size = " + sharedContextCache.size());
newState.configs = new ATNConfigSet(configs, contextCache);
configs.readonly = true;
newState.configs = configs;
dfa.states.put(newState, newState);
if ( debug ) System.out.println("adding new DFA state: "+newState);
return newState;

View File

@ -43,7 +43,8 @@ class TestJavaLR {
public static boolean profile = false;
public static JavaLRLexer lexer;
public static JavaLRParser parser = null;
public static boolean showTree = false;
public static boolean notree = false;
public static boolean gui = false;
public static boolean printTree = false;
public static boolean SLL = false;
public static boolean diag = false;
@ -61,7 +62,8 @@ class TestJavaLR {
if (args.length > 0 ) {
// for each directory/file specified on the command line
for(int i=0; i< args.length;i++) {
if ( args[i].equals("-tree") ) showTree = true;
if ( args[i].equals("-notree") ) notree = true;
else if ( args[i].equals("-gui") ) gui = true;
else if ( args[i].equals("-ptree") ) printTree = true;
else if ( args[i].equals("-SLL") ) SLL = true;
else if ( args[i].equals("-bail") ) bail = true;
@ -143,9 +145,10 @@ class TestJavaLR {
parser.setTokenStream(tokens);
// start parsing at the compilationUnit rule
ParserRuleContext<Token> tree = parser.compilationUnit();
if ( showTree ) tree.inspect(parser);
if ( printTree ) System.out.println(tree.toStringTree(parser));
ParserRuleContext<Token> t = parser.compilationUnit();
if ( notree ) parser.setBuildParseTree(false);
if ( gui ) t.inspect(parser);
if ( printTree ) System.out.println(t.toStringTree(parser));
//System.err.println("finished "+f);
// System.out.println("cache size = "+DefaultErrorStrategy.cache.size());
}