Exemple #1
0
		void RefreshButtonsNonvirtual()
		{
			var s = new MSet<LLShape>();
			foreach (var widget in _widgets)
				widget.AddLLShapesTo(s);
			_toolButtonLayer.Shapes = s;
		}
Exemple #2
0
		/// <summary>Decides whether to use a switch() and for which cases, using
		/// <see cref="BaseCostForSwitch"/> and <see cref="GetRelativeCostForSwitch"/>.</summary>
		public virtual bool ShouldGenerateSwitch(IPGTerminalSet[] sets, MSet<int> casesToInclude, bool hasErrorBranch)
		{
			// Compute scores
			IPGTerminalSet covered = EmptySet;
			int[] score = new int[sets.Length - 1]; // no error branch? then last set must be default
			for (int i = 0; i < score.Length; i++)
			{
				Debug.Assert(sets[i].Subtract(covered).Equals(sets[i]));
				score[i] = GetRelativeCostForSwitch(sets[i]);
			}

			// Consider highest scores first to figure out whether switch is 
			// justified, and which branches should be expressed with "case"s.
			bool should = false;
			int switchScore = -BaseCostForSwitch;
			for (; ; )
			{
				int maxIndex = score.IndexOfMax(), maxScore = score[maxIndex];
				switchScore += maxScore;
				if (switchScore > 0)
					should = true;
				else if (maxScore < 0)
					break;
				casesToInclude.Add(maxIndex);
				score[maxIndex] = -1000000;
			}
			return should;
		}
Exemple #3
0
		public virtual LNode GenerateSwitch(IPGTerminalSet[] branchSets, MSet<int> casesToInclude, LNode[] branchCode, LNode defaultBranch, LNode laVar)
		{
			Debug.Assert(branchSets.Length == branchCode.Length);

			WList<LNode> stmts = new WList<LNode>();
			for (int i = 0; i < branchSets.Length; i++)
			{
				if (casesToInclude.Contains(i))
				{
					int index = -1;
					foreach (LNode value in GetCases(branchSets[i]))
					{
						var label = F.Call(S.Case, value);
						if (++index > 0 && (index % 4) != 0) // write 4 cases per line
							label = label.PlusAttr(F.Id(S.TriviaAppendStatement));
						stmts.Add(label);
						if (stmts.Count > 65535) // sanity check
							throw new InvalidOperationException("switch is too large to generate");
					}
					AddSwitchHandler(branchCode[i], stmts);
				}
			}

			if (!defaultBranch.IsIdNamed(S.Missing))
			{
				stmts.Add(F.Call(S.Label, F.Id(S.Default)));
				AddSwitchHandler(defaultBranch, stmts);
			}

			return F.Call(S.Switch, (LNode)laVar, F.Braces(stmts.ToVList()));
		}
Exemple #4
0
			private void RemoveFalsifiedCases(List<KthSet> alts, MSet<AndPred> falsified)
			{
				if (falsified.Count == 0)
					return;

				var results = new List<KthSet>(alts.Count);
				foreach (var alt in alts) {
					if (alt.Cases.RemoveAll(t => falsified.Overlaps(t.AndPreds)) != 0)
						alt.UpdateSet(alt.Set.ContainsEOF);
				}
				alts.RemoveAll(alt => alt.Cases.Count == 0);
			}
Exemple #5
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);
				}
			}
