Пример #1
0
        private PredictionTree GetFollowDPathSet(FiniteAutomataMultiTargetTransitionTable <GrammarVocabulary, Tuple <int, PredictionTreeBranch> > transitionTableResult, GrammarVocabulary transition, Dictionary <PredictionTreeBranch, int[]> epDepthLookup)
        {
            //var minMinDepth = (from deviationPath in transitionTableResult[transition]
            //                   select deviationPath.Item2.MinDepth).Min();
            //minDepth = minMinDepth;
            //epDepthLookup = epDepthLookup.ToDictionary(dps => new PredictionTreeBranch(dps.Key.Skip(minMinDepth).ToList(), dps.Key.Depth - minMinDepth, minDepth: dps.Key.MinDepth - minMinDepth), dps => dps.Value);
            var result = PredictionTree.GetPathSet(transition, epDepthLookup.Keys.ToList(), this, ProductionRuleProjectionType.FollowAmbiguity, PredictionDerivedFrom.LookAhead_FollowPrediction);

            result.SetFollowEpsilonData(provider => epDepthLookup[provider]);
            return(result);
        }
Пример #2
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));
            }
        }
Пример #3
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();
                }
            }
        }
Пример #4
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);
        }
Пример #5
0
        public bool ConstructEpsilonLookAheadProjection(Dictionary <SyntacticalDFAState, PredictionTreeLeaf> fullSeries, Dictionary <IOilexerGrammarProductionRuleEntry, GrammarVocabulary> ruleVocabulary, int cycleDepth)
        {
            if (cycleDepth > 1)
            {
                this.cyclePaths[cycleDepth - 2].Clear();
            }
            var  currentCycle = this.cyclePaths[cycleDepth - 1];
            bool result       = false;
            FiniteAutomataMultiTargetTransitionTable <GrammarVocabulary, PredictionTreeBranch> resultTable = new FiniteAutomataMultiTargetTransitionTable <GrammarVocabulary, PredictionTreeBranch>();
            var previousLeftRecursive = leftRecursionType;

            if (leftRecursionType == ProductionRuleLeftRecursionType.None)
            {
                var temp =
                    (from p in currentCycle
                     where p.Depth == 0
                     select p.GetRecursionType()).Aggregate(PredictionTreeBranch.LeftRecursionAggregateDelegate);
                if (leftRecursionType != (leftRecursionType | temp))
                {
                    leftRecursionType = temp;
                }
            }
            if (previousLeftRecursive != leftRecursionType)
            {
                result = true;
            }

            var transitionalPaths = (from p in currentCycle
                                     from ePath in p.ObtainEpsilonTransitions(fullSeries)
                                     select ePath).ToArray();

            foreach (var transitionalPath in transitionalPaths)
            {
                if (!currentCycle.Contains(transitionalPath))
                {
                    currentCycle.Add(transitionalPath);
                    var leftRecursionChange =
                        (from path in currentCycle
                         select path.GetRecursionType()).Aggregate(PredictionTreeBranch.LeftRecursionAggregateDelegate);
                }
            }
            var leftRecursivePaths =
                (from p in currentCycle
                 where p.Depth == 0
                 let recurType = p.GetRecursionType()
                                 where recurType != ProductionRuleLeftRecursionType.None
                                 select p.GetFirstRecursion()).ToArray();

            foreach (var path in currentCycle)
            {
                /* *
                 * Use a transition table to sort out ambiguities.
                 * */
                foreach (var transition in path.CurrentNode.Veins.DFAOriginState.OutTransitions.Keys)
                {
                    if (leftRecursionType == ProductionRuleLeftRecursionType.None)
                    {
                        //var tokVariant = transition.GetTokenVariant();
                        var tokenVar     = transition.GetTokenVariant();
                        var reducedRules = transition.GetRuleVariant().GetSymbols().Select(k => (IGrammarRuleSymbol)k).Select(k => new { Node = fullSeries.GetRuleNodeFromFullSeries(k.Source), Symbol = k }).Where(k => k.Node.HasBeenReduced).Select(k => k.Symbol);
                        var ruleVar      = new GrammarVocabulary(transition.symbols, reducedRules.ToArray());

                        if (!tokenVar.IsEmpty)
                        {
                            resultTable.Add(tokenVar, new List <PredictionTreeBranch>()
                            {
                                path
                            });
                        }
                        if (!ruleVar.IsEmpty)
                        {
                            resultTable.Add(ruleVar, new List <PredictionTreeBranch>()
                            {
                                path
                            });
                        }
                    }
                    else
                    {
                        var currentSet = new List <PredictionTreeBranch>()
                        {
                            path
                        };
                        //if (this.Rule.Name == "RelationalExp")
                        //{
                        //    if (transition.ToString() == "Identifier")
                        //    {
                        foreach (var lrPath in leftRecursivePaths)
                        {
                            currentSet.Add(lrPath.GetTransitionPath(lrPath, lrPath.Take(lrPath.Depth).ToArray(), path, ruleVocabulary, false, false, false));
                        }
                        //    }
                        //}
                        resultTable.Add(transition, currentSet);
                    }
                }
            }
            int currentCount = this.Count;

            if (currentCount != resultTable.Count)
            {
                result = true;
                if (this.Count > 0)
                {
                    this._Clear();
                }

                foreach (var transition in resultTable.Keys)
                {
                    var pathSet = PredictionTree.GetPathSet(transition, resultTable[transition], this.Leaf, ProductionRuleProjectionType.LookAhead, PredictionDerivedFrom.Lookahead_Epsilon);
                    this._Add(transition, pathSet);
                    pathSet.CheckReductionState(fullSeries, ruleVocabulary);
                    //pathSet.ProcessCommonSymbol(fullSeries, ruleVocabulary);
                }
            }

            return(result);
        }
Пример #6
0
        FollowTransition(
            Dictionary <SyntacticalDFAState, PredictionTreeLeaf> fullSeries,
            GrammarVocabulary transitionKey,
            Dictionary <IOilexerGrammarProductionRuleEntry, GrammarVocabulary> ruleLookup,
            bool usePrevious,
            bool injectIncomingPaths,
            bool includeRootEdges    = false,
            bool isEpsilonTransition = false,
            bool silentlyFail        = false,
            bool isReduction         = false)
        {
            var resultData = from u in FollowTransitionInternal(fullSeries, transitionKey, ruleLookup, usePrevious, isEpsilonTransition, silentlyFail, isReduction)
                             group u.Item2 by u.Item1;
            FiniteAutomataMultiTargetTransitionTable <GrammarVocabulary, PredictionTreeBranch> result = new FiniteAutomataMultiTargetTransitionTable <GrammarVocabulary, PredictionTreeBranch>();

            foreach (var element in resultData)
            {
                if (element.Key.IsEmpty)
                {
                    result.SetAutoSegment(false);
                }
                result.Add(element.Key, element.ToList());
                if (element.Key.IsEmpty)
                {
                    result.SetAutoSegment(true);
                }
            }
            return(result);
        }