private static Argument ParsePositionalArg(IEnumerator <Token> tokenIterator) { ArgumentDef def = GetNextPositionalDef(); Argument arg = new Argument(); arg.Definition = def; sbyte iter = 0; List <object> argValues = new List <object>(); do { iter++; Token token = tokenIterator.Current; if (token.Type != TokenType.BareArg) { return(arg); } argValues.Add(ConvertTokenDataToType(token.Data, def.DataType)); } while ((def.Consumption < 0 || (iter < def.Consumption)) && tokenIterator.MoveNext()); if (argValues.Count < def.Consumption) { throw new Exception(string.Format( "Not enough values for positional argument '{0}'; {1} {2} required.", def.ToString(), def.Consumption, def.Consumption > 1 ? "are" : "is" )); } if (def.Consumption == 1) { arg.Value = argValues[0]; } else { arg.Value = argValues; } return(arg); }
private static Argument ParseShortArg(IEnumerator <Token> tokenIterator) { Token token = tokenIterator.Current; ArgumentDef def = GetDefByToken(token); Argument arg = new Argument(); arg.Definition = def; if (def.Consumption == 0) // No consumption { return(arg); } else if (def.Consumption == 1) // Consume single following argument { if (tokenIterator.MoveNext()) { Token next = tokenIterator.Current; string data; // If the next token is a ShortOption but we're a consumer, grab new bare data out of the // next sequential ShortOptions switch (next.Type) { case TokenType.ShortOption: data = ConsumeSequentialShortOptions(tokenIterator); break; case TokenType.BareArg: data = (string)next.Data; break; default: throw new Exception(string.Format( "Unexpected token type '{0}' after '{1}': Expected one of '{2}'", next.Type, token.Type, Utils.JoinArray(new TokenType[] { TokenType.BareArg }) )); } arg.Value = ConvertTokenDataToType(data, def.DataType); return(arg); } throw new Exception(string.Format( "No arguments after option '{0}'; {1} {2} required.", def.ToString(), def.Consumption, def.Consumption > 1 ? "are" : "is" )); } else if (def.Consumption < 0) // Greedy { bool firstTime = true; List <object> argData = new List <object>(); while (tokenIterator.MoveNext()) { Token next = tokenIterator.Current; string tokenData; switch (next.Type) { case TokenType.ShortOption: if (firstTime) { tokenData = ConsumeSequentialShortOptions(tokenIterator); } else { arg.Value = argData; return(arg); } break; case TokenType.BareArg: tokenData = (string)next.Data; break; default: if (firstTime) { throw new Exception(string.Format( "Unexpected token type '{0}' after '{1}': Expected one of '{2}'", next.Type, token.Type, Utils.JoinArray(new TokenType[] { TokenType.ShortOption, TokenType.BareArg }) )); } else { arg.Value = argData; return(arg); } } argData.Add(ConvertTokenDataToType(tokenData, def.DataType)); } if (argData.Count < 1) { throw new Exception(string.Format( "No arguments after greedy option '{0}'; at least one is required.", def.ToString() )); } arg.Value = argData; return(arg); } else // Fixed, positive number of args. { bool firstTime = true; List <object> argData = new List <object>(); sbyte iter = 0; while (iter++ < def.Consumption && tokenIterator.MoveNext()) { Token next = tokenIterator.Current; string tokenData; switch (next.Type) { case TokenType.ShortOption: if (firstTime) { tokenData = ConsumeSequentialShortOptions(tokenIterator); } else { arg.Value = argData; return(arg); } break; case TokenType.BareArg: tokenData = (string)next.Data; break; default: if (firstTime) { throw new Exception(string.Format( "Unexpected token type '{0}' after '{1}': Expected one of '{2}'", next.Type, token.Type, Utils.JoinArray(new TokenType[] { TokenType.ShortOption, TokenType.BareArg }) )); } else { if (argData.Count < def.Consumption) { throw new Exception(string.Format( "Not enough arguments after option '{0}'; {1} {2} required.", def.ToString(), def.Consumption, def.Consumption > 1 ? "are" : "is" )); } arg.Value = argData; return(arg); } } argData.Add(ConvertTokenDataToType(tokenData, def.DataType)); } if (argData.Count < def.Consumption) { throw new Exception(string.Format( "Not enough arguments after option '{0}'; {1} {2} required.", def.ToString(), def.Consumption, def.Consumption > 1 ? "are" : "is" )); } arg.Value = argData; return(arg); } }
public static ArgumentDef AddArgument( char shortName, string longName, Type dataType = default(Type), ArgumentType argType = ArgumentType.Positional, ArgumentStatus argStatus = ArgumentStatus.Required, sbyte consumption = 0 ) { ArgumentDef def = new ArgumentDef(shortName, longName, dataType, argType, argStatus, consumption); int _; if (def.ShortName != ArgumentDef.nullChar && defsByShort.TryGetValue(def.ShortName, out _)) { throw new Exception(string.Format("Cannot add new argument with duplicate short name '{0}'", def.ShortName)); } if (def.LongName != ArgumentDef.emptyString && defsByLong.TryGetValue(def.LongName, out _)) { throw new Exception(string.Format("Cannot add new argument with duplicate long name \"{0}\"", def.LongName)); } if (def.ArgType == ArgumentType.Positional && def.ArgStatus == ArgumentStatus.Required && optionalPositionalDefined) { throw new Exception("Cannot add new required positional arguments after optional positional arguments."); } if (def.ArgType == ArgumentType.Positional && def.ArgStatus == ArgumentStatus.Required && greedyArgDefined) { throw new Exception("Cannot add new required positional arguments after greedy arguments."); } defs.Add(def); if (def.Consumption < 0) { greedyArgDefined = true; } if (def.ArgType == ArgumentType.Positional) { positionalDefs.Add(def); if (def.ArgStatus == ArgumentStatus.Optional) { optionalPositionalDefined = true; } } if (def.ArgStatus == ArgumentStatus.Required) { requiredDefs.Add(def); } if (def.ShortName != ArgumentDef.nullChar) { defsByShort[def.ShortName] = defs.Count - 1; } if (def.LongName != ArgumentDef.emptyString) { defsByLong[def.LongName] = defs.Count - 1; } return(def); }