Exemple #6
0
            // GENERATED CODE EXAMPLE: The methods in this region generate
            // the for(;;) loop in this example and everything inside it, except
            // the calls to Match() which are generated by Visit(TerminalPred).
            // The generated code uses "goto" and "match" blocks in some cases
            // to avoid code duplication. This occurs when the matching code
            // requires multiple statements AND appears more than once in the
            // prediction tree. Otherwise, matching is done "inline" during
            // prediction. We generate a for(;;) loop for (...)*, and in certain
            // cases, we generates a do...while(false) loop for (...)?.
            //
            // rule Foo @{ (('a'|'A') 'A')* 'a'..'z' 'a'..'z' };
            // public void Foo()
            // {
            //     int la0, la1;
            //     for (;;) {
            //         la0 = LA(0);
            //         if (la0 == 'a') {
            //             la1 = LA(1);
            //             if (la1 == 'A')
            //                 goto match1;
            //             else
            //                 break;
            //         } else if (la0 == 'A')
            //             goto match1;
            //         else
            //             break;
            //         match1:
            //         {
            //             Match('A', 'a');
            //             Match('A');
            //         }
            //     }
            //     MatchRange('a', 'z');
            //     MatchRange('a', 'z');
            // }

            private void GenerateCodeForAlts(Alts alts, Dictionary <int, int> timesUsed, PredictionTree tree)
            {
                bool needError = LLPG.NeedsErrorBranch(tree, alts);

                if (!needError && alts.ErrorBranch != null)
                {
                    LLPG.Output(Warning, alts, "The error branch will not be used because the other alternatives are exhaustive (cover all cases)");
                }
                bool userDefinedError = needError && !_recognizerMode && alts.ErrorBranch != null && alts.ErrorBranch != DefaultErrorBranch.Value;

                // Generate matching code for each arm. the "string" in each pair
                // becomes non-null if the matching code for that branch needs to be
                // split out (separated) from the prediction tree because it appears
                // multiple times in the tree. The string is the goto-label name.
                Pair <LNode, string>[] matchingCode = new Pair <LNode, string> [alts.Arms.Count + (userDefinedError ? 1: 0)];
                MSet <int>             unreachable  = new MSet <int>();
                int separateCount = 0;

                for (int i = 0; i < alts.Arms.Count; i++)
                {
                    if (!timesUsed.ContainsKey(i))
                    {
                        unreachable.Add(i);
                        continue;
                    }

                    var codeForThisArm = new WList <LNode>();
                    VisitWithNewTarget(alts.Arms[i], codeForThisArm);

                    matchingCode[i].A = F.Braces(codeForThisArm.ToVList());
                    if (timesUsed[i] > 1 && !SimpleEnoughToRepeat(matchingCode[i].A))
                    {
                        separateCount++;
                        matchingCode[i].B = alts.Arms[i].ChooseGotoLabel()
                                            ?? "match" + (i + 1).ToString();
                    }
                }

                // Add matching code for the error branch, if present. Note: the
                // default error branch, which is produced by IPGCodeGenHelper.
                // ErrorBranch() is handled differently: default error code can
                // differ at each error point in the prediction tree. Therefore
                // we generate it later, on-demand.
                if (userDefinedError)
                {
                    int i            = alts.Arms.Count;
                    var errorHandler = new WList <LNode>();
                    VisitWithNewTarget(alts.ErrorBranch, errorHandler);
                    matchingCode[i].A = F.Braces(errorHandler.ToVList());
                    if (timesUsed[ErrorAlt] > 1 && !SimpleEnoughToRepeat(matchingCode[i].A))
                    {
                        matchingCode[i].B = "error";
                        separateCount++;
                    }
                }

                // Print unreachability warnings
                if (unreachable.Count == 1)
                {
                    LLPG.Output(Warning, alts, string.Format("Branch {{{0}}} is unreachable.", alts.AltName(unreachable.First())));
                }
                else if (unreachable.Count > 1)
                {
                    LLPG.Output(Warning, alts, string.Format("Branches {{{0}}} are unreachable.", unreachable.Select(i => alts.AltName(i)).Join(", ")));
                }
                if (!timesUsed.ContainsKey(ExitAlt) && alts.Mode != LoopMode.None)
                {
                    LLPG.Output(Warning, alts, "Infinite loop. The exit branch is unreachable.");
                }

                Symbol loopType = null;

                // Choose a loop type for (...)* or (...)?:
                if (alts.Mode == LoopMode.Star)
                {
                    loopType = S.For;
                }
                else if (alts.Mode == LoopMode.Opt)
                {
                    if (alts.HasErrorBranch(LLPG) || alts.NonExitDefaultArmRequested())
                    {
                        loopType = S.DoWhile;
                    }
                }

                // If the code for an arm is nontrivial and appears multiple times
                // in the prediction table, it will have to be split out into a
                // labeled block and reached via "goto". I'd rather just do a goto
                // from inside one "if" statement to inside another, but in C#
                // (unlike in CIL, and unlike in C) that is prohibited :(
                DeduplicateLabels(matchingCode);
                var extraMatching = GenerateExtraMatchingCode(matchingCode, separateCount, ref loopType);

                if (separateCount != 0)
                {
                    loopType = loopType ?? S.DoWhile;
                }

                Symbol breakMode = loopType;                 // used to request a "goto" label in addition to the loop
                LNode  code      = GeneratePredictionTreeCode(tree, matchingCode, ref breakMode);

                // Add break/continue between prediction tree and extra matching code,
                // if necessary.
                if (extraMatching.Count != 0 && CodeGenHelperBase.EndMayBeReachable(code))
                {
                    loopType = loopType ?? S.DoWhile;
                    extraMatching.Insert(0, GetContinueStmt(loopType));
                }

                if (!extraMatching.IsEmpty)
                {
                    code = LNode.MergeLists(code, F.Braces(extraMatching), S.Braces);
                }

                if (loopType == S.For)
                {
                    // (...)* => for (;;) {}
                    code = F.Call(S.For, F.AltList(), F.Missing, F.AltList(), code);
                }
                else if (loopType == S.DoWhile)
                {
                    // (...)? becomes "do {...} while(false);" IF the exit branch is NOT the default.
                    // If the exit branch is the default, then no loop and no "break" is needed.
                    code = F.Call(S.DoWhile, code, F.@false);
                }
                if (breakMode != loopType && breakMode != null)
                {
                    // Add "stop:" label (plus extra ";" for C# compatibility, in
                    // case the label ends the block in which it is located.)
                    var stopLabel = F.Call(S.Label, F.Id(breakMode))
                                    .PlusTrailingTrivia(F.Trivia(S.TriviaRawText, ";"));
                    code = LNode.MergeLists(code, stopLabel, S.Braces);
                }

                int oldCount = _target.Count;

                _target.SpliceAdd(code, S.Braces);

                // Add comment before code
                if (LLPG.AddComments)
                {
                    var pos     = alts.Basis.Range.Start;
                    var comment = F.Trivia(S.TriviaSLComment, string.Format(" Line {0}: {1}", pos.Line, alts.ToString()));
                    if (_target.Count > oldCount)
                    {
                        _target[oldCount] = _target[oldCount].PlusAttr(comment);
                    }
                }
            }
			protected LNode GeneratePredictionTreeCode(PredictionTree tree, Pair<LNode, string>[] matchingCode, ref Symbol haveLoop)
			{
				var braces = F.Braces();

				Debug.Assert(tree.Children.Count >= 1);
				var alts = (Alts)_currentPred;

				if (tree.Children.Count == 1)
					return GetPredictionSubtreeCode(tree.Children[0], matchingCode, ref haveLoop);

				// From the prediction table, we can generate either an if-else chain:
				//
				//   if (la0 >= '0' && la0 <= '7') sub_tree_1();
				//   else if (la0 == '-') sub_tree_2();
				//   else break;
				//
				// or a switch statement:
				//
				//   switch(la0) {
				//   case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
				//     sub_tree_1();
				//     break;
				//   case '-':
				//     sub_tree_2();
				//     break;
				//   default:
				//     goto breakfor;
				//   }
				//
				// Assertion levels always need an if-else chain; lookahead levels 
				// consider the complexity of switch vs if and decide which is most
				// appropriate. Generally "if" is slower, but a switch may require
				// too many labels since it doesn't support ranges like "la0 >= 'a'
				// && la0 <= 'z'".
				//
				// This class makes if-else chains directly (using IPGTerminalSet.
				// GenerateTest() to generate the test expressions), but the code 
				// snippet generator (CSG) is used to generate switch statements 
				// because the required code may be more complex.
				//
				// We may or may not be generating code inside a for(;;) loop. If we 
				// decide to generate a switch() statement, one of the branches will 
				// usually need to break out of the for loop, but "break" can only
				// break out of the switch(). In that case, add "stop:" after the
				// switch() and use "goto stop" instead of "break".

				WList<LNode> block = new WList<LNode>();
				LNode laVar = null;
				MSet<int> switchCases = new MSet<int>();
				IPGTerminalSet[] branchSets = null;
				bool should = false;

				if (tree.UsesLA()) {
					laVar = F.Id("la" + tree.Lookahead.ToString());

					if (!tree.IsAssertionLevel) {
						IPGTerminalSet covered = CGH.EmptySet;
						branchSets = tree.Children.Select(branch => {
							var set = branch.Set.Subtract(covered);
							covered = covered.Union(branch.Set);
							return set;
						}).ToArray();

						should = CGH.ShouldGenerateSwitch(branchSets, switchCases, tree.Children.Last.IsErrorBranch);
						if (!should)
							switchCases.Clear();
						else if (should && haveLoop == S.For)
							// Can't "break" out of the for-loop when there is a nested switch,
							haveLoop = GSymbol.Get(NextStopLabel()); // so use "goto stop".
					}
				}

				LNode[] branchCode = new LNode[tree.Children.Count];
				for (int i = 0; i < tree.Children.Count; i++)
					if (tree.Children[i].IsErrorBranch) {
						if (alts.ErrorBranch != null && alts.ErrorBranch != DefaultErrorBranch.Value) {
							Debug.Assert(matchingCode.Length == alts.Arms.Count + 1);
							branchCode[i] = matchingCode[alts.Arms.Count].A;
						} else
							branchCode[i] = CGH.ErrorBranch(tree.TotalCoverage, tree.Lookahead);
					} else
						branchCode[i] = GetPredictionSubtreeCode(tree.Children[i], matchingCode, ref haveLoop);

				var code = GenerateIfElseChain(tree, branchCode, ref laVar, switchCases);
				if (laVar != null) {
					block.Insert(0, F.Assign(laVar, CGH.LA(tree.Lookahead)));
					_laVarsNeeded |= 1ul << tree.Lookahead;
				} else if (should)
					laVar = CGH.LA(tree.Lookahead);

				if (should) {
					Debug.Assert(switchCases.Count != 0);
					code = CGH.GenerateSwitch(branchSets, switchCases, branchCode, code, laVar);
				}

				block.Add(code);
				return F.Braces(block.ToVList());
			}
