示例#1
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())));
        }
示例#2
0
            private RWList <LNode> GenerateExtraMatchingCode(Pair <LNode, string>[] matchingCode, int separateCount, ref Symbol loopType)
            {
                var extraMatching = new RWList <LNode>();

                if (separateCount != 0)
                {
                    for (int i = 0; i < matchingCode.Length; i++)
                    {
                        if (matchingCode[i].B != null)                         // split out this case
                        {
                            var label = F.Id(matchingCode[i].B);

                            // break/continue; matchN: matchingCode[i].A;
                            if (extraMatching.Count > 0)
                            {
                                extraMatching.Add(GetContinueStmt(loopType));
                            }
                            extraMatching.Add(F.Call(S.Label, label));
                            extraMatching.Add(matchingCode[i].A);
                            //skipCount++;

                            // put @@{ goto matchN; } in prediction tree
                            matchingCode[i].A = F.Call(S.Goto, label);
                        }
                    }
                }
                return(extraMatching);
            }
示例#3
0
 public virtual void Done()
 {
     _classBody    = null;
     F             = null;
     _setDeclNames = null;
     _currentRule  = null;
 }
示例#4
0
        public static LNode UnpackTuple(LNode node, IMessageSink sink)
        {
            var a = node.Args;

            if (a.Count == 2 && a[0].CallsMin(S.Tuple, 1))
            {
                var output = new RWList <LNode>();
                var tuple  = a[0].Args;
                var rhs    = a[1];

                // Avoid evaluating rhs more than once, if it doesn't look like a simple variable
                rhs = MaybeAddTempVarDecl(rhs, output);

                for (int i = 0; i < tuple.Count; i++)
                {
                    var itemi = F.Dot(rhs, F.Id(GSymbol.Get("Item" + (i + 1))));
                    if (tuple[i].Calls(S.Var, 2))
                    {
                        output.Add(F.Var(tuple[i].Args[0], tuple[i].Args[1], itemi));
                    }
                    else
                    {
                        output.Add(F.Call(S.Assign, tuple[i], itemi));
                    }
                }
                return(F.Call(S.Splice, output.ToRVList()));
            }
            return(null);
        }
示例#5
0
			public void Generate(Rule rule)
			{
				CGH.BeginRule(rule);
				_currentRule = rule;
				_target = new RWList<LNode>();
				_laVarsNeeded = 0;
				_separatedMatchCounter = _stopLabelCounter = 0;
				_recognizerMode = rule.IsRecognizer;
				_labelsInUse.Clear();

				Visit(rule.Pred);

				if (_laVarsNeeded != 0) {
					LNode laVars = F.Call(S.Var, CGH.LAType());
					for (int i = 0; _laVarsNeeded != 0; i++, _laVarsNeeded >>= 1)
						if ((_laVarsNeeded & 1) != 0)
							laVars = laVars.PlusArg(F.Id("la" + i.ToString()));
					_target.Insert(0, laVars);
				}

				LNode method;
				if (rule.TryWrapperName != null) {
					Debug.Assert(rule.IsRecognizer);
					method = CGH.CreateTryWrapperForRecognizer(rule);
					_classBody.SpliceAdd(method, S.Splice);
				}

				method = CGH.CreateRuleMethod(rule, _target.ToRVList());
				_classBody.SpliceAdd(method, S.Splice);
			}
示例#6
0
        public void StmtList(ref RWList <LNode> exprs)
        {
            TT la0;

            exprs = exprs ?? new RWList <LNode>();
            var next = SuperExprOptUntil(TT.Semicolon);

            // Line 187: (TT.Semicolon SuperExprOptUntil)*
            for (;;)
            {
                la0 = LA0;
                if (la0 == TT.Semicolon)
                {
                    exprs.Add(next);
                    Skip();
                    next = SuperExprOptUntil(TT.Semicolon);
                }
                else
                {
                    break;
                }
            }
            if ((next != (object)MissingExpr))
            {
                exprs.Add(next);
            }
        }
示例#7
0
        public IListAndListSource <LNode> ParseExprs()
        {
            var list = new RWList <LNode>();

            ExprList(ref list);
            return(list);
        }
示例#8
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);
        }
示例#9
0
 private void AddSwitchHandler(LNode branch, RWList <LNode> stmts)
 {
     stmts.SpliceAdd(branch, S.Splice);
     if (EndMayBeReachable(branch))
     {
         stmts.Add(F.Call(S.Break));
     }
 }
示例#10
0
            void VisitWithNewTarget(Pred toBeVisited, RWList <LNode> target)
            {
                var old = _target;

                _target = target;
                Visit(toBeVisited);
                _target = old;
            }
示例#11
0
 protected RWList <LNode> AppendInitializersInside(Token group, RWList <LNode> list)
 {
     if (Down(group.Children))
     {
         InitializerList(list);
         return(Up(list));
     }
     return(list);
 }
示例#12
0
 protected RWList <LNode> AppendExprsInside(Token group, RWList <LNode> list, bool allowTrailingComma = false, bool allowUnassignedVarDecl = false)
 {
     if (Down(group.Children))
     {
         ExprList(list, allowTrailingComma, allowUnassignedVarDecl);
         return(Up(list));
     }
     return(list);
 }
示例#13
0
        public IListSource <LNode> ParseExprs()
        {
            var list = new RWList <LNode>();

            try {
                ExprList(list);
            } catch (Exception ex) { UnhandledException(ex); }
            return(list);
        }
示例#14
0
        public IListSource <LNode> ParseStmtsGreedy()
        {
            var list = new RWList <LNode>();

            try {
                StmtList(list);
            } catch (Exception ex) { UnhandledException(ex); }
            return(list);
        }
示例#15
0
 protected RWList <LNode> AppendExprsInside(Token group, RWList <LNode> list)
 {
     if (Down(group.Children))
     {
         ExprList(ref list);
         return(Up(list));
     }
     return(list);
 }
示例#16
0
 protected RWList <LNode> AppendStmtsInside(Token group, RWList <LNode> list)
 {
     if (Down(group.Children))
     {
         StmtList(list);
         return(Up(list));
     }
     return(list);
 }
示例#17
0
 // Restructures an RVList if it has degraded severely. Time: O(Count)
 void AutoOptimize <T>(ref RVList <T> v)
 {
     // Check if the chain length substantially exceeds Sqrt(v.Count)
     if ((v.BlockChainLength - 10) * (v.BlockChainLength - 10) > v.Count)
     {
         RWList <T> w = v.ToRWList();                 // This is basically a no-op
         w[0] = w[0];                                 // Restructure & make mutable
         v    = w.ToRVList();                         // Mark immutable again
     }
 }
示例#18
0
 // Used to avoid evaluating `value` more than once by creating a
 // temporary variable to hold the value. If `value` looks like a
 // simple variable, this fn returns value and leaves output unchanged.
 static LNode MaybeAddTempVarDecl(LNode value, RWList <LNode> output)
 {
     if (value.IsCall || char.IsUpper(value.Name.Name.TryGet(0, '\0')))
     {
         LNode tmpId;
         output.Add(TempVarDecl(value, out tmpId));
         return(tmpId);
     }
     return(value);
 }
