private static TemplateToken ReadValue(TextBuffer buffer, bool required) { var start = required ? '<' : '['; var end = required ? '>' : ']'; var position = buffer.Position; var kind = required ? TemplateToken.Kind.RequiredValue : TemplateToken.Kind.OptionalValue; // Consume start of value character (< or [). buffer.Consume(start); var builder = new StringBuilder(); while (!buffer.ReachedEnd) { var character = buffer.Peek(); if (character == end) { break; } buffer.Read(); builder.Append(character); } if (buffer.ReachedEnd) { var name = builder.ToString(); var token = new TemplateToken(kind, position, name, $"{start}{name}"); throw CommandTemplateException.UnterminatedValueName(buffer.Original, token); } // Consume end of value character (> or ]). buffer.Consume(end); // Get the value (the text within the brackets). var value = builder.ToString(); // Create a token and return it. return(new TemplateToken(kind, position, value, required ? $"<{value}>" : $"[{value}]")); }
public static ArgumentResult ParseArgumentTemplate(string template) { var valueName = default(string); var required = false; foreach (var token in TemplateTokenizer.Tokenize(template)) { if (token.TokenKind == TemplateToken.Kind.ShortName || token.TokenKind == TemplateToken.Kind.LongName) { throw CommandTemplateException.ArgumentCannotContainOptions(template, token); } if (token.TokenKind == TemplateToken.Kind.OptionalValue || token.TokenKind == TemplateToken.Kind.RequiredValue) { if (!string.IsNullOrWhiteSpace(valueName)) { throw CommandTemplateException.MultipleValuesAreNotSupported(template, token); } if (string.IsNullOrWhiteSpace(token.Value)) { throw CommandTemplateException.ValuesMustHaveName(template, token); } valueName = token.Value; required = token.TokenKind == TemplateToken.Kind.RequiredValue; } } if (valueName == null) { throw CommandTemplateException.ArgumentsMustHaveValueName(template); } return(new ArgumentResult(valueName, required)); }
public static IReadOnlyList <TemplateToken> Tokenize(string template) { using var buffer = new TextBuffer(template); var result = new List <TemplateToken>(); while (!buffer.ReachedEnd) { EatWhitespace(buffer); if (!buffer.TryPeek(out var character)) { break; } if (character == '-') { result.Add(ReadOption(buffer)); } else if (character == '|') { buffer.Consume('|'); } else if (character == '<') { result.Add(ReadValue(buffer, true)); } else if (character == '[') { result.Add(ReadValue(buffer, false)); } else { throw CommandTemplateException.UnexpectedCharacter(buffer.Original, buffer.Position, character); } } return(result); }
public static OptionResult ParseOptionTemplate(string template) { var result = new OptionResult(); foreach (var token in TemplateTokenizer.Tokenize(template)) { if (token.TokenKind == TemplateToken.Kind.LongName || token.TokenKind == TemplateToken.Kind.ShortName) { if (string.IsNullOrWhiteSpace(token.Value)) { throw CommandTemplateException.OptionsMustHaveName(template, token); } if (char.IsDigit(token.Value[0])) { throw CommandTemplateException.OptionNamesCannotStartWithDigit(template, token); } foreach (var character in token.Value) { if (!char.IsLetterOrDigit(character) && character != '-' && character != '_') { throw CommandTemplateException.InvalidCharacterInOptionName(template, token, character); } } } if (token.TokenKind == TemplateToken.Kind.LongName) { if (token.Value.Length == 1) { throw CommandTemplateException.LongOptionMustHaveMoreThanOneCharacter(template, token); } result.LongNames.Add(token.Value); } if (token.TokenKind == TemplateToken.Kind.ShortName) { if (token.Value.Length > 1) { throw CommandTemplateException.ShortOptionMustOnlyBeOneCharacter(template, token); } result.ShortNames.Add(token.Value); } if (token.TokenKind == TemplateToken.Kind.RequiredValue || token.TokenKind == TemplateToken.Kind.OptionalValue) { if (!string.IsNullOrWhiteSpace(result.Value)) { throw CommandTemplateException.MultipleOptionValuesAreNotSupported(template, token); } foreach (var character in token.Value) { if (!char.IsLetterOrDigit(character) && character != '=' && character != '-' && character != '_') { throw CommandTemplateException.InvalidCharacterInValueName(template, token, character); } } result.Value = token.Value.ToUpperInvariant(); result.ValueIsOptional = token.TokenKind == TemplateToken.Kind.OptionalValue; } } if (result.LongNames.Count == 0 && result.ShortNames.Count == 0) { throw CommandTemplateException.MissingLongAndShortName(template, null); } return(result); }