Beispiel #1
0
		public void Print(LNode node, StringBuilder target, IMessageSink sink = null, ParsingMode mode = null, ILNodePrinterOptions options = null)
		{
			if (_usePlainCsPrinter)
				EcsNodePrinter.PrintPlainCSharp(node, target, sink, mode, options);
			else
				EcsNodePrinter.PrintECSharp(node, target, sink, mode, options);
		}
Beispiel #2
0
		public static LNode In(LNode node, IMacroContext context)
		{
			{
				LNode range, x;
				if (node.Calls(CodeSymbols.In, 2) && (x = node.Args[0]) != null && (range = node.Args[1]) != null) {
					LNode parens;
					range = range.WithoutAttrNamed(S.TriviaInParens, out parens);
					if (parens == null) {
						{
							LNode hi, lo;
							if (range.Calls(CodeSymbols.DotDot, 2) && (lo = range.Args[0]) != null && (hi = range.Args[1]) != null)
								if (lo.IsIdNamed(__))
									return LNode.Call(CodeSymbols.LT, LNode.List(x, hi)).SetStyle(NodeStyle.Operator);
								else if (hi.IsIdNamed(__))
									return LNode.Call(CodeSymbols.GE, LNode.List(x, lo)).SetStyle(NodeStyle.Operator);
								else
									return LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(x, LNode.Id((Symbol) "IsInRangeExcludeHi"))).SetStyle(NodeStyle.Operator), LNode.List(lo, hi));
							else if (range.Calls(CodeSymbols.DotDot, 1) && (hi = range.Args[0]) != null)
								return LNode.Call(CodeSymbols.LT, LNode.List(x, hi)).SetStyle(NodeStyle.Operator);
							else if (range.Calls(CodeSymbols.DotDotDot, 2) && (lo = range.Args[0]) != null && (hi = range.Args[1]) != null)
								if (lo.IsIdNamed(__))
									return LNode.Call(CodeSymbols.LE, LNode.List(x, hi)).SetStyle(NodeStyle.Operator);
								else if (hi.IsIdNamed(__))
									return LNode.Call(CodeSymbols.GE, LNode.List(x, lo)).SetStyle(NodeStyle.Operator);
								else
									return LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(x, LNode.Id((Symbol) "IsInRange"))).SetStyle(NodeStyle.Operator), LNode.List(lo, hi));
							else if (range.Calls(CodeSymbols.DotDotDot, 1) && (hi = range.Args[0]) != null)
								return LNode.Call(CodeSymbols.LE, LNode.List(x, hi)).SetStyle(NodeStyle.Operator);
						}
					}
					return LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(range, LNode.Id((Symbol) "Contains"))).SetStyle(NodeStyle.Operator), LNode.List(x));
				}
			}
			return null;
		}
Beispiel #3
0
		public static LNode replace(LNode node, IMacroContext context)
		{
			var args_body = context.GetArgsAndBody(true);
			var args = args_body.A;
			var body = args_body.B;
			if (args.Count >= 1)
			{
				var patterns = new Pair<LNode, LNode>[args.Count];
				for (int i = 0; i < patterns.Length; i++)
				{
					var pair = args[i];
					if (pair.Calls(S.Lambda, 2)) {
						LNode pattern = pair[0], repl = pair[1];
						if (pattern.Calls(S.Braces, 1) && repl.Calls(S.Braces)) {
							pattern = pattern.Args[0];
							repl = repl.WithTarget(S.Splice);
						}
						patterns[i] = Pair.Create(pattern, repl);
					} else {
						string msg = "Expected 'pattern => replacement'.";
						if (pair.Descendants().Any(n => n.Calls(S.Lambda, 2)))
							msg += " " + "(Using '=>' already? Put the pattern on the left-hand side in parentheses.)";
						return Reject(context, pair, msg);
					}
				}

				int replacementCount;
				var output = Replace(body, patterns, out replacementCount);
				if (replacementCount == 0)
					context.Write(Severity.Warning, node, "No patterns recognized; no replacements were made.");
				return output.AsLNode(S.Splice);
			}
			return null;
		}
Beispiel #4
0
		public static LNode on_finally(LNode node, IMacroContext context)
		{
			LNode firstArg, rest, on_handler = ValidateOnStmt(node, context, out rest, out firstArg);
			if (on_handler == null || firstArg != null)
				return null;
			return node.With(S.Try, rest, node.With(S.Finally, on_handler));
		}
Beispiel #5
0
		public static RVList<LNode> WithSpliced(this RVList<LNode> list, LNode node, Symbol listName)
		{
			if (node.Calls(listName))
				return list.AddRange(node.Args);
			else
				return list.Add(node);
		}
Beispiel #6
0
		public static LNode concat_id(LNode node, IMessageSink sink)
		{
			var args = node.Args;
			if (args.Count == 0)
				return null;
			if (args.Slice(0, args.Count - 1).Any(n => n.IsCall))
				return Reject(sink, node, "All arguments to ##() or concat() must be identifiers or literals (except the last one)");

			RVList<LNode> attrs = node.Attrs;
			LNode arg = null;
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < args.Count; i++)
			{
				arg = args[i];
				attrs.AddRange(arg.Attrs);

				if (arg.IsLiteral)
					sb.Append(arg.Value ?? "null");
				else if (arg.IsId)
					sb.Append(arg.Name);
				else { // call
					if (i + 1 != args.Count || !arg.HasSimpleHead())
						return Reject(sink, arg, "Expected simple identifier or literal");
					sb.Append(arg.Name);
				}
			}
			Symbol combined = GSymbol.Get(sb.ToString());
			LNode result;
			if (arg.IsCall)
				result = arg.WithTarget(combined);
			else
				result = LNode.Id(combined, node);
			return result.WithAttrs(attrs);
		}
