private void ParseCommand(CommandContext commandContext) { bool ignoreRemainingArguments = false; var remainingOperands = new List <Token>(); Command currentCommand = commandContext.RootCommand; Option currentOption = null; Token currentOptionToken = null; IEnumerator <Operand> operands = new OperandEnumerator(currentCommand.Operands); IEnumerable <Token> tokens = commandContext.Tokens.Arguments; // using TakeWhile ensures we're evaluating ParseSeparatedArguments // with the final command. We know this because separated arguments // can only contain operands. bool UsingEndOfOptions() { var separatorStrategy = currentCommand.GetArgumentSeparatorStrategy(_appSettings); return(separatorStrategy == ArgumentSeparatorStrategy.EndOfOptions); } IEnumerable <Token> EndOfOptionsTokens() { if (!UsingEndOfOptions()) { yield break; } foreach (var token in commandContext.Tokens.Separated) { yield return(token); } } //tokens = tokens.Concat(EndOfOptionsTokens()); tokens = tokens.Concat(commandContext.Tokens.Separated.TakeWhile(t => UsingEndOfOptions())); foreach (var token in tokens) { switch (token.TokenType) { case TokenType.Option: ParseOption(token, currentCommand, out currentOption); if (currentOption != null) { currentOptionToken = token; } break; case TokenType.Value: if (ignoreRemainingArguments && currentOption == null) { remainingOperands.Add(token); } else { var operandResult = ParseArgumentValue( token, ref currentCommand, ref currentOption, ref currentOptionToken, operands); switch (operandResult) { case ParseOperandResult.Succeeded: break; case ParseOperandResult.UnexpectedArgument: ignoreRemainingArguments = true; remainingOperands.Add(token); break; case ParseOperandResult.NewSubCommand: operands = new OperandEnumerator(currentCommand.Operands); break; default: throw new ArgumentOutOfRangeException(operandResult.ToString()); } } break; case TokenType.Separator: throw new ArgumentOutOfRangeException($"The argument list should have already had the separator removed: {token.RawValue}"); case TokenType.Directive: throw new ArgumentOutOfRangeException($"Directives should have already been processed and removed: {token.RawValue}"); default: throw new ArgumentOutOfRangeException($"Unknown {nameof(TokenType)}: {token.TokenType}"); } } if (currentOption != null) // an option was left without a value { throw new CommandParsingException(currentCommand, $"Missing value for option '{currentOption.Name}'"); } commandContext.ParseResult = new ParseResult( currentCommand, remainingOperands, commandContext.Tokens.Separated); }
private void ParseCommand(CommandContext commandContext) { bool ignoreRemainingArguments = false; var remainingOperands = new List <Token>(); Command currentCommand = commandContext.RootCommand; Option currentOption = null; IEnumerator <Operand> operands = new OperandEnumerator(currentCommand.Operands); foreach (var token in commandContext.Tokens.Arguments) { switch (token.TokenType) { case TokenType.Option: ParseOption(token, currentCommand, out currentOption); break; case TokenType.Value: if (ignoreRemainingArguments && currentOption == null) { remainingOperands.Add(token); } else { var operandResult = ParseArgumentValue( token, ref currentCommand, ref currentOption, operands); switch (operandResult) { case ParseOperandResult.Succeeded: break; case ParseOperandResult.UnexpectedArgument: ignoreRemainingArguments = true; break; case ParseOperandResult.NewSubCommand: operands = new OperandEnumerator(currentCommand.Operands); break; default: throw new ArgumentOutOfRangeException(operandResult.ToString()); } } break; case TokenType.Separator: throw new ArgumentOutOfRangeException($"The argument list should have already had the separator removed: {token.RawValue}"); case TokenType.Directive: throw new ArgumentOutOfRangeException($"Directives should have already been processed and removed: {token.RawValue}"); default: throw new ArgumentOutOfRangeException($"Unknown {nameof(TokenType)}: {token.TokenType}"); } } if (currentOption != null) // an option was left without a value { throw new CommandParsingException(currentCommand, $"Missing value for option '{currentOption.Name}'"); } commandContext.ParseResult = new ParseResult( currentCommand, remainingOperands, commandContext.Tokens.Separated); }
private ParseOperandResult ParseArgumentValue(Token token, ref Command command, OperandEnumerator operands) { if (!operands.Any && command.FindArgumentNode(token.Value) is Command subcommand) { command = subcommand; return(ParseOperandResult.NewSubCommand); } if (operands.MoveNext()) { var current = operands.Current; ThrowIfValueNotAllowed(command, current, token); GetArgumentParsedValues(current).Add(new ValueFromToken(token.Value, token, null)); } else { if (command.GetIgnoreUnexpectedOperands(_appSettings)) { return(ParseOperandResult.UnexpectedArgument); } // use the term "argument" for messages displayed to users throw new UnrecognizedArgumentCommandParsingException(command, token, $"Unrecognized command or argument '{token.RawValue}'"); } return(ParseOperandResult.Succeeded); }