Exemple #8
0
		internal void BeginRemoveAnimation(MSet<LLShape> erasedShapes)
		{
			var cancellingShapes = erasedShapes.Select(s => Pair.Create(s, s.Opacity)).ToList();
			var cancellingTimer = new Timer { Interval = 30, Enabled = true };
			var cancellingLayer = AddLayer();
			cancellingLayer.Shapes = erasedShapes;
			int opacity = 255;
			cancellingTimer.Tick += (s, e) =>
			{
				opacity -= 32;
				if (opacity > 0)
				{
					foreach (var pair in cancellingShapes)
						pair.A.Opacity = (byte)(pair.B * opacity >> 8);
					cancellingLayer.Invalidate();
				}
				else
				{
					DisposeLayerAt(Layers.IndexOf(cancellingLayer));
					cancellingTimer.Dispose();
					cancellingLayer.Dispose();
				}
			};
		}
Exemple #9
0
		public DiagramDocumentCore()
		{
			Shapes = new MSet<Shape>();
			Styles = new DList<DiagramDrawStyle>();
		}
Exemple #10
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);
     }
 }
Exemple #11
0
 public Scope(MSet <Symbol> openNamespaces, MMap <object, object> scopedProperties, MacroProcessorTask task, bool isRoot = false)
 {
     OpenNamespaces = openNamespaces; _scopedProperties = scopedProperties; _task = task; _propertiesCopied = _namespacesCopied = isRoot;
 }
