예제 #1
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);
            }
        }
예제 #2
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())));
        }
예제 #3
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);
            }
예제 #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
        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);
        }
예제 #6
0
파일: UnrollMacro.cs 프로젝트: Shaykh/Loyc
		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());
		}
예제 #7
0
 private void AddSwitchHandler(LNode branch, RWList <LNode> stmts)
 {
     stmts.SpliceAdd(branch, S.Splice);
     if (EndMayBeReachable(branch))
     {
         stmts.Add(F.Call(S.Break));
     }
 }
예제 #8
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);
 }
예제 #9
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);
     }
 }
예제 #10
0
            private void AddUserAction(LNode action)
            {
                int i = _target.Count;

                _target.SpliceAdd(action, S.Splice);
                if (action.Range.StartIndex > 0 && _target.Count > i)
                {
                    if (LLPG.AddCsLineDirectives)
                    {
                        // Remove folder name. This only makes sense if the output
                        // file and input file are in the same folder; sadly we have
                        // no access to the output file name, but as of 2015-05 it's
                        // always true that the output file will be in the same folder.
                        string filename = System.IO.Path.GetFileName(_target[i].Range.Source.FileName);
                        int    line     = 0;
                        for (; i < _target.Count; i++, line++)
                        {
                            var r = _target[i].Range;
                            if (line != r.Start.Line)
                            {
                                line       = r.Start.Line;
                                _target[i] = _target[i].PlusAttr(F.Trivia(S.TriviaRawTextBefore,
                                                                          string.Format("#line {0} {1}\n", line, Ecs.EcsNodePrinter.PrintString(filename, '"'))));
                            }
                        }
                        _target.Add(F.Trivia(S.RawText, "#line default"));
                    }
                    else
                    {
                        _target[i] = _target[i].PlusAttr(F.Trivia(S.TriviaSLCommentBefore,
                                                                  string.Format(" line {0}", _target[i].Range.Start.Line)));
                    }
                }
            }
예제 #11
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);
        }
예제 #12
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);
        }
예제 #13
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]);
        }
예제 #14
0
파일: Prelude.cs 프로젝트: BingjieGao/Loyc
		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());
		}
예제 #15
0
파일: UnrollMacro.cs 프로젝트: Shaykh/Loyc
        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()));
        }
예제 #16
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());
			}
예제 #17
0
		void StmtList(RWList<LNode> list)
		{
			TokenType la0;
			// Line 1719: (~(EOF) => Stmt)*
			for (;;) {
				la0 = LA0;
				if (la0 != EOF)
					list.Add(Stmt());
				else
					break;
			}
			Skip();
		}
예제 #18
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();
		}
예제 #19
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
		}
예제 #20
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
		}
예제 #21
0
		private void AddSwitchHandler(LNode branch, RWList<LNode> stmts)
		{
			stmts.SpliceAdd(branch, S.Splice);
			if (EndMayBeReachable(branch))
				stmts.Add(F.Call(S.Break));
		}
예제 #22
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);
        }
예제 #23
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);
		}
예제 #24
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;
			}
		}
예제 #25
0
        protected void ExprList(ref RWList <LNode> exprs)
        {
            TT la0;

            exprs = exprs ?? new RWList <LNode>();
            // Line 160: (SuperExpr (TT.Comma SuperExprOpt)* | TT.Comma SuperExprOpt (TT.Comma SuperExprOpt)*)?
            switch (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 161: (TT.Comma SuperExprOpt)*
                for (;;)
                {
                    la0 = LA0;
                    if (la0 == TT.Comma)
                    {
                        Skip();
                        exprs.Add(SuperExprOpt());
                    }
                    else
                    {
                        break;
                    }
                }
            }
            break;

            case TT.Comma:
            {
                exprs.Add(MissingExpr);
                Skip();
                exprs.Add(SuperExprOpt());
                // Line 163: (TT.Comma SuperExprOpt)*
                for (;;)
                {
                    la0 = LA0;
                    if (la0 == TT.Comma)
                    {
                        Skip();
                        exprs.Add(SuperExprOpt());
                    }
                    else
                    {
                        break;
                    }
                }
            }
            break;
            }
        }
예제 #26
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;
		}