Beispiel #7
0
		/// <summary>Returns true if the specified child of the specified node 
		/// can be an implicit child statement, i.e. a child statement that is
		/// not necessarily a braced block, e.g. the second child of a while 
		/// loop.</summary>
		/// <remarks>
		/// This method helps the printer decide when a newline should be added 
		/// before an unbraced child statement when there are no attributes 
		/// dictating whether to add a newline or not.
		/// <para/>
		/// This method only cares about executable parent nodes. It returns 
		/// false for class/space and function/property bodies, which are always 
		/// braced blocks and therefore get a newline before every child statement 
		/// automatically.
		/// </remarks>
		public static bool MayBeImplicitChildStatement(LNode node, int childIndex)
		{
			CheckParam.IsNotNull("node", node);
			if (childIndex < 0) // target or attributes
				return false;
			var n = node.Name;
			if (!LNode.IsSpecialName(n.Name))
				return false;
			if (n == S.Braces)
				return true;
			if (n == S.Try)
				return childIndex == 0;
			switch (node.ArgCount) {
				case 1:
					if (n == S.Finally)
						return true;
					break;
				case 2:
					if (childIndex == 0 ? n == S.DoWhile :
						n == S.If || n == S.While || n == S.UsingStmt || n == S.Lock || n == S.Switch || n == S.Fixed)
						return true;
					break;
				case 3:
					if (childIndex != 0 && n == S.If)
						return true;
					if (childIndex == 2 && n == S.ForEach)
						return true;
					break;
				case 4:
					if (childIndex == 3 && (n == S.For || n == S.Catch))
						return true;
					break;
			}
			return false;
		}
Beispiel #8
0
		public static LNode @nameof(LNode nameof, IMacroContext context)
		{
			if (nameof.ArgCount != 1)
				return null;
			Symbol expr = EcsValidators.KeyNameComponentOf(nameof.Args[0]);
			return F.Literal(expr.Name);
		}
Beispiel #9
0
		protected override void Stmt(string text, LNode expected, Action<EcsPrinterOptions> configure = null, Mode mode = Mode.Both)
		{
			bool exprMode = (mode & Mode.Expression) != 0;
			if ((mode & Mode.ParserTest) == 0)
				return;
			var sink = (mode & Mode.ExpectAndDropParserError) != 0 ? new MessageHolder() : (IMessageSink)ConsoleMessageSink.Value;
			// This is the easy way: 
			//LNode result = EcsLanguageService.Value.ParseSingle(text, sink, exprMode ? ParsingMode.Expressions : ParsingMode.Statements, preserveComments: true);
			// But to make debugging easier, I'll do it the long way:
			ILexer<Token> lexer = EcsLanguageService.Value.Tokenize(new UString(text), "", ConsoleMessageSink.Value);
			var preprocessed = new EcsPreprocessor(lexer, true);
			var treeified = new TokensToTree(preprocessed, false);
			var parser = new EcsParser(treeified.Buffered(), lexer.SourceFile, sink);
			VList<LNode> results = exprMode ? LNode.List(parser.ExprStart(false)) : LNode.List(parser.ParseStmtsGreedy());
			//if (!preprocessed.TriviaList.IsEmpty) 
			{
				// Inject comments
				var injector = new EcsTriviaInjector(preprocessed.TriviaList, preprocessed.SourceFile, (int)TokenType.Newline, "/*", "*"+"/", "//");
				results = LNode.List(injector.Run(results.GetEnumerator()).ToList());
			}
			LNode result = results.AsLNode(S.Splice);
			AreEqual(TokenType.EOF, parser.LT0.Type(), string.Format("Parser stopped before EOF at [{0}] in {1}", parser.LT0.StartIndex, text));

			if ((mode & Mode.IgnoreTrivia) != 0)
				result = result.ReplaceRecursive(n => n.IsTrivia ? Maybe<LNode>.NoValue : n, LNode.ReplaceOpt.ProcessAttrs).Value;
			AreEqual(expected, result);
			if (sink is MessageHolder)
				GreaterOrEqual(((MessageHolder)sink).List.Count, 1, "Expected an error but got none for "+text);
		}
Beispiel #10
0
		LNode AutoRemoveParens(LNode node)
		{
			int i = node.Attrs.IndexWithName(S.TriviaInParens);
			if ((i > -1))
				 return node.WithAttrs(node.Attrs.RemoveAt(i));
			return node;
		}
Beispiel #11
0
		public static LNode NullDot(LNode node, IMacroContext context)
		{
			if (!node.Calls(S.NullDot, 2))
				return null;

			var a = node.Args;
			LNode leftSide = a[0], rightSide = a[1];
			// So our input will be something like a.b?.c().d<x>, which is parsed
			//     (a.b) ?. (c().d<x>)
			// in EC# we would transform this to 
			//     a.b::tmp != null ? tmp.c().d<x> : null
			// but there's no EC# compiler yet, so instead use code that plain C#
			// can support:
			//     a.b != null ? (a.b).c().d<x> : null
			LNode condition, thenExpr;
			if (StandardMacros.LooksLikeSimpleValue(leftSide))
			{
				condition = F.Call(S.Neq, leftSide, F.@null);
				thenExpr = ConvertToNormalDot(leftSide, rightSide);
			}
			else
			{
				LNode tempVar = F.Id(StandardMacros.NextTempName(context, leftSide));
				condition = F.Call(S.Neq, F.Var(F.Missing, tempVar, leftSide), F.@null);
				thenExpr = ConvertToNormalDot(tempVar, rightSide);
			}
			return F.InParens(F.Call(S.QuestionMark, condition, thenExpr, F.Null));
		}
