private Node ConnectEntry(Node source, Entry entry) { return(entry switch { MatchEntry matchEntry => ConnectMatch(source, matchEntry), StateEntry stateEntry => ConnectState(source, stateEntry, stateEntry.State.Inline || Automata.ForceInlineAll), QuantifierEntry quantifierEntry => ConnectQuantifier(source, quantifierEntry), PredicateEntryBase predicateEntry => ConnectPredicate(source, predicateEntry), ActionEntry actionEntry => ConnectAction(source, actionEntry), EpsilonEntry _ => source, _ => throw new ArgumentOutOfRangeException(nameof(entry)) });
private static void EliminateLeftRecursion(ParserState parserState, List <ParserProduction> productions) { var hasLeftRecursion = false; foreach (var stateProduction in productions) { stateProduction.LeftRecursionClassifier = Classify(stateProduction, parserState); hasLeftRecursion |= IsLeftRecursion(stateProduction.LeftRecursionClassifier); } if (hasLeftRecursion == false) { return; } var count = productions.Count; var recursionState = new ParserState(null, true); var index = 0; foreach (var production in productions) { if (production.LeftRecursionClassifier == LeftRecursionClassifier.Binary || production.LeftRecursionClassifier == LeftRecursionClassifier.Ternary || production.LeftRecursionClassifier == LeftRecursionClassifier.Prefix) { var assoc = production.IsRightAssoc ? 0 : 1; var nextPriority = new PriorityStateEntryContext(count - index + assoc); foreach (var parserStateEntry in production.Entries.Skip(1).OfType <ParserStateEntry>().Where(e => ReferenceEquals(e.State, parserState))) { parserStateEntry.StateEntryContext = nextPriority; } } if (IsLeftRecursion(production.LeftRecursionClassifier) == false) { continue; } production.LeftRecursionEntry = (ParserStateEntry)production.Entries[0]; production.Entries[0] = ShouldPrefixPredicate(production.LeftRecursionClassifier) ? (Entry) new LeftRecursionPredicate(parserState, count - index).Entry : EpsilonEntry.Instance; recursionState.Productions.Add(production); index++; } var quantifierEntry = new QuantifierEntry(new StateEntry(recursionState) { SkipStack = true }, QuantifierKind.ZeroOrMore, QuantifierMode.Greedy); var primaryState = new ParserState(null, true); primaryState.Productions.AddRange(productions.Where(production => IsLeftRecursion(production.LeftRecursionClassifier) == false)); productions.Clear(); productions.Add(new ParserProduction(new Entry[] { new StateEntry(primaryState) { SkipStack = true }, quantifierEntry })); }