Ejemplo n.º 1
0
 protected internal PredictionTreeBranch(IList <PredictionTreeLeaf> baseList, int depth = 0, bool chop = false, bool passAlong = true, short[] deviations = null, int[] epsilonState = null, int minDepth = 0)
     : base(baseList)
 {
     this.epsilonDerivations = epsilonState ?? new int[(baseList.Count + (sizeof(SlotType) - 1)) / sizeof(SlotType)];
     this.MinDepth           = minDepth;
     this.Depth = depth;
     this.SetDeviations(deviations ?? new short[0]);
     if (passAlong)
     {
         if (!chop && depth > 0)
         {
             if (depth == this.Count - 1)
             {
                 baseList[depth].AddPath(this);
             }
             else
             {
                 var addedPath = new PredictionTreeBranch(this.Take(depth + 1).ToList(), depth, true, false);
                 addedPath.SetDeviations(this.deviations);
                 baseList[depth].AddPath(addedPath);
             }
         }
     }
     this.Validate();
 }
Ejemplo n.º 2
0
        private bool IsSafeToExpand(PredictionTreeBranch nPath)
        {
            Dictionary <IOilexerGrammarProductionRuleEntry, int> counts = new Dictionary <IOilexerGrammarProductionRuleEntry, int>();

            //var currentRoot = nPath.CurrentNode.RootLeaf;
            //int currentCount = 1;
            for (int i = nPath.Depth - 1; i >= 0; i--)
            {
                var currentNode = nPath[i];
                if (currentNode.RootLeaf != currentNode)
                {
                    return(true);
                }
                if (counts.ContainsKey(currentNode.Rule))
                {
                    var value = ++counts[currentNode.Rule];
                    if (value > 2)
                    {
                        return(false);
                    }
                }
                else
                {
                    counts[currentNode.Rule] = 1;
                }

                //if (currentNode.RootLeaf == currentRoot)
                //    currentCount++;
            }
            return(true);
            //return currentCount <= 2;
        }
Ejemplo n.º 3
0
 public bool Equals(PredictionTreeBranch other)
 {
     if (other == null)
     {
         return(false);
     }
     if (other.Depth != this.Depth || other.MinDepth != this.MinDepth)
     {
         return(false);
     }
     if (this.CurrentNode != other.CurrentNode)
     {
         return(false);
     }
     if (this.Count != other.Count)
     {
         return(false);
     }
     for (int i = 0; i < this.Count; i++)
     {
         if (this[i] != other[i])
         {
             return(false);
         }
     }
     return(true);
 }
Ejemplo n.º 4
0
 public TransitionRequest(GrammarVocabulary transition, PredictionTreeBranch path, bool usePrevious, bool isReduction)
 {
     this.path = path;
     this.transitionRequirement = transition;
     this.usePrevious           = usePrevious;
     this.isReduction           = isReduction;
 }
Ejemplo n.º 5
0
        private PredictionTreeBranch GetEpsilonTransitionPath(PredictionTreeBranch path)
        {
            short[] deviations = this.GetDeviationsUpTo(this.Depth);//IncrementDeviations(this.Depth, false);
            var     result     = new PredictionTreeBranch(this.Take(this.Depth).Concat(path).ToArray(), this.Depth, passAlong: false, deviations: deviations, epsilonState: this.epsilonDerivations.ToList().ToArray());

            result.SetEpsilonDerived(result.Depth);
            return(result);
        }
Ejemplo n.º 6
0
        internal PredictionTreeBranch GetTransitionPath(PredictionTreeBranch targetPath, PredictionTreeLeaf[] previousNodes, PredictionTreeLeaf currentNode, Dictionary <IOilexerGrammarProductionRuleEntry, GrammarVocabulary> ruleLookup, bool usePrevious, bool isEpsilonTransition = false, bool incrementDeviations = true)
        {
            if (previousNodes.Length > 0)
            {
                Debug.Assert(previousNodes[previousNodes.Length - 1].Veins.DFAOriginState.OutTransitions.Keys.Any(k => !k.Intersect(ruleLookup[currentNode.Rule]).IsEmpty));
            }
            short[] deviations = incrementDeviations ? IncrementDeviations(previousNodes.Length, isEpsilonTransition) : this.GetDeviationsUpTo(previousNodes.Length);

            var result = new PredictionTreeBranch(previousNodes.Concat(new[] { currentNode }).ToArray(), targetPath.Depth, passAlong: false, deviations: deviations);

            result.MinDepth = targetPath.MinDepth;
            return(result);
        }