Beispiel #12
0
		[LexicalMacro("x in lo..hi; x in lo...hi; x in ..hi; x in lo..._; x in range", "Converts an 'in' expression to a normal C# expression using the following rules " + "(keeping in mind that the EC# parser treats `..<` as an alias for `..`):\n" + "1. `x in _..hi` and `x in ..hi` become `x.IsInRangeExcl(hi)`\n" + "2. `x in _...hi` and `x in ...hi` become `x.IsInRangeIncl(hi)`\n" + "3. `x in lo.._` and `x in lo..._` become simply `x >= lo`\n" + "4. `x in lo..hi` becomes `x.IsInRangeExcludeHi(lo, hi)`\n" + "5. `x in lo...hi` becomes `x.IsInRange(lo, hi)`\n" + "6. `x in range` becomes `range.Contains(x)`\n" + "The first applicable rule is used.", "#in")] public static LNode In(LNode node, IMacroContext context)
		{
			{
				LNode range, x;
				if (node.Calls(CodeSymbols.In, 2) && (x = node.Args[0]) != null && (range = node.Args[1]) != null) {
					LNode parens;
					range = range.WithoutAttrNamed(S.TriviaInParens, out parens);
					if (parens == null) {
						{
							LNode hi, lo;
							if (range.Calls(CodeSymbols.DotDot, 2) && (lo = range.Args[0]) != null && (hi = range.Args[1]) != null)
								if (lo.IsIdNamed(__))
									return LNode.Call(CodeSymbols.LT, LNode.List(x, hi)).SetStyle(NodeStyle.Operator);
								else if (hi.IsIdNamed(__))
									return LNode.Call(CodeSymbols.GE, LNode.List(x, lo)).SetStyle(NodeStyle.Operator);
								else
									return LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(x, LNode.Id((Symbol) "IsInRangeExcludeHi"))), LNode.List(lo, hi));
							else if (range.Calls(CodeSymbols.DotDot, 1) && (hi = range.Args[0]) != null)
								return LNode.Call(CodeSymbols.LT, LNode.List(x, hi)).SetStyle(NodeStyle.Operator);
							else if (range.Calls(CodeSymbols.DotDotDot, 2) && (lo = range.Args[0]) != null && (hi = range.Args[1]) != null)
								if (lo.IsIdNamed(__))
									return LNode.Call(CodeSymbols.LE, LNode.List(x, hi)).SetStyle(NodeStyle.Operator);
								else if (hi.IsIdNamed(__))
									return LNode.Call(CodeSymbols.GE, LNode.List(x, lo)).SetStyle(NodeStyle.Operator);
								else
									return LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(x, LNode.Id((Symbol) "IsInRange"))), LNode.List(lo, hi));
							else if (range.Calls(CodeSymbols.DotDotDot, 1) && (hi = range.Args[0]) != null)
								return LNode.Call(CodeSymbols.LE, LNode.List(x, hi)).SetStyle(NodeStyle.Operator);
						}
					}
					return LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(range, LNode.Id((Symbol) "Contains"))), LNode.List(x));
				}
			}
			return null;
		}
        private RoundTripPerformance MakeBltRoundTrip(LNode[] Nodes)
        {
            using (var memStream = new MemoryStream())
            {
                var timer = new Stopwatch();
                timer.Start();

                var writer = new LoycBinaryWriter(memStream);

                for (int i = 0; i < TimedRoundTripCount; i++)
                {
                    writer.WriteFile(Nodes);
                    memStream.Seek(0, SeekOrigin.Begin);
                }

                timer.Stop();
                var writePerf = timer.Elapsed;
                long size = memStream.Length;
                timer.Restart();

                for (int i = 0; i < TimedRoundTripCount; i++)
                {
                    var reader = new LoycBinaryReader(memStream);
                    reader.ReadFile("test.blt");
                    memStream.Seek(0, SeekOrigin.Begin);
                }

                timer.Stop();
                var readPerf = timer.Elapsed;

                return new RoundTripPerformance(readPerf, writePerf, size);
            }
        }
Beispiel #14
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);
		}
Beispiel #15
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);
		}
		public static LNode saveAndRestore(LNode node, IMacroContext context)
		{
			var tmp_0 = context.GetArgsAndBody(true);
			var args = tmp_0.Item1;
			var body = tmp_0.Item2;
			if (args.Count == 1) {
				LNode newValue = null;
				{
					var tmp_1 = args[0];
					LNode property;
					if (tmp_1.Calls(CodeSymbols.Assign, 2) && (property = tmp_1.Args[0]) != null && (newValue = tmp_1.Args[1]) != null || (property = tmp_1) != null) {
						string mainProp = KeyNameComponentOf(property).Name;
						string varPrefix = "old" + mainProp + "_";
						LNode varName, varDecl = TempVarDecl(property, out varName, varPrefix);
						LNode tryFinally = LNode.Call(CodeSymbols.Try, LNode.List(LNode.Call(CodeSymbols.Braces, LNode.List(body)).SetStyle(NodeStyle.Statement), LNode.Call(CodeSymbols.Finally, LNode.List(LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Assign, LNode.List(property, varName)).SetStyle(NodeStyle.Operator))).SetStyle(NodeStyle.Statement)))));
						if (newValue != null) {
							return LNode.Call(CodeSymbols.Splice, LNode.List(varDecl, LNode.Call(CodeSymbols.Assign, LNode.List(property, newValue)).SetStyle(NodeStyle.Operator), tryFinally));
						} else {
							return LNode.Call(CodeSymbols.Splice, LNode.List(varDecl, tryFinally));
						}
					}
				}
			}
			return null;
		}
