/// <summary> /// Parses the given set of tokens based on the rules specified by the <see cref="Command"/>. /// </summary> /// <param name="tokens">Token strings to parse.</param> /// <returns>A <see cref="ParseResult" /> instance.</returns> public ParseResult Parse(IEnumerable <string> tokens) { DebugOutput.Write("Tokens passed", tokens); IReadOnlyList <string> tokenList = tokens.ToList(); // Creates a ParseRun instance, which specifies the sequence of commands specified and // the tokens and any options and arguments that apply to the specified commands. ParseRun run = CreateRun(tokenList); // Extract out just the option and argument objects from their respective run collections. // We want to pass these to parser style methods that only need to deal with the Option // and Argument objects and not have to deal with the 'run' aspects. See some of the calls // to protected methods from this method. IReadOnlyList <Option> justOptions = run.Options.Select(o => o.Option).ToList(); IReadOnlyList <Argument> justArguments = run.Arguments.Select(a => a.Argument).ToList(); // Even though the caller can define the grouping, the parser style can override it based // on the available options and arguments. See the UnixArgStyle class for an example. Grouping = ArgStyle.GetGrouping(Grouping, justOptions, justArguments); // Validate all the available options based on the parser style rules. // See the UnixArgStyle for an example. ArgStyle.ValidateDefinedOptions(justOptions); // Identify all tokens as options or arguments. Identified option details are stored in // the Option instance itself. Identified arguments are returned from the method. List <string> specifiedArguments = ArgStyle.IdentifyTokens(run.Tokens, run.Options, Grouping).ToList(); // Get the groups that match the specified options and arguments. IReadOnlyList <int> matchingGroups = GetMatchingGroups(run, specifiedArguments); // If no groups match, we cannot proceed, so throw a parser exception. if (matchingGroups.Count == 0) { throw new ParserException(-1, "The specified arguments and options are invalid."); } // Trim the argument and option runs to those that contain the matcing groups. TrimRunsToMatchingGroups(run, matchingGroups); //TODO: Come back to this later //if (ConfigReader != null) // specifiedArguments = ConfigReader.Run(specifiedArguments, Options); // Process the specified options and arguments, and resolve their values. ProcessOptions(run.Options); ProcessArguments(specifiedArguments, run.Arguments); var parseResult = new ParseResult(run); // Runs the custom validator, if it is assigned. CommandCustomValidator customCommandValidator = parseResult.Command.CustomValidator; string validationError = customCommandValidator?.Invoke(parseResult.Arguments, parseResult.Options); if (validationError != null) { throw new ValidationException(validationError, null, null); } return(parseResult); }
/// <inheritdoc/> public MethodBuilder Define() { if (this.methodBuilder != null) { return(this.methodBuilder); } int parmCount = this.parms.Count; Type[] parameterTypes = new Type[parmCount]; for (int i = 0; i < parmCount; i++) { parameterTypes[i] = this.parms[i].ParameterType; } this.methodBuilder = this.defineMethod( this.methodName, this.Attributes, this.callingConvention, this.returnType, null, null, parameterTypes, null, null); if (this.genericParameterBuilders != null) { this.genericParameters = this.methodBuilder.DefineGenericParameters( this.genericParameterBuilders.Select(g => g.ParameterName).ToArray()); for (int i = 0; i < this.genericParameterBuilders.Count; i++) { this.genericParameterBuilders[i].Build(this.genericParameters[i]); } } int parmIndex = 0; foreach (var parm in this.parms) { var paramBuilder = this.methodBuilder .DefineParameter(++parmIndex, parm.Attributes, parm.ParameterName); parm.CustomAttributes.SetCustomAttributes(a => paramBuilder.SetCustomAttribute(a)); } this.customAttributes.SetCustomAttributes(a => this.methodBuilder.SetCustomAttribute(a)); DebugOutput.WriteLine(""); DebugOutput.WriteLine("======================================="); DebugOutput.Write($"New Method {this.methodBuilder.Name}"); if (this.methodBuilder.IsGenericMethodDefinition == true) { DebugOutput.Write($"<{string.Join(", ", this.methodBuilder.GetGenericArguments().Select(t => t.Name))}>"); } DebugOutput.WriteLine($"({string.Join(", ", this.parms.Select(p => $"{p.Attributes} {p.ParameterType} {p.ParameterName}"))})"); DebugOutput.WriteLine("Calling Convention: {0}", this.methodBuilder.CallingConvention); DebugOutput.WriteLine("Attributes: {0}", this.Attributes); DebugOutput.WriteLine(""); return(this.methodBuilder); }