Ejemplo n.º 7
0
        private static IEnumerable <PredictionTreeBranch> PushIntersection(
            PredictionTreeBranch sourceMasterPath,
            FiniteAutomataMultiTargetTransitionTable <GrammarVocabulary, Tuple <int, PredictionTreeBranch> > transitionTableResult,
            Stack <Tuple <int, PredictionTreeBranch> > toProcess,
            HashSet <PredictionTreeBranch> seen,
            Tuple <int, PredictionTreeBranch> currentPathTuple,
            PredictionTreeBranch currentPath,
            PredictionTreeBranch path,
            GrammarVocabulary intersection,
            GrammarVocabulary transitionKey = null)
        {
            /* * * * * * * * * * * * * * * * * * * * * * * * * *\
             * Construct the transition table with the matching *
             * paths.                                           *
             * * * * * * * * * * * * * * * * * * * * * * * * * */
            var intersectingCurrent = from key in currentPath.CurrentNode.Veins.Keys
                                      let intersect = key.Intersect(intersection)
                                                      where !intersect.IsEmpty
                                                      let subPathSet = currentPath.CurrentNode.Veins[key]
                                                                       from subPath in subPathSet.UnalteredOriginals
                                                                       let rPath = new PredictionTreeBranch(sourceMasterPath.Take(currentPath.Depth).Concat(subPath).ToList(), currentPath.Depth + subPath.Depth, true, false, currentPath.GetDeviationsUpTo(currentPath.Depth), minDepth: currentPath.Depth)
                                                                                   where rPath.Valid
                                                                                   select rPath;
            var set = new List <Tuple <int, PredictionTreeBranch> >(from ip in intersectingCurrent
                                                                    select Tuple.Create(currentPathTuple.Item1, ip))
            {
                Tuple.Create(currentPathTuple.Item1 + 1, new PredictionTreeBranch(path.baseList, path.Depth, false, false, minDepth: path.Depth))
            };
            var distinctNodeArray = (from element in set
                                     select element.Item2).Distinct().ToArray();

            foreach (var element in distinctNodeArray)
            {
                yield return(element);
            }
            transitionTableResult.Add(transitionKey ?? intersection, set);

            /* * * * * * * * * * * * * * * * * * * * * * * * * * * *\
             * If the current point is an edge, walk further        *
             * up the parse tree to see what else lies in store.    *
             * * * * * * * * * * * * * * * * * * * * * * * * * * * **
             * Further ambiguities might result in additional look- *
             * ahead being necessary.                               *
             * * * * * * * * * * * * * * * * * * * * * * * * * * * */
            if (seen.Add(path) && path.CurrentNode.Veins.DFAOriginState.IsEdge)
            {
                toProcess.Push(Tuple.Create(currentPathTuple.Item1 + 1, path));
            }
        }
