/// <summary> /// This is where the work happens /// </summary> /// <returns>The symbol that was matched. members _state _line,_column,_position,_buffer and _input are also modified.</returns> string _Lex() { string acc; var states = _initialStates; _buffer.Clear(); switch (_state) { case -1: // initial if (!_MoveNextInput()) { _state = -2; acc = _GetAcceptingSymbol(states); if (null != acc) { return(acc); } else { return("#ERROR"); } } _state = 0; // running break; case -2: // end of stream return("#EOS"); } // Here's where we run most of the match. FillMove runs one interation of the NFA state machine. // We match until we can't match anymore (greedy matching) and then report the symbol of the last // match we found, or an error ("#ERROR") if we couldn't find one. while (true) { var next = CharFA.FillMove(states, _input.Current); if (0 == next.Count) // couldn't find any states { break; } _buffer.Append(_input.Current); states = next; if (!_MoveNextInput()) { // end of stream _state = -2; acc = _GetAcceptingSymbol(states); if (null != acc) // do we accept? { return(acc); } else { return("#ERROR"); } } } acc = _GetAcceptingSymbol(states); if (null != acc) // do we accept? { string be; if (_blockEnds.TryGetValue(acc, out be) && !string.IsNullOrEmpty(be as string)) { // we have to resolve our blockends. This is tricky. We break out of the FA // processing and instead we loop until we match the block end. We have to // be very careful when we match only partial block ends and we have to // handle the case where there's no terminating block end. var more = true; while (more) { while (more) { if (_input.Current != be[0]) { _buffer.Append(_input.Current); more = _MoveNextInput(); if (!more) { return("#ERROR"); } break; } else { var i = 0; var found = true; while (i < be.Length && _input.Current == be[i]) { if (!(more = _MoveNextInput())) { ++i; found = false; if (i < be.Length) { acc = "#ERROR"; } break; } ++i; } if (be.Length != i) { found = false; } if (!found) { _buffer.Append(be.Substring(0, i)); } else { more = false; _buffer.Append(be); break; } if (found) { more = _MoveNextInput(); if (!more) { break; } } } } } } return(acc); } else { // handle the error condition _buffer.Append(_input.Current); if (!_MoveNextInput()) { _state = -2; } return("#ERROR"); } }