v4: DFAState.configs now ATNConfig[] instead of OrderedHashSet<ATNConfig>

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 9511]
This commit is contained in:
sharwell 2011-12-01 17:04:25 -08:00
parent 4d942c37c8
commit 682e60b065
8 changed files with 65 additions and 36 deletions

View File

@ -37,12 +37,12 @@ public class LexerNoViableAltException extends RecognitionException {
public int startIndex;
/** Which configurations did we try at input.index() that couldn't match input.LA(1)? */
public OrderedHashSet<ATNConfig> deadEndConfigs;
public ATNConfig[] deadEndConfigs;
public LexerNoViableAltException(Lexer lexer,
CharStream input,
int startIndex,
OrderedHashSet<ATNConfig> deadEndConfigs) {
ATNConfig[] deadEndConfigs) {
super(lexer, input, null);
this.startIndex = startIndex;
this.deadEndConfigs = deadEndConfigs;

View File

@ -29,6 +29,7 @@
package org.antlr.v4.runtime;
import org.antlr.v4.runtime.atn.ATNConfig;
import org.antlr.v4.runtime.misc.Nullable;
import org.antlr.v4.runtime.misc.OrderedHashSet;
/** The parser could not decide which path in the decision to take based
@ -36,7 +37,7 @@ import org.antlr.v4.runtime.misc.OrderedHashSet;
*/
public class NoViableAltException extends RecognitionException {
/** Which configurations did we try at input.index() that couldn't match input.LT(1)? */
public OrderedHashSet<ATNConfig> deadEndConfigs;
public ATNConfig[] deadEndConfigs;
/** The token object at the start index; the input stream might
* not be buffering tokens so get a reference to it. (At the
@ -59,7 +60,7 @@ public class NoViableAltException extends RecognitionException {
Token startToken,
Token offendingToken,
Symbol offendingNode,
OrderedHashSet<ATNConfig> deadEndConfigs,
@Nullable ATNConfig[] deadEndConfigs,
ParserRuleContext ctx)
{
super(recognizer, input, ctx);

View File

@ -30,6 +30,7 @@
package org.antlr.v4.runtime;
import org.antlr.v4.runtime.atn.ATNConfig;
import org.antlr.v4.runtime.misc.Nullable;
import org.antlr.v4.runtime.misc.OrderedHashSet;
import org.antlr.v4.runtime.tree.ASTNodeStream;
import org.antlr.v4.runtime.tree.TreeParser;
@ -50,7 +51,7 @@ public class NoViableTreeGrammarAltException extends NoViableAltException {
ASTNodeStream<Symbol> input,
Symbol startNode,
Symbol offendingNode,
OrderedHashSet<ATNConfig> deadEndConfigs,
@Nullable ATNConfig[] deadEndConfigs,
ParserRuleContext ctx) {
super(recognizer, input,
input.getTreeAdaptor().getToken(startNode),

View File

@ -38,6 +38,7 @@ import org.antlr.v4.runtime.misc.OrderedHashSet;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
/** "dup" of ParserInterpreter */
public class LexerATNSimulator extends ATNSimulator {
@ -339,7 +340,7 @@ public class LexerATNSimulator extends ATNSimulator {
if ( t==CharStream.EOF && input.index()==startIndex ) {
return Token.EOF;
}
throw new LexerNoViableAltException(recog, input, startIndex, reach);
throw new LexerNoViableAltException(recog, input, startIndex, reach.toArray(new ATNConfig[reach.size()]));
}
int ruleIndex = atnPrevAccept.config.state.ruleIndex;
@ -545,10 +546,10 @@ public class LexerATNSimulator extends ATNSimulator {
if ( dfa_debug ) {
System.out.format("no edge for %s\n", getTokenName(input.LA(1)));
System.out.format("ATN exec upon %s at DFA state %d = %s\n",
input.substring(startIndex, input.index()), s.stateNumber, s.configs);
input.substring(startIndex, input.index()), s.stateNumber, Arrays.toString(s.configs));
}
int ttype = exec(input, s.configs);
int ttype = exec(input, new OrderedHashSet<ATNConfig>(s.configs));
if ( dfa_debug ) {
System.out.format("back from DFA update, ttype=%d, dfa[mode %d]=\n%s\n",
@ -653,8 +654,9 @@ public class LexerATNSimulator extends ATNSimulator {
if ( traversedPredicate ) return null; // cannot cache
newState.stateNumber = dfa[mode].states.size();
newState.configs = new OrderedHashSet<ATNConfig>();
newState.configs.addAll(configs);
// Note: the configs array is copied in the DFAState ctor, no need to copy again
//newState.configs = new OrderedHashSet<ATNConfig>();
//newState.configs.addAll(configs);
dfa[mode].states.put(newState, newState);
return newState;
}

View File

@ -202,7 +202,7 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
// start all over with ATN; can't use DFA
input.seek(startIndex);
DFA throwAwayDFA = new DFA(dfa.atnStartState);
int alt = execATN(input, throwAwayDFA, startIndex, s0.configs, false);
int alt = execATN(input, throwAwayDFA, startIndex, new OrderedHashSet<ATNConfig>(s0.configs), false);
s.ctxToPrediction.put(outerContext, alt);
return alt;
}
@ -230,7 +230,7 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
" at DFA state "+s.stateNumber);
}
try {
alt = execATN(input, dfa, startIndex, s.configs, false);
alt = execATN(input, dfa, startIndex, new OrderedHashSet<ATNConfig>(s.configs), false);
// this adds edge even if next state is accept for
// same alt; e.g., s0-A->:s1=>2-B->:s2=>2
// TODO: This next stuff kills edge, but extra states remain. :(
@ -1033,8 +1033,9 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
DFAState newState = proposed;
newState.stateNumber = dfa.states.size();
newState.configs = new OrderedHashSet<ATNConfig>();
newState.configs.addAll(configs);
// Note: the configs array is copied in the DFAState ctor, no need to copy again
//newState.configs = new OrderedHashSet<ATNConfig>();
//newState.configs.addAll(configs);
dfa.states.put(newState, newState);
if ( debug ) System.out.println("adding new DFA state: "+newState);
return newState;
@ -1100,7 +1101,16 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
@NotNull
public NoViableAltException noViableAlt(@NotNull SymbolStream<Symbol> input,
@NotNull ParserRuleContext outerContext,
@NotNull OrderedHashSet<ATNConfig> configs,
@NotNull Set<ATNConfig> configs,
int startIndex)
{
return noViableAlt(input, outerContext, configs.toArray(new ATNConfig[configs.size()]), startIndex);
}
@NotNull
public NoViableAltException noViableAlt(@NotNull SymbolStream<Symbol> input,
@NotNull ParserRuleContext outerContext,
@NotNull ATNConfig[] configs,
int startIndex)
{
if ( parser instanceof TreeParser) {

View File

@ -35,10 +35,7 @@ import org.antlr.v4.runtime.atn.SemanticContext;
import org.antlr.v4.runtime.misc.Nullable;
import org.antlr.v4.runtime.misc.OrderedHashSet;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
/** A DFA state represents a set of possible ATN configurations.
* As Aho, Sethi, Ullman p. 117 says "The DFA uses its state
@ -69,7 +66,7 @@ public class DFAState {
/** The set of ATN configurations (state,alt,context) for this DFA state */
@Nullable
public OrderedHashSet<ATNConfig> configs = new OrderedHashSet<ATNConfig>();
public ATNConfig[] configs;
/** edges[symbol] points to target of symbol */
@Nullable
@ -139,17 +136,21 @@ public class DFAState {
public DFAState(int stateNumber) { this.stateNumber = stateNumber; }
public DFAState(OrderedHashSet<ATNConfig> configs) { this.configs = configs; }
public DFAState(OrderedHashSet<ATNConfig> configs) { this.configs = configs.elements().toArray(new ATNConfig[configs.size()]); }
/** Get the set of all alts mentioned by all ATN configurations in this
* DFA state.
*/
public Set<Integer> getAltSet() {
// TODO (sam): what to do when configs==null?
if (configs == null) {
return null;
}
Set<Integer> alts = new HashSet<Integer>();
for (ATNConfig c : configs) {
alts.add(c.alt);
}
if ( alts.size()==0 ) return null;
return alts;
}
@ -167,11 +168,15 @@ public class DFAState {
/** A decent hash for a DFA state is the sum of the ATN state/alt pairs. */
@Override
public int hashCode() {
// TODO (sam): what to do when configs==null?
if (configs == null) {
return 0;
}
int h = 0;
for (ATNConfig c : configs) {
h += c.alt;
}
return h;
}
@ -190,9 +195,9 @@ public class DFAState {
public boolean equals(Object o) {
// compare set of ATN configurations in this set with other
if ( this==o ) return true;
if (!(o instanceof DFAState)) return false;
DFAState other = (DFAState)o;
// TODO (sam): what to do when configs==null?
boolean sameSet = this.configs.equals(other.configs);
boolean sameSet = this.configs == other.configs || (this.configs != null && Arrays.equals(this.configs, other.configs));
// System.out.println("DFAState.equals: "+configs+(sameSet?"==":"!=")+other.configs);
return sameSet;
}
@ -200,7 +205,7 @@ public class DFAState {
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append(stateNumber + ":" + configs);
buf.append(stateNumber).append(":").append(Arrays.toString(configs));
if ( isAcceptState ) {
buf.append("=>");
if ( predicates!=null ) {

View File

@ -29,10 +29,7 @@
package org.antlr.v4.runtime.misc;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.*;
/** A HashMap that remembers the order that the elements were added.
* You can alter the ith element with set(i,value) too :) Unique list.
@ -43,6 +40,13 @@ public class OrderedHashSet<T> extends LinkedHashSet<T> {
/** Track the elements as they are added to the set */
protected List<T> elements = new ArrayList<T>();
public OrderedHashSet() {
}
public OrderedHashSet(T[] values) {
Collections.addAll(this, values);
}
public T get(int i) {
return elements.get(i);
}
@ -94,6 +98,12 @@ public class OrderedHashSet<T> extends LinkedHashSet<T> {
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (!(o instanceof OrderedHashSet<?>)) {
return false;
}
// System.out.print("equals " + this + ", " + o+" = ");
boolean same = elements!=null && elements.equals(((OrderedHashSet<?>)o).elements);
// System.out.println(same);

View File

@ -32,6 +32,7 @@ package org.antlr.v4.tool;
import org.antlr.v4.misc.Utils;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.*;
import org.antlr.v4.runtime.misc.OrderedHashSet;
import org.stringtemplate.v4.*;
import java.util.*;
@ -106,25 +107,24 @@ public class DOTGenerator {
protected String getStateLabel(DFAState s) {
if ( s==null ) return "null";
StringBuffer buf = new StringBuffer(250);
StringBuilder buf = new StringBuilder(250);
buf.append('s');
buf.append(s.stateNumber);
if ( s.isAcceptState ) {
buf.append("=>"+s.prediction);
buf.append("=>").append(s.prediction);
}
// if ( Tool.internalOption_ShowATNConfigsInDFA ) {
if ( false ) {
Set<Integer> alts = ((DFAState)s).getAltSet();
Set<Integer> alts = s.getAltSet();
if ( alts!=null ) {
buf.append("\\n");
// separate alts
List<Integer> altList = new ArrayList<Integer>();
altList.addAll(alts);
Collections.sort(altList);
Set<ATNConfig> configurations = ((DFAState)s).configs;
Set<ATNConfig> configurations = new OrderedHashSet<ATNConfig>(s.configs);
for (int altIndex = 0; altIndex < altList.size(); altIndex++) {
Integer altI = (Integer) altList.get(altIndex);
int alt = altI.intValue();
int alt = altList.get(altIndex);
if ( altIndex>0 ) {
buf.append("\\n");
}