コード例 #1
0
 protected LNode GetPredictionSubtreeCode(PredictionBranch branch, Pair <LNode, string>[] matchingCode, ref Symbol haveLoop)
 {
     if (branch.Sub.Tree != null)
     {
         return(GeneratePredictionTreeCode(branch.Sub.Tree, matchingCode, ref haveLoop));
     }
     else
     {
         Debug.Assert(branch.Sub.Alt != ErrorAlt);
         if (branch.Sub.Alt == ExitAlt)
         {
             return(GetExitStmt(haveLoop));
         }
         else
         {
             var code = matchingCode[branch.Sub.Alt].A;
             if (code.Calls(S.Braces, 1))
             {
                 return(code.Args[0].Clone());
             }
             else
             {
                 return(code.Clone());
             }
         }
     }
 }
コード例 #2
0
 /// <summary>Recursively merges adjacent duplicate cases in prediction trees.
 /// The tree is modified in-place, but in case a tree collapses to a single
 /// alternative, the return value indicates which single alternative.</summary>
 private PredictionTreeOrAlt SimplifyPredictionTree(PredictionTree tree)
 {
     for (int i = 0; i < tree.Children.Count; i++)
     {
         PredictionBranch pb = tree.Children[i];
         if (pb.Sub.Tree != null)
         {
             pb.Sub = SimplifyPredictionTree(pb.Sub.Tree);
         }
     }
     for (int i = tree.Children.Count - 1; i > 0; i--)
     {
         PredictionBranch a = tree.Children[i - 1], b = tree.Children[i];
         if (a.Sub.Equals(b.Sub))
         {
             // Merge a and b
             if (a.Set != null)
             {
                 a.Set = a.Set.Union(b.Set);
             }
             a.CombineAndPredsWith(b.AndPreds);
             tree.Children.RemoveAt(i);
         }
     }
     if (tree.Children.Count == 1)
     {
         return(tree.Children[0].Sub);
     }
     return(tree);
 }
コード例 #3
0
            private PredictionTreeOrAlt ComputeAssertionTree2(List <KthSet> alts, Set <AndPred> matched)
            {
                int            lookahead = alts[0].LA;
                var            children  = InternalList <PredictionBranch> .Empty;
                MSet <AndPred> falsified = new MSet <AndPred>();
                // Each KthSet represents a branch of the Alts for which we are
                // generating a prediction tree; so if we find an and-predicate
                // that, by failing, will exclude one or more KthSets, that's
                // probably the fastest way to get closer to completing the tree.
                // Any predicate in KthSet.AndReq (that isn't in matched) satisfies
                // this condition.
                var bestAndPreds = alts.SelectMany(alt => alt.AndReq).Where(ap => !matched.Contains(ap)).ToList();
                var altsLeft     = alts.Select(alt => alt.Clone(true)).ToList();

                foreach (AndPred andPred in bestAndPreds)
                {
                    AutoAddBranchForAndPred(ref children, andPred, altsLeft, matched, falsified);
                    if (altsLeft.Count == 0)
                    {
                        break;
                    }
                }
                // Testing any single AndPred will not exclude any KthSets, so
                // we'll proceed the slow way: pick any unmatched AndPred and test
                // it. If it fails then the Transition(s) associated with it can be
                // excluded.
                List <AndPred> predsLeft =
                    altsLeft.SelectMany(alt => alt.Cases)
                    .SelectMany(t => t.AndPreds)
                    .Where(ap => !matched.Contains(ap))
                    .Distinct().ToList();

                foreach (var andPred in predsLeft)
                {
                    AutoAddBranchForAndPred(ref children, andPred, altsLeft, matched, falsified);
                    if (altsLeft.Count == 0)
                    {
                        break;
                    }
                }

                if (children.Count == 0)
                {
                    // If no AndPreds were tested, proceed to the next level of prediction.
                    Debug.Assert(falsified.Count == 0);
                    return(ComputeNestedPredictionTree(altsLeft));
                }

                // If there are any "unguarded" cases left after falsifying all
                // the AndPreds, add a branch for them.
                Debug.Assert(falsified.Count > 0);
                if (altsLeft.Count > 0)
                {
                    var final = new PredictionBranch(new Set <AndPred>(), ComputeNestedPredictionTree(altsLeft));
                    children.Add(final);
                }
                return(new PredictionTree(lookahead, children, null));
            }
