public SyntaxParseResult <IN> ParseNonTerminal(IList <Token <IN> > tokens, NonTerminalClause <IN> nonTermClause,
                                                       int currentPosition)
        {
            var startPosition  = currentPosition;
            var endingPosition = 0;
            var nt             = Configuration.NonTerminals[nonTermClause.NonTerminalName];
            var errors         = new List <UnexpectedTokenSyntaxError <IN> >();

            var i = 0;

            var allAcceptableTokens = new List <IN>();

            nt.Rules.ForEach(r =>
            {
                if (r != null && r.PossibleLeadingTokens != null)
                {
                    allAcceptableTokens.AddRange(r.PossibleLeadingTokens);
                }
            });
            allAcceptableTokens = allAcceptableTokens.Distinct().ToList();

            var rules = nt.Rules
                        .Where(r => startPosition < tokens.Count && r.PossibleLeadingTokens.Contains(tokens[startPosition].TokenID) || r.MayBeEmpty)
                        .ToList();

            if (rules.Count == 0)
            {
                return(NoMatchingRuleError(tokens, currentPosition, allAcceptableTokens));
            }

            var innerRuleErrors = new List <UnexpectedTokenSyntaxError <IN> >();
            var greaterIndex    = 0;
            var rulesResults    = new List <SyntaxParseResult <IN> >();

            while (i < rules.Count)
            {
                var innerrule    = rules[i];
                var innerRuleRes = Parse(tokens, innerrule, startPosition, nonTermClause.NonTerminalName);
                rulesResults.Add(innerRuleRes);

                var other = greaterIndex == 0 && innerRuleRes.EndingPosition == 0;
                if (innerRuleRes.EndingPosition > greaterIndex && innerRuleRes.Errors != null &&
                    !innerRuleRes.Errors.Any() || other)
                {
                    greaterIndex = innerRuleRes.EndingPosition;
                    //innerRuleErrors.Clear();
                    innerRuleErrors.AddRange(innerRuleRes.Errors);
                }

                innerRuleErrors.AddRange(innerRuleRes.Errors);
                i++;
            }

            errors.AddRange(innerRuleErrors);
            SyntaxParseResult <IN> max = null;

            if (rulesResults.Any())
            {
                if (rulesResults.Any(x => x.IsOk))
                {
                    max = rulesResults.Where(x => x.IsOk).OrderBy(x => x.EndingPosition).Last();
                }
                else
                {
                    max = rulesResults.Where(x => !x.IsOk).OrderBy(x => x.EndingPosition).Last();
                }
            }
            else
            {
                max                = new SyntaxParseResult <IN>();
                max.IsError        = true;
                max.Root           = null;
                max.IsEnded        = false;
                max.EndingPosition = currentPosition;
            }

            var result = new SyntaxParseResult <IN>();

            result.Errors         = errors;
            result.Root           = max.Root;
            result.EndingPosition = max.EndingPosition;
            result.IsError        = max.IsError;
            result.IsEnded        = max.IsEnded;

            if (rulesResults.Any())
            {
                var terr       = rulesResults.SelectMany(x => x.Errors).ToList();
                var unexpected = terr.Cast <UnexpectedTokenSyntaxError <IN> >().ToList();
                var expecting  = unexpected.SelectMany(x => x.ExpectedTokens).ToList();
                result.AddExpectings(expecting);
            }

            return(result);
        }
Example #2
0
        public SyntaxParseResult <IN> ParseNonTerminal(IList <Token <IN> > tokens, NonTerminalClause <IN> nonTermClause,
                                                       int currentPosition)
        {
            var startPosition  = currentPosition;
            var endingPosition = 0;
            var nt             = Configuration.NonTerminals[nonTermClause.NonTerminalName];
            var errors         = new List <UnexpectedTokenSyntaxError <IN> >();

            var i = 0;

            var allAcceptableTokens = new List <IN>();

            nt.Rules.ForEach(r =>
            {
                if (r != null && r.PossibleLeadingTokens != null)
                {
                    allAcceptableTokens.AddRange(r.PossibleLeadingTokens);
                }
            });
            allAcceptableTokens = allAcceptableTokens.Distinct().ToList();

            var rules = nt.Rules
                        .Where(r => r.PossibleLeadingTokens.Contains(tokens[startPosition].TokenID) || r.MayBeEmpty)
                        .ToList();

            if (rules.Count == 0)
            {
                errors.Add(new UnexpectedTokenSyntaxError <IN>(tokens[startPosition],
                                                               allAcceptableTokens.ToArray <IN>()));
            }

            var innerRuleErrors             = new List <UnexpectedTokenSyntaxError <IN> >();
            SyntaxParseResult <IN> okResult = null;
            var greaterIndex    = 0;
            var allRulesInError = true;
            var test            = new List <SyntaxParseResult <IN> >();

            while (i < rules.Count)
            {
                var innerrule    = rules[i];
                var innerRuleRes = Parse(tokens, innerrule, startPosition, nonTermClause.NonTerminalName);
                if (!innerRuleRes.IsError && okResult == null ||
                    okResult != null && innerRuleRes.EndingPosition > okResult.EndingPosition)
                {
                    okResult        = innerRuleRes;
                    okResult.Errors = innerRuleRes.Errors;
                    endingPosition  = innerRuleRes.EndingPosition;
                }
                else
                {
                    test.Add(innerRuleRes);
                }

                var other = greaterIndex == 0 && innerRuleRes.EndingPosition == 0;
                if (innerRuleRes.EndingPosition > greaterIndex && innerRuleRes.Errors != null &&
                    !innerRuleRes.Errors.Any() || other)
                {
                    greaterIndex = innerRuleRes.EndingPosition;
                    innerRuleErrors.Clear();
                    innerRuleErrors.AddRange(innerRuleRes.Errors);
                }

                innerRuleErrors.AddRange(innerRuleRes.Errors);
                allRulesInError = allRulesInError && innerRuleRes.IsError;
                i++;
            }

            errors.AddRange(innerRuleErrors);

            var result = new SyntaxParseResult <IN>();

            result.Errors = errors;
            if (okResult != null)
            {
                result.Root           = okResult.Root;
                result.IsError        = false;
                result.EndingPosition = okResult.EndingPosition;
                result.IsEnded        = okResult.IsEnded;

                result.Errors = errors;
            }
            else
            {
                result.IsError        = true;
                result.Errors         = errors;
                greaterIndex          = errors.Count > 0 ? errors.Select(e => e.UnexpectedToken.PositionInTokenFlow).Max() : 0;
                result.EndingPosition = greaterIndex;
                result.AddExpectings(errors.SelectMany(e => e.ExpectedTokens));
            }

            if (test.Any())
            {
                var terr       = test.SelectMany(x => x.Errors).ToList();
                var unexpected = terr.OfType <UnexpectedTokenSyntaxError <IN> >().ToList();
                var expecting  = unexpected.SelectMany(x => x.ExpectedTokens).ToList();
                result.AddExpectings(expecting);
                ;
            }

            return(result);
        }