/// <summary>
        /// Parses a set of arguments
        /// </summary>
        /// <param name="args">The arguments to parse</param>
        /// <returns>The arguments</returns>
        public IEnumerable<CommandLineArgument> ParseArguments(IEnumerable<string> args)
        {
            var soMap = options.Where(x => x.ShortOption != default(char)).ToDictionary(x => ShortOptionStylizer != null ? ShortOptionStylizer(x.ShortOption) : x.ShortOption);
            var loMap = options.Where(x => x.LongOption != null).ToDictionary(x => LongOptionStylizer?.Invoke(x.LongOption) ?? x.LongOption);
            var option = default(CommandLineOption);
            var buffer = new StringBuilder();
            var state = ParseState.Head;
            var argbuf = new List<string>();
            var pos = new CommandLineArgumentPosition(0, 0);

            int pchr = int.MinValue;

            foreach (var chr in new StringArrayEnumerable(args, -1, -2))
            {
                switch (pchr)
                {
                    case -1:
                        pos.Argument++;
                        pos.Index = 0;
                        break;
                    case int.MinValue:
                        break;
                    default:
                        pos.Index++;
                        break;
                }
                pchr = chr;

                switch (state)
                {
                    #region "Discard"
                    case ParseState.Discard:
                        switch (chr)
                        {
                            case -1:
                                state = ParseState.Head;
                                break;
                            default:
                                break;
                        }
                        break;
                    #endregion
                    #region "Head"
                    case ParseState.Head:
                        switch (chr)
                        {
                            case -1:
                                argbuf.Add("");
                                if (option != null && option.MaximumArguments == argbuf.Count)
                                {
                                    yield return new CommandLineArgument(option, argbuf.ToArray(), pos.Argument - argbuf.Count);
                                    option = null;
                                    argbuf.Clear();
                                }
                                break;
                            case -2:
                                if (argbuf.Count > 0 || option != null)
                                {
                                    yield return new CommandLineArgument(option, argbuf.ToArray(), pos.Argument - argbuf.Count);
                                    option = null;
                                    argbuf.Clear();
                                }
                                break;
                            case '-':
                                state = ParseState.FirstDash;
                                break;
                            default:
                                state = ParseState.Body;
                                buffer.Clear();
                                buffer.Append((char)chr);
                                break;
                        }
                        break;
                    #endregion
                    #region "FirstDash"
                    case ParseState.FirstDash:
                        switch (chr)
                        {
                            case -1:
                                argbuf.Add("-");
                                if (option != null && option.MaximumArguments == argbuf.Count)
                                {
                                    yield return new CommandLineArgument(option, argbuf.ToArray(), pos.Argument - argbuf.Count);
                                    option = null;
                                    argbuf.Clear();
                                }
                                state = ParseState.Head;
                                break;
                            case '-':
                                if (option != null)
                                {
                                    yield return new CommandLineArgument(option, argbuf.ToArray(), pos.Argument - argbuf.Count);
                                    option = null;
                                    argbuf.Clear();
                                }
                                state = ParseState.SecondDash;
                                break;
                            default:
                                if (argbuf.Count > 0 || option != null)
                                {
                                    yield return new CommandLineArgument(option, argbuf.ToArray(), pos.Argument - argbuf.Count);
                                    option = null;
                                    argbuf.Clear();
                                }
                                state = ParseState.SingleDash;
                                if (!soMap.TryGetValue((char)chr, out option))
                                {
                                    var ex = new CommandLineParserException(string.Format("Unknown short option: {0}", (char)chr), pos);
                                    if (Error != null)
                                        Error(this, new CommandLineParser.ErrorEventArgs(ex));
                                    else
                                        throw ex;
                                }
                                break;
                        }
                        break;
                    #endregion
                    #region "SingleDash"
                    case ParseState.SingleDash:
                        switch (chr)
                        {
                            case -1:
                                if (option != null && option.MaximumArguments == 0)
                                {
                                    yield return new CommandLineArgument(option, pos.Argument);
                                    option = null;
                                }
                                state = ParseState.Head;
                                break;
                            case '=':
                                if (option == null)
                                {
                                    buffer.Clear();
                                    state = ParseState.Discard;
                                }
                                else if (option.MaximumArguments != 0)
                                {
                                    buffer.Clear();
                                    state = ParseState.Equals;
                                }
                                else
                                {
                                    yield return new CommandLineArgument(option, pos.Argument);
                                    option = null;
                                    state = ParseState.Discard;
                                }
                                break;
                            default:
                                if (option != null)
                                    yield return new CommandLineArgument(option);

                                if (!soMap.TryGetValue((char)chr, out option))
                                {
                                    var ex = new CommandLineParserException(string.Format("Unknown short option: {0}", (char)chr), pos);

                                    if (Error != null)
                                        Error(this, new CommandLineParser.ErrorEventArgs(ex));
                                    else
                                        throw ex;
                                }

                                break;
                        }
                        break;
                    #endregion
                    #region "Equals"
                    case ParseState.Equals:
                        switch (chr)
                        {
                            case -1:
                                yield return new CommandLineArgument(option, buffer.ToString(), pos.Argument - 1);
                                option = null;
                                state = ParseState.Head;
                                break;
                            default:
                                buffer.Append((char)chr);
                                break;
                        }
                        break;
                    #endregion
                    #region "SecondDash"
                    case ParseState.SecondDash:
                        switch (chr)
                        {
                            case -1:
                                buffer.Clear();
                                state = ParseState.Tail;
                                break;
                            default:
                                if (argbuf.Count > 0 || option != null)
                                {
                                    yield return new CommandLineArgument(option, argbuf.ToArray(), pos.Argument - argbuf.Count);
                                    option = null;
                                    argbuf.Clear();
                                }
                                buffer.Clear();
                                buffer.Append((char)chr);
                                state = ParseState.DoubleDash;
                                break;
                        }
                        break;
                    #endregion
                    #region "DoubleDash"
                    case ParseState.DoubleDash:
                        switch (chr)
                        {
                            case -1:
                                if (loMap.TryGetValue(buffer.ToString(), out option))
                                {
                                    if (option.MaximumArguments == 0)
                                    {
                                        yield return new CommandLineArgument(option, pos.Argument);
                                        option = null;
                                    }
                                }
                                else
                                {
                                    var ex = new CommandLineParserException(string.Format("Unknown long option: {0}", buffer.ToString()), pos);
                                    if (Error != null)
                                        Error(this, new CommandLineParser.ErrorEventArgs(ex));
                                    else
                                        throw ex;
                                }
                                state = ParseState.Head;
                                break;
                            case '=':
                                if (loMap.TryGetValue(buffer.ToString(), out option))
                                {
                                    if (option.MaximumArguments != 0)
                                    {
                                        buffer.Clear();
                                        state = ParseState.Equals;
                                    }
                                    else
                                    {
                                        yield return new CommandLineArgument(option, pos.Argument);
                                        option = null;
                                        state = ParseState.Discard;
                                    }
                                }
                                else
                                {
                                    var ex = new CommandLineParserException(string.Format("Unknown long option: {0}", buffer.ToString()), pos);
                                    if (Error != null)
                                        Error(this, new CommandLineParser.ErrorEventArgs(ex));
                                    else
                                        throw ex;
                                    buffer.Clear();
                                    state = ParseState.Discard;
                                }
                                break;
                            default:
                                buffer.Append((char)chr);
                                break;
                        }
                        break;
                    #endregion
                    #region "Tail"
                    case ParseState.Tail:
                        switch (chr)
                        {
                            case -2:
                                if (argbuf.Count > 0)
                                {
                                    yield return new CommandLineArgument(option, argbuf.ToArray(), pos.Argument - argbuf.Count);
                                    option = null;
                                    argbuf.Clear();
                                }
                                break;
                            case -1:
                                argbuf.Add(buffer.ToString());
                                buffer.Clear();
                                break;
                            default:
                                buffer.Append((char)chr);
                                break;
                        }
                        break;
                    #endregion
                    #region "Body"
                    case ParseState.Body:
                        switch (chr)
                        {
                            case -1:
                                argbuf.Add(buffer.ToString());
                                if (option != null && option.MaximumArguments == argbuf.Count)
                                {
                                    yield return new CommandLineArgument(option, argbuf.ToArray(), pos.Argument  - argbuf.Count);
                                    option = null;
                                    argbuf.Clear();
                                }
                                state = ParseState.Head;
                                break;
                            default:
                                buffer.Append((char)chr);
                                break;
                        }
                        break;
                        #endregion
                }

            }
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Creates a new error args
 /// </summary>
 /// <param name="Error">The error</param>
 public ErrorEventArgs(CommandLineParserException Error)
 {
     this.Error = Error;
 }