/** Two contexts are equals() if both have * same call stack; walk upwards to the root. * Recall that the root sentinel node has no invokingStates and no parent. * Note that you may be comparing contexts in different alt trees. * * The hashCode is now cheap as it's computed once upon each context * push on the stack. Use it to make equals() more efficient. */ public override bool Equals(object o) { NFAContext other = ((NFAContext)o); if (this._cachedHashCode != other._cachedHashCode) { return(false); // can't be same if hash is different } if (this == other) { return(true); } // [email protected]("comparing "+this+" with "+other); NFAContext sp = this; while (sp.parent != null && other.parent != null) { if (sp.invokingState != other.invokingState) { return(false); } sp = sp.parent; other = other.parent; } if (!(sp.parent == null && other.parent == null)) { return(false); // both pointers must be at their roots after walk } return(true); }
//protected boolean addedDuringClosure = true; public NFAConfiguration(int state, int alt, NFAContext context, SemanticContext semanticContext) { this._state = state; this._alt = alt; this._context = context; this._semanticContext = semanticContext; }
public virtual NFAConfiguration AddNFAConfiguration(NFAState state, int alt, NFAContext context, SemanticContext semanticContext) { NFAConfiguration c = new NFAConfiguration(state.StateNumber, alt, context, semanticContext); AddNFAConfiguration(state, c); return(c); }
public NFAContext(NFAContext parent, NFAState invokingState) { this.parent = parent; this.invokingState = invokingState; if (invokingState != null) { this._cachedHashCode = invokingState.stateNumber; } if (parent != null) { this._cachedHashCode += parent._cachedHashCode; } }
public override string ToString() { StringBuilder buf = new StringBuilder(); NFAContext sp = this; buf.Append("["); while (sp.parent != null) { buf.Append(sp.invokingState.stateNumber); buf.Append(" "); sp = sp.parent; } buf.Append("$]"); return(buf.ToString()); }
/** Given an NFA state number, how many times has the NFA-to-DFA * conversion pushed that state on the stack? In other words, * the NFA state must be a rule invocation state and this method * tells you how many times you've been to this state. If none, * then you have not called the target rule from this state before * (though another NFA state could have called that target rule). * If n=1, then you've been to this state before during this * DFA construction and are going to invoke that rule again. * * Note that many NFA states can invoke rule r, but we ignore recursion * unless you hit the same rule invocation state again. */ public virtual int RecursionDepthEmanatingFromState(int state) { NFAContext sp = this; int n = 0; // track recursive invocations of target from this state //[email protected]("this.context is "+sp); while (sp.parent != null) { if (sp.invokingState.stateNumber == state) { n++; } sp = sp.parent; } return(n); }
/** Walk upwards to the root of the call stack context looking * for a particular invoking state. */ public virtual bool Contains(int state) { NFAContext sp = this; int n = 0; // track recursive invocations of state System.Console.Out.WriteLine("this.context is " + sp); while (sp.parent != null) { if (sp.invokingState.stateNumber == state) { return(true); } sp = sp.parent; } return(false); }
/** [$] suffix any context * [21 $] suffix [21 12 $] * [21 12 $] suffix [21 $] * [21 18 $] suffix [21 18 12 9 $] * [21 18 12 9 $] suffix [21 18 $] * [21 12 $] not suffix [21 9 $] * * Example "[21 $] suffix [21 12 $]" means: rule r invoked current rule * from state 21. Rule s invoked rule r from state 12 which then invoked * current rule also via state 21. While the context prior to state 21 * is different, the fact that both contexts emanate from state 21 implies * that they are now going to track perfectly together. Once they * converged on state 21, there is no way they can separate. In other * words, the prior stack state is not consulted when computing where to * go in the closure operation. ?$ and ??$ are considered the same stack. * If ? is popped off then $ and ?$ remain; they are now an empty and * nonempty context comparison. So, if one stack is a suffix of * another, then it will still degenerate to the simple empty stack * comparison case. */ protected virtual bool Suffix(NFAContext other) { NFAContext sp = this; // if one of the contexts is empty, it never enters loop and returns true while (sp.parent != null && other.parent != null) { if (sp.invokingState != other.invokingState) { return(false); } sp = sp.parent; other = other.parent; } //[email protected]("suffix"); return(true); }
public virtual NFAConfiguration AddNFAConfiguration( NFAState state, int alt, NFAContext context, SemanticContext semanticContext ) { NFAConfiguration c = new NFAConfiguration( state.stateNumber, alt, context, semanticContext ); AddNFAConfiguration( state, c ); return c; }
/** [$] suffix any context * [21 $] suffix [21 12 $] * [21 12 $] suffix [21 $] * [21 18 $] suffix [21 18 12 9 $] * [21 18 12 9 $] suffix [21 18 $] * [21 12 $] not suffix [21 9 $] * * Example "[21 $] suffix [21 12 $]" means: rule r invoked current rule * from state 21. Rule s invoked rule r from state 12 which then invoked * current rule also via state 21. While the context prior to state 21 * is different, the fact that both contexts emanate from state 21 implies * that they are now going to track perfectly together. Once they * converged on state 21, there is no way they can separate. In other * words, the prior stack state is not consulted when computing where to * go in the closure operation. ?$ and ??$ are considered the same stack. * If ? is popped off then $ and ?$ remain; they are now an empty and * nonempty context comparison. So, if one stack is a suffix of * another, then it will still degenerate to the simple empty stack * comparison case. */ protected virtual bool Suffix( NFAContext other ) { NFAContext sp = this; // if one of the contexts is empty, it never enters loop and returns true while ( sp.parent != null && other.parent != null ) { if ( sp.invokingState != other.invokingState ) { return false; } sp = sp.parent; other = other.parent; } //[email protected]("suffix"); return true; }
/** Two contexts conflict() if they are equals() or one is a stack suffix * of the other. For example, contexts [21 12 $] and [21 9 $] do not * conflict, but [21 $] and [21 12 $] do conflict. Note that I should * probably not show the $ in this case. There is a dummy node for each * stack that just means empty; $ is a marker that's all. * * This is used in relation to checking conflicts associated with a * single NFA state's configurations within a single DFA state. * If there are configurations s and t within a DFA state such that * s.state=t.state && s.alt != t.alt && s.ctx conflicts t.ctx then * the DFA state predicts more than a single alt--it's nondeterministic. * Two contexts conflict if they are the same or if one is a suffix * of the other. * * When comparing contexts, if one context has a stack and the other * does not then they should be considered the same context. The only * way for an NFA state p to have an empty context and a nonempty context * is the case when closure falls off end of rule without a call stack * and re-enters the rule with a context. This resolves the issue I * discussed with Sriram Srinivasan Feb 28, 2005 about not terminating * fast enough upon nondeterminism. */ public virtual bool ConflictsWith( NFAContext other ) { return this.Suffix( other ); // || this.equals(other); }
public NFAContext( NFAContext parent, NFAState invokingState ) { this.parent = parent; this.invokingState = invokingState; if ( invokingState != null ) { this._cachedHashCode = invokingState.stateNumber; } if ( parent != null ) { this._cachedHashCode += parent._cachedHashCode; } }
/** Two contexts conflict() if they are equals() or one is a stack suffix * of the other. For example, contexts [21 12 $] and [21 9 $] do not * conflict, but [21 $] and [21 12 $] do conflict. Note that I should * probably not show the $ in this case. There is a dummy node for each * stack that just means empty; $ is a marker that's all. * * This is used in relation to checking conflicts associated with a * single NFA state's configurations within a single DFA state. * If there are configurations s and t within a DFA state such that * s.state=t.state && s.alt != t.alt && s.ctx conflicts t.ctx then * the DFA state predicts more than a single alt--it's nondeterministic. * Two contexts conflict if they are the same or if one is a suffix * of the other. * * When comparing contexts, if one context has a stack and the other * does not then they should be considered the same context. The only * way for an NFA state p to have an empty context and a nonempty context * is the case when closure falls off end of rule without a call stack * and re-enters the rule with a context. This resolves the issue I * discussed with Sriram Srinivasan Feb 28, 2005 about not terminating * fast enough upon nondeterminism. */ public virtual bool ConflictsWith(NFAContext other) { return(this.Suffix(other)); // || this.equals(other); }