예제 #1
0
            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();
                }
            }
예제 #2
0
        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));
        }
예제 #3
0
 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);
     }
 }
예제 #4
0
        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);
        }
예제 #5
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);
        }
예제 #6
0
            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);
            }
예제 #7
0
        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);
        }
예제 #8
0
 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;
 }
예제 #9
0
 public Transition(Pred prevPosition, IPGTerminalSet set, VList <AndPred> andPreds, GrammarPos position)
 {
     PrevPosition = prevPosition;
     Debug.Assert(position != null);
     Set      = set;
     Position = position;
     AndPreds = andPreds;
 }
예제 #10
0
        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);
        }
예제 #11
0
        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()));
        }
예제 #12
0
        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);
            }
        }
예제 #13
0
        public IPGTerminalSet Optimize(IPGTerminalSet dontcare)
        {
            var dontcareSS = dontcare as PGNodeSet;

            if (dontcareSS == null)
            {
                return(this);
            }
            return(new PGNodeSet(Except(dontcareSS)));
        }
예제 #14
0
파일: PGIntSet.cs 프로젝트: sizzles/ecsharp
        IPGTerminalSet IPGTerminalSet.IntersectionCore(IPGTerminalSet other, bool subtract, bool subtractThis)
        {
            var other_ = other as IntSet;

            if (other_ == null)
            {
                return(null);
            }
            return(Intersection(other_, subtract, subtractThis));
        }
예제 #15
0
파일: PGIntSet.cs 프로젝트: sizzles/ecsharp
        IPGTerminalSet IPGTerminalSet.UnionCore(IPGTerminalSet other)
        {
            var other_ = other as IntSet;

            if (other_ == null)
            {
                return(null);
            }
            return(Union(other_));
        }
예제 #16
0
        IPGTerminalSet IPGTerminalSet.IntersectionCore(IPGTerminalSet other, bool subtract, bool subtractThis)
        {
            var otherSS = other as PGNodeSet;

            if (otherSS == null)
            {
                return(null);
            }
            return(Intersect(otherSS, subtract, subtractThis));
        }
예제 #17
0
        public IPGTerminalSet UnionCore(IPGTerminalSet other)
        {
            var otherSS = other as PGNodeSet;

            if (otherSS == null)
            {
                return(null);
            }
            return(new PGNodeSet(Union(otherSS)));
        }
예제 #18
0
        /// <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>(&amp;{x} 'a' | &amp;{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))));
        }
예제 #19
0
        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);
        }
예제 #20
0
파일: PGIntSet.cs 프로젝트: sizzles/ecsharp
 public bool Equals(IPGTerminalSet other)
 {
     if (other is IntSet)
     {
         return(Equals((IntSet)other));
     }
     else
     {
         return(this.SlowEquals(other));
     }
 }
예제 #21
0
 public bool Equals(IPGTerminalSet other)
 {
     if (other is PGNodeSet)
     {
         return(SetEquals((PGNodeSet)other));
     }
     else
     {
         return(this.SlowEquals(other));
     }
 }
예제 #22
0
        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));
                }
            }
        }
예제 #23
0
        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);
            }
        }
예제 #24
0
            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));
            }
예제 #25
0
        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);
        }
예제 #26
0
        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))));
        }
예제 #27
0
        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);
        }
예제 #28
0
            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);
            }
예제 #29
0
        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);
        }
예제 #30
0
        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);
        }
예제 #31
0
		public virtual IPGTerminalSet Optimize(IPGTerminalSet set, IPGTerminalSet dontcare) { return set.Subtract(dontcare); }
예제 #32
0
		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);
				}
			}
		}
예제 #33
0
		protected override LNode GenerateSetDecl(IPGTerminalSet set, Symbol setName)
		{
			return GenerateSetDecl((PGIntSet)set, setName);
		}
예제 #34
0
		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;
		}
예제 #35
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()));
		}
예제 #36
0
		/// <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(); }
예제 #37
0
		/// <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>(&amp;{x} 'a' | &amp;{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)));
		}
예제 #38
0
		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;
		}
예제 #39
0
		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;
		}
예제 #40
0
		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;
		}
예제 #41
0
		public virtual char? ExampleChar(IPGTerminalSet set) { return null; }
예제 #42
0
		public override IPGTerminalSet Optimize(IPGTerminalSet set, IPGTerminalSet dontcare)
		{
			return ((PGIntSet)set).Optimize((IntSet)dontcare);
		}
예제 #43
0
		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;
		}
예제 #44
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()));
		}
예제 #45
0
		public abstract string Example(IPGTerminalSet set);
예제 #46
0
			public PrematchAnalysisVisitor(LLParserGenerator llpg) 
			{
				LLPG = llpg;
				Anything = LLPG.CodeGenHelper.EmptySet.Inverted();
				_apply = new ApplyPrematchVisitor(llpg);
			}
예제 #47
0
		/// <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' &amp;&amp; '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' &amp;&amp; '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);
예제 #48
0
			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;
			}
예제 #49
0
		/// <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&lt;int> foo = NewSet('a', 'e', 'i', 'o', 'u', 'y');</code>
		/// </remarks>
		protected abstract LNode GenerateSetDecl(IPGTerminalSet set, Symbol setName);
예제 #50
0
			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;
			}
예제 #51
0
		/// <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);
예제 #52
0
			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;
			}
예제 #53
0
		/// <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; }
예제 #54
0
파일: PGIntSet.cs 프로젝트: Shaykh/Loyc
		IPGTerminalSet IPGTerminalSet.UnionCore(IPGTerminalSet other)
		{
			var other_ = other as IntSet;
			if (other_ == null) return null;
			return Union(other_);
		}
예제 #55
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;
		}
예제 #56
0
		protected override LNode GenerateTest(IPGTerminalSet set, LNode subject, Symbol setName)
		{
			return ((PGIntSet)set).GenerateTest(subject, setName);
		}
예제 #57
0
파일: PGIntSet.cs 프로젝트: Shaykh/Loyc
		public bool Equals(IPGTerminalSet other)
		{
			if (other is IntSet)
				return Equals((IntSet)other);
			else
				return this.SlowEquals(other);
		}
예제 #58
0
		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;
		}
예제 #59
0
파일: PGIntSet.cs 프로젝트: Shaykh/Loyc
		IPGTerminalSet IPGTerminalSet.IntersectionCore(IPGTerminalSet other, bool subtract, bool subtractThis)
		{
			var other_ = other as IntSet;
			if (other_ == null) return null;
			return Intersection(other_, subtract, subtractThis);
		}
예제 #60
0
		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();
		}