Exemple #12
0
            private LNode GenerateIfElseChain(PredictionTree tree, LNode[] branchCode, ref LNode laVar, MSet <int> switchCases)
            {
                // From the prediction table, generate a chain of if-else
                // statements in reverse, starting with the final "else" clause.
                // Skip any branches that have been claimed for use in a switch()
                LNode ifChain  = null;
                bool  usedTest = false;

                for (int i = tree.Children.Count - 1; i >= 0; i--)
                {
                    if (switchCases.Contains(i))
                    {
                        continue;
                    }

                    if (ifChain == null)
                    {
                        ifChain = branchCode[i];
                    }
                    else
                    {
                        usedTest = true;
                        var   branch = tree.Children[i];
                        LNode test;
                        if (tree.IsAssertionLevel)
                        {
                            test = GenerateTest(branch.AndPreds, tree.Lookahead, laVar);
                        }
                        else
                        {
                            var set = CGH.Optimize(branch.Set, branch.Covered);
                            test = CGH.GenerateTest(set, laVar);
                        }

                        LNode @if = F.Call(S.If, test, branchCode[i]);
                        if (!ifChain.IsIdWithoutPAttrs(S.Missing))
                        {
                            @if = @if.PlusArg(ifChain);
                        }
                        ifChain = @if;
                    }
                }
                if (!usedTest)
                {
                    laVar = null;                     // unnecessary
                }
                return(ifChain);
            }