示例#19
0
		public static LNode unroll(LNode var, LNode cases, LNode body, IMessageSink sink)
		{
			if (!cases.Calls(S.Tuple) && !cases.Calls(S.Braces))
				return Reject(sink, cases, "unroll: the right-hand side of 'in' should be a tuple");

			// Maps identifiers => replacements. The integer counts how many times replacement occurred.
			var replacements = InternalList<Triplet<Symbol, LNode, int>>.Empty;
			if (var.IsId && !var.HasPAttrs()) {
				replacements.Add(Pair.Create(var.Name, (LNode)LNode.Missing, 0));
			} else {
				var vars = var.Args;
				if ((var.Calls(S.Tuple) || var.Calls(S.Braces)) && vars.All(a => a.IsId && !a.HasPAttrs())) {
					replacements = new Triplet<Symbol, LNode, int>[vars.Count].AsInternalList();
					for (int i = 0; i < vars.Count; i++) {
						replacements.InternalArray[i].A = vars[i].Name;
						
						// Check for duplicate names
						for (int j = 0; j < i; j++)
							if (replacements[i].A == replacements[j].A && replacements[i].A.Name != "_")
								sink.Write(Severity.Error, vars[i], "unroll: duplicate name in the left-hand tuple"); // non-fatal
					}
				} else
					return Reject(sink, cases, "unroll: the left-hand side of 'in' should be a simple identifier or a tuple of simple identifiers.");
			}

			UnrollCtx ctx = new UnrollCtx { Replacements = replacements };
			RWList<LNode> output = new RWList<LNode>();
			int iteration = 0;
			foreach (LNode replacement in cases.Args)
			{
				iteration++;
				bool tuple = replacement.Calls(S.Tuple) || replacement.Calls(S.Braces);
				int count = tuple ? replacement.ArgCount : 1;
				if (replacements.Count != count)
				{
					sink.Write(Severity.Error, replacement, "unroll, iteration {0}: Expected {1} replacement items, got {2}", iteration, replacements.Count, count);
					if (count < replacements.Count)
						continue; // too few
				}
				for (int i = 0; i < replacements.Count; i++)
					replacements.InternalArray[i].B = tuple ? replacement.Args[i] : replacement;

				if (body.Calls(S.Braces)) {
					foreach (LNode stmt in body.Args)
						output.Add(ctx.Replace(stmt));
				} else
					output.Add(ctx.Replace(body));
			}

			foreach (var r in replacements)
				if (r.C == 0 && !r.A.Name.StartsWith("_"))
					sink.Write(Severity.Warning, var, "Replacement variable '{0}' was never used", r.A);
			
			return body.With(S.Splice, output.ToRVList());
		}
示例#20
0
        public LNode Vars(LNode type, params LNode[] namesWithValues)
        {
            type = type ?? _Missing;
            var list = new RWList <LNode>()
            {
                type
            };

            list.AddRange(namesWithValues);
            return(Call(S.Var, list.ToRVList()));
        }
示例#21
0
 public static void SpliceInsert(this RWList <LNode> list, int index, LNode node, Symbol listName)
 {
     if (node.Calls(listName))
     {
         list.InsertRange(index, node.Args);
     }
     else
     {
         list.Insert(index, node);
     }
 }
示例#22
0
 public static void SpliceAdd(this RWList <LNode> list, LNode node, Symbol listName)
 {
     if (node.Calls(listName))
     {
         list.AddRange(node.Args);
     }
     else
     {
         list.Add(node);
     }
 }
示例#23
0
        protected virtual LNode ParseBraces(Token t, int endIndex)
        {
            RWList <LNode> list = new RWList <LNode>();

            if (Down(t.Children))
            {
                StmtList(ref list);
                Up();
            }
            return(F.Braces(list.ToRVList(), t.StartIndex, endIndex));
        }
示例#24
0
                      Mode = MacroMode.ProcessChildrenBefore)]   // post-normal-macro-expansion
        public static LNode with(LNode fn, IMessageSink sink)
        {
            LNode braces;

            if (fn.ArgCount != 2 || !(braces = fn.Args[1]).Calls(S.Braces))
            {
                return(null);
            }

            LNode          tmp   = F.Id(NextTempName());
            RWList <LNode> stmts = braces.Args.ToRWList();

            stmts = stmts.SmartSelect(stmt =>
                                      stmt.FindAndReplace(expr => {
                if (expr.Calls(S.Dot, 1))
                {
                    return(expr.WithArgs(new RVList <LNode>(tmp, expr.Args.Last)));
                }
                return(null);
            }));
            stmts.Insert(0, F.Var(null, tmp.Name, fn.Args[0]));
            return(F.Braces(stmts.ToRVList()));
        }
示例#25
0
        protected LNode SingleExprInside(Token group, string stmtType, RWList <LNode> list = null, bool allowUnassignedVarDecl = false)
        {
            list = list ?? new RWList <LNode>();
            int oldCount = list.Count;

            AppendExprsInside(group, list, false, allowUnassignedVarDecl);
            if (list.Count != oldCount + 1)
            {
                if (list.Count <= oldCount)
                {
                    LNode result = F.Id(S.Missing, group.StartIndex + 1, group.StartIndex + 1);
                    list.Add(result);
                    Error(result, "Missing expression inside '{0}'", stmtType);
                    return(result);
                }
                else
                {
                    Error(list[1], "There should be only one expression inside '{0}'", stmtType);
                    list.Resize(oldCount + 1);
                }
            }
            return(list[0]);
        }
示例#26
0
            public void Generate(Rule rule)
            {
                CGH.BeginRule(rule);
                _currentRule           = rule;
                _target                = new RWList <LNode>();
                _laVarsNeeded          = 0;
                _separatedMatchCounter = _stopLabelCounter = 0;
                _recognizerMode        = rule.IsRecognizer;
                _labelsInUse.Clear();

                Visit(rule.Pred);

                if (_laVarsNeeded != 0)
                {
                    LNode laVars = F.Call(S.Var, CGH.LAType());
                    for (int i = 0; _laVarsNeeded != 0; i++, _laVarsNeeded >>= 1)
                    {
                        if ((_laVarsNeeded & 1) != 0)
                        {
                            laVars = laVars.PlusArg(F.Id("la" + i.ToString()));
                        }
                    }
                    _target.Insert(0, laVars);
                }

                LNode method;

                if (rule.TryWrapperName != null)
                {
                    Debug.Assert(rule.IsRecognizer);
                    method = CGH.CreateTryWrapperForRecognizer(rule);
                    _classBody.SpliceAdd(method, S.Splice);
                }

                method = CGH.CreateRuleMethod(rule, _target.ToRVList());
                _classBody.SpliceAdd(method, S.Splice);
            }
示例#27
0
        public static LNode UnpackTuple(LNode node, IMessageSink sink)
        {
            var a = node.Args;

            if (a.Count == 2 && a[0].CallsMin(S.Tuple, 1))
            {
                var  stmts    = new RWList <LNode>();
                var  tuple    = a[0].Args;
                var  rhs      = a[1];
                bool needTemp = rhs.IsCall || !char.IsLower(rhs.Name.Name.TryGet(0, '\0'));
                if (needTemp)
                {
                    LNode tmp = F.Id(NextTempName());
                    stmts.Add(F.Var(F._Missing, tmp.Name, rhs));
                    rhs = tmp;
                }
                for (int i = 0; i < tuple.Count; i++)
                {
                    stmts.Add(F.Call(S.Assign, tuple[i], F.Dot(rhs, F.Id(GSymbol.Get("Item" + (i + 1))))));
                }
                return(F.Call(S.Splice, stmts.ToRVList()));
            }
            return(null);
        }
示例#28
0
		private void AddSwitchHandler(LNode branch, RWList<LNode> stmts)
		{
			stmts.SpliceAdd(branch, S.Splice);
			if (EndMayBeReachable(branch))
				stmts.Add(F.Call(S.Break));
		}