Beispiel #17
0
		public static LNode BackingField(LNode prop, IMessageSink sink)
		{
			LNode type, name, body;
			if (prop.ArgCount != 3 || !(body = prop.Args[2]).Calls(S.Braces))
				return null;

			LNode fieldAttr = null, fieldVarAttr = null;
			LNode fieldName;
			bool autoType = false;
			int i;
			for (i = 0; i < prop.Attrs.Count; i++)
			{
				LNode attr = prop.Attrs[i];
				if (attr.IsIdNamed(_field)
					|| attr.Calls(S.Var, 2) 
						&& ((autoType = attr.Args[0].IsIdNamed(_field)) ||
							(fieldVarAttr = attr.AttrNamed(_field)) != null && fieldVarAttr.IsId))
				{
					fieldAttr = attr;
					break;
				}
			}
			if (fieldAttr == null)
				return null;

			LNode field = fieldAttr;
			type = prop.Args[0];
			if (field.IsId) {
				name = prop.Args[1];
				fieldName = F.Id(ChooseFieldName(Ecs.EcsNodePrinter.KeyNameComponentOf(name)));
				field = F.Call(S.Var, type, fieldName).WithAttrs(fieldAttr.Attrs);
			} else {
				fieldName = field.Args[1];
				if (fieldName.Calls(S.Assign, 2))
					fieldName = fieldName.Args[0];
			}
			if (autoType)
				field = field.WithArgChanged(0, type);
			if (fieldVarAttr != null)
				field = field.WithoutAttrNamed(_field);

			LNode newBody = body.WithArgs(body.Args.SmartSelect(stmt =>
			{
				var attrs = stmt.Attrs;
				if (stmt.IsIdNamed(S.get)) {
					stmt = F.Call(stmt.WithoutAttrs(), F.Braces(F.Call(S.Return, fieldName))).WithAttrs(attrs);
					stmt.BaseStyle = NodeStyle.Special;
				}
				if (stmt.IsIdNamed(S.set)) {
					stmt = F.Call(stmt.WithoutAttrs(), F.Braces(F.Call(S.Assign, fieldName, F.Id(S.value)))).WithAttrs(attrs);
					stmt.BaseStyle = NodeStyle.Special;
				}
				return stmt;
			}));
			if (newBody == body)
				sink.Write(Severity.Warning, fieldAttr, "The body of the property does not contain a 'get;' or 'set;' statement without a body, so no code was generated to get or set the backing field.");

			prop = prop.WithAttrs(prop.Attrs.RemoveAt(i)).WithArgChanged(2, newBody);
			return F.Call(S.Splice, new RVList<LNode>(field, prop));
		}
Beispiel #18
0
		public static LNode ForwardProperty(LNode prop, IMacroContext context)
		{
			LNode name, fwd, body;
			if (prop.ArgCount != 4)
				return null;
			LNode target = GetForwardingTarget(name = prop.Args[1], fwd = prop.Args[3]);
			if (target != null)
			{
				body = F.Braces(F.Call(S.get, F.Braces(F.Call(S.Return, target))).SetBaseStyle(NodeStyle.Special));
				return prop.WithArgChanged(3, body);
			}
			else if ((body = fwd).Calls(S.Braces))
			{
				var body2 = body.WithArgs(stmt => {
					if (stmt.Calls(S.get, 1) && (target = GetForwardingTarget(name, stmt.Args[0])) != null)
						return stmt.WithArgs(new VList<LNode>(F.Braces(F.Call(S.Return, target))));
					if (stmt.Calls(S.set, 1) && (target = GetForwardingTarget(name, stmt.Args[0])) != null)
						return stmt.WithArgs(new VList<LNode>(F.Braces(F.Call(S.Assign, target, F.Id(S.value)))));
					return stmt;
				});
				if (body2 != body)
					return prop.WithArgChanged(3, body2);
			}
			return null;
		}
Beispiel #19
0
		public static LNode ForwardMethod(LNode fn, IMessageSink sink)
		{
			LNode args, fwd, body;
			if (fn.ArgCount != 4 || !(fwd = fn.Args[3]).Calls(S.Forward, 1) || !(args = fn.Args[2]).Calls(S.List))
				return null;
			
			RVList<LNode> formalArgs = args.Args;
			RVList<LNode> argList =	RVList<LNode>.Empty;
			foreach (var formalArg in formalArgs)
			{
				if (!formalArg.Calls(S.Var, 2))
					return Reject(sink, formalArg, "'==>' expected a variable declaration here");
				LNode argName = formalArg.Args[1];
				if (argName.Calls(S.Assign, 2))
					argName = argName.Args[0];
				LNode @ref = formalArg.AttrNamed(S.Ref) ?? formalArg.AttrNamed(S.Out);
				if (@ref != null)
					argName = argName.PlusAttr(@ref);
				argList.Add(argName);
			}

			LNode target = GetForwardingTarget(fwd, fn.Args[1]);
			LNode call = F.Call(target, argList);
			
			bool isVoidFn = fn.Args[0].IsIdNamed(S.Void);
			body = F.Braces(isVoidFn ? call : F.Call(S.Return, call));
			return fn.WithArgChanged(3, body);
		}
Beispiel #20
0
		public static LNode ForwardProperty(LNode prop, IMessageSink sink)
		{
			LNode name, fwd, body;
			if (prop.ArgCount != 3)
				return null;
			LNode target = GetForwardingTarget(fwd = prop.Args[2], name = prop.Args[1]);
			if (target != null)
			{
				body = F.Braces(new RVList<LNode>(
					F.Call(S.get, F.Braces(F.Call(S.Return, target))),
					F.Call(S.set, F.Braces(F.Call(S.Assign, target, F.Id(S.value))))));

				return prop.WithArgChanged(2, body);
			}
			else if ((body = fwd).Calls(S.Braces))
			{
				var body2 = body.WithArgs(stmt => {
					if (stmt.Calls(S.get, 1) && (target = GetForwardingTarget(stmt.Args[0], name)) != null)
						return stmt.WithArgs(new RVList<LNode>(F.Braces(F.Call(S.Return, target))));
					if (stmt.Calls(S.set, 1) && (target = GetForwardingTarget(stmt.Args[0], name)) != null)
						return stmt.WithArgs(new RVList<LNode>(F.Braces(F.Call(S.Assign, target, F.Id(S.value)))));
					return stmt;
				});
				if (body2 != body)
					return prop.WithArgChanged(2, body2);
			}
			return null;
		}
