private ParseResults <TSource> ParseNodes(CommandNode <TSource> node, StringReader originalReader, CommandContextBuilder <TSource> contextSoFar) { var source = contextSoFar.Source; IDictionary <CommandNode <TSource>, CommandSyntaxException> errors = null; List <ParseResults <TSource> > potentials = null; var cursor = originalReader.Cursor; foreach (var child in node.GetRelevantNodes(originalReader)) { if (!child.CanUse(source)) { continue; } var context = contextSoFar.Copy(); var reader = new StringReader(originalReader); try { try { child.Parse(reader, context); } catch (CommandSyntaxException) { throw; } catch (Exception ex) { throw CommandSyntaxException.BuiltInExceptions.DispatcherParseException().CreateWithContext(reader, ex.Message); } if (reader.CanRead()) { if (reader.Peek() != ArgumentSeparatorChar) { throw CommandSyntaxException.BuiltInExceptions.DispatcherExpectedArgumentSeparator().CreateWithContext(reader); } } } catch (CommandSyntaxException ex) { if (errors == null) { errors = new Dictionary <CommandNode <TSource>, CommandSyntaxException>(); } errors.Add(child, ex); reader.Cursor = cursor; continue; } context.WithCommand(child.Command); if (reader.CanRead(child.Redirect == null ? 2 : 1)) { reader.Skip(); if (child.Redirect != null) { var childContext = new CommandContextBuilder <TSource>(this, source, child.Redirect, reader.Cursor); var parse = ParseNodes(child.Redirect, reader, childContext); context.WithChild(parse.Context); return(new ParseResults <TSource>(context, parse.Reader, parse.Exceptions)); } else { var parse = ParseNodes(child, reader, context); if (potentials == null) { potentials = new List <ParseResults <TSource> >(1); } potentials.Add(parse); } } else { if (potentials == null) { potentials = new List <ParseResults <TSource> >(1); } potentials.Add(new ParseResults <TSource>(context, reader, new Dictionary <CommandNode <TSource>, CommandSyntaxException>())); } } if (potentials != null) { if (potentials.Count > 1) { potentials.Sort((a, b) => { if (!a.Reader.CanRead() && b.Reader.CanRead()) { return(-1); } if (a.Reader.CanRead() && !b.Reader.CanRead()) { return(1); } if (a.Exceptions.Count == 0 && b.Exceptions.Count > 0) { return(-1); } if (a.Exceptions.Count > 0 && b.Exceptions.Count == 0) { return(1); } return(0); }); } return(potentials[0]); } return(new ParseResults <TSource>(contextSoFar, originalReader, errors ?? new Dictionary <CommandNode <TSource>, CommandSyntaxException>())); }