示例#29
0
		LNode Atom(Precedence context, ref RWList<LNode> attrs)
		{
			TT la0, la1;
			// line 39
			LNode e = MissingExpr;
			LNode _;
			// Line 41: ( (TT.Id (&{t.EndIndex == LT($LI).StartIndex && context.CanParse(P.Primary)} TT.LParen TT.RParen / ) | (TT.Number|TT.OtherLit|TT.SQString|TT.String|TT.Symbol) | TT.At TT.LBrack TT.RBrack | (TT.PrefixOp|TT.PreSufOp) Expr) | (TT.Colon TT.Indent TT.Dedent greedy(TT.Colon)? / &{context != P.SuperExpr} (TT.Assignment|TT.BQString|TT.Colon|TT.Dot|TT.NormalOp|TT.Not) Expr) | TT.LBrack TT.RBrack Atom | TT.LParen TT.RParen | TT.LBrace TT.RBrace )
			do {
				switch ((TT) LA0) {
				case TT.Id:
					{
						var t = MatchAny();
						// Line 42: (&{t.EndIndex == LT($LI).StartIndex && context.CanParse(P.Primary)} TT.LParen TT.RParen / )
						la0 = (TT) LA0;
						if (la0 == TT.LParen) {
							if (t.EndIndex == LT(0).StartIndex && context.CanParse(P.Primary)) {
								la1 = (TT) LA(1);
								if (la1 == TT.RParen) {
									var p = MatchAny();
									var rp = MatchAny();
									// line 44
									e = ParseCall(t, p, rp.EndIndex);
								} else
									// line 45
									e = F.Id((Symbol) t.Value, t.StartIndex, t.EndIndex);
							} else
								// line 45
								e = F.Id((Symbol) t.Value, t.StartIndex, t.EndIndex);
						} else
							// line 45
							e = F.Id((Symbol) t.Value, t.StartIndex, t.EndIndex);
					}
					break;
				case TT.Number:
				case TT.OtherLit:
				case TT.SQString:
				case TT.String:
				case TT.Symbol:
					{
						var t = MatchAny();
						// line 49
						e = F.Literal(t.Value, t.StartIndex, t.EndIndex);
					}
					break;
				case TT.At:
					{
						Skip();
						var t = Match((int) TT.LBrack);
						var rb = Match((int) TT.RBrack);
						// line 52
						e = F.Literal(t.Children, t.StartIndex, rb.EndIndex);
					}
					break;
				case TT.PrefixOp:
				case TT.PreSufOp:
					{
						var t = MatchAny();
						e = Expr(PrefixPrecedenceOf(t), out _);
						e = F.Call((Symbol) t.Value, e, t.StartIndex, e.Range.EndIndex);
						e.BaseStyle = NodeStyle.Operator;
					}
					break;
				case TT.Colon:
					{
						if (context != P.SuperExpr) {
							switch ((TT) LA(1)) {
							case TT.Indent:
								goto match5;
							case TT.Assignment:
							case TT.At:
							case TT.BQString:
							case TT.Colon:
							case TT.Dot:
							case TT.Id:
							case TT.LBrace:
							case TT.LBrack:
							case TT.LParen:
							case TT.NormalOp:
							case TT.Not:
							case TT.Number:
							case TT.OtherLit:
							case TT.PrefixOp:
							case TT.PreSufOp:
							case TT.SQString:
							case TT.String:
							case TT.Symbol:
								goto match6;
							default:
								goto error;
							}
						} else
							goto match5;
					}
				case TT.Assignment:
				case TT.BQString:
				case TT.Dot:
				case TT.NormalOp:
				case TT.Not:
					goto match6;
				case TT.LBrack:
					{
						var t = MatchAny();
						Match((int) TT.RBrack);
						// line 69
						attrs = AppendExprsInside(t, attrs);
						e = Atom(context, ref attrs);
					}
					break;
				case TT.LParen:
					{
						var t = MatchAny();
						var rp = Match((int) TT.RParen);
						// line 72
						e = ParseParens(t, rp.EndIndex);
					}
					break;
				case TT.LBrace:
					{
						var t = MatchAny();
						var rb = Match((int) TT.RBrace);
						// line 74
						e = ParseBraces(t, rb.EndIndex);
					}
					break;
				default:
					goto error;
				}
				break;
			match5:
				{
					Skip();
					var t = Match((int) TT.Indent);
					var rb = Match((int) TT.Dedent);
					// Line 59: greedy(TT.Colon)?
					la0 = (TT) LA0;
					if (la0 == TT.Colon)
						Skip();
					// line 60
					e = ParseBraces(t, rb.EndIndex);
				}
				break;
			match6:
				{
					Check(context != P.SuperExpr, "context != P.SuperExpr");
					var t = MatchAny();
					e = Expr(PrefixPrecedenceOf(t), out _);
					e = F.Call((Symbol) t.Value, e, t.StartIndex, e.Range.EndIndex);
					e.BaseStyle = NodeStyle.Operator;
				}
				break;
			error:
				{
					// line 76
					e = F.Id(S.Missing, LT0.StartIndex, LT0.StartIndex);
					Error(0, "Expected an expression here");
				}
			} while (false);
			// line 80
			return e;
		}
示例#30
0
		void StmtList(RWList<LNode> list)
		{
			TokenType la0;
			// Line 1719: (~(EOF) => Stmt)*
			for (;;) {
				la0 = LA0;
				if (la0 != EOF)
					list.Add(Stmt());
				else
					break;
			}
			Skip();
		}
示例#31
0
            protected LNode GeneratePredictionTreeCode(PredictionTree tree, Pair <LNode, string>[] matchingCode, ref Symbol haveLoop)
            {
                var braces = F.Braces();

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

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

                // From the prediction table, we can generate either an if-else chain:
                //
                //   if (la0 >= '0' && la0 <= '7') sub_tree_1();
                //   else if (la0 == '-') sub_tree_2();
                //   else break;
                //
                // or a switch statement:
                //
                //   switch(la0) {
                //   case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
                //     sub_tree_1();
                //     break;
                //   case '-':
                //     sub_tree_2();
                //     break;
                //   default:
                //     goto breakfor;
                //   }
                //
                // Assertion levels always need an if-else chain; lookahead levels
                // consider the complexity of switch vs if and decide which is most
                // appropriate. Generally "if" is slower, but a switch may require
                // too many labels since it doesn't support ranges like "la0 >= 'a'
                // && la0 <= 'z'".
                //
                // This class makes if-else chains directly (using IPGTerminalSet.
                // GenerateTest() to generate the test expressions), but the code
                // 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".

                RWList <LNode> block       = new RWList <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.ToRVList()));
            }
示例#32
0
		LNode DoStmt(int startIndex)
		{
			Skip();
			var block = Stmt();
			Match((int) TT.@while);
			var p = Match((int) TT.LParen);
			Match((int) TT.RParen);
			var end = Match((int) TT.Semicolon);
			#line 1531 "EcsParserGrammar.les"
			var parts = new RWList<LNode> { 
				block
			};
			SingleExprInside(p, "while (...)", parts);
			return F.Call(S.DoWhile, parts.ToRVList(), startIndex, end.EndIndex);
			#line default
		}
示例#33
0
		void ArgList(RWList<LNode> list)
		{
			TokenType la0;
			// Line 1691: nongreedy(ExprOpt (TT.Comma ExprOpt)*)?
			la0 = LA0;
			if (la0 == EOF)
				;
			else {
				list.Add(ExprOpt(true));
				// Line 1692: (TT.Comma ExprOpt)*
				for (;;) {
					la0 = LA0;
					if (la0 == TT.Comma) {
						Skip();
						list.Add(ExprOpt(true));
					} else if (la0 == EOF)
						break;
					else {
						#line 1693 "EcsParserGrammar.les"
						Error("Syntax error in argument list");
						#line default
						// Line 1693: (~(EOF|TT.Comma))*
						for (;;) {
							la0 = LA0;
							if (!(la0 == EOF || la0 == TT.Comma))
								Skip();
							else
								break;
						}
					}
				}
			}
			Skip();
		}
示例#34
0
		public static LNode @try(LNode node, IMessageSink sink)
		{
			if (!node.IsCall)
				return null;

			// try(code, catch, Exception::e, handler, catch, ..., finally, handler)
			// ...becomes...
			// #try(#{ stmt1; stmt2; ... }, #catch(#var(Exception, e), handler), #finally(handler))
			LNode finallyCode = null;
			RWList<LNode> clauses = new RWList<LNode>();
			var parts = node.Args;
			
			for (int i = parts.Count-2; i >= 1; i -= 2)
			{
				var p = parts[i];
				if (p.IsIdNamed(_finally)) {
					if (clauses.Count != 0 || finallyCode != null)
						sink.Write(Severity.Error, p, "The «finally» clause must come last, there can only be one of them.");
					finallyCode = parts[i+1];
				} else if (p.Name == _catch) {
					if (p.ArgCount > 0) {
						// This is a normal catch clause
						clauses.Insert(0, F.Call(S.Catch, F.Call(S.Splice, p.Args), parts[i + 1]));
					} else {
						// This is a catch-all clause (the type argument is missing)
						if (clauses.Count != 0)
							sink.Write(Severity.Error, p, "The catch-all clause must be the last «catch» clause.");
						clauses.Add(F.Call(S.Catch, F._Missing, parts[i + 1]));
					}
				} else if (i > 1 && parts[i-1].IsIdNamed(_catch)) {
					// This is a normal catch clause
					clauses.Insert(0, F.Call(S.Catch, AutoRemoveParens(p), parts[i+1]));
					i--;
				} else {
					return Reject(sink, p, "Expected «catch» or «finally» clause here. Clause is missing or malformed.");
				}
				if (i == 2)
					return Reject(sink, parts[1], "Expected «catch» or «finally» clause here. Clause is missing or malformed.");
			}
			if (clauses.Count == 0 && finallyCode == null) {
				Debug.Assert(node.ArgCount <= 1);
				return Reject(sink, node, "Missing «catch, Type, Code» or «finally, Code» clause");
			}
			if (finallyCode != null)
				clauses.Add(F.Call(S.Finally, finallyCode));
			clauses.Insert(0, node.Args[0]);
			return node.With(S.Try, clauses.ToRVList());
		}
