예제 #1
0
        /// <summary>
        /// Gets tokens for grammar.
        /// </summary>
        /// <param name="text">A text for which tokens will be returned.</param>
        /// <param name="state">A state for lexer.</param>
        /// <returns>An enumerable of tokens.</returns>
        public LexerResult GetTokens(string text, TLexerState state = null)
        {
            if (text == null)
            {
                throw new ArgumentNullException(nameof(text));
            }

            var result = new LexerResult();

            try
            {
                int currentTokenIndex = 0;
                var lineProvider      = new LexerLineNumberProvider(text);

                if (state != null)
                {
                    state.LineNumber = 0;
                }

                while (currentTokenIndex < text.Length)
                {
                    if (state != null)
                    {
                        var currentLineIndex = lineProvider.GetLineForIndex(currentTokenIndex);
                        state.NewLine          = state.LineNumber != currentLineIndex;
                        state.LineNumber       = currentLineIndex;
                        state.StartColumnIndex = lineProvider.GetColumnForIndex(currentTokenIndex);
                    }

                    if (FindBestRule(text, currentTokenIndex, state, out var tokenType, out var returnToken, out var bestMatch, out var length))
                    {
                        if (returnToken)
                        {
                            if (state != null)
                            {
                                state.PreviousReturnedTokenType = tokenType;
                            }

                            result.Tokens.Add(new Token(
                                                  (int)tokenType,
                                                  bestMatch,
                                                  state?.LineNumber ?? 0,
                                                  state?.StartColumnIndex ?? 0,
                                                  null));
                        }

                        currentTokenIndex += length;
                    }
                    else
                    {
                        throw new LexerException(
                                  "Can't get next token from text",
                                  new SpiceLineInfo
                        {
                            LineNumber       = state?.LineNumber ?? 0,
                            StartColumnIndex = state?.StartColumnIndex ?? 0,
                        });
                    }
                }
예제 #2
0
        /// <summary>
        /// Gets tokens for grammar.
        /// </summary>
        /// <param name="text">A text for which tokens will be returned.</param>
        /// <param name="state">A state for lexer.</param>
        /// <returns>An enumerable of tokens.</returns>
        public LexerResult GetTokens(string text, TLexerState state = null)
        {
            if (text == null)
            {
                throw new ArgumentNullException(nameof(text));
            }

            var result = new LexerResult();

            try
            {
                int currentTokenIndex = 0;
                var lineProvider      = new LexerLineInfoProvider(text);

                if (state != null)
                {
                    state.LineNumber = 0;
                }

                while (currentTokenIndex < text.Length)
                {
                    if (state != null)
                    {
                        var currentLineIndex = lineProvider.GetLineForIndex(currentTokenIndex);
                        state.NewLine          = state.LineNumber != currentLineIndex;
                        state.LineNumber       = currentLineIndex;
                        state.StartColumnIndex = lineProvider.GetColumnForIndex(currentTokenIndex);
                    }

                    if (FindBestTokenRule(text, currentTokenIndex, state, out var bestTokenRule, out var bestMatch))
                    {
                        var tokenActionResult = bestTokenRule.ReturnDecisionProvider(state, bestMatch.Value);
                        if (tokenActionResult == LexerRuleReturnDecision.ReturnToken)
                        {
                            if (state != null)
                            {
                                state.PreviousReturnedTokenType = bestTokenRule.TokenType;
                            }

                            result.Tokens.Add(new Token(
                                                  bestTokenRule.TokenType,
                                                  bestMatch.Value,
                                                  state?.LineNumber ?? 0,
                                                  state?.StartColumnIndex ?? 0,
                                                  null));
                        }

                        currentTokenIndex += bestMatch.Length;
                    }
                    else
                    {
                        bool matched             = false;
                        var  textForDynamicRules = text.Substring(currentTokenIndex);
                        foreach (LexerDynamicRule dynamicRule in Grammar.DynamicRules)
                        {
                            bool ruleMatch = textForDynamicRules.StartsWith(dynamicRule.Prefix);
                            if (ruleMatch)
                            {
                                var dynamicResult = dynamicRule.Action(textForDynamicRules, state);

                                result.Tokens.Add(
                                    new Token(
                                        dynamicRule.TokenType,
                                        dynamicResult.Item1,
                                        state?.LineNumber ?? 0,
                                        state?.StartColumnIndex ?? 0,
                                        null));

                                currentTokenIndex += dynamicResult.Item2;
                                matched            = true;
                            }
                        }

                        if (!matched)
                        {
                            throw new LexerException("Can't get next token from text",
                                                     new SpiceLineInfo
                            {
                                LineNumber       = state?.LineNumber ?? 0,
                                StartColumnIndex = state?.StartColumnIndex ?? 0
                            });
                        }
                    }
                }