Exemplo n.º 1
0
        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>()));
        }