Trivia injector customized for Enhanced C#.
How newline trivia works in EC# (mostly this is the same as StandardTriviaInjector):
  • Implicitly, there is a newline before every node within a braced block, and CodeSymbols.TriviaAppendStatement is required to suppress it. The Loyc tree does not specify whether or not there is a newline before the closing brace; it is assumed that there should be a newline unless ALL children of the braced block use #trivia_appendStatement.
  • Implicitly, there is a newline before every top-level statement except the first, and #trivia_appendStatement can be used to suppress it.
  • By default, the printer doesn't print a newline before an opening brace. #trivia_newline can be added to the braced block node to represent one.
  • This injector explicitly encodes newlines in all other locations. However, the EC# printer is designed to print all syntax trees reasonably whether they have passed through the trivia injector or not. Therefore, on non-braced-block child statements of certain nodes (if statements, while loops, for loops, and other statements used without braces), the printer will print a newline before a child statement if it (1) does not have #trivia_newline or #trivia_appendStatement attributes and (2) does not have an ancestor with the NodeStyle.OneLiner style.
  • In an if-else statement, `else` has no representation in the syntax tree and may appear to the injector the same as a blank line. In this situation the first newline is attached to the child of //#if at index 1, and is deleted so that there is only one newline before the second child.
  • Constructors that call another constructor (`: base(...)`) get a newline before the colon by default, which can be suppressed with #trivia_appendStatement. Note: These constructors have an unusual syntax tree which the standard trivia injector can't handle properly; see comment in DoneAttaching() for details.
Inheritance: StandardTriviaInjector
Exemple #1
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);
		}
		public IListSource<LNode> Parse(ILexer<Token> input, IMessageSink msgs, ParsingMode inputType = null, bool preserveComments = true)
		{
			var preprocessed = new EcsPreprocessor(input, preserveComments);
			var treeified = new TokensToTree(preprocessed, false);
			var results = Parse(treeified.Buffered(), input.SourceFile, msgs, inputType);
			if (preserveComments) {
				var injector = new EcsTriviaInjector(preprocessed.TriviaList, input.SourceFile, 
					(int)TokenType.Newline, "/*", "*/", "//");
				return injector.Run(results.GetEnumerator()).Buffered();
			} else
				return results;
		}