/** * Parses and returns a number. * * @param cmd referring command; if specified, the result must not be empty * @return name * @throws QueryException query exception */ private String number(final Cmd cmd) throws QueryException { consumeWS(); final StringBuilder sb = new StringBuilder(); if (parser.curr() == '-') sb.append(parser.consume()); while (digit(parser.curr())) sb.append(parser.consume()); return finish(eoc() || ws(parser.curr()) ? sb : null, cmd); }
/** * Parses and returns a command. A command is limited to letters. * * @param cmd referring command; if specified, the result must not be empty * @return name * @throws QueryException query exception */ private String command(final Cmd cmd) throws QueryException { consumeWS(); final StringBuilder sb = new StringBuilder(); while (!eoc() && !ws(parser.curr())) { sb.append(parser.consume()); } return finish(sb, cmd); }
/** * Parses and returns a glob expression, which extends {@link #name(Cmd)} function with asterisks, * question marks and commands. * * @param cmd referring command; if specified, the result must not be empty * @return glob expression * @throws QueryException query exception */ private String glob(final Cmd cmd) throws QueryException { consumeWS(); final StringBuilder sb = new StringBuilder(); while (true) { final char ch = parser.curr(); if (!Databases.validChar(ch) && ch != '*' && ch != '?' && ch != ',') { return finish(eoc() || ws(ch) ? sb : null, cmd); } sb.append(parser.consume()); } }
/** * Parses and returns the specified keyword. * * @param key token to be parsed * @param cmd referring command; if specified, the keyword is mandatory * @return result of check * @throws QueryException query exception */ private boolean key(final String key, final Cmd cmd) throws QueryException { consumeWS(); final int p = parser.pos; final boolean ok = (parser.consume(key) || parser.consume(key.toLowerCase(Locale.ENGLISH))) && (parser.curr(0) || ws(parser.curr())); if (!ok) { parser.pos = p; if (cmd != null) throw help(null, cmd); } return ok; }
/** * Parses and returns a string, delimited by a semicolon or, optionally, a space. Quotes can be * used to include spaces. * * @param cmd referring command; if specified, the result must not be empty * @param space stop when encountering space * @return string * @throws QueryException query exception */ private String string(final Cmd cmd, final boolean space) throws QueryException { final StringBuilder sb = new StringBuilder(); consumeWS(); boolean q = false; while (parser.more()) { final char c = parser.curr(); if (!q && ((space ? c <= ' ' : c < ' ') || eoc())) break; if (c == '"') q ^= true; else sb.append(c); parser.consume(); } return finish(sb, cmd); }
@Override protected void parse(final ArrayList<Command> cmds) throws QueryException { final Scanner sc = new Scanner(string).useDelimiter(single ? "\0" : "\r\n?|\n"); while (sc.hasNext()) { final String line = sc.next().trim(); if (line.isEmpty() || line.startsWith("#")) continue; parser = new InputParser(line); parser.file = ctx.options.get(MainOptions.QUERYPATH); while (parser.more()) { final Cmd cmd = consume(Cmd.class, null); if (cmd != null) cmds.add(parse(cmd)); if (parser.more() && !parser.consume(';')) throw help(null, cmd); } } }
/** * Parses and returns the remaining string. Quotes at the beginning and end of the argument will * be stripped. * * @param cmd referring command; if specified, the result must not be empty * @return remaining string * @throws QueryException query exception */ private String remaining(final Cmd cmd) throws QueryException { if (single) { final StringBuilder sb = new StringBuilder(); consumeWS(); while (parser.more()) sb.append(parser.consume()); String arg = finish(sb, cmd); if (arg != null) { // chop quotes; substrings are faster than replaces... if (arg.startsWith("\"")) arg = arg.substring(1); if (arg.endsWith("\"")) arg = arg.substring(0, arg.length() - 1); } return arg; } return string(cmd, false); }
/** * Parses and returns an xquery expression. * * @param cmd referring command; if specified, the result must not be empty * @return path * @throws QueryException query exception */ private String xquery(final Cmd cmd) throws QueryException { consumeWS(); final StringBuilder sb = new StringBuilder(); if (!eoc()) { final QueryContext qc = new QueryContext(ctx); try { final QueryParser p = new QueryParser(parser.input, null, qc, null); p.pos = parser.pos; p.parseMain(); sb.append(parser.input.substring(parser.pos, p.pos)); parser.pos = p.pos; } finally { qc.close(); } } return finish(sb, cmd); }
/** * Returns a query exception instance. * * @param comp input completions * @param msg message * @param ext extension * @return query exception */ private QueryException error(final Enum<?>[] comp, final String msg, final Object... ext) { return new QueryException(parser.info(), new QNm(), msg, ext).suggest(parser, list(comp)); }
/** * Checks if the end of a command has been reached. * * @return true if command has ended */ private boolean eoc() { return !parser.more() || parser.curr() == ';'; }
/** Consumes all whitespace characters from the beginning of the remaining query. */ private void consumeWS() { while (parser.pos < parser.length && parser.input.charAt(parser.pos) <= ' ') ++parser.pos; parser.mark = parser.pos - 1; }
/** * Parses and returns a name. A name may contain letters, numbers and any of the special * characters <code>!#$%&'()+-=@[]^_`{}~</code>. * * @param cmd referring command; if specified, the result must not be empty * @return name * @throws QueryException query exception */ private String name(final Cmd cmd) throws QueryException { consumeWS(); final StringBuilder sb = new StringBuilder(); while (Databases.validChar(parser.curr())) sb.append(parser.consume()); return finish(eoc() || ws(parser.curr()) ? sb : null, cmd); }