protected virtual bool GetNFAPath( NFAState s, // starting where?
int labelIndex, // 0..labels.size()-1
IList<Label> labels, // input sequence
IList<NFAState> path )
{
// track a visit to state s at input index labelIndex if not seen
string thisStateKey = GetStateLabelIndexKey( s.StateNumber, labelIndex );
if ( _statesVisitedAtInputDepth.Contains( thisStateKey ) )
{
/*
[email protected]("### already visited "+s.stateNumber+" previously at index "+
labelIndex);
*/
return false;
}
_statesVisitedAtInputDepth.Add( thisStateKey );
/*
[email protected]("enter state "+s.stateNumber+" visited states: "+
statesVisitedAtInputDepth);
*/
// pick the first edge whose target is in states and whose
// label is labels[labelIndex]
for ( int i = 0; i < s.NumberOfTransitions; i++ )
{
Transition t = s.transition[i];
NFAState edgeTarget = (NFAState)t.Target;
Label label = (Label)labels[labelIndex];
/*
[email protected](s.stateNumber+"-"+
t.label.toString(dfa.nfa.Grammar)+"->"+
edgeTarget.stateNumber+" =="+
label.toString(dfa.nfa.Grammar)+"?");
*/
if ( t.Label.IsEpsilon || t.Label.IsSemanticPredicate )
{
// nondeterministically backtrack down epsilon edges
path.Add( edgeTarget );
bool found =
GetNFAPath( edgeTarget, labelIndex, labels, path );
if ( found )
{
_statesVisitedAtInputDepth.Remove( thisStateKey );
return true; // return to "calling" state
}
path.RemoveAt( path.Count - 1 ); // remove; didn't work out
continue; // look at the next edge
}
if ( t.Label.Matches( label ) )
{
path.Add( edgeTarget );
/*
[email protected]("found label "+
t.label.toString(dfa.nfa.Grammar)+
" at state "+s.stateNumber+"; labelIndex="+labelIndex);
*/
if ( labelIndex == labels.Count - 1 )
{
// found last label; done!
_statesVisitedAtInputDepth.Remove( thisStateKey );
return true;
}
// otherwise try to match remaining input
bool found =
GetNFAPath( edgeTarget, labelIndex + 1, labels, path );
if ( found )
{
_statesVisitedAtInputDepth.Remove( thisStateKey );
return true;
}
/*
[email protected]("backtrack; path from "+s.stateNumber+"->"+
t.label.toString(dfa.nfa.Grammar)+" didn't work");
*/
path.RemoveAt( path.Count - 1 ); // remove; didn't work out
continue; // keep looking for a path for labels
}
}
//[email protected]("no epsilon or matching edge; removing "+thisStateKey);
// no edge was found matching label; is ok, some state will have it
_statesVisitedAtInputDepth.Remove( thisStateKey );
return false;
}