示例#35
0
		LNode AssemblyOrModuleAttribute(int startIndex, RVList<LNode> attrs)
		{
			Check(Down(0) && Up(Try_Scan_AsmOrModLabel(0)), "Down($LI) && Up(Try_Scan_AsmOrModLabel(0))");
			var lb = MatchAny();
			var rb = Match((int) TT.RBrack);
			#line 1226 "EcsParserGrammar.les"
			Down(lb);
			#line default
			var kind = AsmOrModLabel();
			#line 1228 "EcsParserGrammar.les"
			var list = new RWList<LNode>();
			#line default
			ExprList(list);
			#line 1231 "EcsParserGrammar.les"
			Up();
			var r = F.Call(kind.Value == _module ? S.Module : S.Assembly, list.ToRVList(), startIndex, rb.EndIndex);
			return r.WithAttrs(attrs);
			#line default
		}
示例#36
0
		[LexicalMacro("matchCode (var) { case ...: ... }; // In LES, use a => b instead of case a: b", "Attempts to match and deconstruct a Loyc tree against a series of cases with patterns, e.g. " + "`case $a + $b:` expects a tree that calls `+` with two parameters, placed in new variables called a and b. " + "`break` is not required or recognized at the end of each case's handler (code block). " + "Use `$(..x)` to gather zero or more parameters into a list `x`. " + "Use `case pattern1, pattern2:` in EC# to handle multiple cases with the same handler.")] public static LNode matchCode(LNode node, IMacroContext context)
		{
			var args_body = context.GetArgsAndBody(true);
			RVList<LNode> args = args_body.Item1, body = args_body.Item2;
			if (args.Count != 1 || body.Count < 1)
				return null;
			var cases = GetCases(body, context.Sink);
			if (cases.IsEmpty)
				return null;
			var output = new RWList<LNode>();
			var @var = MaybeAddTempVarDecl(args[0], output);
			var ifClauses = new List<Pair<LNode,LNode>>();
			var cmc = new CodeMatchContext { 
				Context = context
			};
			foreach (var @case in cases) {
				cmc.ThenClause.Clear();
				LNode testExpr = null;
				if (@case.Key.Count > 0) {
					if (cmc.IsMultiCase = @case.Key.Count > 1) {
						cmc.UsageCounters.Clear();
						testExpr = @case.Key.Aggregate((LNode) null, (test, pattern) => {
							test = LNode.MergeBinary(test, cmc.MakeTopTestExpr(pattern, @var), S.Or);
							return test;
						});
						foreach (var pair in cmc.UsageCounters.Where(p => p.Value < @case.Key.Count)) {
							if (cmc.NodeVars.ContainsKey(pair.Key))
								cmc.NodeVars[pair.Key] = true;
							if (cmc.ListVars.ContainsKey(pair.Key))
								cmc.ListVars[pair.Key] = true;
						}
					} else
						testExpr = cmc.MakeTopTestExpr(@case.Key[0], @var);
				}
				var handler = @case.Value;
				if (cmc.ThenClause.Count > 0)
					handler = LNode.MergeLists(F.Braces(cmc.ThenClause), handler, S.Braces);
				ifClauses.Add(Pair.Create(testExpr, handler));
			}
			LNode ifStmt = null;
			for (int i = ifClauses.Count - 1; i >= 0; i--) {
				if (ifClauses[i].Item1 == null) {
					if (ifStmt == null)
						ifStmt = ifClauses[i].Item2;
					else
						context.Sink.Write(Severity.Error, node, "The default case must appear last, and there can be only one.");
				} else {
					if (ifStmt == null)
						ifStmt = F.Call(S.If, ifClauses[i].Item1, ifClauses[i].Item2);
					else
						ifStmt = F.Call(S.If, ifClauses[i].Item1, ifClauses[i].Item2, ifStmt);
				}
			}
			if (cmc.NodeVars.Count > 0)
				output.Add(F.Call(S.Var, Range.Single(F.Id("LNode")).Concat(cmc.NodeVars.OrderBy(v => v.Key.Name).Select(kvp => kvp.Value ? F.Call(S.Assign, F.Id(kvp.Key), F.Null) : F.Id(kvp.Key)))));
			if (cmc.ListVars.Count > 0) {
				LNode type = LNode.Call(CodeSymbols.Of, LNode.List(LNode.Id((Symbol) "RVList"), LNode.Id((Symbol) "LNode")));
				output.Add(F.Call(S.Var, Range.Single(type).Concat(cmc.ListVars.OrderBy(v => v.Key.Name).Select(kvp => kvp.Value ? LNode.Call(CodeSymbols.Assign, LNode.List(F.Id(kvp.Key), LNode.Call(CodeSymbols.Default, LNode.List(type)))).SetStyle(NodeStyle.Operator) : F.Id(kvp.Key)))));
			}
			if (output.Count == 0)
				return ifStmt;
			else {
				output.Add(ifStmt);
				return F.Braces(output.ToRVList());
			}
		}
示例#37
0
		public void StmtList(ref RWList<LNode> exprs)
		{
			TT la0;
			// line 192
			exprs = exprs ?? new RWList<LNode>();
			var next = SuperExprOptUntil(TT.Semicolon);
			// Line 194: (TT.Semicolon SuperExprOptUntil)*
			for (;;) {
				la0 = (TT) LA0;
				if (la0 == TT.Semicolon) {
					// line 194
					exprs.Add(next);
					Skip();
					next = SuperExprOptUntil(TT.Semicolon);
				} else
					break;
			}
			// line 198
			if ((next != (object) MissingExpr))
				exprs.Add(next);
		}
示例#38
0
        public static LNode unroll(LNode var, LNode cases, LNode body, IMessageSink sink)
        {
            if (!cases.Calls(S.Tuple) && !cases.Calls(S.Braces))
            {
                return(Reject(sink, cases, "unroll: the right-hand side of 'in' should be a tuple"));
            }

            // Maps identifiers => replacements. The integer counts how many times replacement occurred.
            var replacements = InternalList <Triplet <Symbol, LNode, int> > .Empty;

            if (var.IsId && !var.HasPAttrs())
            {
                replacements.Add(Pair.Create(var.Name, (LNode)LNode.Missing, 0));
            }
            else
            {
                var vars = var.Args;
                if ((var.Calls(S.Tuple) || var.Calls(S.Braces)) && vars.All(a => a.IsId && !a.HasPAttrs()))
                {
                    replacements = new Triplet <Symbol, LNode, int> [vars.Count].AsInternalList();
                    for (int i = 0; i < vars.Count; i++)
                    {
                        replacements.InternalArray[i].A = vars[i].Name;

                        // Check for duplicate names
                        for (int j = 0; j < i; j++)
                        {
                            if (replacements[i].A == replacements[j].A && replacements[i].A.Name != "_")
                            {
                                sink.Write(Severity.Error, vars[i], "unroll: duplicate name in the left-hand tuple");                                 // non-fatal
                            }
                        }
                    }
                }
                else
                {
                    return(Reject(sink, cases, "unroll: the left-hand side of 'in' should be a simple identifier or a tuple of simple identifiers."));
                }
            }

            UnrollCtx ctx = new UnrollCtx {
                Replacements = replacements
            };
            RWList <LNode> output = new RWList <LNode>();
            int iteration         = 0;
            foreach (LNode replacement in cases.Args)
            {
                iteration++;
                bool tuple = replacement.Calls(S.Tuple) || replacement.Calls(S.Braces);
                int  count = tuple ? replacement.ArgCount : 1;
                if (replacements.Count != count)
                {
                    sink.Write(Severity.Error, replacement, "unroll, iteration {0}: Expected {1} replacement items, got {2}", iteration, replacements.Count, count);
                    if (count < replacements.Count)
                    {
                        continue;                         // too few
                    }
                }
                for (int i = 0; i < replacements.Count; i++)
                {
                    replacements.InternalArray[i].B = tuple ? replacement.Args[i] : replacement;
                }

                if (body.Calls(S.Braces))
                {
                    foreach (LNode stmt in body.Args)
                    {
                        output.Add(ctx.Replace(stmt));
                    }
                }
                else
                {
                    output.Add(ctx.Replace(body));
                }
            }

            foreach (var r in replacements)
            {
                if (r.C == 0 && !r.A.Name.StartsWith("_"))
                {
                    sink.Write(Severity.Warning, var, "Replacement variable '{0}' was never used", r.A);
                }
            }

            return(body.With(S.Splice, output.ToRVList()));
        }
