forked from jasder/antlr
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:
parent
093af0edce
commit
26165c5d54
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue