예제 #1
0
        /// <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");
            }
        }