Esempio n. 1
0
        private static IEnumerable <Pattern> ParseShorts(Tokens tokens, ICollection <Option> options)
        {
            // shorts ::= '-' ( chars )* [ [ ' ' ] chars ] ;

            var token = tokens.Move();

            Debug.Assert(token.StartsWith("-") && !token.StartsWith("--"));
            var left   = token.TrimStart(new[] { '-' });
            var parsed = new List <Pattern>();

            while (left != "")
            {
                var shortName = "-" + left[0];
                left = left.Substring(1);
                var    similar = options.Where(o => o.ShortName == shortName).ToList();
                Option option  = null;
                if (similar.Count > 1)
                {
                    throw tokens.CreateException(string.Format("{0} is specified ambiguously {1} times", shortName,
                                                               similar.Count));
                }
                if (similar.Count < 1)
                {
                    option = new Option(shortName, null, 0);
                    options.Add(option);
                    if (tokens.ThrowsInputError)
                    {
                        option = new Option(shortName, null, 0, new ValueObject(true));
                    }
                }
                else
                {
                    // why is copying necessary here?
                    option = new Option(shortName, similar[0].LongName, similar[0].ArgCount, similar[0].Value);
                    ValueObject value = null;
                    if (option.ArgCount != 0)
                    {
                        if (left == "")
                        {
                            if (tokens.Current() == null || tokens.Current() == "--")
                            {
                                throw tokens.CreateException(shortName + " requires argument");
                            }
                            value = new ValueObject(tokens.Move());
                        }
                        else
                        {
                            value = new ValueObject(left);
                            left  = "";
                        }
                    }
                    if (tokens.ThrowsInputError)
                    {
                        option.Value = value ?? new ValueObject(true);
                    }
                }
                parsed.Add(option);
            }
            return(parsed);
        }
Esempio n. 2
0
        private static IEnumerable <Pattern> ParseAtom(Tokens tokens, ICollection <Option> options)
        {
            // atom ::= '(' expr ')' | '[' expr ']' | 'options'
            //  | long | shorts | argument | command ;

            var token  = tokens.Current();
            var result = new List <Pattern>();

            switch (token)
            {
            case "[":
            case "(":
            {
                tokens.Move();
                string matching;
                if (token == "(")
                {
                    matching = ")";
                    result.Add(new Required(ParseExpr(tokens, options).ToArray()));
                }
                else
                {
                    matching = "]";
                    result.Add(new Optional(ParseExpr(tokens, options).ToArray()));
                }
                if (tokens.Move() != matching)
                {
                    throw tokens.CreateException("unmatched '" + token + "'");
                }
            }
            break;

            case "options":
                tokens.Move();
                result.Add(new OptionsShortcut());
                break;

            default:
                if (token.StartsWith("--") && token != "--")
                {
                    return(ParseLong(tokens, options));
                }
                if (token.StartsWith("-") && token != "-" && token != "--")
                {
                    return(ParseShorts(tokens, options));
                }
                if (token.StartsWith("<") && token.EndsWith(">") || token.All(char.IsUpper))
                {
                    result.Add(new Argument(tokens.Move()));
                }
                else
                {
                    result.Add(new Command(tokens.Move()));
                }
                break;
            }
            return(result);
        }
Esempio n. 3
0
        private static IEnumerable <Pattern> ParseLong(Tokens tokens, ICollection <Option> options)
        {
            // long ::= '--' chars [ ( ' ' | '=' ) chars ] ;
            var p        = new StringPartition(tokens.Move(), "=");
            var longName = p.LeftString;

            Debug.Assert(longName.StartsWith("--"));
            var value   = (p.NoSeparatorFound) ? null : new ValueObject(p.RightString);
            var similar = options.Where(o => o.LongName == longName).ToList();

            if (tokens.ThrowsInputError && similar.Count == 0)
            {
                // If not exact match
                similar =
                    options.Where(o => !string.IsNullOrEmpty(o.LongName) && o.LongName.StartsWith(longName)).ToList();
            }
            if (similar.Count > 1)
            {
                // Might be simply specified ambiguously 2+ times?
                throw tokens.CreateException($"{longName} is not a unique prefix: {string.Join(", ", similar.Select(o => o.LongName))}?");
            }
            Option option = null;

            if (similar.Count < 1)
            {
                var argCount = p.Separator == "=" ? 1 : 0;
                option = new Option(null, longName, argCount);
                options.Add(option);
                if (tokens.ThrowsInputError)
                {
                    option = new Option(null, longName, argCount, argCount != 0 ? value : new ValueObject(true));
                }
            }
            else
            {
                option = new Option(similar[0].ShortName, similar[0].LongName, similar[0].ArgCount, similar[0].Value);
                if (option.ArgCount == 0)
                {
                    if (value != null)
                    {
                        throw tokens.CreateException(option.LongName + " must not have an argument");
                    }
                }
                else
                {
                    if (value == null)
                    {
                        if (tokens.Current() == null || tokens.Current() == "--")
                        {
                            throw tokens.CreateException(option.LongName + " requires an argument");
                        }
                        value = new ValueObject(tokens.Move());
                    }
                }
                if (tokens.ThrowsInputError)
                {
                    option.Value = value ?? new ValueObject(true);
                }
            }
            return(new[] { option });
        }