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)); } }
/// <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); } } }
// 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); }
public ParseRuleNode(PartialRule rule) { this.Rule = rule; }
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); }