/// <summary> /// Constructs a parser that consumes a whitespace and all comments /// parsed by the commentParser.AnyComment parser, but parses only one trailing /// comment that starts exactly on the last line of the parsed value. /// </summary> /// <typeparam name="T">The result type of the given parser.</typeparam> /// <param name="parser">The parser to wrap.</param> /// <param name="commentParser">The comment parser.</param> /// <returns>An extended Token() version of the given parser.</returns> public static Parser <ICommented <T> > Commented <T>(this Parser <T> parser, IComment commentParser = null) { if (parser == null) { throw new ArgumentNullException(nameof(parser)); } // consume any comment supported by the comment parser var comment = (commentParser ?? DefaultCommentParser).AnyComment; // parses any whitespace except for the new lines var whiteSpaceExceptForNewLine = WhiteSpace.Except(Chars("\r\n")).Many().Text(); // returns true if the second span starts on the first span's last line bool IsSameLine(ITextSpan <T> first, ITextSpan <string> second) => first.End.Line == second.Start.Line; // single comment span followed by a whitespace var commentSpan = from cs in comment.Span() from ws in whiteSpaceExceptForNewLine select cs; // add leading and trailing comments to the parser return (from leadingWhiteSpace in WhiteSpace.Many() from leadingComments in comment.Token().Many() from valueSpan in parser.Span() from trailingWhiteSpace in whiteSpaceExceptForNewLine from trailingPreview in commentSpan.Many().Preview() let trailingCount = trailingPreview.GetOrElse(Enumerable.Empty <ITextSpan <string> >()) .Where(c => IsSameLine(valueSpan, c)).Count() from trailingComments in commentSpan.Repeat(trailingCount) select new CommentedValue <T>(leadingComments, valueSpan.Value, trailingComments.Select(c => c.Value))); }
public static FTL.AST.INode Parse(CharStream cs) { FTL.AST.INode result; // if it's an identifier, it could be either simply be an identifier, // or it could actually be a keyword-argument if (Identifier.PeekAndParse(cs, out result)) { int bufferPos = cs.Position; // ignore any whitespace WhiteSpace.Parse(cs); // if we now encounter a `=` char, we'll assume it's a keyword-argument, // and finish the parsing of that element, // otherwise we'll assume it's simply an identifier and return early if (cs.PeekNext() != '=') { cs.Rewind(bufferPos); return(Expresson.ParseWithIdentifier(cs, result as FTL.AST.StringPrimitive)); } cs.SkipNext(); WhiteSpace.Parse(cs); FTL.AST.Pattern pattern = Pattern.ParseQuoted(cs); return(new FTL.AST.KeywordArgument( result as L20n.FTL.AST.StringPrimitive, pattern)); } // it's not an identifier, so is must be any non-identifier expression return(Expresson.ParseNoneIdentifier(cs)); }
// ([^{"] | '\{' | '\"')+ public static FTL.AST.QuotedText ParseQuoted(CharStream cs) { s_Buffer.Clear(); WhiteSpace.Parse(cs); bool allowSC = false; char next = cs.PeekNext(); while (!CharStream.IsEOF(next) && !CharStream.IsNL(next) && (allowSC || (next != '{' && next != '"'))) { s_Buffer.Add(next); cs.SkipNext(); allowSC = !allowSC && next == '\\'; next = cs.PeekNext(); } if (s_Buffer.Count == 0) { throw cs.CreateException( "no quoted text could be parsed, while this was expected", null); } return(new FTL.AST.QuotedText(new string(s_Buffer.ToArray()))); }
public static bool PeekAndParse(CharStream cs, out FTL.AST.MemberList memberList) { // if next char is not a newline, we can just as well skip already char next = cs.PeekNext(); if (CharStream.IsEOF(next) || !CharStream.IsNL(next)) { memberList = null; return(false); } // let's keep peeking further, requiring our buffer int bufferPos = cs.Position; NewLine.Parse(cs); WhiteSpace.Parse(cs); // we'll always want to rewind no matter what bool isMemberList = Member.Peek(cs); cs.Rewind(bufferPos); if (isMemberList) { memberList = Parse(cs); return(true); } memberList = null; return(false); }
public static FTL.AST.INode Parse(CharStream cs) { FTL.AST.INode expression = Expresson.Parse(cs); int bufferPos = cs.Position; WhiteSpace.Parse(cs); if (cs.PeekNext() != SEPERATOR[0]) { // it's not a select expression, so let's return early cs.Rewind(bufferPos); return(expression); } // it must be a select expression cs.SkipString(SEPERATOR); WhiteSpace.Parse(cs); // we expect now a memberList (REQUIRED) FTL.AST.MemberList memberList = MemberList.Parse(cs); // skip extra new-line in case one is available if (CharStream.IsNL(cs.PeekNext())) { NewLine.Parse(cs); } // return it all return(new FTL.AST.SelectExpression(expression, memberList)); }
public static void SetTextWrap(this VisualElement self, WhiteSpace v) { var c = self.style.whiteSpace; c.value = v; self.style.whiteSpace = c; }
public static FTL.AST.Member Parse(CharStream cs) { WhiteSpace.Parse(cs); bool isDefault = false; if (cs.PeekNext() == '*') { cs.SkipNext(); isDefault = true; } // Parse the MemberKey cs.SkipCharacter('['); FTL.AST.INode key = Memberkey.Parse(cs); cs.SkipCharacter(']'); // skip optional space WhiteSpace.Parse(cs); // Parse the actual pattern FTL.AST.Pattern pattern = Pattern.Parse(cs); // and return it all return(new FTL.AST.Member(key, pattern, isDefault)); }
public static bool PeekAndParse(CharStream cs, out FTL.AST.Pattern pattern) { // A quoted-pattern is the easiest to detect, so we'll try that first if (cs.PeekNext() == '"') { pattern = ParseQuoted(cs); return(true); } // it might still be an unquoted-pattern, but this is trickier to detect // first let's try to detect a placeable and block-text if (Placeable.Peek(cs) || AnyText.PeekBlockText(cs)) { pattern = ParseUnquoted(cs); return(true); } // if not any of the above, the only thing left is unquoted-text int bufferPos = cs.Position; WhiteSpace.Parse(cs); char next = cs.PeekNext(); cs.Rewind(bufferPos); if (!CharStream.IsEOF(next) && !CharStream.IsNL(next)) { pattern = ParseUnquoted(cs); return(true); } pattern = null; return(false); }
public static FTL.AST.CallExpression Parse(CharStream cs, FTL.AST.StringPrimitive builtin) { if (!Builtin.IsValid(builtin.Value)) { throw cs.CreateException( string.Format("{0} is not a valid builtin, while one was expected", builtin.Value), null); } cs.SkipCharacter(PREFIX); FTL.AST.ArgumentsList arguments = new FTL.AST.ArgumentsList(); while (cs.PeekNext() != POSTFIX) { WhiteSpace.Parse(cs); arguments.AddArgument(Argument.Parse(cs)); WhiteSpace.Parse(cs); if (cs.PeekNext() != ',') { break; // exit early, as no more arguments are expected } cs.SkipNext(); // skip ',' } // make sure last non-ws char is ')', // otherwise something went wrong cs.SkipCharacter(POSTFIX); return(new FTL.AST.CallExpression(builtin, arguments)); }
public static bool PeekBlockText(CharStream cs) { char next = cs.PeekNext(); // if next char isn't a NewLine Character, we know for sure we // are not dealing with a block-text if (CharStream.IsEOF(next) || !CharStream.IsNL(next)) { return(false); } // from here on out, we're still not sure if we're dealing with a block-text // thus we start buffering so we can go back in time // here we check if we have the following pattern: `NL __ '|'` int bufferPos = cs.Position; NewLine.Parse(cs); WhiteSpace.Parse(cs); // if the next unbuffered char is not '|' we're not dealing with a block-text // and can return; next = cs.PeekNext(); cs.Rewind(bufferPos); return(next == '|'); }
public void AppendText(string text, TextFormattingOptions formattingOptions = TextFormattingOptions.None, WhiteSpace appendWhiteSpace = WhiteSpace.None) { if (string.IsNullOrEmpty(text)) { throw new ArgumentException("'text' must not be null or empty.", "text"); } var msg = EscapeMarkdown ? chatMd.Replace(text, @"\$0") : text; message += FormatString(msg, formattingOptions); message = AppendWhiteSpace(message, appendWhiteSpace); }
public static VisualElement SetTextWrap(this VisualElement self, WhiteSpace v) { var c = self.style.whiteSpace; c.value = v; self.style.whiteSpace = c; return(self); }
private static FTL.AST.Section Parse(CharStream cs) { cs.SkipString(PREFIX); WhiteSpace.Parse(cs); var keyword = Keyword.Parse(cs); WhiteSpace.Parse(cs); cs.SkipString(POSTFIX); return(new FTL.AST.Section(keyword)); }
protected override (bool isSuccess, Cursol cursol, T parsed) ParseCore(Cursol cursol) { var current = cursol; bool isSuccess; do { (isSuccess, current, _) = WhiteSpace.Parse(current); } while (isSuccess); return(Parser.Parse(current)); }
void TextWrapUpdateToggleIcon(WhiteSpace resolveStyle) { var button = m_TextWrapButton; button.RemoveFromClassList("normal"); button.RemoveFromClassList("nowrap"); switch (resolveStyle) { case WhiteSpace.Normal: button.AddToClassList("normal"); break; case WhiteSpace.NoWrap: button.AddToClassList("nowrap"); break; } }
public WhiteSpace.Kind WhiteSpaceKind(IControl <UIView> control) { Dictionary <Type, Style> styles = _stylesheet.GetStyles(control); if (styles.ContainsKey(typeof(WhiteSpace))) { WhiteSpace wsk = (WhiteSpace)styles [typeof(WhiteSpace)]; return(wsk.Value); } else { return(WhiteSpace.Kind.Nowrap); } }
public void AppendLink(string text, string url, string onHoverText = null, TextFormattingOptions formattingOptions = TextFormattingOptions.None, WhiteSpace appendWhiteSpace = WhiteSpace.Space) { if (MultiLineType != MultiLineMessageType.None) { throw new InvalidOperationException("Cannot append an in-line link when this object's 'MultiLineType' is not set to 'MultiLineMessageType.None'."); } if (string.IsNullOrEmpty(url)) { throw new ArgumentException("'url' must not be null or empty.", "url"); } if (string.IsNullOrEmpty(text)) { throw new ArgumentException("'text' must not be null or empty.", "text"); } var urlSafe = (url.StartsWith("http://") ? url : "http://" + url).Trim(); var textSafe = chatMd.Replace(text.Trim(), @"\$0"); message += "[" + FormatString(textSafe, formattingOptions) + "]"; message += "(" + urlSafe + (string.IsNullOrEmpty(onHoverText) ? "" : " \"" + onHoverText + "\"") + ")"; message = AppendWhiteSpace(message, appendWhiteSpace); }
public void Assign(FormatCodes iFc) { Name = iFc.Name; Notes = iFc.Notes; ColorOn = iFc.ColorOn; ColorOff = iFc.ColorOff; SizeOn = iFc.SizeOn; SizeOff = iFc.SizeOff; BoldOn = iFc.BoldOn; BoldOff = iFc.BoldOff; ItalicOn = iFc.ItalicOn; ItalicOff = iFc.ItalicOff; UnderlineOn = iFc.UnderlineOn; UnderlineOff = iFc.UnderlineOff; Space = iFc.Space; }
public void SetDefault() { Name = string.Empty; Notes = string.Empty; ColorOn = string.Empty; ColorOff = string.Empty; SizeOn = string.Empty; SizeOff = string.Empty; BoldOn = string.Empty; BoldOff = string.Empty; ItalicOn = string.Empty; ItalicOff = string.Empty; UnderlineOn = string.Empty; UnderlineOff = string.Empty; Space = WhiteSpace.Space; }
public static bool PeekAndParse(CharStream cs, out FTL.AST.INode result) { if (!Peek(cs)) { result = null; return(false); } // skip prefix and optional space cs.SkipCharacter(PREFIX); FTL.AST.Placeable placeable = new FTL.AST.Placeable(); // parse all placeable-expressions do { WhiteSpace.Parse(cs); // optional newline if (CharStream.IsNL(cs.PeekNext())) { NewLine.Parse(cs); WhiteSpace.Parse(cs); } placeable.AddExpression(PlaceableExpression.Parse(cs)); WhiteSpace.Parse(cs); if (cs.PeekNext() != ',') { break; } // keep going, until we have no more commas cs.SkipNext(); } while(true); // skip optional space WhiteSpace.Parse(cs); // optional newline if (CharStream.IsNL(cs.PeekNext())) { NewLine.Parse(cs); WhiteSpace.Parse(cs); } cs.SkipCharacter(POSTFIX); result = placeable; return(true); }
public void WhiteSpaceTests() { var stream = NCS(" \t\t "); // This will read everything WhiteSpace.Parse(stream); // This will not read anything, but it's optional // so it will not give an exception WhiteSpace.Parse(stream); stream = NCS(" a <- foo"); // This will read until 'a' WhiteSpace.Parse(stream); WhiteSpace.Parse(stream); Assert.AreEqual("a <- foo", stream.ReadUntilEnd()); }
private static FTL.AST.Message Parse(CharStream cs, Context ctx, FTL.AST.StringPrimitive identifier) { WhiteSpace.Parse(cs); cs.SkipCharacter('='); WhiteSpace.Parse(cs); FTL.AST.Pattern pattern = null; // check if we have a Pattern available bool hasPattern = Pattern.PeekAndParse(cs, out pattern); FTL.AST.MemberList memberList; bool parsedMemberList = MemberList.PeekAndParse(cs, out memberList); if (!parsedMemberList && !hasPattern) { throw cs.CreateException( "member-list was expected, as no pattern was found", null); } return(new FTL.AST.Message(identifier, pattern, memberList)); }
public CssStyle() { color= new Color(0, 0, 0); background= new Background(); border= new Border(); clear= FloatType.none; display= Display.inline; _float= FloatType.none; height= new FlexibleFloat(0f, FlexFloatType.px); margin= new Margin(0f, 0f, 0f, 0f); padding= new Padding(0f, 0f, 0f, 0f); width= new FlexibleFloat(100f, FlexFloatType.percentage); letterSpacing= new FlexibleFloat(FlexibleFloat.letterSpacingNormal, FlexFloatType.px); lineHeight= new FlexibleFloat(FlexibleFloat.lineHeightNormal, FlexFloatType.px); textAlign= TextAlignment.left; textIndex= new FlexibleFloat(0f, FlexFloatType.px); textTransform= TextTransform.none; whiteSpace= WhiteSpace.normal; wordSpacing= new FlexibleFloat(FlexibleFloat.wordSpacingNormal, FlexFloatType.px); textDecoration= TextDecoration.none; font= new Sdx.Font("arial", 14); listStyle= new ListStyle(); }
public static FTL.AST.MemberList Parse(CharStream cs) { // starts with a newline and optional newline NewLine.Parse(cs); WhiteSpace.Parse(cs); FTL.AST.MemberList memberList = new FTL.AST.MemberList(); // parse first required member, as we always need at least 1 memberList.AddMember(Member.Parse(cs)); char next; int bufferPos; do { next = cs.PeekNext(); if (CharStream.IsEOF(next) || !CharStream.IsNL(next)) { break; } bufferPos = cs.Position; NewLine.Parse(cs); WhiteSpace.Parse(cs); if (!Member.Peek(cs)) { cs.Rewind(bufferPos); break; } memberList.AddMember(Member.Parse(cs)); } while(true); return(memberList); }
public void StylesIntersection_FewStyles_ReturnsDelta() { var oldStyles = new Dictionary <Type, IStyle>(); var color = new TextColor(0); color.FromString("#f00"); oldStyles.Add(color.GetType(), color); var font = new Font(2); font.FromString("80% arial"); oldStyles.Add(font.GetType(), font); var dockAlign = new DockAlign(4); dockAlign.FromString("top"); oldStyles.Add(dockAlign.GetType(), dockAlign); var newStyles = new Dictionary <Type, IStyle>(); var whiteSpace = new WhiteSpace(1); whiteSpace.FromString("nowrap"); newStyles.Add(whiteSpace.GetType(), whiteSpace); var newFont = new Font(3); newFont.FromString("5px tahoma"); newStyles.Add(newFont.GetType(), newFont); var newColor = new TextColor(5); newColor.FromString("#F00"); newStyles.Add(newColor.GetType(), newColor); IDictionary <Type, IStyle> actual = _styleSheet.StylesIntersection(oldStyles, newStyles); Assert.AreEqual(2, actual.Count); Assert.AreEqual(whiteSpace, actual[typeof(WhiteSpace)]); Assert.AreEqual(newFont, actual[typeof(Font)]); }
protected bool IsWhitespace(char c) => WhiteSpace.Contains(c);
public Configuration WhiteSpace(WhiteSpace value) { _whiteSpace = value; return(this); }
private static bool IsWhitespace(string token) { return(WhiteSpace.IndexOf(token) >= 0); }
public Configuration() { _bootstrapVersion = FluentMvcGrid.BootstrapVersion.Bootstrap3; _whiteSpace = FluentMvcGrid.WhiteSpace.None; }
public Configuration WhiteSpace(WhiteSpace value) { _whiteSpace = value; return this; }
public IEnumerable <Instruction> Lex(string sourceCode, CompileLog log) { string[] lines = sourceCode.Split(new string[] { LineSperator }, StringSplitOptions.None); int lineCounter = 0; foreach (var line in lines) { var codeLine = line.TrimStart(WhiteSpace); if (codeLine.StartsWith("#")) { log.Warning(lineCounter.ToString(), "Ignoring Compiler Directive", "AbaSim.Compiler does not support compiler directives. You have to configure the runtime separately to change runtime settings."); continue; } Instruction i = new Instruction(); List <string> args = new List <string>(); i.Arguments = args; if (codeLine.StartsWith(CommentSeparator.ToString() + CommentSeparator.ToString())) { i.Comment = codeLine.Substring(2); yield return(i); continue; } int offset = 0; int boffset = 0; Stage stage = Stage.LabelRunning; int commentFirstSymbolSeenOffset = -2; bool seenArgumentSeparatorSymbol = true; //set initially to true, as first argument does not need to be comma separated string location = null; while (offset < codeLine.Length) { location = lineCounter.ToString() + ":" + offset.ToString(); bool isWhiteSpace = WhiteSpace.Contains(codeLine[offset]); switch (stage) { case Stage.LabelRunning: if (codeLine[offset] == LabelTerminator) { i.Label = codeLine.Substring(boffset, offset - boffset); stage = Stage.OperationPending; } else if (isWhiteSpace) { i.Operation = codeLine.Substring(boffset, offset - boffset); stage = Stage.ArgumentsPending; } break; case Stage.OperationPending: if (!isWhiteSpace) { boffset = offset; stage = Stage.OperationRunning; } break; case Stage.OperationRunning: if (isWhiteSpace) { i.Operation = codeLine.Substring(boffset, offset - boffset); stage = Stage.ArgumentsPending; } break; case Stage.ArgumentsPending: if (!isWhiteSpace) { if (codeLine[offset] == ArgumentSeparator) { if (seenArgumentSeparatorSymbol) { args.Add(string.Empty); log.Warning(location, "Empty item in argument list.", null); } } else if (codeLine[offset] == CommentSeparator) { if (commentFirstSymbolSeenOffset == -2) { commentFirstSymbolSeenOffset = offset; } else if (commentFirstSymbolSeenOffset == offset - 1) { stage = Stage.CommentRunning; boffset = offset + 1; } else { log.Error(location, "Unexpected comment separator.", "Comments must be started by 2 comment separator characters (\"" + CommentSeparator.ToString() + "\")."); } } else { boffset = offset; stage = Stage.ArgumentsRunning; if (!seenArgumentSeparatorSymbol) { log.Warning(location, "Arguments are separated by whitespace instead of \"" + ArgumentSeparator.ToString() + "\"", "According to the language standard, arguments must be separated by an argument separator character and optionally additional whitespace."); } } } break; case Stage.ArgumentsRunning: if (isWhiteSpace) { stage = Stage.ArgumentsPending; args.Add(codeLine.Substring(boffset, offset - boffset)); } break; } offset++; } if (stage == Stage.OperationRunning || stage == Stage.LabelRunning) { i.Operation = codeLine.Substring(boffset); } else if (stage == Stage.CommentRunning) { i.Comment = codeLine.Substring(boffset); } else if (stage == Stage.ArgumentsRunning) { args.Add(codeLine.Substring(boffset, offset - boffset)); } i.SourceLine = lineCounter; yield return(i); lineCounter++; //var codeLine = line.TrimStart(WhiteSpace); //if (codeLine.StartsWith("//") || codeLine.StartsWith("#")) //{ // continue; //} //int offset = 0; //int boffset = 0; //Stage stage = Stage.LabelPending; //Instruction i = new Instruction(); //List<string> args = new List<string>(); //i.Arguments = args; //int commentFirstSymbolSeenOffset = -2; //while (offset < codeLine.Length) //{ // bool isWhiteSpace = WhiteSpace.Contains(codeLine[offset]); // if (isWhiteSpace && stage <= Stage.LabelPending) // { // //ignore leading space // boffset++; // } // else if (!isWhiteSpace && stage == Stage.LabelPending) // { // stage = Stage.LabelRunning; // } // else if (codeLine[offset] == ':' && stage <= Stage.LabelRunning) // { // if (offset == 0) // { // throw new InvalidSymbolException(codeLine[offset].ToString(), lineCounter, offset, "label name"); // } // i.Label = codeLine.Substring(boffset, offset - boffset); // boffset = offset + 1; // stage = Stage.OperationPending; // } // else if (isWhiteSpace && stage == Stage.OperationPending) // { // //ignore leading space // boffset++; // } // else if (!isWhiteSpace && stage == Stage.OperationPending) // { // stage = Stage.OperationRunning; // } // else if (isWhiteSpace && stage <= Stage.OperationRunning) // { // i.Operation = codeLine.Substring(boffset, offset - boffset); // if (i.Operation == string.Empty) // { // throw new InvalidSymbolException(codeLine[offset].ToString(), lineCounter, offset, "operation"); // } // boffset = offset + 1; // stage = Stage.ArgumentsPending; // } // else if (isWhiteSpace && stage <= Stage.ArgumentsPending) // { // //ignore leading space // boffset++; // } // else if (!isWhiteSpace && stage == Stage.ArgumentsPending) // { // stage = Stage.ArgumentsRunning; // } // else if ((codeLine[offset] == ',' || isWhiteSpace || codeLine[offset] == '/') && stage == Stage.ArgumentsRunning) // { // if (boffset < offset) // { // //argument completed // args.Add(codeLine.Substring(boffset, offset - boffset)); // boffset = offset + 1; // } // else // { // //more than one space // boffset++; // } // if (codeLine[offset] == '/') // { // if (commentFirstSymbolSeenOffset == offset - 1) // { // stage = Stage.CommentRunning; // boffset = offset + 1; // } // else if (commentFirstSymbolSeenOffset == -2) // { // commentFirstSymbolSeenOffset = offset; // } // else // { // throw new InvalidSymbolException("/", lineCounter, offset, "comment start token (\"\")"); // } // } // } // offset++; //} //if (stage == Stage.CommentRunning) //{ // i.Comment = codeLine.Substring(boffset); //} //else if (stage == Stage.ArgumentsRunning) //{ // args.Add(codeLine.Substring(boffset, offset - boffset)); //} //i.SourceLine = lineCounter; //yield return i; //lineCounter++; } }
public void AppendPing(User targetUser, WhiteSpace appendWhiteSpace = WhiteSpace.Space) { if (targetUser == null) { throw new ArgumentNullException("targetUser"); } AppendPing(targetUser.Name, appendWhiteSpace); }
internal static string GetText(string value, WhiteSpace whiteSpace) { return(GetTextOrDefault(value, whiteSpace == WhiteSpace.Nbsp ? " " : "")); }
private string AppendWhiteSpace(string text, WhiteSpace option = WhiteSpace.None) { if (option == WhiteSpace.None) { return text; } return text + (option == WhiteSpace.Space ? " " : newline); }
public void AppendPing(string targetUserName, WhiteSpace appendWhiteSpace = WhiteSpace.Space) { if (string.IsNullOrEmpty(targetUserName)) { throw new ArgumentException("'targetUserName' must not be null or empty.", "targetUser"); } message += "@" + targetUserName.Replace(" ", ""); message = AppendWhiteSpace(message, appendWhiteSpace); }
/// <summary> /// Succeeds if the specified parser succeeds, ignoring any whitespace characters beforehand. /// </summary> public static IParser <T> TrimStart <T>(this IParser <T> parser) => parser.PrecededBy(WhiteSpace.Many());
/// <summary> /// Succeeds if the specified parser succeeds, ignoring any whitespace characters afterward. /// </summary> public static IParser <T> TrimEnd <T>(this IParser <T> parser) => parser.FollowedBy(WhiteSpace.Many());