public override void Parse(StringReader reader, CommandContextBuilder <TSource> contextBuilder) { var start = reader.Cursor; var end = Parse(reader); if (end > -1) { contextBuilder.WithNode(this, StringRange.Between(start, end)); return; } throw CommandSyntaxException.BuiltInExceptions.LiteralIncorrect().CreateWithContext(reader, Literal); }
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>())); }
/** * Parses a given command. * * <p>The result of this method can be cached, and it is advised to do so where appropriate. Parsing is often the * most expensive step, and this allows you to essentially "precompile" a command if it will be ran often.</p> * * <p>If the command passes through a node that is {@link CommandNode#isFork()} then the resulting context will be marked as 'forked'. * Forked contexts may contain child contexts, which may be modified by the {@link RedirectModifier} attached to the fork.</p> * * <p>Parsing a command can never fail, you will always be provided with a new {@link ParseResults}. * However, that does not mean that it will always parse into a valid command. You should inspect the returned results * to check for validity. If its {@link ParseResults#getReader()} {@link StringReader#canRead()} then it did not finish * parsing successfully. You can use that position as an indicator to the user where the command stopped being valid. * You may inspect {@link ParseResults#getExceptions()} if you know the parse failed, as it will explain why it could * not find any valid commands. It may contain multiple exceptions, one for each "potential node" that it could have visited, * explaining why it did not go down that node.</p> * * <p>When you eventually call {@link #execute(ParseResults)} with the result of this method, the above error checking * will occur. You only need to inspect it yourself if you wish to handle that yourself.</p> * * @param command a command string to parse * @param source a custom "source" object, usually representing the originator of this command * @return the result of parsing this command * @see #parse(String, Object) * @see #execute(ParseResults) * @see #execute(String, Object) */ public ParseResults <TSource> Parse(StringReader command, TSource source) { var context = new CommandContextBuilder <TSource>(this, source, _root, command.Cursor); return(ParseNodes(_root, command, context)); }
public override void Parse(StringReader reader, CommandContextBuilder <TSource> contextBuilder) { }
public ArgumentCommandNodeTest() { _node = RequiredArgumentBuilder <object, int> .RequiredArgument("foo", Arguments.Integer()).Build(); _contextBuilder = new CommandContextBuilder <object>(new CommandDispatcher <object>(), new object(), new RootCommandNode <object>(), 0); }
public CommandContextTest() { _builder = new CommandContextBuilder <object>(_dispatcher, _source, _rootNode, 0); }
public LiteralCommandNodeTest() { _node = LiteralArgumentBuilder <object> .LiteralArgument("foo").Build(); _contextBuilder = new CommandContextBuilder <object>(new CommandDispatcher <object>(), new object(), new RootCommandNode <object>(), 0); }
/// <exception cref="CommandSyntaxException"></exception> public abstract void Parse(StringReader reader, CommandContextBuilder <TSource> contextBuilder);
public ParseResults(CommandContextBuilder <TSource> context, IImmutableStringReader reader, IDictionary <CommandNode <TSource>, CommandSyntaxException> exceptions) { Context = context; Reader = reader; Exceptions = exceptions; }
public ParseResults(CommandContextBuilder <TSource> context) : this(context, new StringReader(""), new Dictionary <CommandNode <TSource>, CommandSyntaxException>()) { }