Esempio n. 1
0
        private static RuleResult WithType(Token t, TokenType type, Action <string> setter)
        {
            if (t.Type != type)
            {
                string msg = $@"Expected a {type}, but got the {t.Type} ""{t.Content}"" instead.";
                return(RuleResult.Failed(t.Position, msg));
            }

            // It was the correct type, so extract its content using the setter.
            setter(t.Content);
            return(RuleResult.GoodSoFar());

            // TODO: Consider adding an overload that returns RuleResult.Complete(), just like Expect.
        }
Esempio n. 2
0
        private IEnumerable <RuleResult> ImplCoroutine(CurrentTokenCallback t)
        {
            while (_shouldKeepLooping(t()))
            {
                _rules.Reset();

                // Keep feeding tokens until one of the rules completes, or
                // until there's an error.
                RuleResult result = RuleResult.GoodSoFar();
                while (result.status == RuleStatus.GoodSoFar)
                {
                    result = _rules.FeedToken(t());

                    if (result.status == RuleStatus.GoodSoFar)
                    {
                        yield return(result);
                    }
                }

                switch (result.status)
                {
                case RuleStatus.Complete:
                    yield return(RuleResult.GoodSoFar());

                    continue;

                case RuleStatus.Failed:
                    IsFinished = true;
                    yield return(result);

                    yield break;

                default:
                    IsFinished = true;
                    yield return(RuleResult.Failed(t().Position, "Unexpected rule result " + result.status));

                    yield break;
                }
            }

            IsFinished = true;
            yield return(RuleResult.Complete(_node));
        }
Esempio n. 3
0
        private static RuleResult SpecificToken(
            Token t,
            TokenType type,
            string content,
            object node = null
            )
        {
            if (t.Type != type || t.Content != content)
            {
                string msg = $@"Expected the {type} ""{content}"", but got the {t.Type} ""{t.Content}"" instead.";
                return(RuleResult.Failed(t.Position, msg));
            }

            // If a node was provided, return a Completed result instead of GoodSoFar
            if (node != null)
            {
                return(RuleResult.Complete(node));
            }

            return(RuleResult.GoodSoFar());
        }
Esempio n. 4
0
        public RuleResult FeedToken(Token t)
        {
            if (!_isInitialized)
            {
                Initialize();
            }

            if (_isFinished)
            {
                throw new Exception("Tried to feed a token to an already-finished MultiRuleParser.");
            }

            if (_remainingRules.Count == 0)
            {
                throw new Exception("Tried to feed a token to an unfinished yet empty MultiRuleParser.");
            }

            // Feed the token to each rule
            var ruleResults = _remainingRules
                              .Select(r => (rule: r, result: r.FeedToken(t)))
                              .ToArray();

            // Eliminate all of the rules that failed
            foreach (var p in ruleResults)
            {
                if (p.result.status == RuleStatus.Failed)
                {
                    _remainingRules.Remove(p.rule);

                    // If that was the last subrule, then the whole
                    // ruleset fails.
                    if (_remainingRules.Count == 0)
                    {
                        return(p.result);
                    }
                }
            }

            // If one of the rules succeeds, crown it the winner.
            // Its result will be returned and its callback will be
            // invoked.
            // If more than one rule succeeds, the first rule added
            // to the list gets priority.
            var completedRules = ruleResults
                                 .Where(p => p.result.status == RuleStatus.Complete);

            if (completedRules.Any())
            {
                _isFinished = true;

                var winner = completedRules.First();
                var node   = winner.result.node;

                _ruleCallbacks[winner.rule](node);
                return(winner.result);
            }

            // None of them succeeded, but not all of them failed.
            // That's the definition of being "good so far".
            return(RuleResult.GoodSoFar());
        }