示例#39
0
		LNode PrimaryExpr()
		{
			TokenType la1;
			var e = Atom();
			// Line 506: greedy( (TT.ColonColon|TT.Dot|TT.PtrArrow|TT.QuickBind) Atom / PrimaryExpr_NewStyleCast / TT.LParen TT.RParen | TT.At TT.LBrace TT.RBrace | TT.LBrack TT.RBrack | TT.IncDec | &(TParams ~(TT.ContextualKeyword|TT.Id)) ((TT.LT|TT.Not) | TT.Dot TT.LBrack) => TParams | BracedBlock )*
			for (;;) {
				switch (LA0) {
				case TT.Dot:
					{
						if (Try_PrimaryExpr_Test0(0)) {
							la1 = LA(1);
							if (PrimaryExpr_set0.Contains((int) la1))
								goto match1;
							else
								TParams(ref e);
						} else
							goto match1;
					}
					break;
				case TT.ColonColon:
				case TT.PtrArrow:
				case TT.QuickBind:
					goto match1;
				case TT.LParen:
					{
						if (Down(0) && Up(LA0 == TT.@as || LA0 == TT.@using || LA0 == TT.PtrArrow))
							e = PrimaryExpr_NewStyleCast(e);
						else {
							var lp = MatchAny();
							var rp = Match((int) TT.RParen);
							#line 510 "EcsParserGrammar.les"
							e = F.Call(e, ExprListInside(lp), e.Range.StartIndex, rp.EndIndex);
							#line default
						}
					}
					break;
				case TT.At:
					{
						Skip();
						var lb = Match((int) TT.LBrace);
						var rb = Match((int) TT.RBrace);
						#line 512 "EcsParserGrammar.les"
						var stmts = StmtListInside(lb).ToRVList();
						e = SetBaseStyle(F.Call(e, stmts, e.Range.StartIndex, rb.EndIndex), NodeStyle.Statement);
						#line default
					}
					break;
				case TT.LBrack:
					{
						var lb = MatchAny();
						var rb = Match((int) TT.RBrack);
						var list = new RWList<LNode> { 
							e
						};
						e = F.Call(S.Bracks, AppendExprsInside(lb, list).ToRVList(), e.Range.StartIndex, rb.EndIndex);
					}
					break;
				case TT.IncDec:
					{
						var t = MatchAny();
						#line 518 "EcsParserGrammar.les"
						e = F.Call(t.Value == S.PreInc ? S.PostInc : S.PostDec, e, e.Range.StartIndex, t.EndIndex);
						#line default
					}
					break;
				case TT.LT:
					{
						if (Try_PrimaryExpr_Test0(0))
							TParams(ref e);
						else
							goto stop;
					}
					break;
				case TT.Not:
					TParams(ref e);
					break;
				case TT.LBrace:
					{
						var bb = BracedBlock();
						#line 522 "EcsParserGrammar.les"
						if ((!e.IsCall || e.BaseStyle == NodeStyle.Operator))
							e = F.Call(e, bb, e.Range.StartIndex, bb.Range.EndIndex);
						else
							e = e.WithArgs(e.Args.Add(bb)).WithRange(e.Range.StartIndex, bb.Range.EndIndex);
						#line default
					}
					break;
				default:
					goto stop;
				}
				continue;
			match1:
				{
					var op = MatchAny();
					var rhs = Atom();
					#line 507 "EcsParserGrammar.les"
					e = F.Call((Symbol) op.Value, e, rhs, e.Range.StartIndex, rhs.Range.EndIndex);
					#line default
				}
			}
		stop:;
			#line 528 "EcsParserGrammar.les"
			return e;
			#line default
		}
示例#40
0
		// Used to avoid evaluating `value` more than once by creating a 
		// temporary variable to hold the value. If `value` looks like a 
		// simple variable, this fn returns value and leaves output unchanged.
		static LNode MaybeAddTempVarDecl(LNode value, RWList<LNode> output)
		{
			if (value.IsCall || char.IsUpper(value.Name.Name.TryGet(0, '\0'))) {
				LNode tmpId;
				output.Add(TempVarDecl(value, out tmpId));
				return tmpId;
			}
			return value;
		}
示例#41
0
            // GENERATED CODE EXAMPLE: The methods in this region generate
            // the for(;;) loop in this example and everything inside it, except
            // the calls to Match() which are generated by Visit(TerminalPred).
            // The generated code uses "goto" and "match" blocks in some cases
            // to avoid code duplication. This occurs when the matching code
            // requires multiple statements AND appears more than once in the
            // prediction tree. Otherwise, matching is done "inline" during
            // prediction. We generate a for(;;) loop for (...)*, and in certain
            // cases, we generates a do...while(false) loop for (...)?.
            //
            // rule Foo ==> @[ (('a'|'A') 'A')* 'a'..'z' 'a'..'z' ];
            // public void Foo()
            // {
            //     int la0, la1;
            //     for (;;) {
            //         la0 = LA(0);
            //         if (la0 == 'a') {
            //             la1 = LA(1);
            //             if (la1 == 'A')
            //                 goto match1;
            //             else
            //                 break;
            //         } else if (la0 == 'A')
            //             goto match1;
            //         else
            //             break;
            //         match1:
            //         {
            //             Match('A', 'a');
            //             Match('A');
            //         }
            //     }
            //     MatchRange('a', 'z');
            //     MatchRange('a', 'z');
            // }

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

                if (!needError && alts.ErrorBranch != null)
                {
                    LLPG.Output(Warning, alts, "The error branch will not be used because the other alternatives are exhaustive (cover all cases)");
                }
                bool userDefinedError = needError && 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 RWList <LNode>();
                    VisitWithNewTarget(alts.Arms[i], codeForThisArm);

                    matchingCode[i].A = F.Braces(codeForThisArm.ToRVList());
                    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 RWList <LNode>();
                    VisitWithNewTarget(alts.ErrorBranch, errorHandler);
                    matchingCode[i].A = F.Braces(errorHandler.ToRVList());
                    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._Missing, F._Missing, F._Missing, 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))
                                    .PlusAttr(F.Trivia(S.TriviaRawTextAfter, ";"));
                    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.TriviaSLCommentBefore, string.Format(" Line {0}: {1}", pos.Line, alts.ToString()));
                    if (_target.Count > oldCount)
                    {
                        _target[oldCount] = _target[oldCount].PlusAttr(comment);
                    }
                }
            }
示例#42
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;
		}
示例#43
0
		void TParams(ref LNode r)
		{
			TokenType la0;
			RWList<LNode> list = new RWList<LNode> { 
				r
			};
			Token end;
			// Line 195: ( TT.LT (DataType (TT.Comma DataType)*)? TT.GT | TT.Dot TT.LBrack TT.RBrack | TT.Not TT.LParen TT.RParen )
			la0 = LA0;
			if (la0 == TT.LT) {
				Skip();
				// Line 195: (DataType (TT.Comma DataType)*)?
				switch (LA0) {
				case TT.@operator:
				case TT.ContextualKeyword:
				case TT.Id:
				case TT.Substitute:
				case TT.TypeKeyword:
					{
						list.Add(DataType());
						// Line 195: (TT.Comma DataType)*
						for (;;) {
							la0 = LA0;
							if (la0 == TT.Comma) {
								Skip();
								list.Add(DataType());
							} else
								break;
						}
					}
					break;
				}
				end = Match((int) TT.GT);
			} else if (la0 == TT.Dot) {
				Skip();
				var t = Match((int) TT.LBrack);
				end = Match((int) TT.RBrack);
				#line 196 "EcsParserGrammar.les"
				list = AppendExprsInside(t, list);
				#line default
			} else {
				Match((int) TT.Not);
				var t = Match((int) TT.LParen);
				end = Match((int) TT.RParen);
				#line 197 "EcsParserGrammar.les"
				list = AppendExprsInside(t, list);
				#line default
			}
			#line 200 "EcsParserGrammar.les"
			int start = r.Range.StartIndex;
			r = F.Call(S.Of, list.ToRVList(), start, end.EndIndex);
			#line default
		}
