Ejemplo n.º 1
0
    private CommandTree ParseCommand(
        CommandTreeParserContext context,
        ICommandContainer current,
        CommandTree?parent,
        CommandTreeTokenStream stream)
    {
        // Find the command.
        var commandToken = stream.Consume(CommandTreeToken.Kind.String);

        if (commandToken == null)
        {
            throw new CommandRuntimeException("Could not consume token when parsing command.");
        }

        var command = current.FindCommand(commandToken.Value, CaseSensitivity);

        if (command == null)
        {
            throw CommandParseException.UnknownCommand(_configuration, parent, context.Arguments, commandToken);
        }

        return(ParseCommandParameters(context, command, parent, stream));
    }
Ejemplo n.º 2
0
    private string?ParseOptionValue(
        CommandTreeParserContext context,
        CommandTreeTokenStream stream,
        CommandTreeToken token,
        CommandTree current,
        CommandParameter?parameter)
    {
        var value = default(string);

        // Parse the value of the token (if any).
        var valueToken = stream.Peek();

        if (valueToken?.TokenKind == CommandTreeToken.Kind.String)
        {
            var parseValue = true;
            if (token.TokenKind == CommandTreeToken.Kind.ShortOption && token.IsGrouped)
            {
                parseValue = false;
            }

            if (context.State == State.Normal && parseValue)
            {
                // Is this a command?
                if (current.Command.FindCommand(valueToken.Value, CaseSensitivity) == null)
                {
                    if (parameter != null)
                    {
                        if (parameter.ParameterKind == ParameterKind.Flag)
                        {
                            if (!CliConstants.AcceptedBooleanValues.Contains(valueToken.Value, StringComparer.OrdinalIgnoreCase))
                            {
                                // Flags cannot be assigned a value.
                                throw CommandParseException.CannotAssignValueToFlag(context.Arguments, token);
                            }
                        }

                        value = stream.Consume(CommandTreeToken.Kind.String)?.Value;
                    }
                    else
                    {
                        // Unknown parameter value.
                        value = stream.Consume(CommandTreeToken.Kind.String)?.Value;

                        // In relaxed parsing mode?
                        if (context.ParsingMode == ParsingMode.Relaxed)
                        {
                            context.AddRemainingArgument(token.Value, value);
                        }
                    }
                }
            }
            else
            {
                context.AddRemainingArgument(token.Value, parseValue ? valueToken.Value : null);
            }
        }
        else
        {
            if (context.State == State.Remaining || context.ParsingMode == ParsingMode.Relaxed)
            {
                context.AddRemainingArgument(token.Value, null);
            }
        }

        // No value?
        if (context.State == State.Normal)
        {
            if (value == null && parameter != null)
            {
                if (parameter.ParameterKind == ParameterKind.Flag)
                {
                    value = "true";
                }
                else
                {
                    if (parameter is CommandOption option)
                    {
                        if (parameter.IsFlagValue())
                        {
                            return(null);
                        }

                        throw CommandParseException.OptionHasNoValue(context.Arguments, token, option);
                    }
                    else
                    {
                        // This should not happen at all. If it does, it's because we've added a new
                        // option type which isn't a CommandOption for some reason.
                        throw new InvalidOperationException($"Found invalid parameter type '{parameter.GetType().FullName}'.");
                    }
                }
            }
        }

        return(value);
    }
Ejemplo n.º 3
0
    private void ParseString(
        CommandTreeParserContext context,
        CommandTreeTokenStream stream,
        CommandTree node)
    {
        if (context.State == State.Remaining)
        {
            stream.Consume(CommandTreeToken.Kind.String);
            return;
        }

        var token = stream.Expect(CommandTreeToken.Kind.String);

        // Command?
        var command = node.Command.FindCommand(token.Value, CaseSensitivity);

        if (command != null)
        {
            if (context.State == State.Normal)
            {
                node.Next = ParseCommand(context, node.Command, node, stream);
            }

            return;
        }

        // Current command has no arguments?
        if (!node.HasArguments())
        {
            throw CommandParseException.UnknownCommand(_configuration, node, context.Arguments, token);
        }

        // Argument?
        var parameter = node.FindArgument(context.CurrentArgumentPosition);

        if (parameter == null)
        {
            // No parameters left. Any commands after this?
            if (node.Command.Children.Count > 0 || node.Command.IsDefaultCommand)
            {
                throw CommandParseException.UnknownCommand(_configuration, node, context.Arguments, token);
            }

            throw CommandParseException.CouldNotMatchArgument(context.Arguments, token);
        }

        // Yes, this was an argument.
        if (parameter.ParameterKind == ParameterKind.Vector)
        {
            // Vector
            var current = stream.Current;
            while (current?.TokenKind == CommandTreeToken.Kind.String)
            {
                var value = stream.Consume(CommandTreeToken.Kind.String)?.Value;
                node.Mapped.Add(new MappedCommandParameter(parameter, value));
                current = stream.Current;
            }
        }
        else
        {
            // Scalar
            var value = stream.Consume(CommandTreeToken.Kind.String)?.Value;
            node.Mapped.Add(new MappedCommandParameter(parameter, value));
            context.IncreaseArgumentPosition();
        }
    }