예제 #1
0
 public PartialRule(PartialRule rule, int start = 0, int?length = null)
     : this(rule.Rule, start + rule.Start, length ?? (rule.Length - start))
 {
     if (length.HasValue && length.Value > rule.Length)
     {
         throw new ArgumentOutOfRangeException(nameof(length), length, "must be in range of " + nameof(rule));
     }
 }
예제 #2
0
        /// <summary>
        /// Recursively gathers a set of <see cref="Symbol"/> lists which could form the remainder after consuming
        /// a <paramref name="prefixToken"/>
        /// </summary>
        private void GatherPostTokenSuffixes(
            Token prefixToken,
            PartialRule rule,
            ImmutableStack <Symbol> suffix,
            ISet <IReadOnlyList <Symbol> > result)
        {
            if (rule.Symbols.Count == 0)
            {
                if (!suffix.IsEmpty)
                {
                    var nextSuffixSymbol = suffix.Peek();
                    if (nextSuffixSymbol is Token)
                    {
                        if (nextSuffixSymbol == prefixToken)
                        {
                            result.Add(suffix.Skip(1).ToArray());
                        }
                    }
                    else
                    {
                        var newSuffix  = suffix.Pop();
                        var innerRules = this.rules[(NonTerminal)nextSuffixSymbol]
                                         .Where(r => this.firstFollow.NextOf(r).Contains(prefixToken));
                        foreach (var innerRule in innerRules)
                        {
                            this.GatherPostTokenSuffixes(prefixToken, new PartialRule(innerRule), newSuffix, result);
                        }
                    }
                }
                else
                {
                    throw new NotSupportedException("can't remove prefix from empty");
                }
            }
            else if (rule.Symbols[0] is Token)
            {
                if (rule.Symbols[0] == prefixToken)
                {
                    result.Add(rule.Symbols.Skip(1).Concat(suffix).ToArray());
                }

                return;
            }
            else
            {
                // the new suffix adds the rest of the current rule, from back to front
                // to preserve ordering
                var newSuffix = suffix;
                for (var i = rule.Symbols.Count - 1; i > 0; --i)
                {
                    newSuffix = newSuffix.Push(rule.Symbols[i]);
                }

                var innerRules = this.rules[(NonTerminal)rule.Symbols[0]]
                                 .Where(r => this.firstFollow.NextOf(r).Contains(prefixToken));
                foreach (var innerRule in innerRules)
                {
                    this.GatherPostTokenSuffixes(prefixToken, new PartialRule(innerRule), newSuffix, result);
                }
            }
        }
예제 #3
0
        // to support initial prefix, we'll just add the ability to pass a null rule plus a suffix stack
        private ISet <IReadOnlyList <Symbol> > GatherPostTokenSuffixes(Token prefixToken, PartialRule rule)
        {
            var result = new HashSet <IReadOnlyList <Symbol> >();

            this.GatherPostTokenSuffixes(prefixToken, rule, ImmutableStack <Symbol> .Empty, result);
            return(result);
        }
예제 #4
0
 public ParseRuleNode(PartialRule rule)
 {
     this.Rule = rule;
 }
예제 #5
0
        public static IImmutableSet <Token> NextOf(this IFirstFollowProvider provider, PartialRule partialRule)
        {
            var firsts = provider.FirstOf(partialRule.Symbols);

            return(firsts.ContainsDefault()
                ? firsts.RemoveDefault().Union(provider.FollowOf(partialRule.Rule))
                : firsts);
        }