コード例 #4
0
 private void AutoAddBranchForAndPred(ref InternalList <PredictionBranch> children, AndPred andPred, List <KthSet> alts, Set <AndPred> matched, MSet <AndPred> falsified)
 {
     if (!falsified.Contains(andPred))
     {
         var innerMatched = matched.With(andPred);
         var result       = new PredictionBranch(new Set <AndPred>().With(andPred),
                                                 ComputeAssertionTree2(alts, innerMatched));
         falsified.Add(andPred);
         RemoveFalsifiedCases(alts, falsified);
         children.Add(result);
     }
 }
コード例 #5
0
			protected LNode GetPredictionSubtreeCode(PredictionBranch branch, Pair<LNode, string>[] matchingCode, ref Symbol haveLoop)
			{
				if (branch.Sub.Tree != null)
					return GeneratePredictionTreeCode(branch.Sub.Tree, matchingCode, ref haveLoop);
				else {
					Debug.Assert(branch.Sub.Alt != ErrorAlt);
					if (branch.Sub.Alt == ExitAlt) {
						return GetExitStmt(haveLoop);
					} else {
						var code = matchingCode[branch.Sub.Alt].A;
						if (code.Calls(S.Braces, 1))
							return code.Args[0].Clone();
						else
							return code.Clone();
					}
				}
			}
コード例 #6
0
            void ScanTree(PredictionTree tree, Alts alts, DList <Prematched> path)
            {
                int oldCount = path.Count;

                while (path.Count <= tree.Lookahead)
                {
                    path.Add(new Prematched {
                        Terminals = Anything
                    });
                }
                Prematched pm = path.Last;

                if (tree.IsAssertionLevel)
                {
                    foreach (PredictionBranch b in tree.Children)
                    {
                        var old      = pm.AndPreds.Clone();
                        var verified = Enumerable.Aggregate(b.AndPreds, (set1, set2) => (set1.Union(set2)));                         // usually empty if more than one
                        pm.AndPreds.UnionWith(verified);

                        if (b.Sub.Tree != null)
                        {
                            ScanTree(b.Sub.Tree, alts, path);
                        }
                        else
                        {
                            Debug.Assert(b.Sub.Alt != ErrorAlt);
                            if (b.Sub.Alt == ExitAlt)
                            {
                                _apply.ApplyPrematchData(alts.Next, path);
                            }
                            else
                            {
                                _apply.ApplyPrematchData(alts.Arms[b.Sub.Alt], path);
                            }
                        }
                        pm.AndPreds = old;
                    }
                }
                else                 // !IsAssertionLevel (terminal-matching level)
                {
                    bool needErrorBranch = LLPG.NeedsErrorBranch(tree, alts);

                    for (int i = 0; i < tree.Children.Count; i++)
                    {
                        PredictionBranch b   = tree.Children[i];
                        IPGTerminalSet   set = b.Set;
                        if (!needErrorBranch && i + 1 == tree.Children.Count)
                        {
                            // Add all the default cases
                            set = set.Union(tree.TotalCoverage.Inverted());
                        }
                        pm.Terminals = set;
                        if (b.Sub.Tree != null)
                        {
                            ScanTree(b.Sub.Tree, alts, path);
                        }
                        else
                        {
                            if (b.Sub.Alt == ExitAlt)
                            {
                                _apply.ApplyPrematchData(alts.Next, path);
                            }
                            else if (b.Sub.Alt != ErrorAlt)
                            {
                                _apply.ApplyPrematchData(alts.Arms[b.Sub.Alt], path);
                            }
                        }
                    }
                    path.PopLast();
                }
                path.Resize(oldCount);
            }