Exemple #13
0
            protected LNode GeneratePredictionTreeCode(PredictionTree tree, Pair <LNode, string>[] matchingCode, ref Symbol haveLoop)
            {
                var braces = F.Braces();

                Debug.Assert(tree.Children.Count >= 1);
                var alts = (Alts)_currentPred;

                if (tree.Children.Count == 1)
                {
                    return(GetPredictionSubtreeCode(tree.Children[0], matchingCode, ref haveLoop));
                }

                // From the prediction table, we can generate either an if-else chain:
                //
                //   if (la0 >= '0' && la0 <= '7') sub_tree_1();
                //   else if (la0 == '-') sub_tree_2();
                //   else break;
                //
                // or a switch statement:
                //
                //   switch(la0) {
                //   case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
                //     sub_tree_1();
                //     break;
                //   case '-':
                //     sub_tree_2();
                //     break;
                //   default:
                //     goto breakfor;
                //   }
                //
                // Assertion levels always need an if-else chain; lookahead levels
                // consider the complexity of switch vs if and decide which is most
                // appropriate. Generally "if" is slower, but a switch may require
                // too many labels since it doesn't support ranges like "la0 >= 'a'
                // && la0 <= 'z'".
                //
                // This class makes if-else chains directly (using IPGTerminalSet.
                // GenerateTest() to generate the test expressions), but the code
                // generation helper (CGH) is used to generate switch statements
                // because the required code may be more complex.
                //
                // We may or may not be generating code inside a for(;;) loop. If we
                // decide to generate a switch() statement, one of the branches will
                // usually need to break out of the for loop, but "break" can only
                // break out of the switch(). In that case, add "stop:" after the
                // switch() and use "goto stop" instead of "break".

                WList <LNode> block       = new WList <LNode>();
                LNode         laVar       = null;
                MSet <int>    switchCases = new MSet <int>();

                IPGTerminalSet[] branchSets = null;
                bool             should     = false;

                if (tree.UsesLA())
                {
                    laVar = F.Id("la" + tree.Lookahead.ToString());

                    if (!tree.IsAssertionLevel)
                    {
                        IPGTerminalSet covered = CGH.EmptySet;
                        branchSets = tree.Children.Select(branch => {
                            var set = branch.Set.Subtract(covered);
                            covered = covered.Union(branch.Set);
                            return(set);
                        }).ToArray();

                        should = CGH.ShouldGenerateSwitch(branchSets, switchCases, tree.Children.Last.IsErrorBranch);
                        if (!should)
                        {
                            switchCases.Clear();
                        }
                        else if (should && haveLoop == S.For)
                        {
                            // Can't "break" out of the for-loop when there is a nested switch,
                            haveLoop = GSymbol.Get(NextStopLabel());                             // so use "goto stop".
                        }
                    }
                }

                LNode[] branchCode = new LNode[tree.Children.Count];
                for (int i = 0; i < tree.Children.Count; i++)
                {
                    if (tree.Children[i].IsErrorBranch)
                    {
                        if (_recognizerMode)
                        {
                            branchCode[i] = F.Call(S.Return, F.False);
                        }
                        else if (alts.ErrorBranch != null && alts.ErrorBranch != DefaultErrorBranch.Value)
                        {
                            Debug.Assert(matchingCode.Length == alts.Arms.Count + 1);
                            branchCode[i] = matchingCode[alts.Arms.Count].A;
                        }
                        else
                        {
                            branchCode[i] = CGH.ErrorBranch(tree.TotalCoverage, tree.Lookahead);
                        }
                    }
                    else
                    {
                        branchCode[i] = GetPredictionSubtreeCode(tree.Children[i], matchingCode, ref haveLoop);
                    }
                }

                var code = GenerateIfElseChain(tree, branchCode, ref laVar, switchCases);

                if (laVar != null)
                {
                    block.Insert(0, F.Assign(laVar, CGH.LA(tree.Lookahead)));
                    _laVarsNeeded |= 1ul << tree.Lookahead;
                }
                else if (should)
                {
                    laVar = CGH.LA(tree.Lookahead);
                }

                if (should)
                {
                    Debug.Assert(switchCases.Count != 0);
                    code = CGH.GenerateSwitch(branchSets, branchCode, switchCases, code ?? F.Missing, laVar);
                }

                block.Add(code);
                return(F.Braces(block.ToVList()));
            }
