#1793 - ENH: Add filterMany() that takes expressions ... as a simpler option

This commit is contained in:
rob bygrave
2019-08-15 22:05:46 +12:00
parent 06542b031e
commit c530883e5e
15 changed files with 279 additions and 132 deletions
@@ -536,4 +536,12 @@ public interface ExpressionFactory {
*/
<T> Junction<T> junction(Junction.Type type, Query<T> query, ExpressionList<T> parent);
/**
* Add the expressions to the given expression list.
*
* @param where The expression list to add the expressions to
* @param expressions The expressions that are parsed
* @param params Bind parameters to match ? or ?1 bind positions.
*/
<T> void where(ExpressionList<T> where, String expressions, Object[] params);
}
+33 -6
View File
@@ -489,7 +489,26 @@ public interface ExpressionList<T> {
* Add some filter predicate expressions to the many property.
*/
@Nonnull
ExpressionList<T> filterMany(String prop);
ExpressionList<T> filterMany(String manyProperty);
/**
* Add filter expressions to the many property.
*
* <pre>{@code
*
* DB.find(Customer.class)
* .where()
* .eq("name", "Rob")
* .filterMany("orders", "status = ?", Status.NEW)
* .findList();
*
* }</pre>
*
* @param manyProperty The many property
* @param expressions Filter expressions with and, or and ? or ?1 type bind parameters
* @param params Bind parameters used in the expressions
*/
Query<T> filterMany(String manyProperty, String expressions, Object... params);
/**
* Specify specific properties to fetch on the main/root bean (aka partial
@@ -663,6 +682,14 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> where();
/**
* Add the expressions to this expression list.
*
* @param expressions The expressions that are parsed and added to this expression list
* @param params Bind parameters to match ? or ?1 bind positions.
*/
ExpressionList<T> where(String expressions, Object... params);
/**
* Path exists - for the given path in a JSON document.
* <pre>{@code
@@ -831,9 +858,9 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> inRange(String propertyName, Object value1, Object value2);
/**
* Between - property between the two given values.
*/
/**
* Between - property between the two given values.
*/
ExpressionList<T> between(String propertyName, Object value1, Object value2);
/**
@@ -1327,7 +1354,7 @@ public interface ExpressionList<T> {
*
* }</pre>
* <p>
* Note that we need to cast the Postgres array for UUID types like:
* Note that we need to cast the Postgres array for UUID types like:
* </p>
* <pre>{@code
*
@@ -1335,7 +1362,7 @@ public interface ExpressionList<T> {
*
* }</pre>
*
* @param raw The raw expression that is typically a subquery
* @param raw The raw expression that is typically a subquery
* @param values The values which is typically a list or set of id values.
*/
ExpressionList<T> rawOrEmpty(String raw, Collection<?> values);
@@ -16,6 +16,7 @@ import io.ebean.search.TextQueryString;
import io.ebean.search.TextSimple;
import io.ebeaninternal.api.SpiExpressionFactory;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.grammer.EqlParser;
import java.util.Arrays;
import java.util.Collection;
@@ -151,6 +152,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
return new BitwiseExpression(propertyName, BitwiseOp.AND, flags, "=", match);
}
@Override
public <T> void where(ExpressionList<T> list, String expressions, Object[] params) {
EqlParser.parseWhere(expressions, list, this, params);
}
/**
* Equal To - property equal to the given value.
*/
@@ -470,8 +470,14 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
}
@Override
public ExpressionList<T> filterMany(String prop) {
return query.filterMany(prop);
public ExpressionList<T> filterMany(String manyProperty) {
return query.filterMany(manyProperty);
}
@Override
public Query<T> filterMany(String manyProperty, String expressions, Object... params) {
query.filterMany(manyProperty).where(expressions, params);
return query;
}
@Override
@@ -745,6 +751,12 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
return this;
}
@Override
public ExpressionList<T> where(String expressions, Object... params) {
expr.where(this, expressions, params);
return this;
}
@Override
public ExpressionList<T> bitwiseAny(String propertyName, long flags) {
add(expr.bitwiseAny(propertyName, flags));
@@ -326,11 +326,21 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
return exprList.exampleLike(example);
}
@Override
public ExpressionList<T> where(String expressions, Object... params) {
throw new IllegalStateException("where not allowed on Junction expression list");
}
@Override
public ExpressionList<T> filterMany(String prop) {
throw new IllegalStateException("filterMany not allowed on Junction expression list");
}
@Override
public Query<T> filterMany(String manyProperty, String expressions, Object... params) {
throw new IllegalStateException("filterMany not allowed on Junction expression list");
}
@Override
public Query<T> usingTransaction(Transaction transaction) {
return exprList.usingTransaction(transaction);
@@ -36,6 +36,11 @@ class EqlAdapter<T> extends EqlWhereListener<T> {
return query.createNamedParameter(parameterName);
}
@Override
Object positionParam(String paramPosition) {
return query.createNamedParameter(paramPosition);
}
/**
* Return the current expression list that expressions should be added to.
*/
@@ -36,7 +36,7 @@ public class EqlParser {
EQLParser parser = new EQLParser(new CommonTokenStream(new EQLLexer(CharStreams.fromString(raw))));
parser.addErrorListener(errorListener);
new ParseTreeWalker().walk(new EqlWhereAdapter<>(where, expr), parser.conditional_expression());
new ParseTreeWalker().walk(new EqlWhereAdapter<>(where, expr, params), parser.conditional_expression());
}
static class ErrorListener extends BaseErrorListener {
@@ -1,6 +1,7 @@
package io.ebeaninternal.server.grammer;
enum EqlValueType {
POS_PARAM,
NAMED_PARAM,
STRING,
BOOL,
@@ -2,20 +2,29 @@ package io.ebeaninternal.server.grammer;
import io.ebean.ExpressionFactory;
import io.ebean.ExpressionList;
import io.ebeaninternal.server.util.ArrayStack;
class EqlWhereAdapter<T> extends EqlWhereListener<T> {
private final ExpressionList<T> where;
private final ExpressionFactory expr;
private final Object[] params;
EqlWhereAdapter(ExpressionList<T> where, ExpressionFactory expr) {
private int paramIndex;
EqlWhereAdapter(ExpressionList<T> where, ExpressionFactory expr, Object[] params) {
this.where = where;
this.expr = expr;
this.params = params;
}
@Override
ExpressionList<T> peekExprList() {
return where;
if (whereStack == null) {
whereStack = new ArrayStack<>();
whereStack.push(where);
}
return whereStack.peek();
}
@Override
@@ -23,8 +32,17 @@ class EqlWhereAdapter<T> extends EqlWhereListener<T> {
return expr;
}
@Override
Object positionParam(String paramPosition) {
if ("?".equals(paramPosition)) {
return params[paramIndex++];
}
final int pos = Integer.parseInt(paramPosition.substring(1));
return params[pos -1];
}
@Override
Object namedParam(String substring) {
return null;
throw new RuntimeException("Not supported");
}
}
@@ -37,7 +37,9 @@ abstract class EqlWhereListener<T> extends EQLBaseListener {
abstract ExpressionFactory expressionFactory();
abstract Object namedParam(String substring);
abstract Object namedParam(String paramName);
abstract Object positionParam(String paramPosition);
/**
* Push the expression list onto the appropriate stack.
@@ -290,6 +292,8 @@ abstract class EqlWhereListener<T> extends EQLBaseListener {
char firstChar = Character.toLowerCase(valueAsText.charAt(0));
switch (firstChar) {
case '?':
return EqlValueType.POS_PARAM;
case ':':
return EqlValueType.NAMED_PARAM;
case 't':
@@ -394,6 +398,8 @@ abstract class EqlWhereListener<T> extends EQLBaseListener {
return new BigDecimal(value);
case STRING:
return unquote(value);
case POS_PARAM:
return positionParam(value);
case NAMED_PARAM:
return namedParam(value.substring(1));
default:
File diff suppressed because one or more lines are too long
@@ -140,7 +140,7 @@ public class EQLLexer extends Lexer {
public ATN getATN() { return _ATN; }
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2I\u0249\b\1\4\2\t"+
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2I\u0252\b\1\4\2\t"+
"\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
@@ -167,76 +167,77 @@ public class EQLLexer extends Lexer {
",\3,\3,\3,\3,\3,\3,\3,\3-\3-\3.\3.\3.\3/\3/\3\60\3\60\3\60\3\61\3\61\3"+
"\61\3\62\3\62\3\62\3\63\3\63\3\63\3\63\3\64\3\64\3\65\3\65\3\65\3\66\3"+
"\66\3\66\3\67\3\67\3\67\38\38\38\38\39\39\39\3:\3:\3:\3;\3;\3;\3<\3<\3"+
"<\3<\3=\3=\3=\3=\3>\3>\3>\7>\u01d4\n>\f>\16>\u01d7\13>\3?\3?\7?\u01db"+
"\n?\f?\16?\u01de\13?\3@\3@\3@\3@\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3"+
"A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3"+
"A\3A\3A\3A\3A\3A\3A\5A\u020e\nA\3B\3B\3B\3B\3B\3B\3B\3B\3B\5B\u0219\n"+
"B\3C\5C\u021c\nC\3C\3C\5C\u0220\nC\3C\3C\5C\u0224\nC\3D\6D\u0227\nD\r"+
"D\16D\u0228\3D\3D\7D\u022d\nD\fD\16D\u0230\13D\3E\3E\7E\u0234\nE\fE\16"+
"E\u0237\13E\3F\3F\3G\3G\3G\3G\7G\u023f\nG\fG\16G\u0242\13G\3G\3G\3H\3"+
"H\3H\3H\2\2I\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16"+
"\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34"+
"\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g"+
"\65i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F"+
"\u008bG\u008dH\u008fI\3\2\t\5\2C\\aac|\6\2\62;C\\aac|\7\2\60\60\62;C\\"+
"aac|\3\2\62;\3\2\63;\3\2))\5\2\13\f\17\17\"\"\2\u0258\2\3\3\2\2\2\2\5"+
"\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2"+
"\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33"+
"\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2"+
"\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2"+
"\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2"+
"\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K"+
"\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2"+
"\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2"+
"\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q"+
"\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2"+
"\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087"+
"\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2"+
"\2\3\u0091\3\2\2\2\5\u0093\3\2\2\2\7\u0095\3\2\2\2\t\u009c\3\2\2\2\13"+
"\u00a5\3\2\2\2\r\u00ab\3\2\2\2\17\u00b1\3\2\2\2\21\u00b4\3\2\2\2\23\u00b6"+
"\3\2\2\2\25\u00bc\3\2\2\2\27\u00c2\3\2\2\2\31\u00c7\3\2\2\2\33\u00cb\3"+
"\2\2\2\35\u00d0\3\2\2\2\37\u00d6\3\2\2\2!\u00dd\3\2\2\2#\u00e3\3\2\2\2"+
"%\u00e5\3\2\2\2\'\u00eb\3\2\2\2)\u00f0\3\2\2\2+\u00f3\3\2\2\2-\u00f7\3"+
"\2\2\2/\u00fb\3\2\2\2\61\u00fe\3\2\2\2\63\u0106\3\2\2\2\65\u010e\3\2\2"+
"\2\67\u0111\3\2\2\29\u0114\3\2\2\2;\u0119\3\2\2\2=\u0120\3\2\2\2?\u012a"+
"\3\2\2\2A\u0132\3\2\2\2C\u0138\3\2\2\2E\u0140\3\2\2\2G\u014b\3\2\2\2I"+
"\u0154\3\2\2\2K\u0159\3\2\2\2M\u015f\3\2\2\2O\u0168\3\2\2\2Q\u0172\3\2"+
"\2\2S\u017d\3\2\2\2U\u0189\3\2\2\2W\u0192\3\2\2\2Y\u019c\3\2\2\2[\u019e"+
"\3\2\2\2]\u01a1\3\2\2\2_\u01a3\3\2\2\2a\u01a6\3\2\2\2c\u01a9\3\2\2\2e"+
"\u01ac\3\2\2\2g\u01b0\3\2\2\2i\u01b2\3\2\2\2k\u01b5\3\2\2\2m\u01b8\3\2"+
"\2\2o\u01bb\3\2\2\2q\u01bf\3\2\2\2s\u01c2\3\2\2\2u\u01c5\3\2\2\2w\u01c8"+
"\3\2\2\2y\u01cc\3\2\2\2{\u01d0\3\2\2\2}\u01d8\3\2\2\2\177\u01df\3\2\2"+
"\2\u0081\u020d\3\2\2\2\u0083\u0218\3\2\2\2\u0085\u0223\3\2\2\2\u0087\u0226"+
"\3\2\2\2\u0089\u0231\3\2\2\2\u008b\u0238\3\2\2\2\u008d\u023a\3\2\2\2\u008f"+
"\u0245\3\2\2\2\u0091\u0092\7*\2\2\u0092\4\3\2\2\2\u0093\u0094\7+\2\2\u0094"+
"\6\3\2\2\2\u0095\u0096\7u\2\2\u0096\u0097\7g\2\2\u0097\u0098\7n\2\2\u0098"+
"\u0099\7g\2\2\u0099\u009a\7e\2\2\u009a\u009b\7v\2\2\u009b\b\3\2\2\2\u009c"+
"\u009d\7f\2\2\u009d\u009e\7k\2\2\u009e\u009f\7u\2\2\u009f\u00a0\7v\2\2"+
"\u00a0\u00a1\7k\2\2\u00a1\u00a2\7p\2\2\u00a2\u00a3\7e\2\2\u00a3\u00a4"+
"\7v\2\2\u00a4\n\3\2\2\2\u00a5\u00a6\7y\2\2\u00a6\u00a7\7j\2\2\u00a7\u00a8"+
"\7g\2\2\u00a8\u00a9\7t\2\2\u00a9\u00aa\7g\2\2\u00aa\f\3\2\2\2\u00ab\u00ac"+
"\7q\2\2\u00ac\u00ad\7t\2\2\u00ad\u00ae\7f\2\2\u00ae\u00af\7g\2\2\u00af"+
"\u00b0\7t\2\2\u00b0\16\3\2\2\2\u00b1\u00b2\7d\2\2\u00b2\u00b3\7{\2\2\u00b3"+
"\20\3\2\2\2\u00b4\u00b5\7.\2\2\u00b5\22\3\2\2\2\u00b6\u00b7\7p\2\2\u00b7"+
"\u00b8\7w\2\2\u00b8\u00b9\7n\2\2\u00b9\u00ba\7n\2\2\u00ba\u00bb\7u\2\2"+
"\u00bb\24\3\2\2\2\u00bc\u00bd\7h\2\2\u00bd\u00be\7k\2\2\u00be\u00bf\7"+
"t\2\2\u00bf\u00c0\7u\2\2\u00c0\u00c1\7v\2\2\u00c1\26\3\2\2\2\u00c2\u00c3"+
"\7n\2\2\u00c3\u00c4\7c\2\2\u00c4\u00c5\7u\2\2\u00c5\u00c6\7v\2\2\u00c6"+
"\30\3\2\2\2\u00c7\u00c8\7c\2\2\u00c8\u00c9\7u\2\2\u00c9\u00ca\7e\2\2\u00ca"+
"\32\3\2\2\2\u00cb\u00cc\7f\2\2\u00cc\u00cd\7g\2\2\u00cd\u00ce\7u\2\2\u00ce"+
"\u00cf\7e\2\2\u00cf\34\3\2\2\2\u00d0\u00d1\7n\2\2\u00d1\u00d2\7k\2\2\u00d2"+
"\u00d3\7o\2\2\u00d3\u00d4\7k\2\2\u00d4\u00d5\7v\2\2\u00d5\36\3\2\2\2\u00d6"+
"\u00d7\7q\2\2\u00d7\u00d8\7h\2\2\u00d8\u00d9\7h\2\2\u00d9\u00da\7u\2\2"+
"\u00da\u00db\7g\2\2\u00db\u00dc\7v\2\2\u00dc \3\2\2\2\u00dd\u00de\7h\2"+
"\2\u00de\u00df\7g\2\2\u00df\u00e0\7v\2\2\u00e0\u00e1\7e\2\2\u00e1\u00e2"+
"\7j\2\2\u00e2\"\3\2\2\2\u00e3\u00e4\7-\2\2\u00e4$\3\2\2\2\u00e5\u00e6"+
"\7s\2\2\u00e6\u00e7\7w\2\2\u00e7\u00e8\7g\2\2\u00e8\u00e9\7t\2\2\u00e9"+
"\u00ea\7{\2\2\u00ea&\3\2\2\2\u00eb\u00ec\7n\2\2\u00ec\u00ed\7c\2\2\u00ed"+
"\u00ee\7|\2\2\u00ee\u00ef\7{\2\2\u00ef(\3\2\2\2\u00f0\u00f1\7q\2\2\u00f1"+
"\u00f2\7t\2\2\u00f2*\3\2\2\2\u00f3\u00f4\7c\2\2\u00f4\u00f5\7p\2\2\u00f5"+
"\u00f6\7f\2\2\u00f6,\3\2\2\2\u00f7\u00f8\7p\2\2\u00f8\u00f9\7q\2\2\u00f9"+
"\u00fa\7v\2\2\u00fa.\3\2\2\2\u00fb\u00fc\7k\2\2\u00fc\u00fd\7p\2\2\u00fd"+
"\60\3\2\2\2\u00fe\u00ff\7d\2\2\u00ff\u0100\7g\2\2\u0100\u0101\7v\2\2\u0101"+
"<\3<\3=\3=\3=\3=\3>\3>\3>\7>\u01d4\n>\f>\16>\u01d7\13>\3>\3>\7>\u01db"+
"\n>\f>\16>\u01de\13>\5>\u01e0\n>\3?\3?\7?\u01e4\n?\f?\16?\u01e7\13?\3"+
"@\3@\3@\3@\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3"+
"A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\5"+
"A\u0217\nA\3B\3B\3B\3B\3B\3B\3B\3B\3B\5B\u0222\nB\3C\5C\u0225\nC\3C\3"+
"C\5C\u0229\nC\3C\3C\5C\u022d\nC\3D\6D\u0230\nD\rD\16D\u0231\3D\3D\7D\u0236"+
"\nD\fD\16D\u0239\13D\3E\3E\7E\u023d\nE\fE\16E\u0240\13E\3F\3F\3G\3G\3"+
"G\3G\7G\u0248\nG\fG\16G\u024b\13G\3G\3G\3H\3H\3H\3H\2\2I\3\3\5\4\7\5\t"+
"\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23"+
"%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G"+
"%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{"+
"?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008fI\3\2\t"+
"\5\2C\\aac|\6\2\62;C\\aac|\7\2\60\60\62;C\\aac|\3\2\62;\3\2\63;\3\2))"+
"\5\2\13\f\17\17\"\"\2\u0263\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3"+
"\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2"+
"\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37"+
"\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3"+
"\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2"+
"\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C"+
"\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2"+
"\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2"+
"\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i"+
"\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2"+
"\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081"+
"\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2"+
"\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2\3\u0091\3\2\2\2\5\u0093"+
"\3\2\2\2\7\u0095\3\2\2\2\t\u009c\3\2\2\2\13\u00a5\3\2\2\2\r\u00ab\3\2"+
"\2\2\17\u00b1\3\2\2\2\21\u00b4\3\2\2\2\23\u00b6\3\2\2\2\25\u00bc\3\2\2"+
"\2\27\u00c2\3\2\2\2\31\u00c7\3\2\2\2\33\u00cb\3\2\2\2\35\u00d0\3\2\2\2"+
"\37\u00d6\3\2\2\2!\u00dd\3\2\2\2#\u00e3\3\2\2\2%\u00e5\3\2\2\2\'\u00eb"+
"\3\2\2\2)\u00f0\3\2\2\2+\u00f3\3\2\2\2-\u00f7\3\2\2\2/\u00fb\3\2\2\2\61"+
"\u00fe\3\2\2\2\63\u0106\3\2\2\2\65\u010e\3\2\2\2\67\u0111\3\2\2\29\u0114"+
"\3\2\2\2;\u0119\3\2\2\2=\u0120\3\2\2\2?\u012a\3\2\2\2A\u0132\3\2\2\2C"+
"\u0138\3\2\2\2E\u0140\3\2\2\2G\u014b\3\2\2\2I\u0154\3\2\2\2K\u0159\3\2"+
"\2\2M\u015f\3\2\2\2O\u0168\3\2\2\2Q\u0172\3\2\2\2S\u017d\3\2\2\2U\u0189"+
"\3\2\2\2W\u0192\3\2\2\2Y\u019c\3\2\2\2[\u019e\3\2\2\2]\u01a1\3\2\2\2_"+
"\u01a3\3\2\2\2a\u01a6\3\2\2\2c\u01a9\3\2\2\2e\u01ac\3\2\2\2g\u01b0\3\2"+
"\2\2i\u01b2\3\2\2\2k\u01b5\3\2\2\2m\u01b8\3\2\2\2o\u01bb\3\2\2\2q\u01bf"+
"\3\2\2\2s\u01c2\3\2\2\2u\u01c5\3\2\2\2w\u01c8\3\2\2\2y\u01cc\3\2\2\2{"+
"\u01df\3\2\2\2}\u01e1\3\2\2\2\177\u01e8\3\2\2\2\u0081\u0216\3\2\2\2\u0083"+
"\u0221\3\2\2\2\u0085\u022c\3\2\2\2\u0087\u022f\3\2\2\2\u0089\u023a\3\2"+
"\2\2\u008b\u0241\3\2\2\2\u008d\u0243\3\2\2\2\u008f\u024e\3\2\2\2\u0091"+
"\u0092\7*\2\2\u0092\4\3\2\2\2\u0093\u0094\7+\2\2\u0094\6\3\2\2\2\u0095"+
"\u0096\7u\2\2\u0096\u0097\7g\2\2\u0097\u0098\7n\2\2\u0098\u0099\7g\2\2"+
"\u0099\u009a\7e\2\2\u009a\u009b\7v\2\2\u009b\b\3\2\2\2\u009c\u009d\7f"+
"\2\2\u009d\u009e\7k\2\2\u009e\u009f\7u\2\2\u009f\u00a0\7v\2\2\u00a0\u00a1"+
"\7k\2\2\u00a1\u00a2\7p\2\2\u00a2\u00a3\7e\2\2\u00a3\u00a4\7v\2\2\u00a4"+
"\n\3\2\2\2\u00a5\u00a6\7y\2\2\u00a6\u00a7\7j\2\2\u00a7\u00a8\7g\2\2\u00a8"+
"\u00a9\7t\2\2\u00a9\u00aa\7g\2\2\u00aa\f\3\2\2\2\u00ab\u00ac\7q\2\2\u00ac"+
"\u00ad\7t\2\2\u00ad\u00ae\7f\2\2\u00ae\u00af\7g\2\2\u00af\u00b0\7t\2\2"+
"\u00b0\16\3\2\2\2\u00b1\u00b2\7d\2\2\u00b2\u00b3\7{\2\2\u00b3\20\3\2\2"+
"\2\u00b4\u00b5\7.\2\2\u00b5\22\3\2\2\2\u00b6\u00b7\7p\2\2\u00b7\u00b8"+
"\7w\2\2\u00b8\u00b9\7n\2\2\u00b9\u00ba\7n\2\2\u00ba\u00bb\7u\2\2\u00bb"+
"\24\3\2\2\2\u00bc\u00bd\7h\2\2\u00bd\u00be\7k\2\2\u00be\u00bf\7t\2\2\u00bf"+
"\u00c0\7u\2\2\u00c0\u00c1\7v\2\2\u00c1\26\3\2\2\2\u00c2\u00c3\7n\2\2\u00c3"+
"\u00c4\7c\2\2\u00c4\u00c5\7u\2\2\u00c5\u00c6\7v\2\2\u00c6\30\3\2\2\2\u00c7"+
"\u00c8\7c\2\2\u00c8\u00c9\7u\2\2\u00c9\u00ca\7e\2\2\u00ca\32\3\2\2\2\u00cb"+
"\u00cc\7f\2\2\u00cc\u00cd\7g\2\2\u00cd\u00ce\7u\2\2\u00ce\u00cf\7e\2\2"+
"\u00cf\34\3\2\2\2\u00d0\u00d1\7n\2\2\u00d1\u00d2\7k\2\2\u00d2\u00d3\7"+
"o\2\2\u00d3\u00d4\7k\2\2\u00d4\u00d5\7v\2\2\u00d5\36\3\2\2\2\u00d6\u00d7"+
"\7q\2\2\u00d7\u00d8\7h\2\2\u00d8\u00d9\7h\2\2\u00d9\u00da\7u\2\2\u00da"+
"\u00db\7g\2\2\u00db\u00dc\7v\2\2\u00dc \3\2\2\2\u00dd\u00de\7h\2\2\u00de"+
"\u00df\7g\2\2\u00df\u00e0\7v\2\2\u00e0\u00e1\7e\2\2\u00e1\u00e2\7j\2\2"+
"\u00e2\"\3\2\2\2\u00e3\u00e4\7-\2\2\u00e4$\3\2\2\2\u00e5\u00e6\7s\2\2"+
"\u00e6\u00e7\7w\2\2\u00e7\u00e8\7g\2\2\u00e8\u00e9\7t\2\2\u00e9\u00ea"+
"\7{\2\2\u00ea&\3\2\2\2\u00eb\u00ec\7n\2\2\u00ec\u00ed\7c\2\2\u00ed\u00ee"+
"\7|\2\2\u00ee\u00ef\7{\2\2\u00ef(\3\2\2\2\u00f0\u00f1\7q\2\2\u00f1\u00f2"+
"\7t\2\2\u00f2*\3\2\2\2\u00f3\u00f4\7c\2\2\u00f4\u00f5\7p\2\2\u00f5\u00f6"+
"\7f\2\2\u00f6,\3\2\2\2\u00f7\u00f8\7p\2\2\u00f8\u00f9\7q\2\2\u00f9\u00fa"+
"\7v\2\2\u00fa.\3\2\2\2\u00fb\u00fc\7k\2\2\u00fc\u00fd\7p\2\2\u00fd\60"+
"\3\2\2\2\u00fe\u00ff\7d\2\2\u00ff\u0100\7g\2\2\u0100\u0101\7v\2\2\u0101"+
"\u0102\7y\2\2\u0102\u0103\7g\2\2\u0103\u0104\7g\2\2\u0104\u0105\7p\2\2"+
"\u0105\62\3\2\2\2\u0106\u0107\7k\2\2\u0107\u0108\7p\2\2\u0108\u0109\7"+
"t\2\2\u0109\u010a\7c\2\2\u010a\u010b\7p\2\2\u010b\u010c\7i\2\2\u010c\u010d"+
@@ -292,44 +293,47 @@ public class EQLLexer extends Lexer {
"\7s\2\2\u01cbx\3\2\2\2\u01cc\u01cd\7k\2\2\u01cd\u01ce\7p\2\2\u01ce\u01cf"+
"\7g\2\2\u01cfz\3\2\2\2\u01d0\u01d1\7<\2\2\u01d1\u01d5\t\2\2\2\u01d2\u01d4"+
"\t\3\2\2\u01d3\u01d2\3\2\2\2\u01d4\u01d7\3\2\2\2\u01d5\u01d3\3\2\2\2\u01d5"+
"\u01d6\3\2\2\2\u01d6|\3\2\2\2\u01d7\u01d5\3\2\2\2\u01d8\u01dc\t\2\2\2"+
"\u01d9\u01db\t\4\2\2\u01da\u01d9\3\2\2\2\u01db\u01de\3\2\2\2\u01dc\u01da"+
"\3\2\2\2\u01dc\u01dd\3\2\2\2\u01dd~\3\2\2\2\u01de\u01dc\3\2\2\2\u01df"+
"\u01e0\7b\2\2\u01e0\u01e1\5}?\2\u01e1\u01e2\7b\2\2\u01e2\u0080\3\2\2\2"+
"\u01e3\u01e4\7u\2\2\u01e4\u01e5\7w\2\2\u01e5\u01e6\7o\2\2\u01e6\u01e7"+
"\7*\2\2\u01e7\u01e8\3\2\2\2\u01e8\u01e9\5}?\2\u01e9\u01ea\7+\2\2\u01ea"+
"\u020e\3\2\2\2\u01eb\u01ec\7o\2\2\u01ec\u01ed\7c\2\2\u01ed\u01ee\7z\2"+
"\2\u01ee\u01ef\7*\2\2\u01ef\u01f0\3\2\2\2\u01f0\u01f1\5}?\2\u01f1\u01f2"+
"\7+\2\2\u01f2\u020e\3\2\2\2\u01f3\u01f4\7o\2\2\u01f4\u01f5\7k\2\2\u01f5"+
"\u01f6\7p\2\2\u01f6\u01f7\7*\2\2\u01f7\u01f8\3\2\2\2\u01f8\u01f9\5}?\2"+
"\u01f9\u01fa\7+\2\2\u01fa\u020e\3\2\2\2\u01fb\u01fc\7c\2\2\u01fc\u01fd"+
"\7x\2\2\u01fd\u01fe\7i\2\2\u01fe\u01ff\7*\2\2\u01ff\u0200\3\2\2\2\u0200"+
"\u0201\5}?\2\u0201\u0202\7+\2\2\u0202\u020e\3\2\2\2\u0203\u0204\7e\2\2"+
"\u0204\u0205\7q\2\2\u0205\u0206\7w\2\2\u0206\u0207\7p\2\2\u0207\u0208"+
"\7v\2\2\u0208\u0209\7*\2\2\u0209\u020a\3\2\2\2\u020a\u020b\5}?\2\u020b"+
"\u020c\7+\2\2\u020c\u020e\3\2\2\2\u020d\u01e3\3\2\2\2\u020d\u01eb\3\2"+
"\2\2\u020d\u01f3\3\2\2\2\u020d\u01fb\3\2\2\2\u020d\u0203\3\2\2\2\u020e"+
"\u0082\3\2\2\2\u020f\u0210\7v\2\2\u0210\u0211\7t\2\2\u0211\u0212\7w\2"+
"\2\u0212\u0219\7g\2\2\u0213\u0214\7h\2\2\u0214\u0215\7c\2\2\u0215\u0216"+
"\7n\2\2\u0216\u0217\7u\2\2\u0217\u0219\7g\2\2\u0218\u020f\3\2\2\2\u0218"+
"\u0213\3\2\2\2\u0219\u0084\3\2\2\2\u021a\u021c\7/\2\2\u021b\u021a\3\2"+
"\2\2\u021b\u021c\3\2\2\2\u021c\u021d\3\2\2\2\u021d\u0224\5\u0087D\2\u021e"+
"\u0220\7/\2\2\u021f\u021e\3\2\2\2\u021f\u0220\3\2\2\2\u0220\u0221\3\2"+
"\2\2\u0221\u0224\5\u0089E\2\u0222\u0224\5\u008bF\2\u0223\u021b\3\2\2\2"+
"\u0223\u021f\3\2\2\2\u0223\u0222\3\2\2\2\u0224\u0086\3\2\2\2\u0225\u0227"+
"\t\5\2\2\u0226\u0225\3\2\2\2\u0227\u0228\3\2\2\2\u0228\u0226\3\2\2\2\u0228"+
"\u0229\3\2\2\2\u0229\u022a\3\2\2\2\u022a\u022e\7\60\2\2\u022b\u022d\t"+
"\5\2\2\u022c\u022b\3\2\2\2\u022d\u0230\3\2\2\2\u022e\u022c\3\2\2\2\u022e"+
"\u022f\3\2\2\2\u022f\u0088\3\2\2\2\u0230\u022e\3\2\2\2\u0231\u0235\t\6"+
"\2\2\u0232\u0234\t\5\2\2\u0233\u0232\3\2\2\2\u0234\u0237\3\2\2\2\u0235"+
"\u0233\3\2\2\2\u0235\u0236\3\2\2\2\u0236\u008a\3\2\2\2\u0237\u0235\3\2"+
"\2\2\u0238\u0239\7\62\2\2\u0239\u008c\3\2\2\2\u023a\u0240\7)\2\2\u023b"+
"\u023f\n\7\2\2\u023c\u023d\7)\2\2\u023d\u023f\7)\2\2\u023e\u023b\3\2\2"+
"\2\u023e\u023c\3\2\2\2\u023f\u0242\3\2\2\2\u0240\u023e\3\2\2\2\u0240\u0241"+
"\3\2\2\2\u0241\u0243\3\2\2\2\u0242\u0240\3\2\2\2\u0243\u0244\7)\2\2\u0244"+
"\u008e\3\2\2\2\u0245\u0246\t\b\2\2\u0246\u0247\3\2\2\2\u0247\u0248\bH"+
"\2\2\u0248\u0090\3\2\2\2\17\2\u01d5\u01dc\u020d\u0218\u021b\u021f\u0223"+
"\u0228\u022e\u0235\u023e\u0240\3\b\2\2";
"\u01d6\3\2\2\2\u01d6\u01e0\3\2\2\2\u01d7\u01d5\3\2\2\2\u01d8\u01dc\7A"+
"\2\2\u01d9\u01db\4\62;\2\u01da\u01d9\3\2\2\2\u01db\u01de\3\2\2\2\u01dc"+
"\u01da\3\2\2\2\u01dc\u01dd\3\2\2\2\u01dd\u01e0\3\2\2\2\u01de\u01dc\3\2"+
"\2\2\u01df\u01d0\3\2\2\2\u01df\u01d8\3\2\2\2\u01e0|\3\2\2\2\u01e1\u01e5"+
"\t\2\2\2\u01e2\u01e4\t\4\2\2\u01e3\u01e2\3\2\2\2\u01e4\u01e7\3\2\2\2\u01e5"+
"\u01e3\3\2\2\2\u01e5\u01e6\3\2\2\2\u01e6~\3\2\2\2\u01e7\u01e5\3\2\2\2"+
"\u01e8\u01e9\7b\2\2\u01e9\u01ea\5}?\2\u01ea\u01eb\7b\2\2\u01eb\u0080\3"+
"\2\2\2\u01ec\u01ed\7u\2\2\u01ed\u01ee\7w\2\2\u01ee\u01ef\7o\2\2\u01ef"+
"\u01f0\7*\2\2\u01f0\u01f1\3\2\2\2\u01f1\u01f2\5}?\2\u01f2\u01f3\7+\2\2"+
"\u01f3\u0217\3\2\2\2\u01f4\u01f5\7o\2\2\u01f5\u01f6\7c\2\2\u01f6\u01f7"+
"\7z\2\2\u01f7\u01f8\7*\2\2\u01f8\u01f9\3\2\2\2\u01f9\u01fa\5}?\2\u01fa"+
"\u01fb\7+\2\2\u01fb\u0217\3\2\2\2\u01fc\u01fd\7o\2\2\u01fd\u01fe\7k\2"+
"\2\u01fe\u01ff\7p\2\2\u01ff\u0200\7*\2\2\u0200\u0201\3\2\2\2\u0201\u0202"+
"\5}?\2\u0202\u0203\7+\2\2\u0203\u0217\3\2\2\2\u0204\u0205\7c\2\2\u0205"+
"\u0206\7x\2\2\u0206\u0207\7i\2\2\u0207\u0208\7*\2\2\u0208\u0209\3\2\2"+
"\2\u0209\u020a\5}?\2\u020a\u020b\7+\2\2\u020b\u0217\3\2\2\2\u020c\u020d"+
"\7e\2\2\u020d\u020e\7q\2\2\u020e\u020f\7w\2\2\u020f\u0210\7p\2\2\u0210"+
"\u0211\7v\2\2\u0211\u0212\7*\2\2\u0212\u0213\3\2\2\2\u0213\u0214\5}?\2"+
"\u0214\u0215\7+\2\2\u0215\u0217\3\2\2\2\u0216\u01ec\3\2\2\2\u0216\u01f4"+
"\3\2\2\2\u0216\u01fc\3\2\2\2\u0216\u0204\3\2\2\2\u0216\u020c\3\2\2\2\u0217"+
"\u0082\3\2\2\2\u0218\u0219\7v\2\2\u0219\u021a\7t\2\2\u021a\u021b\7w\2"+
"\2\u021b\u0222\7g\2\2\u021c\u021d\7h\2\2\u021d\u021e\7c\2\2\u021e\u021f"+
"\7n\2\2\u021f\u0220\7u\2\2\u0220\u0222\7g\2\2\u0221\u0218\3\2\2\2\u0221"+
"\u021c\3\2\2\2\u0222\u0084\3\2\2\2\u0223\u0225\7/\2\2\u0224\u0223\3\2"+
"\2\2\u0224\u0225\3\2\2\2\u0225\u0226\3\2\2\2\u0226\u022d\5\u0087D\2\u0227"+
"\u0229\7/\2\2\u0228\u0227\3\2\2\2\u0228\u0229\3\2\2\2\u0229\u022a\3\2"+
"\2\2\u022a\u022d\5\u0089E\2\u022b\u022d\5\u008bF\2\u022c\u0224\3\2\2\2"+
"\u022c\u0228\3\2\2\2\u022c\u022b\3\2\2\2\u022d\u0086\3\2\2\2\u022e\u0230"+
"\t\5\2\2\u022f\u022e\3\2\2\2\u0230\u0231\3\2\2\2\u0231\u022f\3\2\2\2\u0231"+
"\u0232\3\2\2\2\u0232\u0233\3\2\2\2\u0233\u0237\7\60\2\2\u0234\u0236\t"+
"\5\2\2\u0235\u0234\3\2\2\2\u0236\u0239\3\2\2\2\u0237\u0235\3\2\2\2\u0237"+
"\u0238\3\2\2\2\u0238\u0088\3\2\2\2\u0239\u0237\3\2\2\2\u023a\u023e\t\6"+
"\2\2\u023b\u023d\t\5\2\2\u023c\u023b\3\2\2\2\u023d\u0240\3\2\2\2\u023e"+
"\u023c\3\2\2\2\u023e\u023f\3\2\2\2\u023f\u008a\3\2\2\2\u0240\u023e\3\2"+
"\2\2\u0241\u0242\7\62\2\2\u0242\u008c\3\2\2\2\u0243\u0249\7)\2\2\u0244"+
"\u0248\n\7\2\2\u0245\u0246\7)\2\2\u0246\u0248\7)\2\2\u0247\u0244\3\2\2"+
"\2\u0247\u0245\3\2\2\2\u0248\u024b\3\2\2\2\u0249\u0247\3\2\2\2\u0249\u024a"+
"\3\2\2\2\u024a\u024c\3\2\2\2\u024b\u0249\3\2\2\2\u024c\u024d\7)\2\2\u024d"+
"\u008e\3\2\2\2\u024e\u024f\t\b\2\2\u024f\u0250\3\2\2\2\u0250\u0251\bH"+
"\2\2\u0251\u0090\3\2\2\2\21\2\u01d5\u01dc\u01df\u01e5\u0216\u0221\u0224"+
"\u0228\u022c\u0231\u0237\u023e\u0247\u0249\3\b\2\2";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {