Exemplo n.º 1
0
        private static TemplateToken ReadOption(TextBuffer buffer)
        {
            var position = buffer.Position;

            buffer.Consume('-');
            if (buffer.IsNext('-'))
            {
                buffer.Consume('-');
                var longValue = ReadOptionName(buffer);
                return(new TemplateToken(TemplateToken.Kind.LongName, position, longValue, $"--{longValue}"));
            }

            var shortValue = ReadOptionName(buffer);

            return(new TemplateToken(TemplateToken.Kind.ShortName, position, shortValue, $"-{shortValue}"));
        }
Exemplo n.º 2
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}]"));
        }
        private static IEnumerable <CommandTreeToken> ScanOptions(CommandTreeTokenizerContext context, TextBuffer reader)
        {
            var result = new List <CommandTreeToken>();

            var position = reader.Position;

            reader.Consume('-');
            context.AddRemaining('-');

            if (!reader.TryPeek(out var character))
            {
                var token = new CommandTreeToken(CommandTreeToken.Kind.ShortOption, position, "-", "-");
                throw CommandParseException.OptionHasNoName(reader.Original, token);
            }

            switch (character)
            {
            case '-':
                var option = ScanLongOption(context, reader, position);
                if (option != null)
                {
                    result.Add(option);
                }

                break;

            default:
                result.AddRange(ScanShortOptions(context, reader, position));
                break;
            }

            if (reader.TryPeek(out character))
            {
                // Encountered a separator?
                if (character == '=' || character == ':')
                {
                    reader.Read(); // Consume
                    context.AddRemaining(character);

                    if (!reader.TryPeek(out _))
                    {
                        var token = new CommandTreeToken(CommandTreeToken.Kind.String, reader.Position, "=", "=");
                        throw CommandParseException.OptionValueWasExpected(reader.Original, token);
                    }

                    result.Add(ScanString(context, reader));
                }
            }

            return(result);
        }
        private static CommandTreeToken ScanLongOption(CommandTreeTokenizerContext context, TextBuffer reader, int position)
        {
            reader.Consume('-');
            context.AddRemaining('-');

            if (reader.ReachedEnd)
            {
                // Rest of the arguments are remaining ones.
                context.Mode = Mode.Remaining;
                return(new CommandTreeToken(CommandTreeToken.Kind.Remaining, position, "--", "--"));
            }

            var name = ScanString(context, reader, new[] { '=', ':' });

            // Perform validation of the name.
            if (name.Value.Length == 0)
            {
                throw CommandParseException.LongOptionNameIsMissing(reader, position);
            }

            if (name.Value.Length == 1)
            {
                throw CommandParseException.LongOptionNameIsOneCharacter(reader, position, name.Value);
            }

            if (char.IsDigit(name.Value[0]))
            {
                throw CommandParseException.LongOptionNameStartWithDigit(reader, position, name.Value);
            }

            for (var index = 0; index < name.Value.Length; index++)
            {
                if (!char.IsLetterOrDigit(name.Value[index]) && name.Value[index] != '-' && name.Value[index] != '_')
                {
                    throw CommandParseException.LongOptionNameContainSymbol(reader, position + 2 + index, name.Value[index]);
                }
            }

            return(new CommandTreeToken(CommandTreeToken.Kind.LongOption, position, name.Value, $"--{name.Value}"));
        }
        private static CommandTreeToken ScanQuotedString(CommandTreeTokenizerContext context, TextBuffer reader)
        {
            var position = reader.Position;

            context.FlushRemaining();
            reader.Consume('\"');

            var builder    = new StringBuilder();
            var terminated = false;

            while (!reader.ReachedEnd)
            {
                var character = reader.Peek();
                if (character == '\"')
                {
                    terminated = true;
                    reader.Read();
                    break;
                }

                builder.Append(reader.Read());
            }

            if (!terminated)
            {
                var unterminatedQuote = builder.ToString();
                var token             = new CommandTreeToken(CommandTreeToken.Kind.String, position, unterminatedQuote, $"\"{unterminatedQuote}");
                throw CommandParseException.UnterminatedQuote(reader.Original, token);
            }

            var quotedString = builder.ToString();

            // Add to the context
            context.AddRemaining(quotedString);

            return(new CommandTreeToken(
                       CommandTreeToken.Kind.String,
                       position, quotedString,
                       quotedString));
        }
Exemplo n.º 6
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);
        }
        private static int ParseToken(CommandTreeTokenizerContext context, TextBuffer reader, int position, int start, List <CommandTreeToken> tokens)
        {
            while (reader.Peek() != -1)
            {
                if (reader.ReachedEnd)
                {
                    position += reader.Position - start;
                    break;
                }

                var character = reader.Peek();

                // Eat whitespace
                if (char.IsWhiteSpace(character))
                {
                    reader.Consume();
                    continue;
                }

                if (character == '-')
                {
                    // Option
                    tokens.AddRange(ScanOptions(context, reader));
                }
                else
                {
                    // Command or argument
                    tokens.Add(ScanString(context, reader));
                }

                // Flush remaining tokens
                context.FlushRemaining();
            }

            return(position);
        }