示例#44
0
		LNode ArgList(Token lp, Token rp)
		{
			var list = new RWList<LNode>();
			if ((Down(lp.Children))) {
				ArgList(list);
				Up();
			}
			return F.List(list.ToRVList(), lp.StartIndex, rp.EndIndex);
		}
示例#45
0
		LNode BlockCallStmt()
		{
			TokenType la0;
			var id = MatchAny();
			Check(Try_BlockCallStmt_Test0(0), "( TT.LParen TT.RParen (TT.LBrace TT.RBrace | TT.Id) | TT.LBrace TT.RBrace | TT.Forward )");
			var args = new RWList<LNode>();
			LNode block;
			// Line 1459: ( TT.LParen TT.RParen (BracedBlock | TT.Id => Stmt) | TT.Forward ExprStart TT.Semicolon | BracedBlock )
			la0 = LA0;
			if (la0 == TT.LParen) {
				var lp = MatchAny();
				var rp = Match((int) TT.RParen);
				#line 1459 "EcsParserGrammar.les"
				AppendExprsInside(lp, args, false, true);
				#line default
				// Line 1460: (BracedBlock | TT.Id => Stmt)
				la0 = LA0;
				if (la0 == TT.LBrace)
					block = BracedBlock();
				else {
					block = Stmt();
					#line 1463 "EcsParserGrammar.les"
					if ((ColumnOf(block.Range.StartIndex) <= ColumnOf(id.StartIndex) || !char.IsLower(id.Value.ToString().FirstOrDefault()))) {
						ErrorSink.Write(_Warning, block, "Probable missing semicolon before this statement.");
					}
					#line default
				}
			} else if (la0 == TT.Forward) {
				var fwd = MatchAny();
				var e = ExprStart(true);
				Match((int) TT.Semicolon);
				#line 1470 "EcsParserGrammar.les"
				block = SetOperatorStyle(F.Call(S.Forward, e, fwd.StartIndex, e.Range.EndIndex));
				#line default
			} else
				block = BracedBlock();
			#line 1474 "EcsParserGrammar.les"
			args.Add(block);
			var result = F.Call((Symbol) id.Value, args.ToRVList(), id.StartIndex, block.Range.EndIndex);
			if (block.Calls(S.Forward, 1)) {
				result = F.Attr(_triviaForwardedProperty, result);
			}
			#line 1479 "EcsParserGrammar.les"
			return SetBaseStyle(result, NodeStyle.Special);
			#line default
		}
示例#46
0
		LNode NewExpr()
		{
			TokenType la0, la1;
			#line 419 "EcsParserGrammar.les"
			Token? majorDimension = null;
			int endIndex;
			var list = new RWList<LNode>();
			#line default
			var op = Match((int) TT.@new);
			// Line 425: ( &{(count = CountDims(LT($LI), @false)) > 0} TT.LBrack TT.RBrack TT.LBrace TT.RBrace | TT.LBrace TT.RBrace | DataType (TT.LParen TT.RParen (TT.LBrace TT.RBrace)? / (TT.LBrace TT.RBrace)?) )
			la0 = LA0;
			if (la0 == TT.LBrack) {
				Check((count = CountDims(LT(0), false)) > 0, "(count = CountDims(LT($LI), @false)) > 0");
				var lb = MatchAny();
				var rb = Match((int) TT.RBrack);
				#line 427 "EcsParserGrammar.les"
				var type = F.Id(S.GetArrayKeyword(count), lb.StartIndex, rb.EndIndex);
				#line default
				lb = Match((int) TT.LBrace);
				rb = Match((int) TT.RBrace);
				#line 430 "EcsParserGrammar.les"
				list.Add(LNode.Call(type, type.Range));
				AppendInitializersInside(lb, list);
				endIndex = rb.EndIndex;
				#line default
			} else if (la0 == TT.LBrace) {
				var lb = MatchAny();
				var rb = Match((int) TT.RBrace);
				#line 437 "EcsParserGrammar.les"
				list.Add(F._Missing);
				AppendInitializersInside(lb, list);
				endIndex = rb.EndIndex;
				#line default
			} else {
				var type = DataType(false, out majorDimension);
				// Line 449: (TT.LParen TT.RParen (TT.LBrace TT.RBrace)? / (TT.LBrace TT.RBrace)?)
				do {
					la0 = LA0;
					if (la0 == TT.LParen) {
						la1 = LA(1);
						if (la1 == TT.RParen) {
							var lp = MatchAny();
							var rp = MatchAny();
							#line 451 "EcsParserGrammar.les"
							if ((majorDimension != null)) {
								Error("Syntax error: unexpected constructor argument list (...)");
							}
							#line 454 "EcsParserGrammar.les"
							list.Add(F.Call(type, ExprListInside(lp).ToRVList(), type.Range.StartIndex, rp.EndIndex));
							endIndex = rp.EndIndex;
							#line default
							// Line 457: (TT.LBrace TT.RBrace)?
							la0 = LA0;
							if (la0 == TT.LBrace) {
								la1 = LA(1);
								if (la1 == TT.RBrace) {
									var lb = MatchAny();
									var rb = MatchAny();
									#line 459 "EcsParserGrammar.les"
									AppendInitializersInside(lb, list);
									endIndex = rb.EndIndex;
									#line default
								}
							}
						} else
							goto match2;
					} else
						goto match2;
					break;
				match2:
					{
						#line 466 "EcsParserGrammar.les"
						Token lb = op, rb = op;
						#line 466 "EcsParserGrammar.les"
						bool haveBraces = false;
						#line default
						// Line 467: (TT.LBrace TT.RBrace)?
						la0 = LA0;
						if (la0 == TT.LBrace) {
							la1 = LA(1);
							if (la1 == TT.RBrace) {
								lb = MatchAny();
								rb = MatchAny();
								#line 467 "EcsParserGrammar.les"
								haveBraces = true;
								#line default
							}
						}
						#line 469 "EcsParserGrammar.les"
						if ((majorDimension != null)) {
							list.Add(LNode.Call(type, ExprListInside(majorDimension.Value).ToRVList(), type.Range));
						} else {
							list.Add(LNode.Call(type, type.Range));
						}
						#line 474 "EcsParserGrammar.les"
						if ((haveBraces)) {
							AppendInitializersInside(lb, list);
							endIndex = rb.EndIndex;
						} else {
							endIndex = type.Range.EndIndex;
						}
						#line 480 "EcsParserGrammar.les"
						if ((!haveBraces && majorDimension == null)) {
							if (IsArrayType(type)) {
								Error("Syntax error: missing array size expression");
							} else {
								Error("Syntax error: expected constructor argument list (...) or initializers {...}");
							}
						}
						#line default
					}
				} while (false);
			}
			#line 490 "EcsParserGrammar.les"
			return F.Call(S.New, list.ToRVList(), op.StartIndex, endIndex);
			#line default
		}