Beispiel #21
0
		public static LNode static_matchCode(LNode node, IMacroContext context)
		{
			if (node.AttrNamed(S.Static) == null && !node.HasSpecialName)
				return null; // handled by normal matchCode macro

			var args_body = context.GetArgsAndBody(false);
			VList<LNode> args = args_body.Item1, body = args_body.Item2;
			if (args.Count != 1)
				return Reject(context, args[1], "Expected only one expression to match");

			var expression = context.PreProcess(AutoStripBraces(args[0]));

			var cases = GetCases(body, context.Sink);
			// The `default:` case is represented by an empty list of patterns.
			if (cases.WithoutLast(1).Any(pair => pair.Key.IsEmpty))
				context.Write(Severity.Error, node, "The `default:` case must be the last one, because the cases are tested in the order they appear, so no case after `default:` can be matched.");

			MMap<Symbol, LNode> captures = new MMap<Symbol, LNode>();
			foreach (Pair<VList<LNode>, VList<LNode>> pair in cases)
			{
				var patterns = pair.Key.IsEmpty ? new VList<LNode>((LNode)null) : pair.Key;
				foreach (var pattern in patterns)
				{
					captures.Clear();
					VList<LNode> _;
					if (pattern == null || LNodeExt.MatchesPattern(expression, pattern, ref captures, out _)) {
						captures[_hash] = expression; // define $#
						captures.Remove(__);
						return ReplaceCaptures(pair.Value.AsLNode(S.Splice), captures);
					}
				}
			}
			return F.Call(S.Splice); // none of the cases matched
		}
		public override Pred CodeToTerminalPred(LNode expr, ref string errorMsg)
		{
			bool isInt = false;
			PGIntSet set;

			if (expr.IsIdNamed(_underscore)) {
				set = PGIntSet.AllExceptEOF;
			} else if (expr.IsIdNamed(_EOF)) {
				set = PGIntSet.EOF;
			} else if (expr.Calls(S.DotDot, 2)) {
				int? from = ConstValue(expr.Args[0], ref isInt);
				int? to   = ConstValue(expr.Args[1], ref isInt);
				if (from == null || to == null) {
					errorMsg = "Expected int32 or character literal on each side of «..»";
					return null;
				}
				set = PGIntSet.WithRanges(from.Value, to.Value);
			} else if (expr.Value is string) {
				return Pred.Seq((string)expr.Value);
			} else {
				int? num = ConstValue(expr, ref isInt);
				if (num == null) {
					errorMsg = "Unrecognized expression. Expected int32 or character literal instead of: " + expr.ToString(); // warning
					return null;
				}
				set = PGIntSet.With(num.Value);
			}
			set.IsCharSet = !isInt;
			return new TerminalPred(expr, set, true);
		}
Beispiel #23
0
		public static LNode _set(LNode node, IMacroContext context)
		{
			var lhs = node.Args[0, LNode.Missing];
			var name = lhs.Name;
			bool isSnippet = name == _hash_snippet;
			if ((isSnippet || name == _hash_set) && node.ArgCount == 2 && lhs.IsId)
			{
				node = context.PreProcessChildren();

				Symbol newTarget = isSnippet ? _hash_setScopedPropertyQuote : _hash_setScopedProperty;
				var stmts = node.Args.Slice(1).Select(key =>
					{
						LNode value = F.@true;
						if (key.Calls(S.Assign, 2))
						{
							value = key.Args[1];
							key = key.Args[0];
							if (isSnippet && value.Calls(S.Braces))
								value = value.Args.AsLNode(S.Splice);
						}
						if (!key.IsId)
							context.Write(Severity.Error, key, "Invalid key; expected an identifier.");
						return node.With(newTarget, LNode.Literal(key.Name, key), value);
					});
				return F.Call(S.Splice, stmts);
			}
			return null;
		}
Beispiel #24
0
		public static RVList<LNode> WithSpliced(this RVList<LNode> list, int index, LNode node, Symbol listName)
		{
			if (node.Calls(listName))
				return list.InsertRange(index, node.Args);
			else
				return list.Insert(index, node);
		}
Beispiel #25
0
			Mode = MacroMode.ProcessChildrenBefore)] // post-normal-macro-expansion
		public static LNode with(LNode fn, IMacroContext context)
		{
			LNode braces;
			if (fn.ArgCount != 2 || !(braces = fn.Args[1]).Calls(S.Braces))
				return null;

			LNode tmp = F.Id(NextTempName(context));
			WList<LNode> stmts = braces.Args.ToWList();
			stmts = stmts.SmartSelect(stmt => 
				stmt.ReplaceRecursive(expr => {
					if (expr.Calls(S.Dot, 1))
						return expr.WithArgs(new VList<LNode>(tmp, expr.Args.Last));
					else if (expr.IsIdNamed("#"))
						return tmp;
					return null;
				}));

			stmts.Insert(0, F.Var(null, tmp.Name, fn.Args[0]));
			if (IsExpressionContext(context)) {
				stmts.Add(tmp);
				return F.Call("#runSequence", stmts.ToVList());
			} else {
				return F.Braces(stmts.ToVList());
			}
		}
		public static LNode runSequence(LNode node, IMacroContext context)
		{
			if (context.Parent.Calls(S.Braces))
				return node.With(S.Splice, MaybeRemoveNoOpFromRunSeq(node.Args));
			if (!context.ScopedProperties.ContainsKey(_useSequenceExpressionsIsRunning))
				Reject(context, node, "#useSequenceExpressions is required to make #runSequence work");
			return null;
		}
Beispiel #27
0
		public static LNode static_tryDeconstruct(LNode node, IMacroContext context)
		{
			if (node.AttrNamed(S.Static) == null && !node.HasSpecialName)
				return Reject(context, node, "Expected 'static' attribute");
			foreach (var arg in node.Args)
				DoDeconstruct(arg, context, printErrorOnFailure: false);
			return F.Call(S.Splice);
		}
