Beispiel #1
0
    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);
    }
Beispiel #2
0
    private static CommandTreeToken ScanString(
        CommandTreeTokenizerContext context,
        TextBuffer reader,
        char[]?stop = null)
    {
        if (reader.TryPeek(out var character))
        {
            // Is this a quoted string?
            if (character == '\"')
            {
                return(ScanQuotedString(context, reader));
            }
        }

        var position = reader.Position;
        var builder  = new StringBuilder();

        while (!reader.ReachedEnd)
        {
            var current = reader.Peek();
            if (stop?.Contains(current) ?? false)
            {
                break;
            }

            reader.Read(); // Consume
            context.AddRemaining(current);
            builder.Append(current);
        }

        var value = builder.ToString();

        return(new CommandTreeToken(CommandTreeToken.Kind.String, position, value.Trim(), value));
    }
Beispiel #3
0
    private static IEnumerable <CommandTreeToken> ScanShortOptions(CommandTreeTokenizerContext context, TextBuffer reader, int position)
    {
        var result = new List <CommandTreeToken>();

        while (!reader.ReachedEnd)
        {
            var current = reader.Peek();
            if (char.IsWhiteSpace(current))
            {
                break;
            }

            // Encountered a separator?
            if (current == '=' || current == ':')
            {
                break;
            }

            if (char.IsLetter(current))
            {
                context.AddRemaining(current);
                reader.Read(); // Consume

                var value = current.ToString(CultureInfo.InvariantCulture);
                result.Add(result.Count == 0
                    ? new CommandTreeToken(CommandTreeToken.Kind.ShortOption, position, value, $"-{value}")
                    : new CommandTreeToken(CommandTreeToken.Kind.ShortOption, position + result.Count, value, value));
            }
            else
            {
                // Create a token representing the short option.
                var tokenPosition = position + 1 + result.Count;
                var represntation = current.ToString(CultureInfo.InvariantCulture);
                var token         = new CommandTreeToken(CommandTreeToken.Kind.ShortOption, tokenPosition, represntation, represntation);
                throw CommandParseException.InvalidShortOptionName(reader.Original, token);
            }
        }

        if (result.Count > 1)
        {
            foreach (var item in result)
            {
                item.IsGrouped = true;
            }
        }

        return(result);
    }
Beispiel #4
0
    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}"));
    }
Beispiel #5
0
    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));
    }