Exemple #14
0
		public virtual LNode GenerateSwitch(IPGTerminalSet[] branchSets, MSet<int> casesToInclude, LNode[] branchCode, LNode defaultBranch, LNode laVar)
		{
			Debug.Assert(branchSets.Length == branchCode.Length);

			RWList<LNode> stmts = new RWList<LNode>();
			for (int i = 0; i < branchSets.Length; i++)
			{
				if (casesToInclude.Contains(i))
				{
					foreach (LNode value in GetCases(branchSets[i]))
					{
						stmts.Add(F.Call(S.Case, value));
						if (stmts.Count > 65535) // sanity check
							throw new InvalidOperationException("switch is too large to generate");
					}
					AddSwitchHandler(branchCode[i], stmts);
				}
			}

			if (!defaultBranch.IsIdNamed(S.Missing))
			{
				stmts.Add(F.Call(S.Label, F.Id(S.Default)));
				AddSwitchHandler(defaultBranch, stmts);
			}

			return F.Call(S.Switch, (LNode)laVar, F.Braces(stmts.ToRVList()));
		}
		private void ShowEraseDuringDrag(DragState state, MSet<LLShape> adorners, IEnumerable<Shape> eraseSet, List<PointT> simplified, bool cancel)
		{
			DiagramControl.EraseLineStyle.LineColor = Color.FromArgb(128, Control.BackColor);
			var eraseLine = new LLPolyline(DiagramControl.EraseLineStyle, simplified);
			adorners.Add(eraseLine);

			if (cancel)
			{
				eraseLine.Style = Control.LineStyle;
				Control.BeginRemoveAnimation(adorners);
				adorners.Clear();
				state.IsComplete = true;
			}
			else
			{
				// Show which shapes are erased by drawing them in the background color
				foreach (Shape s in eraseSet)
				{
					Shape s_ = s.Clone();
					s_.Style = (DiagramDrawStyle)s.Style.Clone();
					s_.Style.FillColor = s_.Style.LineColor = s_.Style.TextColor = Color.FromArgb(192, Control.BackColor);
					// avoid an outline artifact, in which color from the edges of the 
					// original shape bleeds through by a variable amount that depends 
					// on subpixel offsets.
					s_.Style.LineWidth++;
					s_.AddLLShapesTo(adorners);
				}
			}
		}
