public bool IsNongreedyExit; // indicates a nongreedy exit branch (which takes priority in case of ambiguity) public void UpdateSet(bool addEOF) { if (Cases.Count == 0) { Set = Set.Empty; if (addEOF) { Set = Set.WithEOF(); } AndReq = new Set <AndPred>(); return; } Set = Cases[0].Set; var andI = new MSet <AndPred>(Cases[0].AndPreds); for (int i = 1; i < Cases.Count; i++) { Set = Set.Union(Cases[i].Set); andI.IntersectWith(Cases[i].AndPreds); } AndReq = (Set <AndPred>)andI; if (addEOF) { Set = Set.WithEOF(); } }
public override string Example(IPGTerminalSet set_) { var set = (PGNodeSet)set_; if (set.IsInverted) { if (set.Contains(__)) { return("_"); } else { for (int i = 0; ; i++) { if (set.Contains(F.Literal(i))) { return(i.ToString()); } } } } var ex = set.BaseSet.FirstOrDefault(); if (ex == null) { return(set.IsEmpty ? "<nothing>" : "<EOF>"); } return(ex.Print(NodeStyle.Expression)); }
private void NarrowDownToSet(List <KthSet> thisBranch, IPGTerminalSet set) { // Scans the Transitions of thisBranch, removing cases that are // unreachable given the current set and intersecting the reachable // sets with 'set'. This method is needed in rare cases involving // nested Alts, but it is called unconditionally just in case // futher lookahead steps might rely on the results. Here are two // examples where it is needed: // // ( ( &foo 'a' | 'b' 'b') | 'b' 'c' ) // // In this case, a prediction subtree is generated for LA(0)=='b'. // Initially, thisBranch will contain a case for (&foo 'a') but it // is unreachable given that we know LA(0)=='b', so &foo should not // be tested. This method will remove that case so it'll be ignored. // // (('a' | 'd' 'd') 't' | ('a'|'o') 'd' 'd') // test suite: NestedAlts() // // Without this method, prediction would think that the sequence // 'a' 'd' could match the first alt because it fails to discard the // second nested alt ('d' 'd') after matching 'a'. for (int i = 0; i < thisBranch.Count; i++) { thisBranch[i] = NarrowDownToSet(thisBranch[i], set); } }
public override LNode GenerateMatchExpr(IPGTerminalSet set_, bool savingResult, bool recognizerMode) { var set = (PGIntSet)set_; LNode call; var type = set.ChooseMatchType(2, 4); if (type != PGIntSet.Match.Set) { var args = new RWList <LNode>(); if (type == PGIntSet.Match.Ranges) { // Use MatchRange or MatchExceptRange foreach (var r in set) { if (!set.IsInverted || r.Lo != EOF_int || r.Hi != EOF_int) { args.Add((LNode)set.MakeLiteral(r.Lo)); args.Add((LNode)set.MakeLiteral(r.Hi)); } } var target = recognizerMode ? (set.IsInverted ? _TryMatchExceptRange : _TryMatchRange) : (set.IsInverted ? _MatchExceptRange : _MatchRange); call = ApiCall(target, args); } else { // Use Match or MatchExcept foreach (var r in set) { for (int c = r.Lo; c <= r.Hi; c++) { if (!set.IsInverted || c != EOF_int) { args.Add((LNode)set.MakeLiteral(c)); } } } var target = recognizerMode ? (set.IsInverted ? _TryMatchExcept : _TryMatch) : (set.IsInverted ? _MatchExcept : _Match); call = ApiCall(target, args.ToRVList()); } } else { var setName = GenerateSetDecl(set); if (set.IsInverted) { call = ApiCall(recognizerMode ? _TryMatchExcept : _MatchExcept, F.Id(setName)); } else { call = ApiCall(recognizerMode ? _TryMatch : _Match, F.Id(setName)); } } return(call); }
/// <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); }
private IPGTerminalSet NarrowDownToOneCase(IPGTerminalSet normalSet, List <Transition> cases) { if (cases.Count == 1) { return(normalSet); // a small optimization } IPGTerminalSet narrowSet, next; int i; for (i = 0; ; i++) { if (i == cases.Count) { // this happens if normalSet is {EOF} and none of the cases have EOF. // (LLLPG puts EOF in all exit branches to prevent infinite loops) Debug.Assert(normalSet.ContainsEOF); return(normalSet); } if (!(narrowSet = cases[i].Set.Intersection(normalSet)).IsEmptySet) { break; } } for (i++; i < cases.Count; i++) { if (!(next = cases[i].Set.Intersection(narrowSet)).IsEmptySet) { narrowSet = next; } } return(narrowSet); }
public static bool SlowEquals(this IPGTerminalSet @this, IPGTerminalSet other) { Debug.Assert(@this != null); if (other == null) { return(false); } bool e = @this.ContainsEverything; if (e == other.ContainsEverything && @this.ContainsEOF == other.ContainsEOF) { if (e) { return(true); } var sub1 = @this.Subtract(other); if (sub1 == null || !sub1.IsEmptySet) { return(false); } var sub2 = other.Subtract(@this); return(sub2 != null && sub2.IsEmptySet); } return(false); }
public KthSet(Pred start, int alt, IPGTerminalSet emptySet, bool isNongreedyExit = false) { Cases.Add(new Transition(null, null, new GrammarPos(start, null))); Alt = alt; IsNongreedyExit = isNongreedyExit; Set = emptySet; }
public Transition(Pred prevPosition, IPGTerminalSet set, VList <AndPred> andPreds, GrammarPos position) { PrevPosition = prevPosition; Debug.Assert(position != null); Set = set; Position = position; AndPreds = andPreds; }
protected override int GetRelativeCostForSwitch(IPGTerminalSet set) { var intset = (PGIntSet)set; int switchCost = (int)System.Math.Min(1 + intset.Size, 1000000); int ifCost = System.Math.Min(intset.ExprComplexity() * 4, 32); return(ifCost - switchCost); }
protected override IEnumerable <LNode> GetCases(IPGTerminalSet set_) { var set = (PGNodeSet)set_; Debug.Assert(!set.IsInverted); // Sort the cases so they don't change order each time they are generated return(set.BaseSet.OrderBy(n => n.ToString())); }
protected override LNode GenerateTest(IPGTerminalSet set_, LNode subject, Symbol setName) { var set = (PGNodeSet)set_; if (setName != null) { // setName.Contains($subject) if (MatchCast != null) { subject = F.Call(S.Cast, subject, MatchCast); } var test = F.Call(F.Dot(setName, _Contains), subject); return(set.IsInverted ? F.Call(S.Not, test) : test); } else { if (set.BaseSet.Count > 5) { return(null); // complex } LNode test, result = null; // Note: sort the set so that the unit tests are deterministic foreach (LNode item in set.BaseSet.OrderBy(s => s.ToString())) { var item2 = item; if (item == PGNodeSet.EOF_node && InputClass != null) { item2 = F.Dot(InputClass, item); } test = F.Call(S.Eq, subject, item2); if (result == null) { result = test; } else { result = F.Call(S.Or, result, test); } } if (set.IsInverted) { if (result == null) { return(F.@true); } if (result.Calls(S.Eq)) { result = result.WithTarget(S.Neq); } else { result = F.Call(S.Not, F.InParens(result)); } } return(result ?? F.@false); } }
public IPGTerminalSet Optimize(IPGTerminalSet dontcare) { var dontcareSS = dontcare as PGNodeSet; if (dontcareSS == null) { return(this); } return(new PGNodeSet(Except(dontcareSS))); }
IPGTerminalSet IPGTerminalSet.IntersectionCore(IPGTerminalSet other, bool subtract, bool subtractThis) { var other_ = other as IntSet; if (other_ == null) { return(null); } return(Intersection(other_, subtract, subtractThis)); }
IPGTerminalSet IPGTerminalSet.UnionCore(IPGTerminalSet other) { var other_ = other as IntSet; if (other_ == null) { return(null); } return(Union(other_)); }
IPGTerminalSet IPGTerminalSet.IntersectionCore(IPGTerminalSet other, bool subtract, bool subtractThis) { var otherSS = other as PGNodeSet; if (otherSS == null) { return(null); } return(Intersect(otherSS, subtract, subtractThis)); }
public IPGTerminalSet UnionCore(IPGTerminalSet other) { var otherSS = other as PGNodeSet; if (otherSS == null) { return(null); } return(new PGNodeSet(Union(otherSS))); }
/// <summary>Generates code for the default error branch of prediction /// (called when there is no explicit error branch).</summary> /// <param name="covered">The permitted token set, which the input did not match. /// NOTE: if the input matched but there were and-predicates that did not match, /// this parameter will be null (e.g. the input is 'b' in <c>(&{x} 'a' | &{y} 'b')</c>, /// but y is false.</param> /// <param name="laIndex">Location of unexpected input, relative to current position.</param> public virtual LNode ErrorBranch(IPGTerminalSet covered, int laIndex) { string coveredS = covered.ToString(); if (coveredS.Length > 45) { coveredS = coveredS.Substring(0, 40) + "..."; } return(ApiCall(_Error, F.Literal(laIndex), F.Literal(string.Format("In rule '{0}', expected one of: {1}", _currentRule.Name.Name, coveredS)))); }
public virtual LNode GenerateTest(IPGTerminalSet set, LNode laVar) { LNode test = GenerateTest(set, laVar, null); if (test == null) { var setName = GenerateSetDecl(set); test = GenerateTest(set, laVar, setName); } return(test); }
public bool Equals(IPGTerminalSet other) { if (other is IntSet) { return(Equals((IntSet)other)); } else { return(this.SlowEquals(other)); } }
public bool Equals(IPGTerminalSet other) { if (other is PGNodeSet) { return(SetEquals((PGNodeSet)other)); } else { return(this.SlowEquals(other)); } }
protected override IEnumerable <LNode> GetCases(IPGTerminalSet set) { var intset = (PGIntSet)set; foreach (IntRange range in intset) { for (int ch = range.Lo; ch <= range.Hi; ch++) { bool isChar = intset.IsCharSet && (char)ch == ch; yield return(F.Literal(isChar ? (object)(char)ch : (object)ch)); } } }
public virtual LNode GenerateMatch(IPGTerminalSet set, bool savingResult, bool recognizerMode) { LNode call = GenerateMatchExpr(set, savingResult, recognizerMode); if (recognizerMode) { return(F.Call(S.If, F.Call(S.Not, call), F.Call(S.Return, F.@false))); } else { return(call); } }
protected PredictionTree ComputePredictionTree(KthSet[] kthSets) { var children = InternalList <PredictionBranch> .Empty; var thisBranch = new List <KthSet>(); int lookahead = kthSets[0].LA; Debug.Assert(kthSets.All(p => p.LA == lookahead)); IPGTerminalSet covered = CGH.EmptySet; for (;;) { thisBranch.Clear(); // e.g. given an Alts value of ('0' '0'..'7'+ | '0'..'9'+), // ComputeSetForNextBranch finds the set '0' in the first // iteration (recording both alts in 'thisBranch'), '1'..'9' // on the second iteration, and finally null. IPGTerminalSet set = ComputeSetForNextBranch(kthSets, thisBranch, covered); if (set == null) { break; } if (thisBranch.Count == 1) { var branch = thisBranch[0]; children.Add(new PredictionBranch(set, branch.Alt, covered)); } else { Debug.Assert(thisBranch.Count > 1); NarrowDownToSet(thisBranch, set); PredictionTreeOrAlt sub; if (thisBranch.Any(ks => ks.HasAnyAndPreds)) { sub = ComputeAssertionTree(thisBranch); } else { sub = ComputeNestedPredictionTree(thisBranch); } children.Add(new PredictionBranch(set, sub, covered)); } covered = covered.Union(set); } return(new PredictionTree(lookahead, children, covered)); }
protected virtual Symbol GenerateSetDecl(IPGTerminalSet set) { Symbol setName; if (_setDeclNames.TryGetValue(set, out setName)) { return(setName); } setName = GenerateSetName(_currentRule); _classBody.Add(GenerateSetDecl(set, setName)); return(_setDeclNames[set] = setName); }
protected override LNode GenerateSetDecl(IPGTerminalSet set_, Symbol setName) { var set = (PGNodeSet)set_; // static readonly $SetType $setName = NewSet(new $SetType[] { ... }); // Sort the list so that the test suite can compare results deterministically IEnumerable <LNode> setMemberList = set.BaseSet.OrderBy(s => s.ToString()); if (MatchCast != null) { setMemberList = setMemberList.Select(item => F.Call(S.Cast, item, MatchCast)); } return(F.Attr(F.Id(S.Static), F.Id(S.Readonly), F.Var(SetType, setName, F.Call(_NewSet, setMemberList)))); }
protected override int GetRelativeCostForSwitch(IPGTerminalSet set_) { var set = (PGNodeSet)set_; if (!AllowSwitch || set.IsInverted) { return(-1000000); } int switchCost = 1 + set.BaseSet.Count; int ifCost = System.Math.Min(set.BaseSet.Count * 4, 32); return(ifCost - switchCost); }
private KthSet NarrowDownToSet(KthSet kthSet, IPGTerminalSet set) { kthSet = kthSet.Clone(false); var cases = kthSet.Cases; for (int i = cases.Count - 1; i >= 0; i--) { cases[i].Set = cases[i].Set.Intersection(set); if (cases[i].Set.IsEmptySet) { cases.RemoveAt(i); } } kthSet.UpdateSet(false); return(kthSet); }
public override char?ExampleChar(IPGTerminalSet set_) { var set = ((PGIntSet)set_); if (!set.IsCharSet) { return(null); } int? ex = ExampleInt(set); char c; if (ex == null || (c = (char)ex.Value) != ex.Value) { return(null); } return(c); }
public override LNode GenerateMatchExpr(IPGTerminalSet set_, bool savingResult, bool recognizerMode) { var set = (PGNodeSet)set_; LNode call; int baseCount = set.BaseSet.Count; IEnumerable <LNode> symbols = set.BaseSet; if (set.IsInverted) { if (set.ContainsEOF) // Unusual set: ((~something)|EOF) { baseCount = int.MaxValue; } else // Normal inverted set ~X has output "MatchExcept(X)" // which is a synonym for "MatchExcept(X, EOF)" { symbols = symbols.Where(s => !s.IsIdNamed(EOF.Name)); baseCount--; } } if (baseCount <= 4) { call = ApiCall(recognizerMode ? (set.IsInverted ? _TryMatchExcept : _TryMatch) : (set.IsInverted ? _MatchExcept : _Match), MatchArgs(symbols)); } else { var setName = GenerateSetDecl(set); if (set.IsInverted) { call = ApiCall(recognizerMode ? _TryMatchExcept : _MatchExcept, F.Id(setName)); } else { call = ApiCall(recognizerMode ? _TryMatch : _Match, F.Id(setName)); } } return(call); }
public virtual IPGTerminalSet Optimize(IPGTerminalSet set, IPGTerminalSet dontcare) { return set.Subtract(dontcare); }
protected override IEnumerable<LNode> GetCases(IPGTerminalSet set) { var intset = (PGIntSet)set; foreach (IntRange range in intset) { for (int ch = range.Lo; ch <= range.Hi; ch++) { bool isChar = intset.IsCharSet && (char)ch == ch; yield return F.Literal(isChar ? (object)(char)ch : (object)ch); } } }
protected override LNode GenerateSetDecl(IPGTerminalSet set, Symbol setName) { return GenerateSetDecl((PGIntSet)set, setName); }
protected override int GetRelativeCostForSwitch(IPGTerminalSet set) { var intset = (PGIntSet)set; int switchCost = (int)System.Math.Min(1 + intset.Size, 1000000); int ifCost = System.Math.Min(intset.ExprComplexity() * 4, 32); return ifCost - switchCost; }
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())); }
/// <summary>Gets the literals or symbols to use for switch cases of /// a set (just the values, not including the case labels.)</summary> protected virtual IEnumerable<LNode> GetCases(IPGTerminalSet set) { throw new NotImplementedException(); }
/// <summary>Generates code for the default error branch of prediction /// (called when there is no explicit error branch).</summary> /// <param name="covered">The permitted token set, which the input did not match. /// NOTE: if the input matched but there were and-predicates that did not match, /// this parameter will be null (e.g. the input is 'b' in <c>(&{x} 'a' | &{y} 'b')</c>, /// but y is false.</param> /// <param name="laIndex">Location of unexpected input, relative to current position.</param> public virtual LNode ErrorBranch(IPGTerminalSet covered, int laIndex) { string coveredS = covered.ToString(); if (coveredS.Length > 45) coveredS = coveredS.Substring(0, 40) + "..."; return ApiCall(_Error, F.Literal(laIndex), F.Literal(string.Format("In rule '{0}', expected one of: {1}", _currentRule.Name.Name, coveredS))); }
public virtual LNode GenerateMatch(IPGTerminalSet set, bool savingResult, bool recognizerMode) { LNode call = GenerateMatchExpr(set, savingResult, recognizerMode); if (recognizerMode) return F.Call(S.If, F.Call(S.Not, call), F.Call(S.Return, F.@false)); else return call; }
protected virtual Symbol GenerateSetDecl(IPGTerminalSet set) { Symbol setName; if (_setDeclNames.TryGetValue(set, out setName)) return setName; setName = GenerateSetName(_currentRule); _classBody.Add(GenerateSetDecl(set, setName)); return _setDeclNames[set] = setName; }
public virtual LNode GenerateTest(IPGTerminalSet set, LNode laVar) { LNode test = GenerateTest(set, laVar, null); if (test == null) { var setName = GenerateSetDecl(set); test = GenerateTest(set, laVar, setName); } return test; }
public virtual char? ExampleChar(IPGTerminalSet set) { return null; }
public override IPGTerminalSet Optimize(IPGTerminalSet set, IPGTerminalSet dontcare) { return ((PGIntSet)set).Optimize((IntSet)dontcare); }
public override char? ExampleChar(IPGTerminalSet set_) { var set = ((PGIntSet)set_); if (!set.IsCharSet) return null; int? ex = ExampleInt(set); char c; if (ex == null || (c = (char)ex.Value) != ex.Value) return null; return c; }
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())); }
public abstract string Example(IPGTerminalSet set);
public PrematchAnalysisVisitor(LLParserGenerator llpg) { LLPG = llpg; Anything = LLPG.CodeGenHelper.EmptySet.Inverted(); _apply = new ApplyPrematchVisitor(llpg); }
/// <summary>Generates code to test whether a terminal is in the set.</summary> /// <param name="subject">Represents the variable to be tested.</param> /// <param name="setName">Names an external set variable to use for the test.</param> /// <returns>A test expression such as <c>(la0 >= '0' && '9' >= la0)</c>, or /// null if an external setName is needed and was not provided.</returns> /// <remarks> /// At first, <see cref="LLParserGenerator"/> calls this method with /// <c>setName == null</c>. If it returns null, it calls the method a /// second time, giving the name of an external variable in which the /// set is held (see <see cref="GenerateSetDecl(IPGTerminalSet)"/>). /// <para/> /// For example, if the subject is @la0, the test for a simple set /// like [a-z?] might be something like <c>(la0 >= 'a' && 'z' >= la0) /// || la0 == '?'</c>. When the setName is <c>foo</c>, the test might be /// <c>foo.Contains(la0)</c> instead. /// </remarks> protected abstract LNode GenerateTest(IPGTerminalSet set, LNode subject, Symbol setName);
private IPGTerminalSet NarrowDownToOneCase(IPGTerminalSet normalSet, List<Transition> cases) { if (cases.Count == 1) return normalSet; // a small optimization IPGTerminalSet narrowSet, next; int i; for (i = 0; ; i++) { if (i == cases.Count) { // this happens if normalSet is {EOF} and none of the cases have EOF. // (LLLPG puts EOF in all exit branches to prevent infinite loops) Debug.Assert(normalSet.ContainsEOF); return normalSet; } if (!(narrowSet = cases[i].Set.Intersection(normalSet)).IsEmptySet) break; } for (i++; i < cases.Count; i++) if (!(next = cases[i].Set.Intersection(narrowSet)).IsEmptySet) narrowSet = next; return narrowSet; }
/// <summary>Generates a declaration for a variable that holds the set.</summary> /// <remarks> /// For example, if setName is foo, a set such as [aeiouy] /// might use an external declaration such as /// <code>HashSet<int> foo = NewSet('a', 'e', 'i', 'o', 'u', 'y');</code> /// </remarks> protected abstract LNode GenerateSetDecl(IPGTerminalSet set, Symbol setName);
private IPGTerminalSet ComputeSetForNextBranch(KthSet[] kthSets, List<KthSet> thisBranch, IPGTerminalSet covered) { int i; IPGTerminalSet set = null; for (i = 0; ; i++) { if (i == kthSets.Length) return null; // done! set = kthSets[i].Set.Subtract(covered); if (!set.IsEmptySet) { if (_currentRule.FullLLk ?? LLPG.FullLLk) set = NarrowDownToOneCase(set, kthSets[i].Cases); break; } } thisBranch.Add(kthSets[i]); for (i++; i < kthSets.Length; i++) { var next = set.Intersection(kthSets[i].Set); if (!next.IsEmptySet) { set = next; if (_currentRule.FullLLk ?? LLPG.FullLLk) set = NarrowDownToOneCase(set, kthSets[i].Cases); thisBranch.Add(kthSets[i]); } } return set; }
/// <summary>Generate code to match a set, e.g. /// <c>@{ MatchRange('a', 'z');</c> or <c>@{ MatchExcept('\n', '\r'); }</c>. /// If the set is too complex, a declaration for it is created in classBody.</summary> public abstract LNode GenerateMatchExpr(IPGTerminalSet set, bool savingResult, bool recognizerMode);
private KthSet NarrowDownToSet(KthSet kthSet, IPGTerminalSet set) { kthSet = kthSet.Clone(false); var cases = kthSet.Cases; for (int i = cases.Count-1; i >= 0; i--) { cases[i].Set = cases[i].Set.Intersection(set); if (cases[i].Set.IsEmptySet) cases.RemoveAt(i); } kthSet.UpdateSet(kthSet.Set.ContainsEOF); Debug.Assert(cases.Count > 0 || set.ContainsEOF); return kthSet; }
/// <summary>Used to help decide whether a "switch" or an if statement /// will be used to handle a prediction tree, and if so which branches. /// This method should calculate the "cost of switch" (which generally /// represents a code size penalty, as there is a separate case for /// every element of the set) and the "cost of if" (which generally /// represents a speed penalty) and return the difference (so that /// positive numbers favor "switch" and negative numbers favor "if".)</summary> /// <remarks>If the set is inverted, return a something like -1000000 /// to ensure 'switch' is not used for that set.</remarks> protected virtual int GetRelativeCostForSwitch(IPGTerminalSet set) { return -1000000; }
IPGTerminalSet IPGTerminalSet.UnionCore(IPGTerminalSet other) { var other_ = other as IntSet; if (other_ == null) return null; return Union(other_); }
/// <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; }
protected override LNode GenerateTest(IPGTerminalSet set, LNode subject, Symbol setName) { return ((PGIntSet)set).GenerateTest(subject, setName); }
public bool Equals(IPGTerminalSet other) { if (other is IntSet) return Equals((IntSet)other); else return this.SlowEquals(other); }
public override LNode GenerateMatchExpr(IPGTerminalSet set_, bool savingResult, bool recognizerMode) { var set = (PGIntSet)set_; LNode call; var type = set.ChooseMatchType(2, 4); if (type != PGIntSet.Match.Set) { var args = new RWList<LNode>(); if (type == PGIntSet.Match.Ranges) { // Use MatchRange or MatchExceptRange foreach (var r in set) { if (!set.IsInverted || r.Lo != EOF_int || r.Hi != EOF_int) { args.Add((LNode)set.MakeLiteral(r.Lo)); args.Add((LNode)set.MakeLiteral(r.Hi)); } } var target = recognizerMode ? (set.IsInverted ? _TryMatchExceptRange : _TryMatchRange) : (set.IsInverted ? _MatchExceptRange : _MatchRange); call = ApiCall(target, args); } else { // Use Match or MatchExcept foreach (var r in set) { for (int c = r.Lo; c <= r.Hi; c++) { if (!set.IsInverted || c != EOF_int) args.Add((LNode)set.MakeLiteral(c)); } } var target = recognizerMode ? (set.IsInverted ? _TryMatchExcept : _TryMatch) : (set.IsInverted ? _MatchExcept : _Match); call = ApiCall(target, args.ToRVList()); } } else { var setName = GenerateSetDecl(set); if (set.IsInverted) call = ApiCall(recognizerMode ? _TryMatchExcept : _MatchExcept, F.Id(setName)); else call = ApiCall(recognizerMode ? _TryMatch : _Match, F.Id(setName)); } return call; }
IPGTerminalSet IPGTerminalSet.IntersectionCore(IPGTerminalSet other, bool subtract, bool subtractThis) { var other_ = other as IntSet; if (other_ == null) return null; return Intersection(other_, subtract, subtractThis); }
public override string Example(IPGTerminalSet set_) { var set = ((PGIntSet)set_); char? ch = ExampleChar(set); if (ch != null) return ch == '\'' ? @"'\''" : string.Format("'{0}'", ch); int? ex = ExampleInt(set); if (ex == null) return "<nothing>"; if (ex == EOF_int) return "<EOF>"; return ex.Value.ToString(); }