Beispiel #28
0
		public Rule(LNode basis, Symbol name, Pred pred, bool isStartingRule = true)
		{
			Basis = basis; Pred = pred; Name = name;
			IsStartingRule = isStartingRule;
			EndOfRule = new EndOfRule(this);
			if (basis != null && basis.Calls(S.Fn) && basis.ArgCount >= 3)
				ReturnType = basis.Args[0];
		}
Beispiel #29
0
		public static LNode on_throw(LNode node, IMacroContext context)
		{
			LNode firstArg, rest, on_handler = ValidateOnStmt(node, context, out rest, out firstArg);
			if (on_handler == null)
				return null;
			on_handler = on_handler.PlusArg(F.Call(S.Throw));
			return TransformOnCatch(node, firstArg, rest, on_handler);
		}
Beispiel #30
0
		public static LNode useDefaultTupleTypes(LNode node, IMacroContext context)
		{
			if (node.ArgCount != 0)
				return null;
			context.ScopedProperties.Remove(TupleMakers);
			context.ScopedProperties.Remove(DefaultTupleMaker);
			return F.Call(S.Splice);
		}
Beispiel #31
0
 public static LNode tom(LNode node, IMacroContext context)
 {
     return(LNode.Id("tommy"));
 }
Beispiel #32
0
 public static string Print(this IParsingService self, LNode node)
 {
     return(self.Print(node, MessageSink.Current));
 }
Beispiel #33
0
 public static bool IsParenthesizedExpr(this LNode node)
 {
     return(node.AttrNamed(CodeSymbols.TriviaInParens) != null);
 }
Beispiel #34
0
 protected LiteralNode(LNode ras) : base(ras)
 {
 }
Beispiel #35
0
 protected CallNode(LNode ras) : base(ras)
 {
 }
Beispiel #36
0
 public static LNode partlyDeprecatedMacro(LNode node, IMacroContext context)
 {
     return(LNode.Id("multi_name_macro"));
 }
Beispiel #37
0
 public static VList <LNode> WithoutNodeNamed(this VList <LNode> list, Symbol name, out LNode removedNode)
 {
     removedNode = null;
     for (int i = 0, c = list.Count; i < c; i++)
     {
         if (list[i].Name == name)
         {
             removedNode = list[i];
             return(list.RemoveAt(i));
         }
     }
     return(list);
 }
Beispiel #38
0
 private void Test(string input, string output, int maxExpand = 0xFFFF, IParsingService parser = null, ILNodePrinter printer = null, IMessageSink sink = null)
 {
     using (ParsingService.SetDefault(parser ?? Les2LanguageService.Value))
         using (LNode.SetPrinter(printer ?? EcsLanguageService.WithPlainCSharpPrinter))
             TestCompiler.Test(input, output, sink ?? _sink, maxExpand, "LeMP.les2.to.ecs");
 }
Beispiel #39
0
        public static LNode WithoutAttrNamed(this LNode self, Symbol name)
        {
            LNode _;

            return(WithoutAttrNamed(self, name, out _));
        }
Beispiel #40
0
        static void AddCapture(MMap <Symbol, LNode> captures, Symbol capName, LNode candidate)
        {
            LNode oldCap = captures.TryGetValue(capName, null);

            captures[capName] = LNode.MergeLists(oldCap, candidate, S.Splice);
        }
Beispiel #41
0
        public static bool MatchesPattern(this LNode candidate, LNode pattern, out IDictionary <Symbol, LNode> captures)
        {
            VList <LNode> unmatchedAttrs;

            return(MatchesPattern(candidate, pattern, out captures, out unmatchedAttrs));
        }
Beispiel #42
0
            void PrintMessages(List <Result> results, LNode input, int accepted, Severity maxSeverity)
            {
                if (accepted > 1)
                {
                    // Multiple macros accepted the input. If AllowDuplicates is used,
                    // this is fine if as long as they produced the same result.
                    bool allowed, equal = AreResultsEqual(results, out allowed);
                    if (!equal || !allowed)
                    {
                        string list = results.Where(r => r.Node != null).Select(r => QualifiedName(r.Macro.Macro.Method)).Join(", ");
                        if (equal)
                        {
                            _sink.Write(Severity.Warning, input, "Ambiguous macro call. {0} macros accepted the input and produced identical results: {1}", accepted, list);
                        }
                        else
                        {
                            _sink.Write(Severity.Error, input, "Ambiguous macro call. {0} macros accepted the input: {1}", accepted, list);
                        }
                    }
                }

                bool macroStyleCall = input.BaseStyle == NodeStyle.Special;

                if (accepted > 0 || macroStyleCall || maxSeverity >= Severity.Warning)
                {
                    if (macroStyleCall && maxSeverity < Severity.Warning)
                    {
                        maxSeverity = Severity.Warning;
                    }
                    var rejected = results.Where(r => r.Node == null && (r.Macro.Mode & MacroMode.Passive) == 0);
                    if (accepted == 0 && macroStyleCall && _sink.IsEnabled(maxSeverity) && rejected.Any())
                    {
                        _sink.Write(maxSeverity, input, "{0} macro(s) saw the input and declined to process it: {1}",
                                    results.Count, rejected.Select(r => QualifiedName(r.Macro.Macro.Method)).Join(", "));
                    }

                    foreach (var result in results)
                    {
                        bool printedLast = true;
                        foreach (var msg in result.Msgs)
                        {
                            // Print all messages from macros that accepted the input.
                            // For rejecting macros, print warning/error messages, and
                            // other messages when macroStyleCall.
                            if (_sink.IsEnabled(msg.Severity) && (result.Node != null ||
                                                                  (msg.Severity == Severity.Detail && printedLast) ||
                                                                  msg.Severity >= Severity.Warning ||
                                                                  macroStyleCall))
                            {
                                var msg2 = new MessageHolder.Message(msg.Severity, msg.Context,
                                                                     QualifiedName(result.Macro.Macro.Method) + ": " + msg.Format, msg.Args);
                                msg2.WriteTo(_sink);
                                printedLast = true;
                            }
                            else
                            {
                                printedLast = false;
                            }
                        }
                    }
                }
            }
