From 26165c5d5454195b0553fc623d7510aba23d80b4 Mon Sep 17 00:00:00 2001 From: Terence Parr Date: Fri, 27 Jul 2012 10:34:59 -0700 Subject: [PATCH] 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 --- .../antlr/v4/runtime/atn/ATNConfigSet.java | 30 ++++++++++++++----- .../v4/runtime/atn/LexerATNSimulator.java | 26 +++++++++------- .../v4/runtime/atn/ParserATNSimulator.java | 6 ++-- tool/playground/TestJavaLR.java | 13 ++++---- 4 files changed, 49 insertions(+), 26 deletions(-) diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/ATNConfigSet.java b/runtime/Java/src/org/antlr/v4/runtime/atn/ATNConfigSet.java index c478ca60f..2cbe777ca 100755 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/ATNConfigSet.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/ATNConfigSet.java @@ -88,9 +88,10 @@ public class ATNConfigSet implements Set { } } + protected boolean readonly = false; + /** Track every config we add */ - public final LinkedHashMap configToContext = - new LinkedHashMap(); + public final LinkedHashMap 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 { */ public final boolean fullCtx; - public ATNConfigSet(boolean fullCtx) { this.fullCtx = fullCtx; } - public ATNConfigSet() { this.fullCtx = true; } + public ATNConfigSet(boolean fullCtx) { + configToContext = new LinkedHashMap(); + this.fullCtx = fullCtx; + } + public ATNConfigSet() { this(true); } public ATNConfigSet(ATNConfigSet old, PredictionContextCache contextCache) { - addAll(old, contextCache); + configToContext = new LinkedHashMap(old.configToContext); this.fullCtx = old.fullCtx; this.uniqueAlt = old.uniqueAlt; this.conflictingAlts = old.conflictingAlts; @@ -133,6 +137,7 @@ public class ATNConfigSet implements Set { * 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 { 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 { @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 { @Override public void clear() { + if ( readonly ) throw new IllegalStateException("This set is readonly"); configToContext.clear(); } diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/LexerATNSimulator.java b/runtime/Java/src/org/antlr/v4/runtime/atn/LexerATNSimulator.java index e5db900e7..396cf4c10 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/LexerATNSimulator.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/LexerATNSimulator.java @@ -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 extends ATNSimulator { if ( debug ) System.out.println("in computeReachSet, starting closure: " + closure); ATNConfigSet reach = new ATNConfigSet(fullCtx); Set closureBusy = new HashSet(); - 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 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; diff --git a/tool/playground/TestJavaLR.java b/tool/playground/TestJavaLR.java index 475e7c67a..c86b00b2e 100644 --- a/tool/playground/TestJavaLR.java +++ b/tool/playground/TestJavaLR.java @@ -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 tree = parser.compilationUnit(); - if ( showTree ) tree.inspect(parser); - if ( printTree ) System.out.println(tree.toStringTree(parser)); + ParserRuleContext 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()); }