예제 #1
0
        public FSMLexerBuilder <N> End(N nodeValue)
        {
            if (Fsm.HasState(CurrentState))
            {
                FSMNode <N> node = Fsm.GetNode(CurrentState);

                node.IsEnd = true;
                node.Value = nodeValue;
            }
            return(this);
        }
예제 #2
0
        private FSMNode <N> Move(FSMNode <N> from, char token, ReadOnlyMemory <char> value)
        {
            if (from != null && Transitions.TryGetValue(from.Id, out var transitions))
            {
                // Do NOT use Linq, increases allocations AND running time
                for (var i = 0; i < transitions.Count; ++i)
                {
                    var transition = transitions[i];
                    if (transition.Match(token, value))
                    {
                        return(Nodes[transition.ToNode]);
                    }
                }
            }

            return(null);
        }
예제 #3
0
파일: FSMLexer.cs 프로젝트: dotted/csly
        public FSMMatch <N> Run(string source, int start)
        {
            string value     = "";
            var    result    = new FSMMatch <N>(false);
            var    successes = new Stack <FSMMatch <N> >();

            CurrentPosition = start;
            FSMNode <N>   currentNode = Nodes[0];
            int           lastNode    = 0;
            TokenPosition position    = null;

            bool tokenStarted = false;


            if (CurrentPosition < source.Length)
            {
                char currentToken = source[CurrentPosition];

                while (CurrentPosition < source.Length && currentNode != null)
                {
                    currentToken = source[CurrentPosition];

                    bool consumeSkipped = true;

                    while (consumeSkipped && !tokenStarted && CurrentPosition < source.Length)
                    {
                        currentToken = source[CurrentPosition];
                        if (IgnoreWhiteSpace && WhiteSpaces.Contains(currentToken))
                        {
                            if (successes.Any())
                            {
                                currentNode = null;
                            }
                            else
                            {
                                currentNode = Nodes[0];
                            }
                            CurrentPosition++;
                            CurrentColumn++;
                        }
                        else
                        {
                            var eol = EOLManager.IsEndOfLine(source, CurrentPosition);

                            if (IgnoreEOL && eol != EOLType.No)
                            {
                                if (successes.Any())
                                {
                                    currentNode = null;
                                }
                                else
                                {
                                    currentNode = Nodes[0];
                                }
                                CurrentPosition += (eol == EOLType.Windows ? 2 : 1);
                                CurrentColumn    = 0;
                                CurrentLine++;
                            }
                            else
                            {
                                consumeSkipped = false;
                            }
                        }
                    }



                    currentNode = Move(currentNode, currentToken, value);
                    if (currentNode != null)
                    {
                        lastNode = currentNode.Id;
                        value   += currentToken;

                        if (!tokenStarted)
                        {
                            tokenStarted = true;
                            position     = new TokenPosition(CurrentPosition, CurrentLine, CurrentColumn);
                        }
                        if (currentNode.IsEnd)
                        {
                            var resultInter = new FSMMatch <N>(true, currentNode.Value, value, position);
                            successes.Push(resultInter);
                        }
                        if (HasAction(currentNode.Id))
                        {
                            value = Actions[currentNode.Id](value);
                        }
                        CurrentPosition++;
                        CurrentColumn++;
                    }
                    else
                    {
                        if (lastNode == 0 && !tokenStarted && !successes.Any() && CurrentPosition < source.Length)
                        {
                            throw new LexerException(new LexicalError(CurrentLine, CurrentColumn, source[CurrentPosition]));
                        }
                        ;
                    }
                }
            }


            if (successes.Any())
            {
                result = successes.Pop();
                if (HasCallback(lastNode))
                {
                    result = Callbacks[lastNode](result);
                }
            }

            return(result);
        }