Beispiel #43
0
 public static LNode WithoutAttr(this LNode self, LNode node)
 {
     return(self.WithAttrs(self.Attrs.Without(node)));
 }
Beispiel #44
0
 public static LNode bob(LNode node, IMacroContext context)
 {
     return(LNode.Id("bobby"));
 }
Beispiel #45
0
 public static LNode braceTheRest(LNode node, IMacroContext context)
 {
     context.DropRemainingNodes = true;
     return(LNode.Call(S.Braces, LNode.List(context.RemainingNodes)));
 }
Beispiel #46
0
 /// <summary>Returns the same node with a parentheses attribute added.</summary>
 public static LNode InParens(this LNode node)
 {
     return(node.PlusAttrBefore(LNode.Id(CodeSymbols.TriviaInParens)));
 }
Beispiel #47
0
 public static LNode splice(LNode node, IMessageSink sink)
 {
     return(node.WithName(S.Splice));
 }
Beispiel #48
0
 /// <summary>Interprets a node as a list by returning <c>block.Args</c> if
 /// <c>block.Calls(listIdentifier)</c>, otherwise returning a one-item list
 /// of nodes with <c>block</c> as the only item.</summary>
 public static VList <LNode> AsList(this LNode block, Symbol listIdentifier)
 {
     return(block.Calls(listIdentifier) ? block.Args : new VList <LNode>(block));
 }
Beispiel #49
0
 public static LNode uppercasemacro(LNode node, IMacroContext context)
 {
     return(LNode.Id("UPPERCASE"));
 }
Beispiel #50
0
 /// <summary>Adds additional trailing trivia to a node.</summary>
 public static LNode PlusTrailingTrivia(this LNode node, LNode trivia)
 {
     return(node.WithAttrs(PlusTrailingTrivia(node.Attrs, trivia)));
 }
Beispiel #51
0
 public static LNode DeprecatedMacro(LNode node, IMacroContext context)
 {
     return(LNode.Id("groovy_macro_dude"));
 }
Beispiel #52
0
        private LNode Term()
        {
            TokenType    la0;
            LNode        first  = default(LNode);
            List <LNode> rest   = new List <LNode>();
            LNode        result = default(LNode);

            // Line 222: ( TT.Id | TT.Num | TT.LBrace TT.RBrace | TT.LBrace Expr (TT.Comma Expr)* TT.RBrace | TT.LParen Expr TT.RParen )
            do
            {
                la0 = (TokenType)LA0;
                if (la0 == TT.Id)
                {
                    var t = MatchAny();
                    // line 222
                    result = F.Id(t);
                }
                else if (la0 == TT.Num)
                {
                    var t = MatchAny();
                    // line 223
                    result = F.Literal(t);
                }
                else if (la0 == TT.LBrace)
                {
                    switch ((TokenType)LA(1))
                    {
                    case TT.RBrace:
                    {
                        Skip();
                        Skip();
                        // line 224
                        result = F.AltList();
                    }
                    break;

                    case TT.Id:
                    case TT.LBrace:
                    case TT.LParen:
                    case TT.Num:
                    case TT.Sub:
                    {
                        Skip();
                        first = Expr();
                        // Line 225: (TT.Comma Expr)*
                        for (;;)
                        {
                            la0 = (TokenType)LA0;
                            if (la0 == TT.Comma)
                            {
                                Skip();
                                rest.Add(Expr());
                            }
                            else
                            {
                                break;
                            }
                        }
                        Match((int)TT.RBrace);
                        // line 225
                        result = F.AltList(rest?.Prepend(first) ?? Enumerable.Repeat(first, 1));
                    }
                    break;

                    default:
                        goto error;
                    }
                }
                else if (la0 == TT.LParen)
                {
                    Skip();
                    result = Expr();
                    Match((int)TT.RParen);
                    // line 226
                    result = F.InParens(result);
                }
                else
                {
                    goto error;
                }
                break;
error:
                {
                    // line 227
                    result = F.Missing;
                    Error(0, "Expected identifer, number, or (parens)");
                }
            } while (false);
            return(result);
        }
Beispiel #53
0
 protected IdNode(LNode ras) : base(ras)
 {
 }
Beispiel #54
0
        // Handle multiple precedence levels with one rule, as explained in Part 5 article
        private LNode Expr(int prec = 0)
        {
            LNode result = default(LNode);

            result = PrefixExpr();
            // Line 198: greedy( &{prec <= 10} TT.LBrace Expr TT.RBrace | &{prec <= 20} TT.Assign Expr | &{prec < 30} (TT.Eq|TT.GE|TT.GT|TT.LE|TT.LT|TT.NotEq) Expr | &{prec < 40} (TT.Add|TT.Sub) Expr | &{prec < 50} (TT.Div|TT.Mul) Expr )*
            for (;;)
            {
                switch ((TokenType)LA0)
                {
                case TT.LBrace:
                {
                    if (prec <= 10)
                    {
                        Skip();
                        var index = Expr();
                        Match((int)TT.RBrace);
                        // line 200
                        result = F.Call(S.IndexBracks, F.AltList(result, index));
                    }
                    else
                    {
                        goto stop;
                    }
                }
                break;

                case TT.Assign:
                {
                    if (prec <= 20)
                    {
                        var op = MatchAny();
                        var r  = Expr(20);
                        // line 203
                        result = BinOp((Symbol)op.Value, result, r);
                    }
                    else
                    {
                        goto stop;
                    }
                }
                break;

                case TT.Eq:
                case TT.GE:
                case TT.GT:
                case TT.LE:
                case TT.LT:
                case TT.NotEq:
                {
                    if (prec < 30)
                    {
                        var op = MatchAny();
                        var r  = Expr(30);
                        // line 206
                        result = BinOp((Symbol)op.Value, result, r);
                    }
                    else
                    {
                        goto stop;
                    }
                }
                break;

                case TT.Add:
                case TT.Sub:
                {
                    if (prec < 40)
                    {
                        var op = MatchAny();
                        var r  = Expr(40);
                        // line 209
                        result = BinOp((Symbol)op.Value, result, r);
                    }
                    else
                    {
                        goto stop;
                    }
                }
                break;

                case TT.Div:
                case TT.Mul:
                {
                    if (prec < 50)
                    {
                        var op = MatchAny();
                        var r  = Expr(50);
                        // line 212
                        result = BinOp((Symbol)op.Value, result, r);
                    }
                    else
                    {
                        goto stop;
                    }
                }
                break;

                default:
                    goto stop;
                }
            }
            stop :;
            return(result);
        }
