public override MatchResult Match(IList<Pattern> left, IEnumerable<Pattern> collected = null) { var coll = collected ?? new List<Pattern>(); var sresult = SingleMatch(left); var match = sresult.Match; if (match == null) { return new MatchResult(false, left, coll); } var left_ = new List<Pattern>(); left_.AddRange(left.Take(sresult.Position)); left_.AddRange(left.Skip(sresult.Position + 1)); var sameName = coll.Where(a => a.Name == Name).ToList(); if (Value != null && (Value.IsList || Value.IsOfTypeInt)) { var increment = new ValueObject(1); if (!Value.IsOfTypeInt) { increment = match.Value.IsString ? new ValueObject(new [] {match.Value}) : match.Value; } if (sameName.Count == 0) { match.Value = increment; var res = new List<Pattern>(coll) {match}; return new MatchResult(true, left_, res); } sameName[0].Value.Add(increment); return new MatchResult(true, left_, coll); } var resColl = new List<Pattern>(); resColl.AddRange(coll); resColl.Add(match); return new MatchResult(true, left_, resColl); }
public static Option Parse(string optionDescription) { if (optionDescription == null) throw new ArgumentNullException("optionDescription"); string shortName = null; string longName = null; var argCount = 0; var value = new ValueObject(false); var p = new StringPartition(optionDescription, DESC_SEPARATOR); var options = p.LeftString; var description = p.RightString; foreach (var s in options.Split(" \t,=".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)) { if (s.StartsWith("--")) longName = s; else if (s.StartsWith("-")) { shortName = s; } else { argCount = 1; } } if (argCount > 0) { var r = new Regex(@"\[default: (.*)\]", RegexOptions.IgnoreCase); var m = r.Match(description); value = m.Success ? new ValueObject(m.Groups[1].Value) : null; } return new Option(shortName, longName, argCount, value); }
public Option(string shortName = null, string longName = null, int argCount = 0, ValueObject value = null) : base() { ShortName = shortName; LongName = longName; ArgCount = argCount; var v = value ?? new ValueObject(false); Value = (v.IsFalse && argCount > 0) ? null : v; }
public Argument(string name, ValueObject value = null) : base(name, value) { }
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(string.Format("{0} is not a unique prefix: {1}?", longName, 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}; }
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; }
public Command(string name, ValueObject value = null) : base(name, value ?? new ValueObject(false)) { }
protected LeafPattern(string name, ValueObject value=null) { _name = name; Value = value; }
static string Normalize(ValueObject v) { if (v == null) return null; var s = v.ToString(); return string.IsNullOrWhiteSpace(s) ? null : s; }
public void Add(ValueObject increment) { if (increment == null) throw new ArgumentNullException("increment"); if (increment.Value == null) throw new InvalidOperationException("increment.Value is null"); if (Value == null) throw new InvalidOperationException("Value is null"); if (increment.IsInt) { if (IsList) (Value as ArrayList).Add(increment.AsInt); else Value = increment.AsInt + AsInt; } else { var l = new ArrayList(); if (IsList) { l.AddRange(AsList); } else { l.Add(Value); } if (increment.IsList) { l.AddRange(increment.AsList); } else { l.Add(increment); } Value = l; } }
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 }); }
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('-'); 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; if (similar.Count > 1) { throw tokens.CreateException($"{shortName} is specified ambiguously {similar.Count} times"); } if (similar.Count < 1) { option = new Option(shortName); 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); }