示例#47
0
		void ExprList(RWList<LNode> list, bool allowTrailingComma = false, bool allowUnassignedVarDecl = false)
		{
			TokenType la0, la1;
			// Line 1682: nongreedy(ExprOpt (TT.Comma &{allowTrailingComma} EOF / TT.Comma ExprOpt)*)?
			la0 = LA0;
			if (la0 == EOF)
				;
			else {
				list.Add(ExprOpt(allowUnassignedVarDecl));
				// Line 1683: (TT.Comma &{allowTrailingComma} EOF / TT.Comma ExprOpt)*
				for (;;) {
					la0 = LA0;
					if (la0 == TT.Comma) {
						la1 = LA(1);
						if (la1 == EOF) {
							if (allowTrailingComma) {
								Skip();
								Skip();
							} else
								goto match2;
						} else if (ExprList_set0.Contains((int) la1))
							goto match2;
						else
							goto error;
					} else if (la0 == EOF)
						break;
					else
						goto error;
					continue;
				match2:
					{
						Skip();
						list.Add(ExprOpt(allowUnassignedVarDecl));
					}
					continue;
				error:
					{
						#line 1685 "EcsParserGrammar.les"
						Error("Syntax error in expression list");
						#line default
						// Line 1685: (~(EOF|TT.Comma))*
						for (;;) {
							la0 = LA0;
							if (!(la0 == EOF || la0 == TT.Comma))
								Skip();
							else
								break;
						}
					}
				}
			}
			Skip();
		}
示例#48
0
        public static LNode QuoteOne(LNode node, bool substitutions = true)
        {
            LNode result;

            switch (node.Kind)
            {
            case LNodeKind.Literal:             // => F.Literal(value)
                result = F.Call(F_Literal, node.WithoutAttrs());
                break;

            case LNodeKind.Id:             // => F.Id(string), F.Id(CodeSymbols.Name)
                result = F.Call(F_Id, QuoteIdHelper(node.Name));
                break;

            default:             // NodeKind.Call => F.Dot(...), F.Of(...), F.Call(...), F.Braces(...)
                if (substitutions && node.Calls(S.Substitute, 1))
                {
                    result = node.Args[0];
                }
                else if (node.Calls(S.Braces))                 // F.Braces(...)
                {
                    result = F.Call(F_Braces, node.Args.SmartSelect(arg => QuoteOne(arg)));
                }
                else if (node.Calls(S.Dot) && node.ArgCount.IsInRange(1, 2))
                {
                    result = F.Call(F_Dot, node.Args.SmartSelect(arg => QuoteOne(arg)));
                }
                else if (node.Calls(S.Of))
                {
                    result = F.Call(F_Of, node.Args.SmartSelect(arg => QuoteOne(arg)));
                }
                else                   // General case: F.Call(<Target>, <Args>)
                {
                    LNode outTarget;
                    if (node.Target.IsId)
                    {
                        outTarget = QuoteIdHelper(node.Name);
                    }
                    else
                    {
                        outTarget = QuoteOne(node.Target);
                    }
                    RVList <LNode> outArgs = new RVList <LNode>(outTarget);
                    foreach (LNode arg in node.Args)
                    {
                        outArgs.Add(QuoteOne(arg));
                    }
                    result = F.Call(F_Call, outArgs);
                }
                break;
            }
            // Translate attributes too (if any)
            RWList <LNode> outAttrs = null;

            foreach (LNode attr in node.Attrs)
            {
                if (!attr.IsTrivia)
                {
                    outAttrs = outAttrs ?? new RWList <LNode>();
                    outAttrs.Add(QuoteOne(attr));
                }
            }
            if (outAttrs != null)
            {
                result = F.Call(F.Dot(result, Id_WithAttrs), outAttrs.ToRVList());
            }

            return(result);
        }
示例#49
0
		void InitializerList(RWList<LNode> list)
		{
			TokenType la0, la1;
			// Line 1711: nongreedy(InitializerExpr (TT.Comma EOF / TT.Comma InitializerExpr)*)?
			la0 = LA0;
			if (la0 == EOF)
				;
			else {
				list.Add(InitializerExpr());
				// Line 1712: (TT.Comma EOF / TT.Comma InitializerExpr)*
				for (;;) {
					la0 = LA0;
					if (la0 == TT.Comma) {
						la1 = LA(1);
						if (la1 == EOF) {
							Skip();
							Skip();
						} else if (ExprList_set0.Contains((int) la1)) {
							Skip();
							list.Add(InitializerExpr());
						} else
							goto error;
					} else if (la0 == EOF)
						break;
					else
						goto error;
					continue;
				error:
					{
						#line 1714 "EcsParserGrammar.les"
						Error("Syntax error in initializer list");
						#line default
						// Line 1714: (~(EOF|TT.Comma))*
						for (;;) {
							la0 = LA0;
							if (!(la0 == EOF || la0 == TT.Comma))
								Skip();
							else
								break;
						}
					}
				}
			}
			Skip();
		}
示例#50
0
		public virtual void Done()
		{
			_classBody = null;
			F = null;
			_setDeclNames = null;
			_currentRule = null;
		}
示例#51
0
		LNode PrimaryExpr()
		{
			var e = Atom();
			// Line 518: greedy( (TT.ColonColon|TT.Dot|TT.PtrArrow|TT.QuickBind) Atom / PrimaryExpr_NewStyleCast / TT.LParen TT.RParen | TT.LBrack TT.RBrack | TT.IncDec | &(TParams ~(TT.ContextualKeyword|TT.Id)) ((TT.LT|TT.Not) | TT.Dot TT.LBrack) => TParams | BracedBlock )*
			for (;;) {
				switch (LA0) {
				case TT.Dot:
					{
						if (Try_PrimaryExpr_Test0(0)) {
							switch (LA(1)) {
							case TT.@base:
							case TT.@default:
							case TT.@this:
							case TT.@checked:
							case TT.@delegate:
							case TT.@new:
							case TT.@operator:
							case TT.@sizeof:
							case TT.@typeof:
							case TT.@unchecked:
							case TT.At:
							case TT.ContextualKeyword:
							case TT.Dot:
							case TT.Id:
							case TT.LBrace:
							case TT.Literal:
							case TT.LParen:
							case TT.Substitute:
							case TT.TypeKeyword:
								goto match1;
							default:
								TParams(ref e);
								break;
							}
						} else
							goto match1;
					}
					break;
				case TT.ColonColon:
				case TT.PtrArrow:
				case TT.QuickBind:
					goto match1;
				case TT.LParen:
					{
						if (Down(0) && Up(LA0 == TT.@as || LA0 == TT.@using || LA0 == TT.PtrArrow))
							e = PrimaryExpr_NewStyleCast(e);
						else {
							var lp = MatchAny();
							var rp = Match((int) TT.RParen);
							#line 522 "EcsParserGrammar.les"
							e = F.Call(e, ExprListInside(lp), e.Range.StartIndex, rp.EndIndex);
							#line default
						}
					}
					break;
				case TT.LBrack:
					{
						var lb = MatchAny();
						var rb = Match((int) TT.RBrack);
						var list = new RWList<LNode> { 
							e
						};
						e = F.Call(S.IndexBracks, AppendExprsInside(lb, list).ToRVList(), e.Range.StartIndex, rb.EndIndex);
					}
					break;
				case TT.IncDec:
					{
						var t = MatchAny();
						#line 526 "EcsParserGrammar.les"
						e = F.Call(t.Value == S.PreInc ? S.PostInc : S.PostDec, e, e.Range.StartIndex, t.EndIndex);
						#line default
					}
					break;
				case TT.LT:
					{
						if (Try_PrimaryExpr_Test0(0))
							TParams(ref e);
						else
							goto stop;
					}
					break;
				case TT.Not:
					TParams(ref e);
					break;
				case TT.LBrace:
					{
						var bb = BracedBlock();
						#line 530 "EcsParserGrammar.les"
						if ((!e.IsCall || e.BaseStyle == NodeStyle.Operator)) {
							e = F.Call(e, bb, e.Range.StartIndex, bb.Range.EndIndex);
						} else {
							e = e.WithArgs(e.Args.Add(bb)).WithRange(e.Range.StartIndex, bb.Range.EndIndex);
						}
						#line default
					}
					break;
				default:
					goto stop;
				}
				continue;
			match1:
				{
					var op = MatchAny();
					var rhs = Atom();
					#line 519 "EcsParserGrammar.les"
					e = F.Call((Symbol) op.Value, e, rhs, e.Range.StartIndex, rhs.Range.EndIndex);
					#line default
				}
			}
		stop:;
			#line 537 "EcsParserGrammar.les"
			return e;
			#line default
		}
示例#52
0
 public GenerateCodeVisitor(LLParserGenerator llpg)
 {
     LLPG       = llpg;
     F          = new LNodeFactory(llpg._sourceFile);
     _classBody = llpg._classBody;
 }
