From 8f94981bb093f104228d267b532e0a3d5b7f6a38 Mon Sep 17 00:00:00 2001 From: Marios Trivyzas Date: Fri, 18 Sep 2020 10:00:52 +0200 Subject: [PATCH] EQL: Disallow chained comparisons (#62567) Expressions like `1 = 2 = 3 = 4` or `1 < 2 = 3 >= 4` were treated with leftmost priority: ((1 = 2) = 3) = 4 which can lead to confusing results. Since such expressions don't make so much change for EQL filters we disallow them in the parser to prevent unexpected results from their bad usage. Major DBs like PostgreSQL and Oracle also disallow them in their SQL syntax. (counter example would be MySQL which interprets them as we did before with leftmost priority). Fixes: #61654 --- x-pack/plugin/eql/src/main/antlr/EqlBase.g4 | 14 +- .../xpack/eql/parser/EqlBaseBaseListener.java | 12 + .../xpack/eql/parser/EqlBaseBaseVisitor.java | 7 + .../xpack/eql/parser/EqlBaseListener.java | 20 +- .../xpack/eql/parser/EqlBaseParser.java | 736 ++++++++++-------- .../xpack/eql/parser/EqlBaseVisitor.java | 11 +- .../xpack/eql/parser/ExpressionBuilder.java | 5 +- .../xpack/eql/parser/ExpressionTests.java | 42 +- 8 files changed, 494 insertions(+), 353 deletions(-) diff --git a/x-pack/plugin/eql/src/main/antlr/EqlBase.g4 b/x-pack/plugin/eql/src/main/antlr/EqlBase.g4 index aaf0c56519fe..3b93cbc6e2c1 100644 --- a/x-pack/plugin/eql/src/main/antlr/EqlBase.g4 +++ b/x-pack/plugin/eql/src/main/antlr/EqlBase.g4 @@ -84,11 +84,15 @@ booleanExpression valueExpression - : primaryExpression predicate? #valueExpressionDefault - | operator=(MINUS | PLUS) valueExpression #arithmeticUnary - | left=valueExpression operator=(ASTERISK | SLASH | PERCENT) right=valueExpression #arithmeticBinary - | left=valueExpression operator=(PLUS | MINUS) right=valueExpression #arithmeticBinary - | left=valueExpression comparisonOperator right=valueExpression #comparison + : operatorExpression #valueExpressionDefault + | left=operatorExpression comparisonOperator right=operatorExpression #comparison + ; + +operatorExpression + : primaryExpression predicate? #operatorExpressionDefault + | operator=(MINUS | PLUS) operatorExpression #arithmeticUnary + | left=operatorExpression operator=(ASTERISK | SLASH | PERCENT) right=operatorExpression #arithmeticBinary + | left=operatorExpression operator=(PLUS | MINUS) right=operatorExpression #arithmeticBinary ; // workaround for diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseBaseListener.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseBaseListener.java index d0c10757df19..76e5f219b160 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseBaseListener.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseBaseListener.java @@ -263,6 +263,18 @@ class EqlBaseBaseListener implements EqlBaseListener { *

The default implementation does nothing.

*/ @Override public void exitComparison(EqlBaseParser.ComparisonContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterOperatorExpressionDefault(EqlBaseParser.OperatorExpressionDefaultContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitOperatorExpressionDefault(EqlBaseParser.OperatorExpressionDefaultContext ctx) { } /** * {@inheritDoc} * diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseBaseVisitor.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseBaseVisitor.java index 48d66d265ed3..beadef3d0922 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseBaseVisitor.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseBaseVisitor.java @@ -158,6 +158,13 @@ class EqlBaseBaseVisitor extends AbstractParseTreeVisitor implements EqlBa * {@link #visitChildren} on {@code ctx}.

*/ @Override public T visitComparison(EqlBaseParser.ComparisonContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitOperatorExpressionDefault(EqlBaseParser.OperatorExpressionDefaultContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseListener.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseListener.java index 6d360106c1cb..031f80d8e037 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseListener.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseListener.java @@ -229,27 +229,39 @@ interface EqlBaseListener extends ParseTreeListener { * @param ctx the parse tree */ void exitComparison(EqlBaseParser.ComparisonContext ctx); + /** + * Enter a parse tree produced by the {@code operatorExpressionDefault} + * labeled alternative in {@link EqlBaseParser#operatorExpression}. + * @param ctx the parse tree + */ + void enterOperatorExpressionDefault(EqlBaseParser.OperatorExpressionDefaultContext ctx); + /** + * Exit a parse tree produced by the {@code operatorExpressionDefault} + * labeled alternative in {@link EqlBaseParser#operatorExpression}. + * @param ctx the parse tree + */ + void exitOperatorExpressionDefault(EqlBaseParser.OperatorExpressionDefaultContext ctx); /** * Enter a parse tree produced by the {@code arithmeticBinary} - * labeled alternative in {@link EqlBaseParser#valueExpression}. + * labeled alternative in {@link EqlBaseParser#operatorExpression}. * @param ctx the parse tree */ void enterArithmeticBinary(EqlBaseParser.ArithmeticBinaryContext ctx); /** * Exit a parse tree produced by the {@code arithmeticBinary} - * labeled alternative in {@link EqlBaseParser#valueExpression}. + * labeled alternative in {@link EqlBaseParser#operatorExpression}. * @param ctx the parse tree */ void exitArithmeticBinary(EqlBaseParser.ArithmeticBinaryContext ctx); /** * Enter a parse tree produced by the {@code arithmeticUnary} - * labeled alternative in {@link EqlBaseParser#valueExpression}. + * labeled alternative in {@link EqlBaseParser#operatorExpression}. * @param ctx the parse tree */ void enterArithmeticUnary(EqlBaseParser.ArithmeticUnaryContext ctx); /** * Exit a parse tree produced by the {@code arithmeticUnary} - * labeled alternative in {@link EqlBaseParser#valueExpression}. + * labeled alternative in {@link EqlBaseParser#operatorExpression}. * @param ctx the parse tree */ void exitArithmeticUnary(EqlBaseParser.ArithmeticUnaryContext ctx); diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseParser.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseParser.java index 13608aef13b1..4648c04da2a7 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseParser.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseParser.java @@ -28,16 +28,18 @@ class EqlBaseParser extends Parser { RULE_query = 3, RULE_sequenceParams = 4, RULE_sequence = 5, RULE_join = 6, RULE_pipe = 7, RULE_joinKeys = 8, RULE_joinTerm = 9, RULE_sequenceTerm = 10, RULE_subquery = 11, RULE_eventQuery = 12, RULE_eventFilter = 13, RULE_expression = 14, - RULE_booleanExpression = 15, RULE_valueExpression = 16, RULE_predicate = 17, - RULE_primaryExpression = 18, RULE_functionExpression = 19, RULE_constant = 20, - RULE_comparisonOperator = 21, RULE_booleanValue = 22, RULE_qualifiedName = 23, - RULE_identifier = 24, RULE_timeUnit = 25, RULE_number = 26, RULE_string = 27; + RULE_booleanExpression = 15, RULE_valueExpression = 16, RULE_operatorExpression = 17, + RULE_predicate = 18, RULE_primaryExpression = 19, RULE_functionExpression = 20, + RULE_constant = 21, RULE_comparisonOperator = 22, RULE_booleanValue = 23, + RULE_qualifiedName = 24, RULE_identifier = 25, RULE_timeUnit = 26, RULE_number = 27, + RULE_string = 28; public static final String[] ruleNames = { "singleStatement", "singleExpression", "statement", "query", "sequenceParams", "sequence", "join", "pipe", "joinKeys", "joinTerm", "sequenceTerm", "subquery", "eventQuery", "eventFilter", "expression", "booleanExpression", "valueExpression", - "predicate", "primaryExpression", "functionExpression", "constant", "comparisonOperator", - "booleanValue", "qualifiedName", "identifier", "timeUnit", "number", "string" + "operatorExpression", "predicate", "primaryExpression", "functionExpression", + "constant", "comparisonOperator", "booleanValue", "qualifiedName", "identifier", + "timeUnit", "number", "string" }; private static final String[] _LITERAL_NAMES = { @@ -134,9 +136,9 @@ public final SingleStatementContext singleStatement() throws RecognitionExceptio try { enterOuterAlt(_localctx, 1); { - setState(56); + setState(58); statement(); - setState(57); + setState(59); match(EOF); } } @@ -181,9 +183,9 @@ public final SingleExpressionContext singleExpression() throws RecognitionExcept try { enterOuterAlt(_localctx, 1); { - setState(59); + setState(61); expression(); - setState(60); + setState(62); match(EOF); } } @@ -234,19 +236,19 @@ public final StatementContext statement() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(62); + setState(64); query(); - setState(66); + setState(68); _errHandler.sync(this); _la = _input.LA(1); while (_la==PIPE) { { { - setState(63); + setState(65); pipe(); } } - setState(68); + setState(70); _errHandler.sync(this); _la = _input.LA(1); } @@ -296,19 +298,19 @@ public final QueryContext query() throws RecognitionException { QueryContext _localctx = new QueryContext(_ctx, getState()); enterRule(_localctx, 6, RULE_query); try { - setState(72); + setState(74); switch (_input.LA(1)) { case SEQUENCE: enterOuterAlt(_localctx, 1); { - setState(69); + setState(71); sequence(); } break; case JOIN: enterOuterAlt(_localctx, 2); { - setState(70); + setState(72); join(); } break; @@ -317,7 +319,7 @@ public final QueryContext query() throws RecognitionException { case IDENTIFIER: enterOuterAlt(_localctx, 3); { - setState(71); + setState(73); eventQuery(); } break; @@ -368,14 +370,14 @@ public final SequenceParamsContext sequenceParams() throws RecognitionException try { enterOuterAlt(_localctx, 1); { - setState(74); + setState(76); match(WITH); { - setState(75); + setState(77); match(MAXSPAN); - setState(76); + setState(78); match(EQ); - setState(77); + setState(79); timeUnit(); } } @@ -435,19 +437,19 @@ public final SequenceContext sequence() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(79); + setState(81); match(SEQUENCE); - setState(88); + setState(90); switch (_input.LA(1)) { case BY: { - setState(80); - ((SequenceContext)_localctx).by = joinKeys(); setState(82); + ((SequenceContext)_localctx).by = joinKeys(); + setState(84); _la = _input.LA(1); if (_la==WITH) { { - setState(81); + setState(83); sequenceParams(); } } @@ -456,13 +458,13 @@ public final SequenceContext sequence() throws RecognitionException { break; case WITH: { - setState(84); - sequenceParams(); setState(86); + sequenceParams(); + setState(88); _la = _input.LA(1); if (_la==BY) { { - setState(85); + setState(87); ((SequenceContext)_localctx).disallowed = joinKeys(); } } @@ -474,29 +476,29 @@ public final SequenceContext sequence() throws RecognitionException { default: throw new NoViableAltException(this); } - setState(90); + setState(92); sequenceTerm(); - setState(92); + setState(94); _errHandler.sync(this); _la = _input.LA(1); do { { { - setState(91); + setState(93); sequenceTerm(); } } - setState(94); + setState(96); _errHandler.sync(this); _la = _input.LA(1); } while ( _la==LB ); - setState(98); + setState(100); _la = _input.LA(1); if (_la==UNTIL) { { - setState(96); + setState(98); match(UNTIL); - setState(97); + setState(99); ((SequenceContext)_localctx).until = sequenceTerm(); } } @@ -554,40 +556,40 @@ public final JoinContext join() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(100); - match(JOIN); setState(102); + match(JOIN); + setState(104); _la = _input.LA(1); if (_la==BY) { { - setState(101); + setState(103); ((JoinContext)_localctx).by = joinKeys(); } } - setState(104); + setState(106); joinTerm(); - setState(106); + setState(108); _errHandler.sync(this); _la = _input.LA(1); do { { { - setState(105); + setState(107); joinTerm(); } } - setState(108); + setState(110); _errHandler.sync(this); _la = _input.LA(1); } while ( _la==LB ); - setState(112); + setState(114); _la = _input.LA(1); if (_la==UNTIL) { { - setState(110); + setState(112); match(UNTIL); - setState(111); + setState(113); ((JoinContext)_localctx).until = joinTerm(); } } @@ -645,29 +647,29 @@ public final PipeContext pipe() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(114); + setState(116); match(PIPE); - setState(115); + setState(117); ((PipeContext)_localctx).kind = match(IDENTIFIER); - setState(124); + setState(126); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << FALSE) | (1L << NOT) | (1L << NULL) | (1L << TRUE) | (1L << PLUS) | (1L << MINUS) | (1L << LP) | (1L << ESCAPED_IDENTIFIER) | (1L << STRING) | (1L << INTEGER_VALUE) | (1L << DECIMAL_VALUE) | (1L << IDENTIFIER))) != 0)) { { - setState(116); + setState(118); booleanExpression(0); - setState(121); + setState(123); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(117); + setState(119); match(COMMA); - setState(118); + setState(120); booleanExpression(0); } } - setState(123); + setState(125); _errHandler.sync(this); _la = _input.LA(1); } @@ -725,23 +727,23 @@ public final JoinKeysContext joinKeys() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(126); + setState(128); match(BY); - setState(127); + setState(129); expression(); - setState(132); + setState(134); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(128); + setState(130); match(COMMA); - setState(129); + setState(131); expression(); } } - setState(134); + setState(136); _errHandler.sync(this); _la = _input.LA(1); } @@ -792,13 +794,13 @@ public final JoinTermContext joinTerm() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(135); - subquery(); setState(137); + subquery(); + setState(139); _la = _input.LA(1); if (_la==BY) { { - setState(136); + setState(138); ((JoinTermContext)_localctx).by = joinKeys(); } } @@ -855,21 +857,21 @@ public final SequenceTermContext sequenceTerm() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(139); + setState(141); subquery(); - setState(145); + setState(147); _la = _input.LA(1); if (_la==FORK) { { - setState(140); + setState(142); match(FORK); - setState(143); + setState(145); _la = _input.LA(1); if (_la==EQ) { { - setState(141); + setState(143); match(EQ); - setState(142); + setState(144); booleanValue(); } } @@ -877,11 +879,11 @@ public final SequenceTermContext sequenceTerm() throws RecognitionException { } } - setState(148); + setState(150); _la = _input.LA(1); if (_la==BY) { { - setState(147); + setState(149); ((SequenceTermContext)_localctx).by = joinKeys(); } } @@ -930,11 +932,11 @@ public final SubqueryContext subquery() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(150); + setState(152); match(LB); - setState(151); + setState(153); eventFilter(); - setState(152); + setState(154); match(RB); } } @@ -978,7 +980,7 @@ public final EventQueryContext eventQuery() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(154); + setState(156); eventFilter(); } } @@ -1028,27 +1030,27 @@ public final EventFilterContext eventFilter() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(158); + setState(160); switch (_input.LA(1)) { case ANY: { - setState(156); + setState(158); match(ANY); } break; case ESCAPED_IDENTIFIER: case IDENTIFIER: { - setState(157); + setState(159); ((EventFilterContext)_localctx).event = identifier(); } break; default: throw new NoViableAltException(this); } - setState(160); + setState(162); match(WHERE); - setState(161); + setState(163); expression(); } } @@ -1092,7 +1094,7 @@ public final ExpressionContext expression() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(163); + setState(165); booleanExpression(0); } } @@ -1222,7 +1224,7 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc int _alt; enterOuterAlt(_localctx, 1); { - setState(172); + setState(174); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,18,_ctx) ) { case 1: @@ -1231,9 +1233,9 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _ctx = _localctx; _prevctx = _localctx; - setState(166); + setState(168); match(NOT); - setState(167); + setState(169); booleanExpression(5); } break; @@ -1242,11 +1244,11 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new ProcessCheckContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(168); + setState(170); ((ProcessCheckContext)_localctx).relationship = match(IDENTIFIER); - setState(169); + setState(171); match(OF); - setState(170); + setState(172); subquery(); } break; @@ -1255,13 +1257,13 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new BooleanDefaultContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(171); - valueExpression(0); + setState(173); + valueExpression(); } break; } _ctx.stop = _input.LT(-1); - setState(182); + setState(184); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,20,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -1269,7 +1271,7 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(180); + setState(182); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,19,_ctx) ) { case 1: @@ -1277,11 +1279,11 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); ((LogicalBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_booleanExpression); - setState(174); + setState(176); if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); - setState(175); + setState(177); ((LogicalBinaryContext)_localctx).operator = match(AND); - setState(176); + setState(178); ((LogicalBinaryContext)_localctx).right = booleanExpression(3); } break; @@ -1290,18 +1292,18 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); ((LogicalBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_booleanExpression); - setState(177); + setState(179); if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(178); + setState(180); ((LogicalBinaryContext)_localctx).operator = match(OR); - setState(179); + setState(181); ((LogicalBinaryContext)_localctx).right = booleanExpression(2); } break; } } } - setState(184); + setState(186); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,20,_ctx); } @@ -1330,11 +1332,8 @@ public void copyFrom(ValueExpressionContext ctx) { } } public static class ValueExpressionDefaultContext extends ValueExpressionContext { - public PrimaryExpressionContext primaryExpression() { - return getRuleContext(PrimaryExpressionContext.class,0); - } - public PredicateContext predicate() { - return getRuleContext(PredicateContext.class,0); + public OperatorExpressionContext operatorExpression() { + return getRuleContext(OperatorExpressionContext.class,0); } public ValueExpressionDefaultContext(ValueExpressionContext ctx) { copyFrom(ctx); } @Override @@ -1352,16 +1351,16 @@ public T accept(ParseTreeVisitor visitor) { } } public static class ComparisonContext extends ValueExpressionContext { - public ValueExpressionContext left; - public ValueExpressionContext right; + public OperatorExpressionContext left; + public OperatorExpressionContext right; public ComparisonOperatorContext comparisonOperator() { return getRuleContext(ComparisonOperatorContext.class,0); } - public List valueExpression() { - return getRuleContexts(ValueExpressionContext.class); + public List operatorExpression() { + return getRuleContexts(OperatorExpressionContext.class); } - public ValueExpressionContext valueExpression(int i) { - return getRuleContext(ValueExpressionContext.class,i); + public OperatorExpressionContext operatorExpression(int i) { + return getRuleContext(OperatorExpressionContext.class,i); } public ComparisonContext(ValueExpressionContext ctx) { copyFrom(ctx); } @Override @@ -1378,22 +1377,96 @@ public T accept(ParseTreeVisitor visitor) { else return visitor.visitChildren(this); } } - public static class ArithmeticBinaryContext extends ValueExpressionContext { - public ValueExpressionContext left; + + public final ValueExpressionContext valueExpression() throws RecognitionException { + ValueExpressionContext _localctx = new ValueExpressionContext(_ctx, getState()); + enterRule(_localctx, 32, RULE_valueExpression); + try { + setState(192); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,21,_ctx) ) { + case 1: + _localctx = new ValueExpressionDefaultContext(_localctx); + enterOuterAlt(_localctx, 1); + { + setState(187); + operatorExpression(0); + } + break; + case 2: + _localctx = new ComparisonContext(_localctx); + enterOuterAlt(_localctx, 2); + { + setState(188); + ((ComparisonContext)_localctx).left = operatorExpression(0); + setState(189); + comparisonOperator(); + setState(190); + ((ComparisonContext)_localctx).right = operatorExpression(0); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class OperatorExpressionContext extends ParserRuleContext { + public OperatorExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_operatorExpression; } + + public OperatorExpressionContext() { } + public void copyFrom(OperatorExpressionContext ctx) { + super.copyFrom(ctx); + } + } + public static class OperatorExpressionDefaultContext extends OperatorExpressionContext { + public PrimaryExpressionContext primaryExpression() { + return getRuleContext(PrimaryExpressionContext.class,0); + } + public PredicateContext predicate() { + return getRuleContext(PredicateContext.class,0); + } + public OperatorExpressionDefaultContext(OperatorExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof EqlBaseListener ) ((EqlBaseListener)listener).enterOperatorExpressionDefault(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof EqlBaseListener ) ((EqlBaseListener)listener).exitOperatorExpressionDefault(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof EqlBaseVisitor ) return ((EqlBaseVisitor)visitor).visitOperatorExpressionDefault(this); + else return visitor.visitChildren(this); + } + } + public static class ArithmeticBinaryContext extends OperatorExpressionContext { + public OperatorExpressionContext left; public Token operator; - public ValueExpressionContext right; - public List valueExpression() { - return getRuleContexts(ValueExpressionContext.class); + public OperatorExpressionContext right; + public List operatorExpression() { + return getRuleContexts(OperatorExpressionContext.class); } - public ValueExpressionContext valueExpression(int i) { - return getRuleContext(ValueExpressionContext.class,i); + public OperatorExpressionContext operatorExpression(int i) { + return getRuleContext(OperatorExpressionContext.class,i); } public TerminalNode ASTERISK() { return getToken(EqlBaseParser.ASTERISK, 0); } public TerminalNode SLASH() { return getToken(EqlBaseParser.SLASH, 0); } public TerminalNode PERCENT() { return getToken(EqlBaseParser.PERCENT, 0); } public TerminalNode PLUS() { return getToken(EqlBaseParser.PLUS, 0); } public TerminalNode MINUS() { return getToken(EqlBaseParser.MINUS, 0); } - public ArithmeticBinaryContext(ValueExpressionContext ctx) { copyFrom(ctx); } + public ArithmeticBinaryContext(OperatorExpressionContext ctx) { copyFrom(ctx); } @Override public void enterRule(ParseTreeListener listener) { if ( listener instanceof EqlBaseListener ) ((EqlBaseListener)listener).enterArithmeticBinary(this); @@ -1408,14 +1481,14 @@ public T accept(ParseTreeVisitor visitor) { else return visitor.visitChildren(this); } } - public static class ArithmeticUnaryContext extends ValueExpressionContext { + public static class ArithmeticUnaryContext extends OperatorExpressionContext { public Token operator; - public ValueExpressionContext valueExpression() { - return getRuleContext(ValueExpressionContext.class,0); + public OperatorExpressionContext operatorExpression() { + return getRuleContext(OperatorExpressionContext.class,0); } public TerminalNode MINUS() { return getToken(EqlBaseParser.MINUS, 0); } public TerminalNode PLUS() { return getToken(EqlBaseParser.PLUS, 0); } - public ArithmeticUnaryContext(ValueExpressionContext ctx) { copyFrom(ctx); } + public ArithmeticUnaryContext(OperatorExpressionContext ctx) { copyFrom(ctx); } @Override public void enterRule(ParseTreeListener listener) { if ( listener instanceof EqlBaseListener ) ((EqlBaseListener)listener).enterArithmeticUnary(this); @@ -1431,23 +1504,23 @@ public T accept(ParseTreeVisitor visitor) { } } - public final ValueExpressionContext valueExpression() throws RecognitionException { - return valueExpression(0); + public final OperatorExpressionContext operatorExpression() throws RecognitionException { + return operatorExpression(0); } - private ValueExpressionContext valueExpression(int _p) throws RecognitionException { + private OperatorExpressionContext operatorExpression(int _p) throws RecognitionException { ParserRuleContext _parentctx = _ctx; int _parentState = getState(); - ValueExpressionContext _localctx = new ValueExpressionContext(_ctx, _parentState); - ValueExpressionContext _prevctx = _localctx; - int _startState = 32; - enterRecursionRule(_localctx, 32, RULE_valueExpression, _p); + OperatorExpressionContext _localctx = new OperatorExpressionContext(_ctx, _parentState); + OperatorExpressionContext _prevctx = _localctx; + int _startState = 34; + enterRecursionRule(_localctx, 34, RULE_operatorExpression, _p); int _la; try { int _alt; enterOuterAlt(_localctx, 1); { - setState(192); + setState(201); switch (_input.LA(1)) { case FALSE: case NULL: @@ -1459,18 +1532,18 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti case DECIMAL_VALUE: case IDENTIFIER: { - _localctx = new ValueExpressionDefaultContext(_localctx); + _localctx = new OperatorExpressionDefaultContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(186); + setState(195); primaryExpression(); - setState(188); + setState(197); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,21,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,22,_ctx) ) { case 1: { - setState(187); + setState(196); predicate(); } break; @@ -1483,7 +1556,7 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti _localctx = new ArithmeticUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(190); + setState(199); ((ArithmeticUnaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { @@ -1491,33 +1564,33 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti } else { consume(); } - setState(191); - valueExpression(4); + setState(200); + operatorExpression(3); } break; default: throw new NoViableAltException(this); } _ctx.stop = _input.LT(-1); - setState(206); + setState(211); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,24,_ctx); + _alt = getInterpreter().adaptivePredict(_input,25,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(204); + setState(209); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,23,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,24,_ctx) ) { case 1: { - _localctx = new ArithmeticBinaryContext(new ValueExpressionContext(_parentctx, _parentState)); + _localctx = new ArithmeticBinaryContext(new OperatorExpressionContext(_parentctx, _parentState)); ((ArithmeticBinaryContext)_localctx).left = _prevctx; - pushNewRecursionContext(_localctx, _startState, RULE_valueExpression); - setState(194); - if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)"); - setState(195); + pushNewRecursionContext(_localctx, _startState, RULE_operatorExpression); + setState(203); + if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); + setState(204); ((ArithmeticBinaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ASTERISK) | (1L << SLASH) | (1L << PERCENT))) != 0)) ) { @@ -1525,18 +1598,18 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti } else { consume(); } - setState(196); - ((ArithmeticBinaryContext)_localctx).right = valueExpression(4); + setState(205); + ((ArithmeticBinaryContext)_localctx).right = operatorExpression(3); } break; case 2: { - _localctx = new ArithmeticBinaryContext(new ValueExpressionContext(_parentctx, _parentState)); + _localctx = new ArithmeticBinaryContext(new OperatorExpressionContext(_parentctx, _parentState)); ((ArithmeticBinaryContext)_localctx).left = _prevctx; - pushNewRecursionContext(_localctx, _startState, RULE_valueExpression); - setState(197); - if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); - setState(198); + pushNewRecursionContext(_localctx, _startState, RULE_operatorExpression); + setState(206); + if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); + setState(207); ((ArithmeticBinaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { @@ -1544,29 +1617,16 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti } else { consume(); } - setState(199); - ((ArithmeticBinaryContext)_localctx).right = valueExpression(3); - } - break; - case 3: - { - _localctx = new ComparisonContext(new ValueExpressionContext(_parentctx, _parentState)); - ((ComparisonContext)_localctx).left = _prevctx; - pushNewRecursionContext(_localctx, _startState, RULE_valueExpression); - setState(200); - if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(201); - comparisonOperator(); - setState(202); - ((ComparisonContext)_localctx).right = valueExpression(2); + setState(208); + ((ArithmeticBinaryContext)_localctx).right = operatorExpression(2); } break; } } } - setState(208); + setState(213); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,24,_ctx); + _alt = getInterpreter().adaptivePredict(_input,25,_ctx); } } } @@ -1618,43 +1678,43 @@ public T accept(ParseTreeVisitor visitor) { public final PredicateContext predicate() throws RecognitionException { PredicateContext _localctx = new PredicateContext(_ctx, getState()); - enterRule(_localctx, 34, RULE_predicate); + enterRule(_localctx, 36, RULE_predicate); int _la; try { enterOuterAlt(_localctx, 1); { - setState(210); + setState(215); _la = _input.LA(1); if (_la==NOT) { { - setState(209); + setState(214); match(NOT); } } - setState(212); + setState(217); ((PredicateContext)_localctx).kind = match(IN); - setState(213); + setState(218); match(LP); - setState(214); - expression(); setState(219); + expression(); + setState(224); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(215); + setState(220); match(COMMA); - setState(216); + setState(221); expression(); } } - setState(221); + setState(226); _errHandler.sync(this); _la = _input.LA(1); } - setState(222); + setState(227); match(RP); } } @@ -1761,16 +1821,16 @@ public T accept(ParseTreeVisitor visitor) { public final PrimaryExpressionContext primaryExpression() throws RecognitionException { PrimaryExpressionContext _localctx = new PrimaryExpressionContext(_ctx, getState()); - enterRule(_localctx, 36, RULE_primaryExpression); + enterRule(_localctx, 38, RULE_primaryExpression); try { - setState(231); + setState(236); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,27,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,28,_ctx) ) { case 1: _localctx = new ConstantDefaultContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(224); + setState(229); constant(); } break; @@ -1778,7 +1838,7 @@ public final PrimaryExpressionContext primaryExpression() throws RecognitionExce _localctx = new FunctionContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(225); + setState(230); functionExpression(); } break; @@ -1786,7 +1846,7 @@ public final PrimaryExpressionContext primaryExpression() throws RecognitionExce _localctx = new DereferenceContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(226); + setState(231); qualifiedName(); } break; @@ -1794,11 +1854,11 @@ public final PrimaryExpressionContext primaryExpression() throws RecognitionExce _localctx = new ParenthesizedExpressionContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(227); + setState(232); match(LP); - setState(228); + setState(233); expression(); - setState(229); + setState(234); match(RP); } break; @@ -1851,41 +1911,41 @@ public T accept(ParseTreeVisitor visitor) { public final FunctionExpressionContext functionExpression() throws RecognitionException { FunctionExpressionContext _localctx = new FunctionExpressionContext(_ctx, getState()); - enterRule(_localctx, 38, RULE_functionExpression); + enterRule(_localctx, 40, RULE_functionExpression); int _la; try { enterOuterAlt(_localctx, 1); { - setState(233); + setState(238); ((FunctionExpressionContext)_localctx).name = match(IDENTIFIER); - setState(234); + setState(239); match(LP); - setState(243); + setState(248); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << FALSE) | (1L << NOT) | (1L << NULL) | (1L << TRUE) | (1L << PLUS) | (1L << MINUS) | (1L << LP) | (1L << ESCAPED_IDENTIFIER) | (1L << STRING) | (1L << INTEGER_VALUE) | (1L << DECIMAL_VALUE) | (1L << IDENTIFIER))) != 0)) { { - setState(235); - expression(); setState(240); + expression(); + setState(245); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(236); + setState(241); match(COMMA); - setState(237); + setState(242); expression(); } } - setState(242); + setState(247); _errHandler.sync(this); _la = _input.LA(1); } } } - setState(245); + setState(250); match(RP); } } @@ -1988,15 +2048,15 @@ public T accept(ParseTreeVisitor visitor) { public final ConstantContext constant() throws RecognitionException { ConstantContext _localctx = new ConstantContext(_ctx, getState()); - enterRule(_localctx, 40, RULE_constant); + enterRule(_localctx, 42, RULE_constant); try { - setState(251); + setState(256); switch (_input.LA(1)) { case NULL: _localctx = new NullLiteralContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(247); + setState(252); match(NULL); } break; @@ -2005,7 +2065,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new NumericLiteralContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(248); + setState(253); number(); } break; @@ -2014,7 +2074,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new BooleanLiteralContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(249); + setState(254); booleanValue(); } break; @@ -2022,7 +2082,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new StringLiteralContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(250); + setState(255); string(); } break; @@ -2069,12 +2129,12 @@ public T accept(ParseTreeVisitor visitor) { public final ComparisonOperatorContext comparisonOperator() throws RecognitionException { ComparisonOperatorContext _localctx = new ComparisonOperatorContext(_ctx, getState()); - enterRule(_localctx, 42, RULE_comparisonOperator); + enterRule(_localctx, 44, RULE_comparisonOperator); int _la; try { enterOuterAlt(_localctx, 1); { - setState(253); + setState(258); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << EQ) | (1L << NEQ) | (1L << LT) | (1L << LTE) | (1L << GT) | (1L << GTE))) != 0)) ) { _errHandler.recoverInline(this); @@ -2118,12 +2178,12 @@ public T accept(ParseTreeVisitor visitor) { public final BooleanValueContext booleanValue() throws RecognitionException { BooleanValueContext _localctx = new BooleanValueContext(_ctx, getState()); - enterRule(_localctx, 44, RULE_booleanValue); + enterRule(_localctx, 46, RULE_booleanValue); int _la; try { enterOuterAlt(_localctx, 1); { - setState(255); + setState(260); _la = _input.LA(1); if ( !(_la==FALSE || _la==TRUE) ) { _errHandler.recoverInline(this); @@ -2187,49 +2247,49 @@ public T accept(ParseTreeVisitor visitor) { public final QualifiedNameContext qualifiedName() throws RecognitionException { QualifiedNameContext _localctx = new QualifiedNameContext(_ctx, getState()); - enterRule(_localctx, 46, RULE_qualifiedName); + enterRule(_localctx, 48, RULE_qualifiedName); int _la; try { int _alt; enterOuterAlt(_localctx, 1); { - setState(257); + setState(262); identifier(); - setState(269); + setState(274); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,33,_ctx); + _alt = getInterpreter().adaptivePredict(_input,34,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { - setState(267); + setState(272); switch (_input.LA(1)) { case DOT: { - setState(258); + setState(263); match(DOT); - setState(259); + setState(264); identifier(); } break; case LB: { - setState(260); + setState(265); match(LB); - setState(262); + setState(267); _errHandler.sync(this); _la = _input.LA(1); do { { { - setState(261); + setState(266); match(INTEGER_VALUE); } } - setState(264); + setState(269); _errHandler.sync(this); _la = _input.LA(1); } while ( _la==INTEGER_VALUE ); - setState(266); + setState(271); match(RB); } break; @@ -2238,9 +2298,9 @@ public final QualifiedNameContext qualifiedName() throws RecognitionException { } } } - setState(271); + setState(276); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,33,_ctx); + _alt = getInterpreter().adaptivePredict(_input,34,_ctx); } } } @@ -2279,12 +2339,12 @@ public T accept(ParseTreeVisitor visitor) { public final IdentifierContext identifier() throws RecognitionException { IdentifierContext _localctx = new IdentifierContext(_ctx, getState()); - enterRule(_localctx, 48, RULE_identifier); + enterRule(_localctx, 50, RULE_identifier); int _la; try { enterOuterAlt(_localctx, 1); { - setState(272); + setState(277); _la = _input.LA(1); if ( !(_la==ESCAPED_IDENTIFIER || _la==IDENTIFIER) ) { _errHandler.recoverInline(this); @@ -2331,18 +2391,18 @@ public T accept(ParseTreeVisitor visitor) { public final TimeUnitContext timeUnit() throws RecognitionException { TimeUnitContext _localctx = new TimeUnitContext(_ctx, getState()); - enterRule(_localctx, 50, RULE_timeUnit); + enterRule(_localctx, 52, RULE_timeUnit); int _la; try { enterOuterAlt(_localctx, 1); { - setState(274); + setState(279); number(); - setState(276); + setState(281); _la = _input.LA(1); if (_la==IDENTIFIER) { { - setState(275); + setState(280); ((TimeUnitContext)_localctx).unit = match(IDENTIFIER); } } @@ -2408,15 +2468,15 @@ public T accept(ParseTreeVisitor visitor) { public final NumberContext number() throws RecognitionException { NumberContext _localctx = new NumberContext(_ctx, getState()); - enterRule(_localctx, 52, RULE_number); + enterRule(_localctx, 54, RULE_number); try { - setState(280); + setState(285); switch (_input.LA(1)) { case DECIMAL_VALUE: _localctx = new DecimalLiteralContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(278); + setState(283); match(DECIMAL_VALUE); } break; @@ -2424,7 +2484,7 @@ public final NumberContext number() throws RecognitionException { _localctx = new IntegerLiteralContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(279); + setState(284); match(INTEGER_VALUE); } break; @@ -2466,11 +2526,11 @@ public T accept(ParseTreeVisitor visitor) { public final StringContext string() throws RecognitionException { StringContext _localctx = new StringContext(_ctx, getState()); - enterRule(_localctx, 54, RULE_string); + enterRule(_localctx, 56, RULE_string); try { enterOuterAlt(_localctx, 1); { - setState(282); + setState(287); match(STRING); } } @@ -2489,8 +2549,8 @@ public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { switch (ruleIndex) { case 15: return booleanExpression_sempred((BooleanExpressionContext)_localctx, predIndex); - case 16: - return valueExpression_sempred((ValueExpressionContext)_localctx, predIndex); + case 17: + return operatorExpression_sempred((OperatorExpressionContext)_localctx, predIndex); } return true; } @@ -2503,117 +2563,117 @@ private boolean booleanExpression_sempred(BooleanExpressionContext _localctx, in } return true; } - private boolean valueExpression_sempred(ValueExpressionContext _localctx, int predIndex) { + private boolean operatorExpression_sempred(OperatorExpressionContext _localctx, int predIndex) { switch (predIndex) { case 2: - return precpred(_ctx, 3); - case 3: return precpred(_ctx, 2); - case 4: + case 3: return precpred(_ctx, 1); } return true; } public static final String _serializedATN = - "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3-\u011f\4\2\t\2\4"+ + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3-\u0124\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"+ - "\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\3\2\3\2\3\2\3\3\3\3\3\3\3\4\3"+ - "\4\7\4C\n\4\f\4\16\4F\13\4\3\5\3\5\3\5\5\5K\n\5\3\6\3\6\3\6\3\6\3\6\3"+ - "\7\3\7\3\7\5\7U\n\7\3\7\3\7\5\7Y\n\7\5\7[\n\7\3\7\3\7\6\7_\n\7\r\7\16"+ - "\7`\3\7\3\7\5\7e\n\7\3\b\3\b\5\bi\n\b\3\b\3\b\6\bm\n\b\r\b\16\bn\3\b\3"+ - "\b\5\bs\n\b\3\t\3\t\3\t\3\t\3\t\7\tz\n\t\f\t\16\t}\13\t\5\t\177\n\t\3"+ - "\n\3\n\3\n\3\n\7\n\u0085\n\n\f\n\16\n\u0088\13\n\3\13\3\13\5\13\u008c"+ - "\n\13\3\f\3\f\3\f\3\f\5\f\u0092\n\f\5\f\u0094\n\f\3\f\5\f\u0097\n\f\3"+ - "\r\3\r\3\r\3\r\3\16\3\16\3\17\3\17\5\17\u00a1\n\17\3\17\3\17\3\17\3\20"+ - "\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21\5\21\u00af\n\21\3\21\3\21\3\21"+ - "\3\21\3\21\3\21\7\21\u00b7\n\21\f\21\16\21\u00ba\13\21\3\22\3\22\3\22"+ - "\5\22\u00bf\n\22\3\22\3\22\5\22\u00c3\n\22\3\22\3\22\3\22\3\22\3\22\3"+ - "\22\3\22\3\22\3\22\3\22\7\22\u00cf\n\22\f\22\16\22\u00d2\13\22\3\23\5"+ - "\23\u00d5\n\23\3\23\3\23\3\23\3\23\3\23\7\23\u00dc\n\23\f\23\16\23\u00df"+ - "\13\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\24\5\24\u00ea\n\24\3"+ - "\25\3\25\3\25\3\25\3\25\7\25\u00f1\n\25\f\25\16\25\u00f4\13\25\5\25\u00f6"+ - "\n\25\3\25\3\25\3\26\3\26\3\26\3\26\5\26\u00fe\n\26\3\27\3\27\3\30\3\30"+ - "\3\31\3\31\3\31\3\31\3\31\6\31\u0109\n\31\r\31\16\31\u010a\3\31\7\31\u010e"+ - "\n\31\f\31\16\31\u0111\13\31\3\32\3\32\3\33\3\33\5\33\u0117\n\33\3\34"+ - "\3\34\5\34\u011b\n\34\3\35\3\35\3\35\2\4 \"\36\2\4\6\b\n\f\16\20\22\24"+ - "\26\30\32\34\36 \"$&(*,.\60\62\64\668\2\7\3\2\32\33\3\2\34\36\3\2\24\31"+ - "\4\2\6\6\20\20\4\2&&**\u012e\2:\3\2\2\2\4=\3\2\2\2\6@\3\2\2\2\bJ\3\2\2"+ - "\2\nL\3\2\2\2\fQ\3\2\2\2\16f\3\2\2\2\20t\3\2\2\2\22\u0080\3\2\2\2\24\u0089"+ - "\3\2\2\2\26\u008d\3\2\2\2\30\u0098\3\2\2\2\32\u009c\3\2\2\2\34\u00a0\3"+ - "\2\2\2\36\u00a5\3\2\2\2 \u00ae\3\2\2\2\"\u00c2\3\2\2\2$\u00d4\3\2\2\2"+ - "&\u00e9\3\2\2\2(\u00eb\3\2\2\2*\u00fd\3\2\2\2,\u00ff\3\2\2\2.\u0101\3"+ - "\2\2\2\60\u0103\3\2\2\2\62\u0112\3\2\2\2\64\u0114\3\2\2\2\66\u011a\3\2"+ - "\2\28\u011c\3\2\2\2:;\5\6\4\2;<\7\2\2\3<\3\3\2\2\2=>\5\36\20\2>?\7\2\2"+ - "\3?\5\3\2\2\2@D\5\b\5\2AC\5\20\t\2BA\3\2\2\2CF\3\2\2\2DB\3\2\2\2DE\3\2"+ - "\2\2E\7\3\2\2\2FD\3\2\2\2GK\5\f\7\2HK\5\16\b\2IK\5\32\16\2JG\3\2\2\2J"+ - "H\3\2\2\2JI\3\2\2\2K\t\3\2\2\2LM\7\23\2\2MN\7\n\2\2NO\7\24\2\2OP\5\64"+ - "\33\2P\13\3\2\2\2QZ\7\17\2\2RT\5\22\n\2SU\5\n\6\2TS\3\2\2\2TU\3\2\2\2"+ - "U[\3\2\2\2VX\5\n\6\2WY\5\22\n\2XW\3\2\2\2XY\3\2\2\2Y[\3\2\2\2ZR\3\2\2"+ - "\2ZV\3\2\2\2Z[\3\2\2\2[\\\3\2\2\2\\^\5\26\f\2]_\5\26\f\2^]\3\2\2\2_`\3"+ - "\2\2\2`^\3\2\2\2`a\3\2\2\2ad\3\2\2\2bc\7\21\2\2ce\5\26\f\2db\3\2\2\2d"+ - "e\3\2\2\2e\r\3\2\2\2fh\7\t\2\2gi\5\22\n\2hg\3\2\2\2hi\3\2\2\2ij\3\2\2"+ - "\2jl\5\24\13\2km\5\24\13\2lk\3\2\2\2mn\3\2\2\2nl\3\2\2\2no\3\2\2\2or\3"+ - "\2\2\2pq\7\21\2\2qs\5\24\13\2rp\3\2\2\2rs\3\2\2\2s\17\3\2\2\2tu\7%\2\2"+ - "u~\7*\2\2v{\5 \21\2wx\7 \2\2xz\5 \21\2yw\3\2\2\2z}\3\2\2\2{y\3\2\2\2{"+ - "|\3\2\2\2|\177\3\2\2\2}{\3\2\2\2~v\3\2\2\2~\177\3\2\2\2\177\21\3\2\2\2"+ - "\u0080\u0081\7\5\2\2\u0081\u0086\5\36\20\2\u0082\u0083\7 \2\2\u0083\u0085"+ - "\5\36\20\2\u0084\u0082\3\2\2\2\u0085\u0088\3\2\2\2\u0086\u0084\3\2\2\2"+ - "\u0086\u0087\3\2\2\2\u0087\23\3\2\2\2\u0088\u0086\3\2\2\2\u0089\u008b"+ - "\5\30\r\2\u008a\u008c\5\22\n\2\u008b\u008a\3\2\2\2\u008b\u008c\3\2\2\2"+ - "\u008c\25\3\2\2\2\u008d\u0093\5\30\r\2\u008e\u0091\7\7\2\2\u008f\u0090"+ - "\7\24\2\2\u0090\u0092\5.\30\2\u0091\u008f\3\2\2\2\u0091\u0092\3\2\2\2"+ - "\u0092\u0094\3\2\2\2\u0093\u008e\3\2\2\2\u0093\u0094\3\2\2\2\u0094\u0096"+ - "\3\2\2\2\u0095\u0097\5\22\n\2\u0096\u0095\3\2\2\2\u0096\u0097\3\2\2\2"+ - "\u0097\27\3\2\2\2\u0098\u0099\7!\2\2\u0099\u009a\5\34\17\2\u009a\u009b"+ - "\7\"\2\2\u009b\31\3\2\2\2\u009c\u009d\5\34\17\2\u009d\33\3\2\2\2\u009e"+ - "\u00a1\7\4\2\2\u009f\u00a1\5\62\32\2\u00a0\u009e\3\2\2\2\u00a0\u009f\3"+ - "\2\2\2\u00a1\u00a2\3\2\2\2\u00a2\u00a3\7\22\2\2\u00a3\u00a4\5\36\20\2"+ - "\u00a4\35\3\2\2\2\u00a5\u00a6\5 \21\2\u00a6\37\3\2\2\2\u00a7\u00a8\b\21"+ - "\1\2\u00a8\u00a9\7\13\2\2\u00a9\u00af\5 \21\7\u00aa\u00ab\7*\2\2\u00ab"+ - "\u00ac\7\r\2\2\u00ac\u00af\5\30\r\2\u00ad\u00af\5\"\22\2\u00ae\u00a7\3"+ - "\2\2\2\u00ae\u00aa\3\2\2\2\u00ae\u00ad\3\2\2\2\u00af\u00b8\3\2\2\2\u00b0"+ - "\u00b1\f\4\2\2\u00b1\u00b2\7\3\2\2\u00b2\u00b7\5 \21\5\u00b3\u00b4\f\3"+ - "\2\2\u00b4\u00b5\7\16\2\2\u00b5\u00b7\5 \21\4\u00b6\u00b0\3\2\2\2\u00b6"+ - "\u00b3\3\2\2\2\u00b7\u00ba\3\2\2\2\u00b8\u00b6\3\2\2\2\u00b8\u00b9\3\2"+ - "\2\2\u00b9!\3\2\2\2\u00ba\u00b8\3\2\2\2\u00bb\u00bc\b\22\1\2\u00bc\u00be"+ - "\5&\24\2\u00bd\u00bf\5$\23\2\u00be\u00bd\3\2\2\2\u00be\u00bf\3\2\2\2\u00bf"+ - "\u00c3\3\2\2\2\u00c0\u00c1\t\2\2\2\u00c1\u00c3\5\"\22\6\u00c2\u00bb\3"+ - "\2\2\2\u00c2\u00c0\3\2\2\2\u00c3\u00d0\3\2\2\2\u00c4\u00c5\f\5\2\2\u00c5"+ - "\u00c6\t\3\2\2\u00c6\u00cf\5\"\22\6\u00c7\u00c8\f\4\2\2\u00c8\u00c9\t"+ - "\2\2\2\u00c9\u00cf\5\"\22\5\u00ca\u00cb\f\3\2\2\u00cb\u00cc\5,\27\2\u00cc"+ - "\u00cd\5\"\22\4\u00cd\u00cf\3\2\2\2\u00ce\u00c4\3\2\2\2\u00ce\u00c7\3"+ - "\2\2\2\u00ce\u00ca\3\2\2\2\u00cf\u00d2\3\2\2\2\u00d0\u00ce\3\2\2\2\u00d0"+ - "\u00d1\3\2\2\2\u00d1#\3\2\2\2\u00d2\u00d0\3\2\2\2\u00d3\u00d5\7\13\2\2"+ - "\u00d4\u00d3\3\2\2\2\u00d4\u00d5\3\2\2\2\u00d5\u00d6\3\2\2\2\u00d6\u00d7"+ - "\7\b\2\2\u00d7\u00d8\7#\2\2\u00d8\u00dd\5\36\20\2\u00d9\u00da\7 \2\2\u00da"+ - "\u00dc\5\36\20\2\u00db\u00d9\3\2\2\2\u00dc\u00df\3\2\2\2\u00dd\u00db\3"+ - "\2\2\2\u00dd\u00de\3\2\2\2\u00de\u00e0\3\2\2\2\u00df\u00dd\3\2\2\2\u00e0"+ - "\u00e1\7$\2\2\u00e1%\3\2\2\2\u00e2\u00ea\5*\26\2\u00e3\u00ea\5(\25\2\u00e4"+ - "\u00ea\5\60\31\2\u00e5\u00e6\7#\2\2\u00e6\u00e7\5\36\20\2\u00e7\u00e8"+ - "\7$\2\2\u00e8\u00ea\3\2\2\2\u00e9\u00e2\3\2\2\2\u00e9\u00e3\3\2\2\2\u00e9"+ - "\u00e4\3\2\2\2\u00e9\u00e5\3\2\2\2\u00ea\'\3\2\2\2\u00eb\u00ec\7*\2\2"+ - "\u00ec\u00f5\7#\2\2\u00ed\u00f2\5\36\20\2\u00ee\u00ef\7 \2\2\u00ef\u00f1"+ - "\5\36\20\2\u00f0\u00ee\3\2\2\2\u00f1\u00f4\3\2\2\2\u00f2\u00f0\3\2\2\2"+ - "\u00f2\u00f3\3\2\2\2\u00f3\u00f6\3\2\2\2\u00f4\u00f2\3\2\2\2\u00f5\u00ed"+ - "\3\2\2\2\u00f5\u00f6\3\2\2\2\u00f6\u00f7\3\2\2\2\u00f7\u00f8\7$\2\2\u00f8"+ - ")\3\2\2\2\u00f9\u00fe\7\f\2\2\u00fa\u00fe\5\66\34\2\u00fb\u00fe\5.\30"+ - "\2\u00fc\u00fe\58\35\2\u00fd\u00f9\3\2\2\2\u00fd\u00fa\3\2\2\2\u00fd\u00fb"+ - "\3\2\2\2\u00fd\u00fc\3\2\2\2\u00fe+\3\2\2\2\u00ff\u0100\t\4\2\2\u0100"+ - "-\3\2\2\2\u0101\u0102\t\5\2\2\u0102/\3\2\2\2\u0103\u010f\5\62\32\2\u0104"+ - "\u0105\7\37\2\2\u0105\u010e\5\62\32\2\u0106\u0108\7!\2\2\u0107\u0109\7"+ - "(\2\2\u0108\u0107\3\2\2\2\u0109\u010a\3\2\2\2\u010a\u0108\3\2\2\2\u010a"+ - "\u010b\3\2\2\2\u010b\u010c\3\2\2\2\u010c\u010e\7\"\2\2\u010d\u0104\3\2"+ - "\2\2\u010d\u0106\3\2\2\2\u010e\u0111\3\2\2\2\u010f\u010d\3\2\2\2\u010f"+ - "\u0110\3\2\2\2\u0110\61\3\2\2\2\u0111\u010f\3\2\2\2\u0112\u0113\t\6\2"+ - "\2\u0113\63\3\2\2\2\u0114\u0116\5\66\34\2\u0115\u0117\7*\2\2\u0116\u0115"+ - "\3\2\2\2\u0116\u0117\3\2\2\2\u0117\65\3\2\2\2\u0118\u011b\7)\2\2\u0119"+ - "\u011b\7(\2\2\u011a\u0118\3\2\2\2\u011a\u0119\3\2\2\2\u011b\67\3\2\2\2"+ - "\u011c\u011d\7\'\2\2\u011d9\3\2\2\2&DJTXZ`dhnr{~\u0086\u008b\u0091\u0093"+ - "\u0096\u00a0\u00ae\u00b6\u00b8\u00be\u00c2\u00ce\u00d0\u00d4\u00dd\u00e9"+ - "\u00f2\u00f5\u00fd\u010a\u010d\u010f\u0116\u011a"; + "\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\3\2\3\2\3\2\3\3\3\3"+ + "\3\3\3\4\3\4\7\4E\n\4\f\4\16\4H\13\4\3\5\3\5\3\5\5\5M\n\5\3\6\3\6\3\6"+ + "\3\6\3\6\3\7\3\7\3\7\5\7W\n\7\3\7\3\7\5\7[\n\7\5\7]\n\7\3\7\3\7\6\7a\n"+ + "\7\r\7\16\7b\3\7\3\7\5\7g\n\7\3\b\3\b\5\bk\n\b\3\b\3\b\6\bo\n\b\r\b\16"+ + "\bp\3\b\3\b\5\bu\n\b\3\t\3\t\3\t\3\t\3\t\7\t|\n\t\f\t\16\t\177\13\t\5"+ + "\t\u0081\n\t\3\n\3\n\3\n\3\n\7\n\u0087\n\n\f\n\16\n\u008a\13\n\3\13\3"+ + "\13\5\13\u008e\n\13\3\f\3\f\3\f\3\f\5\f\u0094\n\f\5\f\u0096\n\f\3\f\5"+ + "\f\u0099\n\f\3\r\3\r\3\r\3\r\3\16\3\16\3\17\3\17\5\17\u00a3\n\17\3\17"+ + "\3\17\3\17\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21\5\21\u00b1\n\21"+ + "\3\21\3\21\3\21\3\21\3\21\3\21\7\21\u00b9\n\21\f\21\16\21\u00bc\13\21"+ + "\3\22\3\22\3\22\3\22\3\22\5\22\u00c3\n\22\3\23\3\23\3\23\5\23\u00c8\n"+ + "\23\3\23\3\23\5\23\u00cc\n\23\3\23\3\23\3\23\3\23\3\23\3\23\7\23\u00d4"+ + "\n\23\f\23\16\23\u00d7\13\23\3\24\5\24\u00da\n\24\3\24\3\24\3\24\3\24"+ + "\3\24\7\24\u00e1\n\24\f\24\16\24\u00e4\13\24\3\24\3\24\3\25\3\25\3\25"+ + "\3\25\3\25\3\25\3\25\5\25\u00ef\n\25\3\26\3\26\3\26\3\26\3\26\7\26\u00f6"+ + "\n\26\f\26\16\26\u00f9\13\26\5\26\u00fb\n\26\3\26\3\26\3\27\3\27\3\27"+ + "\3\27\5\27\u0103\n\27\3\30\3\30\3\31\3\31\3\32\3\32\3\32\3\32\3\32\6\32"+ + "\u010e\n\32\r\32\16\32\u010f\3\32\7\32\u0113\n\32\f\32\16\32\u0116\13"+ + "\32\3\33\3\33\3\34\3\34\5\34\u011c\n\34\3\35\3\35\5\35\u0120\n\35\3\36"+ + "\3\36\3\36\2\4 $\37\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60"+ + "\62\64\668:\2\7\3\2\32\33\3\2\34\36\3\2\24\31\4\2\6\6\20\20\4\2&&**\u0132"+ + "\2<\3\2\2\2\4?\3\2\2\2\6B\3\2\2\2\bL\3\2\2\2\nN\3\2\2\2\fS\3\2\2\2\16"+ + "h\3\2\2\2\20v\3\2\2\2\22\u0082\3\2\2\2\24\u008b\3\2\2\2\26\u008f\3\2\2"+ + "\2\30\u009a\3\2\2\2\32\u009e\3\2\2\2\34\u00a2\3\2\2\2\36\u00a7\3\2\2\2"+ + " \u00b0\3\2\2\2\"\u00c2\3\2\2\2$\u00cb\3\2\2\2&\u00d9\3\2\2\2(\u00ee\3"+ + "\2\2\2*\u00f0\3\2\2\2,\u0102\3\2\2\2.\u0104\3\2\2\2\60\u0106\3\2\2\2\62"+ + "\u0108\3\2\2\2\64\u0117\3\2\2\2\66\u0119\3\2\2\28\u011f\3\2\2\2:\u0121"+ + "\3\2\2\2<=\5\6\4\2=>\7\2\2\3>\3\3\2\2\2?@\5\36\20\2@A\7\2\2\3A\5\3\2\2"+ + "\2BF\5\b\5\2CE\5\20\t\2DC\3\2\2\2EH\3\2\2\2FD\3\2\2\2FG\3\2\2\2G\7\3\2"+ + "\2\2HF\3\2\2\2IM\5\f\7\2JM\5\16\b\2KM\5\32\16\2LI\3\2\2\2LJ\3\2\2\2LK"+ + "\3\2\2\2M\t\3\2\2\2NO\7\23\2\2OP\7\n\2\2PQ\7\24\2\2QR\5\66\34\2R\13\3"+ + "\2\2\2S\\\7\17\2\2TV\5\22\n\2UW\5\n\6\2VU\3\2\2\2VW\3\2\2\2W]\3\2\2\2"+ + "XZ\5\n\6\2Y[\5\22\n\2ZY\3\2\2\2Z[\3\2\2\2[]\3\2\2\2\\T\3\2\2\2\\X\3\2"+ + "\2\2\\]\3\2\2\2]^\3\2\2\2^`\5\26\f\2_a\5\26\f\2`_\3\2\2\2ab\3\2\2\2b`"+ + "\3\2\2\2bc\3\2\2\2cf\3\2\2\2de\7\21\2\2eg\5\26\f\2fd\3\2\2\2fg\3\2\2\2"+ + "g\r\3\2\2\2hj\7\t\2\2ik\5\22\n\2ji\3\2\2\2jk\3\2\2\2kl\3\2\2\2ln\5\24"+ + "\13\2mo\5\24\13\2nm\3\2\2\2op\3\2\2\2pn\3\2\2\2pq\3\2\2\2qt\3\2\2\2rs"+ + "\7\21\2\2su\5\24\13\2tr\3\2\2\2tu\3\2\2\2u\17\3\2\2\2vw\7%\2\2w\u0080"+ + "\7*\2\2x}\5 \21\2yz\7 \2\2z|\5 \21\2{y\3\2\2\2|\177\3\2\2\2}{\3\2\2\2"+ + "}~\3\2\2\2~\u0081\3\2\2\2\177}\3\2\2\2\u0080x\3\2\2\2\u0080\u0081\3\2"+ + "\2\2\u0081\21\3\2\2\2\u0082\u0083\7\5\2\2\u0083\u0088\5\36\20\2\u0084"+ + "\u0085\7 \2\2\u0085\u0087\5\36\20\2\u0086\u0084\3\2\2\2\u0087\u008a\3"+ + "\2\2\2\u0088\u0086\3\2\2\2\u0088\u0089\3\2\2\2\u0089\23\3\2\2\2\u008a"+ + "\u0088\3\2\2\2\u008b\u008d\5\30\r\2\u008c\u008e\5\22\n\2\u008d\u008c\3"+ + "\2\2\2\u008d\u008e\3\2\2\2\u008e\25\3\2\2\2\u008f\u0095\5\30\r\2\u0090"+ + "\u0093\7\7\2\2\u0091\u0092\7\24\2\2\u0092\u0094\5\60\31\2\u0093\u0091"+ + "\3\2\2\2\u0093\u0094\3\2\2\2\u0094\u0096\3\2\2\2\u0095\u0090\3\2\2\2\u0095"+ + "\u0096\3\2\2\2\u0096\u0098\3\2\2\2\u0097\u0099\5\22\n\2\u0098\u0097\3"+ + "\2\2\2\u0098\u0099\3\2\2\2\u0099\27\3\2\2\2\u009a\u009b\7!\2\2\u009b\u009c"+ + "\5\34\17\2\u009c\u009d\7\"\2\2\u009d\31\3\2\2\2\u009e\u009f\5\34\17\2"+ + "\u009f\33\3\2\2\2\u00a0\u00a3\7\4\2\2\u00a1\u00a3\5\64\33\2\u00a2\u00a0"+ + "\3\2\2\2\u00a2\u00a1\3\2\2\2\u00a3\u00a4\3\2\2\2\u00a4\u00a5\7\22\2\2"+ + "\u00a5\u00a6\5\36\20\2\u00a6\35\3\2\2\2\u00a7\u00a8\5 \21\2\u00a8\37\3"+ + "\2\2\2\u00a9\u00aa\b\21\1\2\u00aa\u00ab\7\13\2\2\u00ab\u00b1\5 \21\7\u00ac"+ + "\u00ad\7*\2\2\u00ad\u00ae\7\r\2\2\u00ae\u00b1\5\30\r\2\u00af\u00b1\5\""+ + "\22\2\u00b0\u00a9\3\2\2\2\u00b0\u00ac\3\2\2\2\u00b0\u00af\3\2\2\2\u00b1"+ + "\u00ba\3\2\2\2\u00b2\u00b3\f\4\2\2\u00b3\u00b4\7\3\2\2\u00b4\u00b9\5 "+ + "\21\5\u00b5\u00b6\f\3\2\2\u00b6\u00b7\7\16\2\2\u00b7\u00b9\5 \21\4\u00b8"+ + "\u00b2\3\2\2\2\u00b8\u00b5\3\2\2\2\u00b9\u00bc\3\2\2\2\u00ba\u00b8\3\2"+ + "\2\2\u00ba\u00bb\3\2\2\2\u00bb!\3\2\2\2\u00bc\u00ba\3\2\2\2\u00bd\u00c3"+ + "\5$\23\2\u00be\u00bf\5$\23\2\u00bf\u00c0\5.\30\2\u00c0\u00c1\5$\23\2\u00c1"+ + "\u00c3\3\2\2\2\u00c2\u00bd\3\2\2\2\u00c2\u00be\3\2\2\2\u00c3#\3\2\2\2"+ + "\u00c4\u00c5\b\23\1\2\u00c5\u00c7\5(\25\2\u00c6\u00c8\5&\24\2\u00c7\u00c6"+ + "\3\2\2\2\u00c7\u00c8\3\2\2\2\u00c8\u00cc\3\2\2\2\u00c9\u00ca\t\2\2\2\u00ca"+ + "\u00cc\5$\23\5\u00cb\u00c4\3\2\2\2\u00cb\u00c9\3\2\2\2\u00cc\u00d5\3\2"+ + "\2\2\u00cd\u00ce\f\4\2\2\u00ce\u00cf\t\3\2\2\u00cf\u00d4\5$\23\5\u00d0"+ + "\u00d1\f\3\2\2\u00d1\u00d2\t\2\2\2\u00d2\u00d4\5$\23\4\u00d3\u00cd\3\2"+ + "\2\2\u00d3\u00d0\3\2\2\2\u00d4\u00d7\3\2\2\2\u00d5\u00d3\3\2\2\2\u00d5"+ + "\u00d6\3\2\2\2\u00d6%\3\2\2\2\u00d7\u00d5\3\2\2\2\u00d8\u00da\7\13\2\2"+ + "\u00d9\u00d8\3\2\2\2\u00d9\u00da\3\2\2\2\u00da\u00db\3\2\2\2\u00db\u00dc"+ + "\7\b\2\2\u00dc\u00dd\7#\2\2\u00dd\u00e2\5\36\20\2\u00de\u00df\7 \2\2\u00df"+ + "\u00e1\5\36\20\2\u00e0\u00de\3\2\2\2\u00e1\u00e4\3\2\2\2\u00e2\u00e0\3"+ + "\2\2\2\u00e2\u00e3\3\2\2\2\u00e3\u00e5\3\2\2\2\u00e4\u00e2\3\2\2\2\u00e5"+ + "\u00e6\7$\2\2\u00e6\'\3\2\2\2\u00e7\u00ef\5,\27\2\u00e8\u00ef\5*\26\2"+ + "\u00e9\u00ef\5\62\32\2\u00ea\u00eb\7#\2\2\u00eb\u00ec\5\36\20\2\u00ec"+ + "\u00ed\7$\2\2\u00ed\u00ef\3\2\2\2\u00ee\u00e7\3\2\2\2\u00ee\u00e8\3\2"+ + "\2\2\u00ee\u00e9\3\2\2\2\u00ee\u00ea\3\2\2\2\u00ef)\3\2\2\2\u00f0\u00f1"+ + "\7*\2\2\u00f1\u00fa\7#\2\2\u00f2\u00f7\5\36\20\2\u00f3\u00f4\7 \2\2\u00f4"+ + "\u00f6\5\36\20\2\u00f5\u00f3\3\2\2\2\u00f6\u00f9\3\2\2\2\u00f7\u00f5\3"+ + "\2\2\2\u00f7\u00f8\3\2\2\2\u00f8\u00fb\3\2\2\2\u00f9\u00f7\3\2\2\2\u00fa"+ + "\u00f2\3\2\2\2\u00fa\u00fb\3\2\2\2\u00fb\u00fc\3\2\2\2\u00fc\u00fd\7$"+ + "\2\2\u00fd+\3\2\2\2\u00fe\u0103\7\f\2\2\u00ff\u0103\58\35\2\u0100\u0103"+ + "\5\60\31\2\u0101\u0103\5:\36\2\u0102\u00fe\3\2\2\2\u0102\u00ff\3\2\2\2"+ + "\u0102\u0100\3\2\2\2\u0102\u0101\3\2\2\2\u0103-\3\2\2\2\u0104\u0105\t"+ + "\4\2\2\u0105/\3\2\2\2\u0106\u0107\t\5\2\2\u0107\61\3\2\2\2\u0108\u0114"+ + "\5\64\33\2\u0109\u010a\7\37\2\2\u010a\u0113\5\64\33\2\u010b\u010d\7!\2"+ + "\2\u010c\u010e\7(\2\2\u010d\u010c\3\2\2\2\u010e\u010f\3\2\2\2\u010f\u010d"+ + "\3\2\2\2\u010f\u0110\3\2\2\2\u0110\u0111\3\2\2\2\u0111\u0113\7\"\2\2\u0112"+ + "\u0109\3\2\2\2\u0112\u010b\3\2\2\2\u0113\u0116\3\2\2\2\u0114\u0112\3\2"+ + "\2\2\u0114\u0115\3\2\2\2\u0115\63\3\2\2\2\u0116\u0114\3\2\2\2\u0117\u0118"+ + "\t\6\2\2\u0118\65\3\2\2\2\u0119\u011b\58\35\2\u011a\u011c\7*\2\2\u011b"+ + "\u011a\3\2\2\2\u011b\u011c\3\2\2\2\u011c\67\3\2\2\2\u011d\u0120\7)\2\2"+ + "\u011e\u0120\7(\2\2\u011f\u011d\3\2\2\2\u011f\u011e\3\2\2\2\u01209\3\2"+ + "\2\2\u0121\u0122\7\'\2\2\u0122;\3\2\2\2\'FLVZ\\bfjpt}\u0080\u0088\u008d"+ + "\u0093\u0095\u0098\u00a2\u00b0\u00b8\u00ba\u00c2\u00c7\u00cb\u00d3\u00d5"+ + "\u00d9\u00e2\u00ee\u00f7\u00fa\u0102\u010f\u0112\u0114\u011b\u011f"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseVisitor.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseVisitor.java index 485835598435..020c8c2768df 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseVisitor.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseVisitor.java @@ -142,16 +142,23 @@ interface EqlBaseVisitor extends ParseTreeVisitor { * @return the visitor result */ T visitComparison(EqlBaseParser.ComparisonContext ctx); + /** + * Visit a parse tree produced by the {@code operatorExpressionDefault} + * labeled alternative in {@link EqlBaseParser#operatorExpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitOperatorExpressionDefault(EqlBaseParser.OperatorExpressionDefaultContext ctx); /** * Visit a parse tree produced by the {@code arithmeticBinary} - * labeled alternative in {@link EqlBaseParser#valueExpression}. + * labeled alternative in {@link EqlBaseParser#operatorExpression}. * @param ctx the parse tree * @return the visitor result */ T visitArithmeticBinary(EqlBaseParser.ArithmeticBinaryContext ctx); /** * Visit a parse tree produced by the {@code arithmeticUnary} - * labeled alternative in {@link EqlBaseParser#valueExpression}. + * labeled alternative in {@link EqlBaseParser#operatorExpression}. * @param ctx the parse tree * @return the visitor result */ diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/ExpressionBuilder.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/ExpressionBuilder.java index 8e7edf62bcdd..4d82f4b77113 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/ExpressionBuilder.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/ExpressionBuilder.java @@ -17,7 +17,6 @@ import org.elasticsearch.xpack.eql.parser.EqlBaseParser.LogicalBinaryContext; import org.elasticsearch.xpack.eql.parser.EqlBaseParser.LogicalNotContext; import org.elasticsearch.xpack.eql.parser.EqlBaseParser.PredicateContext; -import org.elasticsearch.xpack.eql.parser.EqlBaseParser.ValueExpressionDefaultContext; import org.elasticsearch.xpack.ql.QlIllegalArgumentException; import org.elasticsearch.xpack.ql.expression.Attribute; import org.elasticsearch.xpack.ql.expression.Expression; @@ -85,7 +84,7 @@ public List visitJoinKeys(JoinKeysContext ctx) { @Override public Expression visitArithmeticUnary(ArithmeticUnaryContext ctx) { - Expression expr = expression(ctx.valueExpression()); + Expression expr = expression(ctx.operatorExpression()); Source source = source(ctx); int type = ctx.operator.getType(); @@ -149,7 +148,7 @@ public Expression visitComparison(ComparisonContext ctx) { } @Override - public Expression visitValueExpressionDefault(ValueExpressionDefaultContext ctx) { + public Object visitOperatorExpressionDefault(EqlBaseParser.OperatorExpressionDefaultContext ctx) { Expression expr = expression(ctx.primaryExpression()); Source source = source(ctx); diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/ExpressionTests.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/ExpressionTests.java index b69f12563be6..b6cc95ea4e2c 100644 --- a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/ExpressionTests.java +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/ExpressionTests.java @@ -15,6 +15,7 @@ import org.elasticsearch.xpack.ql.expression.predicate.logical.And; import org.elasticsearch.xpack.ql.expression.predicate.logical.Not; import org.elasticsearch.xpack.ql.expression.predicate.logical.Or; +import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Mul; import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Neg; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Equals; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.GreaterThan; @@ -96,7 +97,7 @@ public void testDoubleQuotedString() { assertEquals(expected, parsed); } - public void testSingleQuotedUnescapedStringForbidden() { + public void testSingleQuotedUnescapedStringDisallowed() { ParsingException e = expectThrows(ParsingException.class, () -> expr("?'hello world'")); assertEquals("line 1:2: Use double quotes [\"] to define string literals, not single quotes [']", e.getMessage()); @@ -221,4 +222,43 @@ public void testInEmptySet() { expectThrows(ParsingException.class, "Expected syntax error", () -> expr("name in ()")); } + + public void testComplexComparison() { + String comparison; + if (randomBoolean()) { + comparison = "1 * -2 <= -3 * 4"; + } else { + comparison = "(1 * -2) <= (-3 * 4)"; + } + + Mul left = new Mul(null, + new Literal(null, 1, DataTypes.INTEGER), + new Neg(null, new Literal(null, 2, DataTypes.INTEGER))); + Mul right = new Mul(null, + new Neg(null, new Literal(null, 3, DataTypes.INTEGER)), + new Literal(null, 4, DataTypes.INTEGER)); + + assertEquals(new LessThanOrEqual(null, left, right, UTC), expr(comparison)); + } + + public void testChainedComparisonsDisallowed() { + int noComparisions = randomIntBetween(2, 20); + String firstComparator = ""; + String secondComparator = ""; + StringBuilder sb = new StringBuilder("a "); + for (int i = 0 ; i < noComparisions; i++) { + String comparator = randomFrom("=", "==", "!=", "<", "<=", ">", ">="); + sb.append(comparator).append(" a "); + + if (i == 0) { + firstComparator = comparator; + } else if (i == 1) { + secondComparator = comparator; + } + } + ParsingException e = expectThrows(ParsingException.class, () -> expr(sb.toString())); + assertEquals("line 1:" + (6 + firstComparator.length()) + ": mismatched input '" + secondComparator + + "' expecting {, 'and', 'in', 'not', 'or', '+', '-', '*', '/', '%', '.', '['}", + e.getMessage()); + } }