/// <summary> /// Gets the index of the terminal with the highest priority that is possible in the contexts /// </summary> /// <param name="state">The DFA state</param> /// <param name="provider">The current applicable contexts</param> /// <returns>The index of the terminal</returns> private int GetTerminalFor(int state, IContextProvider provider) { AutomatonState stateData = automaton.GetState(state); MatchedTerminal mt = stateData.GetTerminal(0); int id = symTerminals[mt.Index].ID; int currentResult = mt.Index; if (id == separatorID) { // the separator trumps all return(currentResult); } int currentPriority = provider.GetContextPriority(mt.Context, id); for (int i = 1; i != stateData.TerminalsCount; i++) { mt = stateData.GetTerminal(i); id = symTerminals[mt.Index].ID; if (id == separatorID) { // the separator trumps all return(mt.Index); } int priority = provider.GetContextPriority(mt.Context, id); if (currentPriority < 0 || (priority >= 0 && priority < currentPriority)) { currentResult = mt.Index; currentPriority = priority; } } return(currentResult); }
/// <summary> /// Inspects a head with a specified character ahead /// </summary> /// <param name="head">The head to inspect</param> /// <param name="offset">The current offset from the original index</param> /// <param name="current">The leading character in the input</param> private void Inspect(Head head, int offset, char current) { AutomatonState stateData = automaton.GetState(head.State); // is it a matching state if (stateData.TerminalsCount != 0 && stateData.GetTerminal(0).Index != separator) { OnMatchingHead(head, offset); } if (head.Distance >= maxDistance || stateData.IsDeadEnd) { // cannot stray further return; } // could be a straight match int target = stateData.GetTargetBy(current); if (target != Automaton.DEAD_STATE) { // it is! PushHead(head, target); } // could try a drop PushHead(head, head.State, offset); // lookup the transitions ExploreTransitions(head, stateData, offset, false); ExploreInsertions(head, offset, false, current); }
/// <summary> /// Inspects a head while at the end of the input /// </summary> /// <param name="head">The head to inspect</param> /// <param name="offset">The current offset from the original index</param> private void InspectAtEnd(Head head, int offset) { AutomatonState stateData = automaton.GetState(head.State); // is it a matching state if (stateData.TerminalsCount != 0 && stateData.GetTerminal(0).Index != separator) { OnMatchingHead(head, offset); } if (head.Distance >= maxDistance || stateData.IsDeadEnd) { // cannot stray further return; } // lookup the transitions ExploreTransitions(head, stateData, offset, true); ExploreInsertions(head, offset, true, '\0'); }
/// <summary> /// Explores an insertion /// </summary> /// <param name="head">The head to inspect</param> /// <param name="offset">The current offset from the original index</param> /// <param name="atEnd">Whether the current index is at the end of the input</param> /// <param name="current">The leading character in the input</param> /// <param name="state">The DFA state for the insertion</param> /// <param name="distance">The distance associated to this insertion</param> private void ExploreInsertion(Head head, int offset, bool atEnd, char current, int state, int distance) { AutomatonState stateData = automaton.GetState(state); if (stateData.TerminalsCount != 0 && stateData.GetTerminal(0).Index != separator) { OnMatchingInsertion(head, offset, state, distance); } if (!atEnd) { int target = stateData.GetTargetBy(current); if (target != Automaton.DEAD_STATE) { PushHead(head, target, offset, distance); } } if (distance >= maxDistance) { return; } // continue insertion ExploreTransitions(head, stateData, offset, true); }