示例#53
0
		public virtual void Begin(RWList<LNode> classBody, ISourceFile sourceFile)
		{
			_classBody = classBody;
			F = new LNodeFactory(sourceFile);
			_setDeclNames = new Dictionary<IPGTerminalSet, Symbol>();
		}
示例#54
0
		void NormalAttributes(ref RWList<LNode> attrs)
		{
			TokenType la0, la1;
			// Line 804: (&!{Down($LI) && Up(Try_Scan_AsmOrModLabel(0))} TT.LBrack TT.RBrack)*
			for (;;) {
				la0 = LA0;
				if (la0 == TT.LBrack) {
					if (!(Down(0) && Up(Try_Scan_AsmOrModLabel(0)))) {
						la1 = LA(1);
						if (la1 == TT.RBrack) {
							var t = MatchAny();
							Skip();
							#line 807 "EcsParserGrammar.les"
							if ((Down(t))) {
								AttributeContents(ref attrs);
								Up();
							}
							#line default
						} else
							break;
					} else
						break;
				} else
					break;
			}
		}
示例#55
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()));
		}
示例#56
0
		void AttributeContents(ref RWList<LNode> attrs)
		{
			TokenType la0, la1;
			#line 815 "EcsParserGrammar.les"
			Token attrTarget = default(Token);
			#line default
			// Line 817: greedy((@`.`(TT, noMacro(@return))|TT.ContextualKeyword|TT.Id) TT.Colon)?
			la0 = LA0;
			if (la0 == TT.@return || la0 == TT.ContextualKeyword || la0 == TT.Id) {
				la1 = LA(1);
				if (la1 == TT.Colon) {
					attrTarget = MatchAny();
					Skip();
				}
			}
			ExprList(attrs = attrs ?? new RWList<LNode>(), allowTrailingComma: true, allowUnassignedVarDecl: true);
			#line 822 "EcsParserGrammar.les"
			if (attrTarget.Value != null) {
				var attrTargetNode = IdNode(attrTarget);
				for (int i = 0; i < attrs.Count; i++) {
					var attr = attrs[i];
					if ((!IsNamedArg(attr))) {
						attrs[i] = SetOperatorStyle(F.Call(S.NamedArg, attrTargetNode, attr, attrTarget.StartIndex, attr.Range.EndIndex));
					} else {
						attrTargetNode = attrs[i].Args[1];
						Error(attrTargetNode, "Syntax error: only one attribute target is allowed");
					}
				}
			}
			#line default
		}
示例#57
0
		protected void ExprList(ref RWList<LNode> exprs)
		{
			TT la0;
			// line 166
			exprs = exprs ?? new RWList<LNode>();
			// Line 167: (SuperExpr (TT.Comma SuperExprOpt)* | TT.Comma SuperExprOpt (TT.Comma SuperExprOpt)*)?
			switch ((TT) LA0) {
			case TT.Assignment:
			case TT.At:
			case TT.BQString:
			case TT.Colon:
			case TT.Dot:
			case TT.Id:
			case TT.LBrace:
			case TT.LBrack:
			case TT.LParen:
			case TT.NormalOp:
			case TT.Not:
			case TT.Number:
			case TT.OtherLit:
			case TT.PrefixOp:
			case TT.PreSufOp:
			case TT.SQString:
			case TT.String:
			case TT.Symbol:
				{
					exprs.Add(SuperExpr());
					// Line 168: (TT.Comma SuperExprOpt)*
					for (;;) {
						la0 = (TT) LA0;
						if (la0 == TT.Comma) {
							Skip();
							exprs.Add(SuperExprOpt());
						} else
							break;
					}
				}
				break;
			case TT.Comma:
				{
					// line 169
					exprs.Add(MissingExpr);
					Skip();
					exprs.Add(SuperExprOpt());
					// Line 170: (TT.Comma SuperExprOpt)*
					for (;;) {
						la0 = (TT) LA0;
						if (la0 == TT.Comma) {
							Skip();
							exprs.Add(SuperExprOpt());
						} else
							break;
					}
				}
				break;
			}
		}
示例#58
0
		void TParamAttributeKeywords(ref RWList<LNode> attrs)
		{
			TokenType la0;
			// Line 847: ((TT.@in|TT.AttrKeyword))*
			for (;;) {
				la0 = LA0;
				if (la0 == TT.@in || la0 == TT.AttrKeyword) {
					var t = MatchAny();
					#line 848 "EcsParserGrammar.les"
					(attrs = attrs ?? new RWList<LNode>()).Add(IdNode(t));
					#line default
				} else
					break;
			}
		}
示例#59
0
		int WordAttributes(ref RWList<LNode> attrs)
		{
			TokenType la0;
			#line 914 "EcsParserGrammar.les"
			TokenType LA1;
			int nonKeywords = 0;
			if (LA0 == TT.Id && ((LA1 = LA(1)) == TT.Set || LA1 == TT.LParen || LA1 == TT.Dot))
				 return 0;
			#line 918 "EcsParserGrammar.les"
			Token t;
			#line default
			// Line 920: (TT.AttrKeyword | ((@`.`(TT, noMacro(@this))|TT.@new|TT.Id) | UnusualId) &(( DataType ((TT.AttrKeyword|TT.Id|TT.TypeKeyword) | UnusualId) | (TT.@new|TT.AttrKeyword) | @`.`(TT, noMacro(@this)) | TT.@checked TT.LBrace TT.RBrace | TT.@unchecked TT.LBrace TT.RBrace | @`.`(TT, noMacro(@default)) TT.Colon | TT.@using TT.LParen | (@`.`(TT, noMacro(@break))|@`.`(TT, noMacro(@continue))|@`.`(TT, noMacro(@return))|@`.`(TT, noMacro(@throw))|TT.@case|TT.@class|TT.@delegate|TT.@do|TT.@enum|TT.@event|TT.@fixed|TT.@for|TT.@foreach|TT.@goto|TT.@interface|TT.@lock|TT.@namespace|TT.@struct|TT.@switch|TT.@try|TT.@while) )))*
			for (;;) {
				switch (LA0) {
				case TT.AttrKeyword:
					{
						t = MatchAny();
						#line 920 "EcsParserGrammar.les"
						attrs.Add(IdNode(t));
						#line default
					}
					break;
				case TT.@this:
				case TT.@new:
				case TT.ContextualKeyword:
				case TT.Id:
					{
						if (Try_WordAttributes_Test0(1)) {
							// Line 921: ((@`.`(TT, noMacro(@this))|TT.@new|TT.Id) | UnusualId)
							la0 = LA0;
							if (la0 == TT.@this || la0 == TT.@new || la0 == TT.Id)
								t = MatchAny();
							else
								t = UnusualId();
							#line 934 "EcsParserGrammar.les"
							LNode node;
							if ((t.Type() == TT.@new || t.Type() == TT.@this)) {
								node = IdNode(t);
							} else {
								node = F.Attr(_triviaWordAttribute, F.Id("#" + t.Value.ToString(), t.StartIndex, t.EndIndex));
							}
							#line 940 "EcsParserGrammar.les"
							attrs = attrs ?? new RWList<LNode>();
							attrs.Add(node);
							nonKeywords++;
							#line default
						} else
							goto stop;
					}
					break;
				default:
					goto stop;
				}
			}
		stop:;
			#line 945 "EcsParserGrammar.les"
			return nonKeywords;
			#line default
		}
示例#60
0
		public static LNode UnpackTuple(LNode node, IMessageSink sink)
		{
			var a = node.Args;
			if (a.Count == 2 && a[0].CallsMin(S.Tuple, 1)) {
				var output = new RWList<LNode>();
				var tuple = a[0].Args;
				var rhs = a[1];
				
				// Avoid evaluating rhs more than once, if it doesn't look like a simple variable
				rhs = MaybeAddTempVarDecl(rhs, output);

				for (int i = 0; i < tuple.Count; i++) {
					var itemi = F.Dot(rhs, F.Id(GSymbol.Get("Item" + (i + 1))));
					if (tuple[i].Calls(S.Var, 2))
						output.Add(F.Var(tuple[i].Args[0], tuple[i].Args[1], itemi));
					else
						output.Add(F.Call(S.Assign, tuple[i], itemi));
				}
				return F.Call(S.Splice, output.ToRVList());
			}
			return null;
		}