Ejemplo n.º 8
0
 /// <summary>
 /// Returns the <see cref="PredictionTreeBranch"/> which is
 /// one level above.
 /// </summary>
 /// <returns>A <see cref="PredictionTreeBranch"/> instance
 /// which represents a single level above
 /// the path chain.</returns>
 /// <remarks><seealso cref="Depth"/>.</remarks>
 /// <exception cref="System.InvalidOperationException">thrown when
 /// <see cref="Depth"/> is equal to <see cref="MinDepth"/>.</exception>
 public PredictionTreeBranch DecreaseDepth(bool passAlong = true)
 {
     if (this.Depth <= MinDepth)
     {
         throw new InvalidOperationException();
     }
     if (this.previous == null)
     {
         this.previous = new PredictionTreeBranch(this.baseList, this.Depth - 1, passAlong: passAlong, deviations: this.deviations, epsilonState: this.epsilonDerivations)
         {
             next = this
         }
     }
     ;
     return(this.previous);
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Returns the <see cref="PredictionTreeBranch"/> which is
 /// one level deeper.
 /// </summary>
 /// <returns>A <see cref="PredictionTreeBranch"/> instance
 /// which represents a single level deeper within
 /// the path chain.</returns>
 /// <remarks><seealso cref="Depth"/>.</remarks>
 /// <exception cref="System.InvalidOperationException">thrown when
 /// <see cref="Depth"/> is equal to <see cref="IControlledCollection{T}.Count"/> - 1.</exception>
 public PredictionTreeBranch IncreaseDepth(bool passAlong = true)
 {
     if (Depth >= Count - 1)
     {
         throw new InvalidOperationException();
     }
     if (this.next == null)
     {
         this.next = new PredictionTreeBranch(this.baseList, this.Depth + 1, passAlong: passAlong, deviations: this.deviations, epsilonState: this.epsilonDerivations)
         {
             previous = this
         }
     }
     ;
     return(this.next);
 }
Ejemplo n.º 10
0
        private void ObtainTerminalAmbiguitiesOnPath(
            PredictionTreeBranch sourceMasterPath,
            Dictionary <SyntacticalDFAState, PredictionTreeLeaf> fullSeries,
            ControlledDictionary <IOilexerGrammarProductionRuleEntry, SyntacticalDFARootState> ruleDFAs,
            Dictionary <IOilexerGrammarProductionRuleEntry, GrammarVocabulary> ruleLookup,
            FiniteAutomataMultiTargetTransitionTable <GrammarVocabulary, Tuple <int, PredictionTreeBranch> > transitionTableResult,
            GrammarSymbolSet grammarSymbols)
        {
            var ambiguousSymbols = grammarSymbols.AmbiguousSymbols.ToList();
            Stack <Tuple <int, PredictionTreeBranch> > toProcess = new Stack <Tuple <int, PredictionTreeBranch> >();
            var fullCheck = this.Veins.Keys.Aggregate(GrammarVocabulary.UnionAggregateDelegate);

            /* * * * * * * * * * * * * * * * * * * * * * * * * *  * *\
             * Kick things off with the master path, this is derived *
             * from the incoming states from the parent rule.        *
             * * * * * * * * * * * * * * * * * * * * * * * * * *  * */
            toProcess.Push(Tuple.Create(0, sourceMasterPath));
            //foreach (var transition in this.Value.Keys)
            //    foreach (var target in this.Value[transition])
            //        toProcess.Push(new PredictionTreeBranch(sourceMasterPath.Take(sourceMasterPath.Depth).Concat(target).ToList(), sourceMasterPath.Depth, true, false, sourceMasterPath.GetDeviationsUpTo(sourceMasterPath.Depth)));
            HashSet <PredictionTreeBranch> seen = new HashSet <PredictionTreeBranch>();

            while (toProcess.Count > 0)
            {
                var currentPathTuple = toProcess.Pop();
                var currentPath      = currentPathTuple.Item2;
                if (currentPath.Depth == 0)
                {
                    continue;
                }
                if (currentPath.CurrentNode.Veins.Keys.Aggregate(GrammarVocabulary.UnionAggregateDelegate).Intersect(fullCheck).IsEmpty)
                {
                    continue;
                }

                /* *
                 * Walk up the tree one level into the state that
                 * follows the current rule in whatever the current
                 * calling rule might be.
                 * */
                var incomingTransitions = currentPath.FollowTransition(fullSeries, ruleLookup[currentPath.CurrentNode.Veins.Rule], ruleLookup, true, false, true, true);

                /* *
                 * Aggregate the transitions from our previously
                 * calculated LL(1) look-ahead information.
                 * */
                /* *
                 * On the state following this rule, gather up the
                 * targets which do overlap one or more of our
                 * transitions.
                 * */
                var fullAmbiguityContext = incomingTransitions.FullCheck | fullCheck;

                var intersectionPoints = (from t in incomingTransitions.Keys
                                          let intersection = t.Intersect(fullCheck)
                                                             where !intersection.IsEmpty
                                                             from path in incomingTransitions[t]
                                                             select new { Intersection = intersection, Path = path }).ToArray();
                var overlap = GrammarVocabulary.NullInst;
                if ((fullAmbiguityContext != null && !fullAmbiguityContext.IsEmpty) && grammarSymbols.IsGrammarPotentiallyAmbiguous(fullAmbiguityContext))
                {
                    foreach (var ambiguity in ambiguousSymbols)
                    {
                        var localIntersect    = fullCheck & ambiguity.AmbiguityKey;
                        var incomingIntersect = incomingTransitions.FullCheck & ambiguity.AmbiguityKey;
                        if (localIntersect.IsEmpty || incomingIntersect.IsEmpty)
                        {
                            /* If the intersection isn't present on one or the other sides; then, for the purposes of
                             * this follow check, the union would not be relevant, it would likely be identified within the
                             * prediction upon the state itself. */
                            continue;
                        }
                        var aggregateIntersect = fullAmbiguityContext & ambiguity.AmbiguityKey;
                        var overlapIntersect   = overlap & ambiguity.AmbiguityKey;
                        if (aggregateIntersect.Equals(ambiguity.AmbiguityKey) && !overlapIntersect.Equals(ambiguity.AmbiguityKey))
                        {
                            /*  */
                            var ambiguityIntersection =
                                (from t in incomingTransitions.Keys
                                 let intersection = t.Intersect(incomingIntersect)
                                                    where !intersection.IsEmpty
                                                    from path in incomingTransitions[t]
                                                    select new { Intersection = intersection, Path = path }).ToArray();
                            var ambiguityVocabulary = new GrammarVocabulary(grammarSymbols, ambiguity);
                            foreach (var intersectingPoint in ambiguityIntersection)
                            {
                                var path         = intersectingPoint.Path;
                                var intersection = localIntersect;
                                if (path.Equals(currentPath))
                                {
                                    continue;
                                }

                                /* Notify the nodes of the ambiguities so their state-machines can be patched up.
                                 * This is done explicitly to avoid the ambiguity cropping up and allowing it everywhere,
                                 * which is incorrect. If it shows up where it's not supposed to, we have a logic error
                                 * somwehere. */
                                foreach (var node in (from ambigPath in PushIntersection(sourceMasterPath, transitionTableResult, toProcess, seen, currentPathTuple, currentPath, path, intersection, ambiguityVocabulary)
                                                      select ambigPath.CurrentNode).Distinct().ToArray())
                                {
                                    node.DenoteLexicalAmbiguity(ambiguity);
                                }
                            }
                            ambiguity.Occurrences++;
                            overlap |= aggregateIntersect;
                        }
                    }
                }
                foreach (var intersectingPoint in intersectionPoints)
                {
                    var path         = intersectingPoint.Path;
                    var intersection = intersectingPoint.Intersection;
                    if (path.Equals(currentPath))
                    {
                        continue;
                    }
                    PushIntersection(sourceMasterPath, transitionTableResult, toProcess, seen, currentPathTuple, currentPath, path, intersection).ToArray();
                }
            }
        }
Ejemplo n.º 11
0
        internal MultikeyedDictionary <GrammarVocabulary, int, List <Tuple <Tuple <int[], PredictionTree>[], int[]> > > ObtainTerminalAmbiguities(
            Dictionary <SyntacticalDFAState, PredictionTreeLeaf> fullSeries,
            ControlledDictionary <IOilexerGrammarProductionRuleEntry, SyntacticalDFARootState> ruleDFAs,
            Dictionary <IOilexerGrammarProductionRuleEntry, GrammarVocabulary> ruleLookup,
            GrammarSymbolSet grammarSymbols)
        {
            if (!this.Veins.DFAOriginState.IsEdge)
            {
                return(new MultikeyedDictionary <GrammarVocabulary, int, List <Tuple <Tuple <int[], PredictionTree>[], int[]> > >());
            }
            var tempDictionary  = new MultikeyedDictionary <PredictionTreeBranch, GrammarVocabulary, Tuple <int[], PredictionTree> >();
            var rootNode        = fullSeries[ruleDFAs[this.Rule]];
            var currentIncoming = new List <PredictionTreeBranch>(rootNode.incoming);
            var reductions      = rootNode.PointsOfReduction.ToArray();

            if (reductions.Length > 0)
            {
            }
            var totalIncoming = new HashSet <PredictionTreeBranch>();
            Dictionary <PredictionTree, PredictionTree> uniqueSet = new Dictionary <PredictionTree, PredictionTree>();

            foreach (var path in currentIncoming)
            {
                var transitionTableResult = new FiniteAutomataMultiTargetTransitionTable <GrammarVocabulary, Tuple <int, PredictionTreeBranch> >();
                var masterPathChop        = new PredictionTreeBranch(path.Take(path.Depth).Concat(new[] { this }).ToArray(), path.Depth, false, false);

                masterPathChop.SetDeviations(path.GetDeviationsUpTo(path.Depth));
                ObtainTerminalAmbiguitiesOnPath(masterPathChop, fullSeries, ruleDFAs, ruleLookup, transitionTableResult, grammarSymbols);

                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
                 * Construct the sequence of Path->Grammar->PathSets based           *
                 * off of the table provided by the ObtainTerminalAmbiguitiesOnPath. *
                 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * **/
                foreach (var transition in transitionTableResult.Keys)
                {
                    var epDepthLookup =
                        (from entry in transitionTableResult[transition]
                         group entry.Item1 by entry.Item2).ToDictionary(k => k.Key, v => v.ToArray());
                    //int minDepth;
                    //var uniqueCurrent = GetUniqueDPathSet(uniqueSet, transitionTableResult, transition, epDepthLookup);
                    //var subPath = new PredictionTreeBranch(path.Skip(minDepth).ToList(), path.Depth - minDepth, minDepth: path.MinDepth);
                    tempDictionary.TryAdd(path, transition, Tuple.Create((from epDepth in transitionTableResult[transition]
                                                                          select epDepth.Item1).ToArray(), GetFollowDPathSet(transitionTableResult, transition, epDepthLookup)));
                }
            }



            var regrouping = (from ksvp in tempDictionary
                              group new { Path = ksvp.Keys.Key1, Set = ksvp.Value } by ksvp.Keys.Key2).ToDictionary(k => k.Key, v => v.ToArray());

            /*
             * foreach (var pathSet in from key in regrouping.Keys
             *                      let value = regrouping[key]
             *                      from r in value
             *                      select r.Set)
             *  pathSet.Item2.FixAllPaths();//*/

            var comparisons = (from key in regrouping.Keys
                               let value = regrouping[key]
                                           let kRewrite = from r in value
                                                          select r.Set
                                                          let commonalities = PredictionTree.GetCompoundRightSideSimilarities(kRewrite)
                                                                              select new { Commonalities = commonalities, Transition = key }).ToDictionary(k => k.Transition, v => v.Commonalities);
            var resultDictionary = new MultikeyedDictionary <GrammarVocabulary, int, List <Tuple <Tuple <int[], PredictionTree>[], int[]> > >();

            /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
             * Once we're done, we need to rebuild the paths with the MinDepth set to  *
             * their current Depth.  This is to ensure that it the PathSets don't try  *
             * to reduce more than necessary.                                          *
             * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
             * Then we take that set and perform a right-hand-side comparison between  *
             * the elements.                                                           *
             * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
             * This will be used later to reduce the walking necessary to isolate the  *
             * proper machine to use to disambiguate the look-ahead.                   *
             \ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * **/
            foreach (var comparison in comparisons.Keys)
            {
                var comparisonElements = comparisons[comparison];
                foreach (var memberCount in comparisonElements.Keys)
                {
                    var comparisonElement = comparisonElements[memberCount];
                    resultDictionary.Add(comparison, memberCount, comparisonElement);
                }
            }
            return(resultDictionary);
        }
Ejemplo n.º 12
0
 internal void AddPath(PredictionTreeBranch path)
 {
     lock (incoming)
         incoming.Add(path);
 }
Ejemplo n.º 13
0
        private static TransitionRequest PushTransitionRequest(GrammarVocabulary transition, PredictionTreeBranch path, bool usePrevious, bool isReduction)
        {
            var fKey = Tuple.Create(usePrevious, isReduction);

            lock (transitionRequests)
            {
                List <TransitionRequest> resultSet;
                if (!transitionRequests.TryGetValue(fKey, transition, path, out resultSet))
                {
                    transitionRequests.Add(fKey, transition, path, resultSet = new List <TransitionRequest>());
                }
                lock (resultSet)
                {
                    TransitionRequest result = resultSet.FirstOrDefault(p => p.DeviationDetail.SequenceEqual(path.deviations));
                    if (result == null)
                    {
                        resultSet.Add(result = new TransitionRequest(transition, path, usePrevious, isReduction));
                    }
                    return(result);
                }
            }
        }
Ejemplo n.º 14
0
        private static TransitionRequest GetTransitionRequest(GrammarVocabulary transition, PredictionTreeBranch path, bool usePrevious, bool isReduction)
        {
            List <TransitionRequest> result;
            var fKey = Tuple.Create(usePrevious, isReduction);

            lock (transitionRequests)
                if (transitionRequests.TryGetValue(fKey, transition, path, out result))
                {
                    lock (result)
                        return(result.FirstOrDefault(p => p.DeviationDetail.SequenceEqual(path.deviations)));
                }
            return(null);
        }
Ejemplo n.º 15
0
 private void HandleLeftRecursiveInjection(Dictionary <SyntacticalDFAState, PredictionTreeLeaf> fullSeries, Dictionary <IOilexerGrammarProductionRuleEntry, GrammarVocabulary> ruleLookup, bool usePrevious, bool isEpsilonTransition, bool silentlyFail, List <Tuple <GrammarVocabulary, PredictionTreeBranch> > result, PredictionTreeBranch targetPath, PredictionTreeLeaf targetNodeOfTransition, PredictionTreeLeaf[] previousNodes)
 {
     if (targetNodeOfTransition.RootLeaf.Veins.LeftRecursionType != ProductionRuleLeftRecursionType.None && targetNodeOfTransition.RootLeaf.Veins.LeftRecursionType != ProductionRuleLeftRecursionType.Direct /* && !isReduction*/)
     {
         var sPaths          = targetNodeOfTransition.RootLeaf.IncomingPaths.Where(k => k.Depth > 0 && k.CurrentNode == targetNodeOfTransition.RootLeaf && k.MinDepth == targetPath.MinDepth && k[0] == targetNodeOfTransition.RootLeaf).ToArray();
         var transitionPaths =
             (from p in sPaths
              let nPath = GetTransitionPath(targetPath, previousNodes, p, ruleLookup, usePrevious, isEpsilonTransition, false)
                          where IsSafeToExpand(nPath)
                          select nPath).ToArray();
         foreach (var nPath in transitionPaths)
         {
             result.AddRange(nPath.FollowTransitionInternal(fullSeries, ruleLookup[targetNodeOfTransition.Rule], ruleLookup, true, isEpsilonTransition: isEpsilonTransition, silentlyFail: silentlyFail));
         }
     }
 }
Ejemplo n.º 16
0
        FollowTransitionInternal(
            Dictionary <SyntacticalDFAState, PredictionTreeLeaf> fullSeries,
            GrammarVocabulary transitionKey,
            Dictionary <IOilexerGrammarProductionRuleEntry, GrammarVocabulary> ruleLookup,
            bool usePrevious,
            bool isEpsilonTransition = false,
            bool silentlyFail        = false,
            bool isReduction         = false)
        {
            if (transitionKey.IsEmpty)
            {
                return(new Tuple <GrammarVocabulary, PredictionTreeBranch> [0]);
            }


            List <Tuple <GrammarVocabulary, PredictionTreeBranch> > result = new List <Tuple <GrammarVocabulary, PredictionTreeBranch> >();

            /* *
             * The transition was broken up earlier to yield
             * subsets that overlapped on a portion of the
             * transition.
             * */
            var ambiguityVocabulary = transitionKey.DisambiguateVocabulary();

            short[] deviationsToPass = this.deviations;
            if (isReduction)
            {
                deviationsToPass = this.IncrementDeviations(this.Depth, false);
            }
            var targetPath = usePrevious ? this.Depth == this.MinDepth && this.Depth > 0 ? new PredictionTreeBranch(this.baseList, this.Depth - 1, false, false, deviationsToPass, this.epsilonDerivations, this.MinDepth - 1) : this.DecreaseDepth(false) : this;

            if (isReduction)
            {
                targetPath = new PredictionTreeBranch(targetPath.baseList, targetPath.Depth, false, false, deviationsToPass, this.epsilonDerivations, targetPath.MinDepth);
            }
            var fullTransitionKey = targetPath.CurrentNode.Veins.DFAOriginState.OutTransitions.Keys.FirstOrDefault(v => !v.Intersect(transitionKey.DisambiguateVocabulary()).IsEmpty);
            var cachedRequest     = GetTransitionRequest(transitionKey, targetPath, usePrevious, isReduction);

            if (cachedRequest != null)
            {
                return(cachedRequest.Detail);
            }
            if (fullTransitionKey == null && !silentlyFail)
            {
                Debug.Assert(fullTransitionKey != null);
            }
            else if (fullTransitionKey == null && silentlyFail)
            {
                return(result);
            }
            var targetOfTransition = targetPath.CurrentNode.Veins.DFAOriginState.OutTransitions[fullTransitionKey];

            var targetNodeOfTransition = fullSeries[targetOfTransition];

            PredictionTreeLeaf[] previousNodes = null;
            if (targetPath.Depth > 0)
            {
                previousNodes = targetPath.Take(targetPath.Depth).ToArray();
            }
            else
            {
                previousNodes = new PredictionTreeLeaf[0];
            }
            if (targetNodeOfTransition.Veins.Keys.Count > 0)
            {
                foreach (var key in targetNodeOfTransition.Veins.Keys)
                {
                    var tokenVar     = key.GetTokenVariant();
                    var originalSet  = key.GetRuleVariant().GetSymbols().Select(k => (IGrammarRuleSymbol)k).Select(k => new { Node = fullSeries.GetRuleNodeFromFullSeries(k.Source), Symbol = k }).Where(k => k.Node.HasBeenReduced).ToArray();
                    var reducedRules = originalSet.Where(k => NodeIsRelevantToThis(k.Node, targetNodeOfTransition)).Select(k => k.Symbol).ToArray();
                    var ruleVar      = new GrammarVocabulary(key.symbols, reducedRules);
                    foreach (var path in targetNodeOfTransition.Veins[key].UnalteredOriginals)
                    {
                        var currentSubPath = path;

                        /* *
                         * The transition is derived from the parent node's transitions because the current node is omittable.
                         * */
                        while (!currentSubPath.CurrentNode.Veins.Keys.Any(k => !k.Intersect(key).IsEmpty) && currentSubPath.Depth > 0)
                        {
                            currentSubPath = currentSubPath.DecreaseDepth(false);
                        }
                        if (!tokenVar.IsEmpty)
                        {
                            result.Add(Tuple.Create(tokenVar, GetTransitionPath(targetPath, previousNodes, currentSubPath, ruleLookup, usePrevious, isEpsilonTransition)));
                        }
                        if (!ruleVar.IsEmpty)
                        {
                            result.Add(Tuple.Create(ruleVar, GetTransitionPath(targetPath, previousNodes, currentSubPath, ruleLookup, usePrevious, isEpsilonTransition)));
                        }
                    }
                }
                if (targetOfTransition.IsEdge)
                {
                    HandleLeftRecursiveInjection(fullSeries, ruleLookup, usePrevious, isEpsilonTransition, silentlyFail, result, targetPath, targetNodeOfTransition, previousNodes);
                    var result2 = result.ToArray().ToList();
                    if (previousNodes.Length > 0)
                    {
                        result.AddRange(GetTransitionPath(targetPath, previousNodes, targetNodeOfTransition, ruleLookup, usePrevious, isEpsilonTransition, false).FollowTransitionInternal(fullSeries, ruleLookup[targetNodeOfTransition.Veins.Rule], ruleLookup, true, isEpsilonTransition: isEpsilonTransition));
                    }
                    else
                    {
                        result.Add(Tuple.Create(GrammarVocabulary.NullInst, new PredictionTreeBranch(new[] { targetNodeOfTransition }, passAlong: false)));
                    }
                }
            }
            else if (targetOfTransition.IsEdge && previousNodes.Length > 0)
            {
                HandleLeftRecursiveInjection(fullSeries, ruleLookup, usePrevious, isEpsilonTransition, silentlyFail, result, targetPath, targetNodeOfTransition, previousNodes);
                result.AddRange(targetPath.FollowTransitionInternal(fullSeries, ruleLookup[targetNodeOfTransition.Veins.Rule], ruleLookup, true, isEpsilonTransition: isEpsilonTransition));
            }
            else if (targetOfTransition.IsEdge && previousNodes.Length == 0 /* && includeRootEdges*/)
            {
                result.Add(Tuple.Create(GrammarVocabulary.NullInst, new PredictionTreeBranch(new[] { targetNodeOfTransition }, passAlong: false)));
            }
            var transitionDetail = PushTransitionRequest(transitionKey, targetPath, usePrevious, isReduction);

            if (transitionDetail.Detail == null)
            {
                transitionDetail.Detail = result;
            }
            return(result);
        }