Exemple #16
0
		void AfterShapesRemoved(IReadOnlyCollection<Shape> eraseSet)
		{
			MSet<LLShape> eraseSetLL = new MSet<LLShape>();
			foreach (var s in eraseSet)
				s.AddLLShapesTo(eraseSetLL);
			BeginRemoveAnimation(eraseSetLL);
		}
		private Shape DetectNewShapeDuringDrag(DragState state, MSet<LLShape> adorners, out bool potentialSelection)
		{
			potentialSelection = false;
			Shape newShape = null;
			adorners.Add(new LLPolyline(DiagramControl.MouseLineStyle, state.Points.Select(p => p.Point).AsList()) { ZOrder = 0x100 });

			if (state.Points.Count == 1)
			{
				newShape = new Marker(Control.BoxStyle, state.FirstPoint, Control.MarkerRadius, Control.MarkerType);
			}
			else if (state.MousePoints.Count > 1)
			{
#if DEBUG
				List<Section> ss = BreakIntoSections(state);
				EliminateTinySections(ss, 10 + (int)(ss.Sum(s => s.LengthPx) * 0.05));
				foreach (Section s in ss)
					adorners.Add(new LLMarker(new DrawStyle { LineColor = Color.Gainsboro, FillColor = Color.Gray }, s.StartSS, 5, MarkerPolygon.Circle));
#endif

				newShape = RecognizeBoxOrLines(state, out potentialSelection);
			}
			return newShape;
		}
			// GENERATED CODE EXAMPLE: The methods in this region generate
			// the for(;;) loop in this example and everything inside it, except
			// the calls to Match() which are generated by Visit(TerminalPred).
			// The generated code uses "goto" and "match" blocks in some cases
			// to avoid code duplication. This occurs when the matching code 
			// requires multiple statements AND appears more than once in the 
			// prediction tree. Otherwise, matching is done "inline" during 
			// prediction. We generate a for(;;) loop for (...)*, and in certain 
			// cases, we generates a do...while(false) loop for (...)?.
			//
			// rule Foo @{ (('a'|'A') 'A')* 'a'..'z' 'a'..'z' };
			// public void Foo()
			// {
			//     int la0, la1;
			//     for (;;) {
			//         la0 = LA(0);
			//         if (la0 == 'a') {
			//             la1 = LA(1);
			//             if (la1 == 'A')
			//                 goto match1;
			//             else
			//                 break;
			//         } else if (la0 == 'A')
			//             goto match1;
			//         else
			//             break;
			//         match1:
			//         {
			//             Match('A', 'a');
			//             Match('A');
			//         }
			//     }
			//     MatchRange('a', 'z');
			//     MatchRange('a', 'z');
			// }

			private void GenerateCodeForAlts(Alts alts, Dictionary<int, int> timesUsed, PredictionTree tree)
			{
				bool needError = LLPG.NeedsErrorBranch(tree, alts);
				if (!needError && alts.ErrorBranch != null)
					LLPG.Output(Warning, alts, "The error branch will not be used because the other alternatives are exhaustive (cover all cases)");
				bool userDefinedError = needError && alts.ErrorBranch != null && alts.ErrorBranch != DefaultErrorBranch.Value;

				// Generate matching code for each arm. the "string" in each pair 
				// becomes non-null if the matching code for that branch needs to be
				// split out (separated) from the prediction tree because it appears
				// multiple times in the tree. The string is the goto-label name.
				Pair<LNode, string>[] matchingCode = new Pair<LNode, string>[alts.Arms.Count + (userDefinedError ? 1 : 0)];
				MSet<int> unreachable = new MSet<int>();
				int separateCount = 0;
				for (int i = 0; i < alts.Arms.Count; i++) {
					if (!timesUsed.ContainsKey(i)) {
						unreachable.Add(i);
						continue;
					}

					var codeForThisArm = new WList<LNode>();
					VisitWithNewTarget(alts.Arms[i], codeForThisArm);

					matchingCode[i].A = F.Braces(codeForThisArm.ToVList());
					if (timesUsed[i] > 1 && !SimpleEnoughToRepeat(matchingCode[i].A)) {
						separateCount++;
						matchingCode[i].B = alts.Arms[i].ChooseGotoLabel() 
							?? "match" + (i + 1).ToString();
					}
				}

				// Add matching code for the error branch, if present. Note: the
				// default error branch, which is produced by IPGCodeGenHelper.
				// ErrorBranch() is handled differently: default error code can 
				// differ at each error point in the prediction tree. Therefore 
				// we generate it later, on-demand.
				if (userDefinedError) {
					int i = alts.Arms.Count;
					var errorHandler = new WList<LNode>();
					VisitWithNewTarget(alts.ErrorBranch, errorHandler);
					matchingCode[i].A = F.Braces(errorHandler.ToVList());
					if (timesUsed[ErrorAlt] > 1 && !SimpleEnoughToRepeat(matchingCode[i].A)) {
						matchingCode[i].B = "error";
						separateCount++;
					}
				}

				// Print unreachability warnings 
				if (unreachable.Count == 1)
					LLPG.Output(Warning, alts, string.Format("Branch {{{0}}} is unreachable.", alts.AltName(unreachable.First())));
				else if (unreachable.Count > 1)
					LLPG.Output(Warning, alts, string.Format("Branches {{{0}}} are unreachable.", unreachable.Select(i => alts.AltName(i)).Join(", ")));
				if (!timesUsed.ContainsKey(ExitAlt) && alts.Mode != LoopMode.None)
					LLPG.Output(Warning, alts, "Infinite loop. The exit branch is unreachable.");

				Symbol loopType = null;

				// Choose a loop type for (...)* or (...)?:
				if (alts.Mode == LoopMode.Star)
					loopType = S.For;
				else if (alts.Mode == LoopMode.Opt) {
					if (alts.HasErrorBranch(LLPG) || alts.NonExitDefaultArmRequested())
						loopType = S.DoWhile;
				}

				// If the code for an arm is nontrivial and appears multiple times 
				// in the prediction table, it will have to be split out into a 
				// labeled block and reached via "goto". I'd rather just do a goto
				// from inside one "if" statement to inside another, but in C# 
				// (unlike in CIL, and unlike in C) that is prohibited :(
				DeduplicateLabels(matchingCode);
				var extraMatching = GenerateExtraMatchingCode(matchingCode, separateCount, ref loopType);
				if (separateCount != 0)
					loopType = loopType ?? S.DoWhile;

				Symbol breakMode = loopType; // used to request a "goto" label in addition to the loop
				LNode code = GeneratePredictionTreeCode(tree, matchingCode, ref breakMode);

				// Add break/continue between prediction tree and extra matching code,
				// if necessary.
				if (extraMatching.Count != 0 && CodeGenHelperBase.EndMayBeReachable(code)) {
					loopType = loopType ?? S.DoWhile;
					extraMatching.Insert(0, GetContinueStmt(loopType));
				}

				if (!extraMatching.IsEmpty)
					code = LNode.MergeLists(code, F.Braces(extraMatching), S.Braces);

				if (loopType == S.For) {
					// (...)* => for (;;) {}
					code = F.Call(S.For, F.List(), F.Missing, F.List(), code);
				} else if (loopType == S.DoWhile) {
					// (...)? becomes "do {...} while(false);" IF the exit branch is NOT the default.
					// If the exit branch is the default, then no loop and no "break" is needed.
					code = F.Call(S.DoWhile, code, F.@false);
				}
				if (breakMode != loopType && breakMode != null) {
					// Add "stop:" label (plus extra ";" for C# compatibility, in 
					// case the label ends the block in which it is located.)
					var stopLabel = F.Call(S.Label, F.Id(breakMode))
									 .PlusTrailingTrivia(F.Trivia(S.TriviaRawText, ";"));
					code = LNode.MergeLists(code, stopLabel, S.Braces);
				}

				int oldCount = _target.Count;
				_target.SpliceAdd(code, S.Braces);
				
				// Add comment before code
				if (LLPG.AddComments) {
					var pos = alts.Basis.Range.Start;
					var comment = F.Trivia(S.TriviaSLComment, string.Format(" Line {0}: {1}", pos.Line, alts.ToString()));
					if (_target.Count > oldCount)
						_target[oldCount] = _target[oldCount].PlusAttr(comment);
				}
			}
Exemple #19
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);
			}
			private LNode GenerateIfElseChain(PredictionTree tree, LNode[] branchCode, ref LNode laVar, MSet<int> switchCases)
			{
				// From the prediction table, generate a chain of if-else 
				// statements in reverse, starting with the final "else" clause.
				// Skip any branches that have been claimed for use in a switch()
				LNode ifChain = null;
				bool usedTest = false;

				for (int i = tree.Children.Count - 1; i >= 0; i--) {
					if (switchCases.Contains(i))
						continue;

					if (ifChain == null)
						ifChain = branchCode[i];
					else {
						usedTest = true;
						var branch = tree.Children[i];
						LNode test;
						if (tree.IsAssertionLevel)
							test = GenerateTest(branch.AndPreds, tree.Lookahead, laVar);
						else {
							var set = CGH.Optimize(branch.Set, branch.Covered);
							test = CGH.GenerateTest(set, laVar);
						}

						LNode @if = F.Call(S.If, test, branchCode[i]);
						if (!ifChain.IsIdWithoutPAttrs(S.Missing))
							@if = @if.PlusArg(ifChain);
						ifChain = @if;
					}
				}
				if (!usedTest)
					laVar = null; // unnecessary

				return ifChain;
			}
Exemple #21
0
        public List <SearchEntry> Search(IBaseWindow baseWin, string searchText)
        {
            if (baseWin == null)
            {
                throw new ArgumentNullException("baseWin");
            }

            const uint flags = (uint)(QueryParser.feature_flag.FLAG_PARTIAL | QueryParser.feature_flag.FLAG_WILDCARD |
                                      QueryParser.feature_flag.FLAG_PHRASE | QueryParser.feature_flag.FLAG_BOOLEAN |
                                      QueryParser.feature_flag.FLAG_LOVEHATE);

            List <SearchEntry> res = new List <SearchEntry>();

            try
            {
                lock (fLock)
                {
                    using (Database database = new Database(GetXDBFolder()))
                        using (Enquire enquire = new Enquire(database))
                            using (Stem stemmer = new Stem("russian"))
                                using (QueryParser qp = new QueryParser())
                                {
                                    qp.SetStemmer(stemmer);
                                    qp.SetDatabase(database);
                                    qp.SetDefaultOp(Query.op.OP_AND);
                                    qp.SetStemmingStrategy(QueryParser.stem_strategy.STEM_SOME);

                                    string qs = searchText + " ged:" + GetSign(baseWin);
                                    qp.AddBooleanPrefix("ged", "GDB");

                                    using (Query query = qp.ParseQuery(qs, flags))
                                    {
                                        enquire.SetQuery(query);

                                        using (MSet matches = enquire.GetMSet(0, 100))
                                        {
                                            MSetIterator m = matches.Begin();
                                            while (m != matches.End())
                                            {
                                                try
                                                {
                                                    using (Document mDoc = m.GetDocument()) {
                                                        SearchEntry entry = new SearchEntry();
                                                        entry.XRef    = mDoc.GetData();
                                                        entry.Rank    = m.GetRank() + 1;
                                                        entry.Percent = m.GetPercent();
                                                        res.Add(entry);
                                                    }
                                                }
                                                catch (Exception ex)
                                                {
                                                    Logger.LogWrite("SearchManager.Search(): " + ex.Message);
                                                }

                                                m = m.Next();
                                            }
                                        }
                                    }
                                }
                }
            }
            catch (Exception ex)
            {
                Logger.LogWrite("SearchManager.Search(): " + ex.Message);
            }

            return(res);
        }