Пример #1
0
        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}]"));
        }
Пример #2
0
        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);
        }
Пример #3
0
        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));
        }
Пример #4
0
        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);
        }