/// <summary>
        /// Parses the specified <see><cref>T:System.String[]</cref></see> using the setup Options.
        /// </summary>
        /// <param name="args">The <see><cref>T:System.String[]</cref></see> to parse.</param>
        /// <returns>An <see cref="ICommandLineParserResult"/> representing the results of the parse operation.</returns>
        public ICommandLineParserResult Parse(string[] args)
        {
            var parserEngineResult = this.ParserEngine.Parse(args);
            var parsedOptions      = parserEngineResult.ParsedOptions.ToList();

            var result = new CommandLineParserResult {
                EmptyArgs = parsedOptions.IsNullOrEmpty()
            };

            if (this.HelpOption.ShouldShowHelp(parsedOptions, StringComparison))
            {
                result.HelpCalled = true;
                this.HelpOption.ShowHelp(this.Options);
                return(result);
            }

            foreach (var setupOption in this.Options)
            {
                /*
                 * Step 1. match the setup Option to one provided in the args by either long or short names
                 * Step 2. if the key has been matched then bind the value
                 * Step 3. if the key is not matched and it is required, then add a new error
                 * Step 4. the key is not matched and optional, bind the default value if available
                 */

                // Step 1
                ICommandLineOption option = setupOption;
                var match = parsedOptions.FirstOrDefault(pair =>
                                                         pair.Key.Equals(option.ShortName, this.StringComparison) || // tries to match the short name
                                                         pair.Key.Equals(option.LongName, this.StringComparison)); // or else the long name

                if (match != null)                                                                                 // Step 2
                {
                    try
                    {
                        option.Bind(match);
                    }
                    catch (OptionSyntaxException)
                    {
                        result.Errors.Add(new OptionSyntaxParseError(option, match));
                        if (option.HasDefault)
                        {
                            option.BindDefault();
                        }
                    }

                    parsedOptions.Remove(match);
                }
                else
                {
                    if (option.IsRequired)                     // Step 3
                    {
                        result.Errors.Add(new ExpectedOptionNotFoundParseError(option));
                    }
                    else if (option.HasDefault)
                    {
                        option.BindDefault();                         // Step 4
                    }
                    result.UnMatchedOptions.Add(option);
                }
            }

            parsedOptions.ForEach(item => result.AdditionalOptionsFound.Add(new KeyValuePair <string, string>(item.Key, item.Value)));

            result.ErrorText = ErrorFormatter.Format(result.Errors);

            return(result);
        }