Beispiel #55
0
 LNode BinOp(Symbol type, LNode lhs, LNode rhs) =>
 F.Call(type, lhs, rhs, lhs.Range.StartIndex, rhs.Range.EndIndex);
Beispiel #56
0
 public static LNode ArgNamed(this LNode self, Symbol name)
 {
     return(self.Args.NodeNamed(name));
 }
Beispiel #57
0
 /// <summary>Returns the same node with a parentheses attribute added.</summary>
 public static LNode InParens(this LNode node, ISourceFile file, int startIndex, int endIndex)
 {
     return(InParens(node, new SourceRange(file, startIndex, endIndex - startIndex)));
 }
Beispiel #58
0
 /// <summary>Gets all trailing trivia attached to the specified node.</summary>
 public static VList <LNode> GetTrailingTrivia(this LNode node)
 {
     return(GetTrailingTrivia(node.Attrs));
 }
Beispiel #59
0
 /// <summary>Returns the same node with a parentheses attribute added.</summary>
 /// <remarks>The node's range is changed to the provided <see cref="SourceRange"/>
 /// and the original range of the node is assigned to the parentheses attribute.</remarks>
 public static LNode InParens(this LNode node, SourceRange range)
 {
     return(node.WithRange(range).PlusAttrBefore(LNode.Id(CodeSymbols.TriviaInParens)));
 }
Beispiel #60
0
            private LNode ApplyMacrosFound2(LNode input, int maxExpansions, ListSlice <MacroInfo> foundMacros, ref ApplyMacroState s)
            {
                s.results.Clear();
                s.messageHolder.List.Clear();

                int accepted = 0, acceptedIndex = -1;

                for (int i = 0; i < foundMacros.Count; i++)
                {
                    var macro      = foundMacros[i];
                    var macroInput = input;
                    if ((macro.Mode & MacroMode.ProcessChildrenBefore) != 0)
                    {
                        if (maxExpansions == 1)
                        {
                            continue;                             // avoid expanding both this macro and its children
                        }
                        if (s.preprocessed == null)
                        {
                            // _foundMacros, _results, and _messageHolder are re-used
                            // by callee for unrelated contexts, so make copies of the s.*
                            // variables which point to them.
                            s.foundMacros   = new List <MacroInfo>(s.foundMacros);
                            s.results       = new List <Result>(s.results);
                            s.messageHolder = s.messageHolder.Clone();
                            foundMacros     = new List <MacroInfo>(foundMacros).Slice(0);

                            s.preprocessed = ApplyMacrosToChildren(input, maxExpansions) ?? input;
                        }
                        macroInput = s.preprocessed;
                    }

                    LNode output = null;
                    int   mhi    = s.messageHolder.List.Count;
                    try {
                        output = macro.Macro(macroInput, s.messageHolder);
                        if (output != null)
                        {
                            accepted++; acceptedIndex = i;
                        }
                    } catch (ThreadAbortException e) {
                        _sink.Write(Severity.Error, input, "Macro-processing thread aborted in {0}", QualifiedName(macro.Macro.Method));
                        _sink.Write(Severity.Detail, input, e.StackTrace);
                        s.results.Add(new Result(macro, output, s.messageHolder.List.Slice(mhi, s.messageHolder.List.Count - mhi)));
                        PrintMessages(s.results, input, accepted, Severity.Error);
                        throw;
                    } catch (Exception e) {
                        s.messageHolder.Write(Severity.Error, input, "{0}: {1}", e.GetType().Name, e.Message);
                        s.messageHolder.Write(Severity.Detail, input, e.StackTrace);
                    }
                    s.results.Add(new Result(macro, output, s.messageHolder.List.Slice(mhi, s.messageHolder.List.Count - mhi)));
                }

                PrintMessages(s.results, input, accepted,
                              s.messageHolder.List.MaxOrDefault(msg => (int)msg.Severity).Severity);

                if (accepted >= 1)
                {
                    var result = s.results[acceptedIndex];

                    Debug.Assert(result.Node != null);
                    if ((result.Macro.Mode & MacroMode.ProcessChildrenBefore) != 0)
                    {
                        maxExpansions--;
                    }

                    if ((result.Macro.Mode & MacroMode.Normal) != 0)
                    {
                        if (result.Node == input)
                        {
                            return(ApplyMacrosToChildren(result.Node, maxExpansions - 1) ?? result.Node);
                        }
                        else
                        {
                            return(ApplyMacros(result.Node, maxExpansions - 1) ?? result.Node);
                        }
                    }
                    else if ((result.Macro.Mode & MacroMode.ProcessChildrenAfter) != 0)
                    {
                        return(ApplyMacrosToChildren(result.Node, maxExpansions - 1) ?? result.Node);
                    }
                    else
                    {
                        return(result.Node);
                    }
                }
                else
                {
                    // "{}" needs special treatment
                    if (input.Calls(S.Braces))
                    {
                        try {
                            return(s.preprocessed ?? ApplyMacrosToChildren(input, maxExpansions));
                        } finally {
                            PopScope();
                        }
                    }
                    return(s.preprocessed ?? ApplyMacrosToChildren(input, maxExpansions));
                }
            }