コード例 #7
0
            /// <summary>Extends each level of the prediction tree so that it has
            /// total coverage. For example, a typicaly prediction tree might have
            /// branches for 'a'..'z' and '0..'9'; this method will add coverage for
            /// all other possible inputs. It does this either by adding an error
            /// branch, or by extending the set handled by the default branch of
            /// each level.</summary>
            private void AddElseCases(Alts alts, PredictionTree tree)
            {
                foreach (var branch in tree.Children)
                {
                    if (branch.Sub.Tree != null)
                    {
                        AddElseCases(alts, branch.Sub.Tree);
                    }
                }

                if (tree.IsAssertionLevel)
                {
                    tree.Children.Last.AndPreds.Clear();
                    tree.Children.Last.AndPreds.Add(Set <AndPred> .Empty);
                }
                else if (!tree.TotalCoverage.ContainsEverything)
                {
                    var rest = tree.TotalCoverage.Inverted();
                    if (alts.HasErrorBranch(LLPG))
                    {
                        tree.Children.Add(new PredictionBranch(rest, new PredictionTreeOrAlt {
                            Alt = ErrorAlt
                        }, tree.TotalCoverage));
                    }
                    else
                    {
                        // No error branch, so use default arm
                                        #if false
                        // First try: this tends to produce less intuitive code. Neither
                        // version is objectively better; sometimes this version gives
                        // faster code and sometimes the other version gives faster code.
                        int defaultArm = alts.DefaultArmInt();
                        foreach (PredictionBranch branch in tree.Children)
                        {
                            if (branch.Sub.Tree == null && branch.Sub.Alt == defaultArm)
                            {
                                branch.Set = branch.Set.Union(rest);
                                goto done;
                            }
                        }
                        if (alts.DefaultArm != null)
                        {
                            tree.Children.Add(new PredictionBranch(rest, defaultArm, tree.TotalCoverage));
                        }
                        else
                        {
                            tree.Children.Last.Set = tree.Children.Last.Set.Union(rest);
                        }
                        done :;
                                        #else
                        PredictionBranch last = tree.Children.Last;
                        if (alts.DefaultArm != null && (last.Sub.Tree != null || last.Sub.Alt != alts.DefaultArm.Value))
                        {
                            tree.Children.Add(new PredictionBranch(rest, alts.DefaultArm.Value, tree.TotalCoverage));
                        }
                        else
                        {
                            last.Set = last.Set.Union(rest);
                        }
                                        #endif
                    }
                }
            }
コード例 #8
0
ファイル: AnalysisVisitors.cs プロジェクト: qwertie/ecsharp
			private void AutoAddBranchForAndPred(ref InternalList<PredictionBranch> children, AndPred andPred, List<KthSet> alts, Set<AndPred> matched, MSet<AndPred> falsified)
			{
				if (!falsified.Contains(andPred)) {
					var innerMatched = matched.With(andPred);
					var result = new PredictionBranch(new Set<AndPred>().With(andPred),
						ComputeAssertionTree2(alts, innerMatched));
					falsified.Add(andPred);
					RemoveFalsifiedCases(alts, falsified);
					children.Add(result);
				}
			}
コード例 #9
0
ファイル: AnalysisVisitors.cs プロジェクト: qwertie/ecsharp
			private PredictionTreeOrAlt ComputeAssertionTree2(List<KthSet> alts, Set<AndPred> matched)
			{
				int lookahead = alts[0].LA;
				var children = InternalList<PredictionBranch>.Empty;
				MSet<AndPred> falsified = new MSet<AndPred>();
				// Each KthSet represents a branch of the Alts for which we are 
				// generating a prediction tree; so if we find an and-predicate 
				// that, by failing, will exclude one or more KthSets, that's
				// probably the fastest way to get closer to completing the tree.
				// Any predicate in KthSet.AndReq (that isn't in matched) satisfies
				// this condition.
				var bestAndPreds = alts.SelectMany(alt => alt.AndReq).Where(ap => !matched.Contains(ap)).ToList();
				var altsLeft = alts.Select(alt => alt.Clone(true)).ToList();
				foreach (AndPred andPred in bestAndPreds)
				{
					AutoAddBranchForAndPred(ref children, andPred, altsLeft, matched, falsified);
					if (altsLeft.Count == 0)
						break;
				}
				// Testing any single AndPred will not exclude any KthSets, so
				// we'll proceed the slow way: pick any unmatched AndPred and test 
				// it. If it fails then the Transition(s) associated with it can be 
				// excluded.
				List<AndPred> predsLeft = 
					altsLeft.SelectMany(alt => alt.Cases)
					        .SelectMany(t => t.AndPreds)
					        .Where(ap => !matched.Contains(ap))
					        .Distinct().ToList();
				foreach (var andPred in predsLeft) {
					AutoAddBranchForAndPred(ref children, andPred, altsLeft, matched, falsified);
					if (altsLeft.Count == 0)
						break;
				}

				if (children.Count == 0)
				{
					// If no AndPreds were tested, proceed to the next level of prediction.
					Debug.Assert(falsified.Count == 0);
					return ComputeNestedPredictionTree(altsLeft);
				}
				
				// If there are any "unguarded" cases left after falsifying all 
				// the AndPreds, add a branch for them.
				Debug.Assert(falsified.Count > 0);
				if (altsLeft.Count > 0)
				{
					var final = new PredictionBranch(new Set<AndPred>(), ComputeNestedPredictionTree(altsLeft));
					children.Add(final);
				}
				return new PredictionTree(lookahead, children, null);
			}