예제 #27
0
            private void MakeTestExpr(LNode pattern, LNode candidate, out Symbol varArgSym, out LNode varArgCond)
            {
                varArgSym  = null;
                varArgCond = null;
                LNode condition;
                bool  isParams, refExistingVar;
                var   nodeVar        = GetSubstitutionVar(pattern, out condition, out isParams, out refExistingVar);
                int   predictedTests = pattern.Attrs.Count + (nodeVar != null ? 0 : pattern.Args.Count) + (!pattern.HasSimpleHeadWithoutPAttrs() ? 1 : 0);

                if (predictedTests > 1)
                {
                    candidate = MaybePutCandidateInTempVar(candidate.IsCall, candidate);
                }
                MatchAttributes(pattern, candidate);
                if (nodeVar != null)
                {
                    if (nodeVar != __ || condition != null)
                    {
                        if (!refExistingVar)
                        {
                            AddVar(nodeVar, isParams, errAt: pattern);
                        }
                        if (!isParams)
                        {
                            var assignment = LNode.Call(CodeSymbols.Assign, LNode.List(F.Id(nodeVar), candidate)).SetStyle(NodeStyle.Operator);
                            Tests.Add(LNode.Call(CodeSymbols.Neq, LNode.List(assignment.PlusAttrs(LNode.List(LNode.InParensTrivia)), LNode.Literal(null))).SetStyle(NodeStyle.Operator));
                            Tests.Add(condition);
                        }
                    }
                    if (isParams)
                    {
                        varArgSym  = nodeVar;
                        varArgCond = condition;
                        return;
                    }
                }
                else if (pattern.IsId)
                {
                    Tests.Add(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"IsIdNamed"))), LNode.List(LNode.Call(CodeSymbols.Cast, LNode.List(F.Literal(pattern.Name.Name), LNode.Id((Symbol)"Symbol"))).SetStyle(NodeStyle.Operator))));
                }
                else if (pattern.IsLiteral)
                {
                    if (pattern.Value == null)
                    {
                        Tests.Add(LNode.Call(CodeSymbols.Eq, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Value"))), LNode.Literal(null))).SetStyle(NodeStyle.Operator));
                    }
                    else
                    {
                        Tests.Add(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(pattern, LNode.Id((Symbol)"Equals"))), LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Value"))))));
                    }
                }
                else
                {
                    int?varArgAt;
                    int fixedArgC = GetFixedArgCount(pattern.Args, out varArgAt);
                    var pTarget   = pattern.Target;
                    if (pTarget.IsId && !pTarget.HasPAttrs())
                    {
                        var   quoteTarget = QuoteSymbol(pTarget.Name);
                        LNode targetTest;
                        if (varArgAt.HasValue && fixedArgC == 0)
                        {
                            targetTest = LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Calls"))), LNode.List(quoteTarget));
                        }
                        else if (varArgAt.HasValue)
                        {
                            targetTest = LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"CallsMin"))), LNode.List(quoteTarget, F.Literal(fixedArgC)));
                        }
                        else
                        {
                            targetTest = LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Calls"))), LNode.List(quoteTarget, F.Literal(fixedArgC)));
                        }
                        Tests.Add(targetTest);
                    }
                    else
                    {
                        if (fixedArgC == 0)
                        {
                            Tests.Add(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"IsCall"))));
                            if (!varArgAt.HasValue)
                            {
                                Tests.Add(LNode.Call(CodeSymbols.Eq, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Args"))), LNode.Id((Symbol)"Count"))), LNode.Literal(0))).SetStyle(NodeStyle.Operator));
                            }
                        }
                        else
                        {
                            var op = varArgAt.HasValue ? S.GE : S.Eq;
                            Tests.Add(LNode.Call(op, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Args"))), LNode.Id((Symbol)"Count"))), F.Literal(fixedArgC))));
                        }
                        int i = Tests.Count;
                        MakeTestExpr(pTarget, LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Target"))));
                    }
                    MakeArgListTests(pattern.Args, ref candidate);
                }
            }
예제 #28
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
		}
예제 #29
0
 private void Add(Properties.Property property)
 {
     propertyByName[property.name] = property;
     properties.Add(property);
 }
예제 #30
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
		}
예제 #31
0
 public override void Reset()
 {
     value.Clear();
     value.Add(new IntInfo(defaultValue, null));
 }
예제 #32
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();
		}
예제 #33
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()));
            }
예제 #34
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();
		}
예제 #35
0
파일: TupleMacros.cs 프로젝트: Shaykh/Loyc
		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;
		}
예제 #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
			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;
			}
예제 #38
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()));
		}
예제 #39
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;
		}
예제 #40
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;
		}
예제 #41
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()));
            }
        }