void RefreshButtonsNonvirtual() { var s = new MSet<LLShape>(); foreach (var widget in _widgets) widget.AddLLShapesTo(s); _toolButtonLayer.Shapes = s; }
/// <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; }
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())); }
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); }
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); } }
// 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()); }
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(); } }; }
public DiagramDocumentCore() { Shapes = new MSet<Shape>(); Styles = new DList<DiagramDrawStyle>(); }
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); } }
public Scope(MSet <Symbol> openNamespaces, MMap <object, object> scopedProperties, MacroProcessorTask task, bool isRoot = false) { OpenNamespaces = openNamespaces; _scopedProperties = scopedProperties; _task = task; _propertiesCopied = _namespacesCopied = isRoot; }
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); }
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())); }
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); } } }
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); } }
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; }
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); }