Browse Source

Painless: Add } as a delimiter. Kindof.

Add `}` is statement delimiter but only in places where it is
otherwise a valid part of the syntax, specificall the end of a block.
We do this by matching but not consuming it. Antlr 4 doesn't have
syntax for this so we have to kind of hack it together by actually
matching the `}` and then seeking backwards in the token stream to
"unmatch" it. This looks reasonably efficient. Not perfect, but way
better than the alternatives.

I tried and rejected a few options:
1. Actually consuming the `}` and piping a boolean all through the
grammar from the last statement in a block to the delimiter. This
ended up being a rather large change and made the grammar way more
complicated.
2. Adding a semantic predicate to delimiter that just does the
lookahead. This doesn't work out well because it doesn't work (I
never figured out why) and because it generates an *amazing*
`adaptivePredict` which makes a super huge DFA. It looks super
inefficient.

Closes #18821
Nik Everett 9 years ago
parent
commit
4a265d0279

+ 11 - 0
modules/lang-painless/src/main/antlr/PainlessParser.g4

@@ -92,6 +92,17 @@ trap
 delimiter
     : SEMICOLON
     | EOF
+    // RBRACK is a delimiter but we don't consume it because it is only valid
+    // in places where RBRACK can follow the statement. It is simpler to not
+    // consume it here then it is to consume it here. Unfortunately, they
+    // obvious syntax to do this `| { _input.LA(1) == RBRACK }?` generates an
+    // amazingly intense `adaptivePredict` call that doesn't actually work
+    // and builds a serious DFA. Huge. So instead we use standard ANTLR syntax
+    // to consume the token and then undo the consumption. This looks hairy but
+    // it is better than the alternatives.
+    |   { int mark = _input.mark(); int index = _input.index(); }
+            RBRACK
+        { _input.seek(index); _input.release(mark); }
     ;
 
 // Note we return the boolean s.  This is returned as true

+ 351 - 331
modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/PainlessParser.java

@@ -1283,6 +1283,7 @@ class PainlessParser extends Parser {
   public static class DelimiterContext extends ParserRuleContext {
     public TerminalNode SEMICOLON() { return getToken(PainlessParser.SEMICOLON, 0); }
     public TerminalNode EOF() { return getToken(PainlessParser.EOF, 0); }
+    public TerminalNode RBRACK() { return getToken(PainlessParser.RBRACK, 0); }
     public DelimiterContext(ParserRuleContext parent, int invokingState) {
       super(parent, invokingState);
     }
@@ -1297,17 +1298,34 @@ class PainlessParser extends Parser {
   public final DelimiterContext delimiter() throws RecognitionException {
     DelimiterContext _localctx = new DelimiterContext(_ctx, getState());
     enterRule(_localctx, 26, RULE_delimiter);
-    int _la;
     try {
-      enterOuterAlt(_localctx, 1);
-      {
-      setState(217);
-      _la = _input.LA(1);
-      if ( !(_la==EOF || _la==SEMICOLON) ) {
-      _errHandler.recoverInline(this);
-      } else {
-        consume();
-      }
+      setState(222);
+      switch (_input.LA(1)) {
+      case SEMICOLON:
+        enterOuterAlt(_localctx, 1);
+        {
+        setState(217);
+        match(SEMICOLON);
+        }
+        break;
+      case EOF:
+        enterOuterAlt(_localctx, 2);
+        {
+        setState(218);
+        match(EOF);
+        }
+        break;
+      case RBRACK:
+        enterOuterAlt(_localctx, 3);
+        {
+         int mark = _input.mark(); int index = _input.index(); 
+        setState(220);
+        match(RBRACK);
+         _input.seek(index); _input.release(mark); 
+        }
+        break;
+      default:
+        throw new NoViableAltException(this);
       }
     }
     catch (RecognitionException re) {
@@ -1470,24 +1488,24 @@ class PainlessParser extends Parser {
       int _alt;
       enterOuterAlt(_localctx, 1);
       {
-      setState(228);
-      switch ( getInterpreter().adaptivePredict(_input,18,_ctx) ) {
+      setState(233);
+      switch ( getInterpreter().adaptivePredict(_input,19,_ctx) ) {
       case 1:
         {
         _localctx = new AssignmentContext(_localctx);
         _ctx = _localctx;
         _prevctx = _localctx;
 
-        setState(220);
+        setState(225);
         chain(true);
-        setState(221);
+        setState(226);
         _la = _input.LA(1);
         if ( !(((((_la - 53)) & ~0x3f) == 0 && ((1L << (_la - 53)) & ((1L << (ASSIGN - 53)) | (1L << (AADD - 53)) | (1L << (ASUB - 53)) | (1L << (AMUL - 53)) | (1L << (ADIV - 53)) | (1L << (AREM - 53)) | (1L << (AAND - 53)) | (1L << (AXOR - 53)) | (1L << (AOR - 53)) | (1L << (ALSH - 53)) | (1L << (ARSH - 53)) | (1L << (AUSH - 53)))) != 0)) ) {
         _errHandler.recoverInline(this);
         } else {
           consume();
         }
-        setState(222);
+        setState(227);
         expression(1);
          ((AssignmentContext)_localctx).s =  false; 
         }
@@ -1497,37 +1515,37 @@ class PainlessParser extends Parser {
         _localctx = new SingleContext(_localctx);
         _ctx = _localctx;
         _prevctx = _localctx;
-        setState(225);
+        setState(230);
         ((SingleContext)_localctx).u = unary(false);
          ((SingleContext)_localctx).s =  ((SingleContext)_localctx).u.s; 
         }
         break;
       }
       _ctx.stop = _input.LT(-1);
-      setState(289);
+      setState(294);
       _errHandler.sync(this);
-      _alt = getInterpreter().adaptivePredict(_input,20,_ctx);
+      _alt = getInterpreter().adaptivePredict(_input,21,_ctx);
       while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
         if ( _alt==1 ) {
           if ( _parseListeners!=null ) triggerExitRuleEvent();
           _prevctx = _localctx;
           {
-          setState(287);
-          switch ( getInterpreter().adaptivePredict(_input,19,_ctx) ) {
+          setState(292);
+          switch ( getInterpreter().adaptivePredict(_input,20,_ctx) ) {
           case 1:
             {
             _localctx = new BinaryContext(new ExpressionContext(_parentctx, _parentState));
             pushNewRecursionContext(_localctx, _startState, RULE_expression);
-            setState(230);
+            setState(235);
             if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)");
-            setState(231);
+            setState(236);
             _la = _input.LA(1);
             if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << MUL) | (1L << DIV) | (1L << REM))) != 0)) ) {
             _errHandler.recoverInline(this);
             } else {
               consume();
             }
-            setState(232);
+            setState(237);
             expression(13);
              ((BinaryContext)_localctx).s =  false; 
             }
@@ -1536,16 +1554,16 @@ class PainlessParser extends Parser {
             {
             _localctx = new BinaryContext(new ExpressionContext(_parentctx, _parentState));
             pushNewRecursionContext(_localctx, _startState, RULE_expression);
-            setState(235);
+            setState(240);
             if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)");
-            setState(236);
+            setState(241);
             _la = _input.LA(1);
             if ( !(_la==ADD || _la==SUB) ) {
             _errHandler.recoverInline(this);
             } else {
               consume();
             }
-            setState(237);
+            setState(242);
             expression(12);
              ((BinaryContext)_localctx).s =  false; 
             }
@@ -1554,16 +1572,16 @@ class PainlessParser extends Parser {
             {
             _localctx = new BinaryContext(new ExpressionContext(_parentctx, _parentState));
             pushNewRecursionContext(_localctx, _startState, RULE_expression);
-            setState(240);
+            setState(245);
             if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)");
-            setState(241);
+            setState(246);
             _la = _input.LA(1);
             if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << LSH) | (1L << RSH) | (1L << USH))) != 0)) ) {
             _errHandler.recoverInline(this);
             } else {
               consume();
             }
-            setState(242);
+            setState(247);
             expression(11);
              ((BinaryContext)_localctx).s =  false; 
             }
@@ -1572,16 +1590,16 @@ class PainlessParser extends Parser {
             {
             _localctx = new CompContext(new ExpressionContext(_parentctx, _parentState));
             pushNewRecursionContext(_localctx, _startState, RULE_expression);
-            setState(245);
+            setState(250);
             if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
-            setState(246);
+            setState(251);
             _la = _input.LA(1);
             if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << LT) | (1L << LTE) | (1L << GT) | (1L << GTE))) != 0)) ) {
             _errHandler.recoverInline(this);
             } else {
               consume();
             }
-            setState(247);
+            setState(252);
             expression(10);
              ((CompContext)_localctx).s =  false; 
             }
@@ -1590,16 +1608,16 @@ class PainlessParser extends Parser {
             {
             _localctx = new CompContext(new ExpressionContext(_parentctx, _parentState));
             pushNewRecursionContext(_localctx, _startState, RULE_expression);
-            setState(250);
+            setState(255);
             if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)");
-            setState(251);
+            setState(256);
             _la = _input.LA(1);
             if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << EQ) | (1L << EQR) | (1L << NE) | (1L << NER))) != 0)) ) {
             _errHandler.recoverInline(this);
             } else {
               consume();
             }
-            setState(252);
+            setState(257);
             expression(9);
              ((CompContext)_localctx).s =  false; 
             }
@@ -1608,11 +1626,11 @@ class PainlessParser extends Parser {
             {
             _localctx = new BinaryContext(new ExpressionContext(_parentctx, _parentState));
             pushNewRecursionContext(_localctx, _startState, RULE_expression);
-            setState(255);
+            setState(260);
             if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
-            setState(256);
+            setState(261);
             match(BWAND);
-            setState(257);
+            setState(262);
             expression(8);
              ((BinaryContext)_localctx).s =  false; 
             }
@@ -1621,11 +1639,11 @@ class PainlessParser extends Parser {
             {
             _localctx = new BinaryContext(new ExpressionContext(_parentctx, _parentState));
             pushNewRecursionContext(_localctx, _startState, RULE_expression);
-            setState(260);
+            setState(265);
             if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)");
-            setState(261);
+            setState(266);
             match(XOR);
-            setState(262);
+            setState(267);
             expression(7);
              ((BinaryContext)_localctx).s =  false; 
             }
@@ -1634,11 +1652,11 @@ class PainlessParser extends Parser {
             {
             _localctx = new BinaryContext(new ExpressionContext(_parentctx, _parentState));
             pushNewRecursionContext(_localctx, _startState, RULE_expression);
-            setState(265);
+            setState(270);
             if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)");
-            setState(266);
+            setState(271);
             match(BWOR);
-            setState(267);
+            setState(272);
             expression(6);
              ((BinaryContext)_localctx).s =  false; 
             }
@@ -1647,11 +1665,11 @@ class PainlessParser extends Parser {
             {
             _localctx = new BoolContext(new ExpressionContext(_parentctx, _parentState));
             pushNewRecursionContext(_localctx, _startState, RULE_expression);
-            setState(270);
+            setState(275);
             if (!(precpred(_ctx, 4))) throw new FailedPredicateException(this, "precpred(_ctx, 4)");
-            setState(271);
+            setState(276);
             match(BOOLAND);
-            setState(272);
+            setState(277);
             expression(5);
              ((BoolContext)_localctx).s =  false; 
             }
@@ -1660,11 +1678,11 @@ class PainlessParser extends Parser {
             {
             _localctx = new BoolContext(new ExpressionContext(_parentctx, _parentState));
             pushNewRecursionContext(_localctx, _startState, RULE_expression);
-            setState(275);
+            setState(280);
             if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)");
-            setState(276);
+            setState(281);
             match(BOOLOR);
-            setState(277);
+            setState(282);
             expression(4);
              ((BoolContext)_localctx).s =  false; 
             }
@@ -1673,15 +1691,15 @@ class PainlessParser extends Parser {
             {
             _localctx = new ConditionalContext(new ExpressionContext(_parentctx, _parentState));
             pushNewRecursionContext(_localctx, _startState, RULE_expression);
-            setState(280);
+            setState(285);
             if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)");
-            setState(281);
+            setState(286);
             match(COND);
-            setState(282);
+            setState(287);
             ((ConditionalContext)_localctx).e0 = expression(0);
-            setState(283);
+            setState(288);
             match(COLON);
-            setState(284);
+            setState(289);
             ((ConditionalContext)_localctx).e1 = expression(2);
              ((ConditionalContext)_localctx).s =  ((ConditionalContext)_localctx).e0.s && ((ConditionalContext)_localctx).e1.s; 
             }
@@ -1689,9 +1707,9 @@ class PainlessParser extends Parser {
           }
           } 
         }
-        setState(291);
+        setState(296);
         _errHandler.sync(this);
-        _alt = getInterpreter().adaptivePredict(_input,20,_ctx);
+        _alt = getInterpreter().adaptivePredict(_input,21,_ctx);
       }
       }
     }
@@ -1836,22 +1854,22 @@ class PainlessParser extends Parser {
     enterRule(_localctx, 30, RULE_unary);
     int _la;
     try {
-      setState(321);
-      switch ( getInterpreter().adaptivePredict(_input,21,_ctx) ) {
+      setState(326);
+      switch ( getInterpreter().adaptivePredict(_input,22,_ctx) ) {
       case 1:
         _localctx = new PreContext(_localctx);
         enterOuterAlt(_localctx, 1);
         {
-        setState(292);
+        setState(297);
         if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
-        setState(293);
+        setState(298);
         _la = _input.LA(1);
         if ( !(_la==INCR || _la==DECR) ) {
         _errHandler.recoverInline(this);
         } else {
           consume();
         }
-        setState(294);
+        setState(299);
         chain(true);
         }
         break;
@@ -1859,11 +1877,11 @@ class PainlessParser extends Parser {
         _localctx = new PostContext(_localctx);
         enterOuterAlt(_localctx, 2);
         {
-        setState(295);
+        setState(300);
         if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
-        setState(296);
+        setState(301);
         chain(true);
-        setState(297);
+        setState(302);
         _la = _input.LA(1);
         if ( !(_la==INCR || _la==DECR) ) {
         _errHandler.recoverInline(this);
@@ -1876,9 +1894,9 @@ class PainlessParser extends Parser {
         _localctx = new ReadContext(_localctx);
         enterOuterAlt(_localctx, 3);
         {
-        setState(299);
+        setState(304);
         if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
-        setState(300);
+        setState(305);
         chain(false);
         }
         break;
@@ -1886,9 +1904,9 @@ class PainlessParser extends Parser {
         _localctx = new NumericContext(_localctx);
         enterOuterAlt(_localctx, 4);
         {
-        setState(301);
+        setState(306);
         if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
-        setState(302);
+        setState(307);
         _la = _input.LA(1);
         if ( !(((((_la - 65)) & ~0x3f) == 0 && ((1L << (_la - 65)) & ((1L << (OCTAL - 65)) | (1L << (HEX - 65)) | (1L << (INTEGER - 65)) | (1L << (DECIMAL - 65)))) != 0)) ) {
         _errHandler.recoverInline(this);
@@ -1902,9 +1920,9 @@ class PainlessParser extends Parser {
         _localctx = new TrueContext(_localctx);
         enterOuterAlt(_localctx, 5);
         {
-        setState(304);
+        setState(309);
         if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
-        setState(305);
+        setState(310);
         match(TRUE);
          ((TrueContext)_localctx).s =  false; 
         }
@@ -1913,9 +1931,9 @@ class PainlessParser extends Parser {
         _localctx = new FalseContext(_localctx);
         enterOuterAlt(_localctx, 6);
         {
-        setState(307);
+        setState(312);
         if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
-        setState(308);
+        setState(313);
         match(FALSE);
          ((FalseContext)_localctx).s =  false; 
         }
@@ -1924,9 +1942,9 @@ class PainlessParser extends Parser {
         _localctx = new NullContext(_localctx);
         enterOuterAlt(_localctx, 7);
         {
-        setState(310);
+        setState(315);
         if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
-        setState(311);
+        setState(316);
         match(NULL);
          ((NullContext)_localctx).s =  false; 
         }
@@ -1935,16 +1953,16 @@ class PainlessParser extends Parser {
         _localctx = new OperatorContext(_localctx);
         enterOuterAlt(_localctx, 8);
         {
-        setState(313);
+        setState(318);
         if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
-        setState(314);
+        setState(319);
         _la = _input.LA(1);
         if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << BOOLNOT) | (1L << BWNOT) | (1L << ADD) | (1L << SUB))) != 0)) ) {
         _errHandler.recoverInline(this);
         } else {
           consume();
         }
-        setState(315);
+        setState(320);
         unary(false);
         }
         break;
@@ -1952,13 +1970,13 @@ class PainlessParser extends Parser {
         _localctx = new CastContext(_localctx);
         enterOuterAlt(_localctx, 9);
         {
-        setState(316);
+        setState(321);
         match(LP);
-        setState(317);
+        setState(322);
         decltype();
-        setState(318);
+        setState(323);
         match(RP);
-        setState(319);
+        setState(324);
         unary(_localctx.c);
         }
         break;
@@ -2067,29 +2085,29 @@ class PainlessParser extends Parser {
     enterRule(_localctx, 32, RULE_chain);
     try {
       int _alt;
-      setState(357);
-      switch ( getInterpreter().adaptivePredict(_input,27,_ctx) ) {
+      setState(362);
+      switch ( getInterpreter().adaptivePredict(_input,28,_ctx) ) {
       case 1:
         _localctx = new DynamicContext(_localctx);
         enterOuterAlt(_localctx, 1);
         {
-        setState(323);
+        setState(328);
         ((DynamicContext)_localctx).p = primary(_localctx.c);
-        setState(327);
+        setState(332);
         _errHandler.sync(this);
-        _alt = getInterpreter().adaptivePredict(_input,22,_ctx);
+        _alt = getInterpreter().adaptivePredict(_input,23,_ctx);
         while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
           if ( _alt==1 ) {
             {
             {
-            setState(324);
+            setState(329);
             secondary(((DynamicContext)_localctx).p.s);
             }
             } 
           }
-          setState(329);
+          setState(334);
           _errHandler.sync(this);
-          _alt = getInterpreter().adaptivePredict(_input,22,_ctx);
+          _alt = getInterpreter().adaptivePredict(_input,23,_ctx);
         }
         }
         break;
@@ -2097,25 +2115,25 @@ class PainlessParser extends Parser {
         _localctx = new StaticContext(_localctx);
         enterOuterAlt(_localctx, 2);
         {
-        setState(330);
+        setState(335);
         decltype();
-        setState(331);
+        setState(336);
         dot();
-        setState(335);
+        setState(340);
         _errHandler.sync(this);
-        _alt = getInterpreter().adaptivePredict(_input,23,_ctx);
+        _alt = getInterpreter().adaptivePredict(_input,24,_ctx);
         while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
           if ( _alt==1 ) {
             {
             {
-            setState(332);
+            setState(337);
             secondary(true);
             }
             } 
           }
-          setState(337);
+          setState(342);
           _errHandler.sync(this);
-          _alt = getInterpreter().adaptivePredict(_input,23,_ctx);
+          _alt = getInterpreter().adaptivePredict(_input,24,_ctx);
         }
         }
         break;
@@ -2123,11 +2141,11 @@ class PainlessParser extends Parser {
         _localctx = new NewarrayContext(_localctx);
         enterOuterAlt(_localctx, 3);
         {
-        setState(338);
+        setState(343);
         match(NEW);
-        setState(339);
+        setState(344);
         match(TYPE);
-        setState(344); 
+        setState(349); 
         _errHandler.sync(this);
         _alt = 1;
         do {
@@ -2135,11 +2153,11 @@ class PainlessParser extends Parser {
           case 1:
             {
             {
-            setState(340);
+            setState(345);
             match(LBRACE);
-            setState(341);
+            setState(346);
             expression(0);
-            setState(342);
+            setState(347);
             match(RBRACE);
             }
             }
@@ -2147,31 +2165,31 @@ class PainlessParser extends Parser {
           default:
             throw new NoViableAltException(this);
           }
-          setState(346); 
+          setState(351); 
           _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 );
-        setState(355);
-        switch ( getInterpreter().adaptivePredict(_input,26,_ctx) ) {
+        setState(360);
+        switch ( getInterpreter().adaptivePredict(_input,27,_ctx) ) {
         case 1:
           {
-          setState(348);
+          setState(353);
           dot();
-          setState(352);
+          setState(357);
           _errHandler.sync(this);
-          _alt = getInterpreter().adaptivePredict(_input,25,_ctx);
+          _alt = getInterpreter().adaptivePredict(_input,26,_ctx);
           while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
             if ( _alt==1 ) {
               {
               {
-              setState(349);
+              setState(354);
               secondary(true);
               }
               } 
             }
-            setState(354);
+            setState(359);
             _errHandler.sync(this);
-            _alt = getInterpreter().adaptivePredict(_input,25,_ctx);
+            _alt = getInterpreter().adaptivePredict(_input,26,_ctx);
           }
           }
           break;
@@ -2283,19 +2301,19 @@ class PainlessParser extends Parser {
     PrimaryContext _localctx = new PrimaryContext(_ctx, getState(), c);
     enterRule(_localctx, 34, RULE_primary);
     try {
-      setState(377);
-      switch ( getInterpreter().adaptivePredict(_input,28,_ctx) ) {
+      setState(382);
+      switch ( getInterpreter().adaptivePredict(_input,29,_ctx) ) {
       case 1:
         _localctx = new ExprprecContext(_localctx);
         enterOuterAlt(_localctx, 1);
         {
-        setState(359);
+        setState(364);
         if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
-        setState(360);
+        setState(365);
         match(LP);
-        setState(361);
+        setState(366);
         ((ExprprecContext)_localctx).e = expression(0);
-        setState(362);
+        setState(367);
         match(RP);
          ((ExprprecContext)_localctx).s =  ((ExprprecContext)_localctx).e.s; 
         }
@@ -2304,13 +2322,13 @@ class PainlessParser extends Parser {
         _localctx = new ChainprecContext(_localctx);
         enterOuterAlt(_localctx, 2);
         {
-        setState(365);
+        setState(370);
         if (!( _localctx.c )) throw new FailedPredicateException(this, " $c ");
-        setState(366);
+        setState(371);
         match(LP);
-        setState(367);
+        setState(372);
         unary(true);
-        setState(368);
+        setState(373);
         match(RP);
         }
         break;
@@ -2318,7 +2336,7 @@ class PainlessParser extends Parser {
         _localctx = new StringContext(_localctx);
         enterOuterAlt(_localctx, 3);
         {
-        setState(370);
+        setState(375);
         match(STRING);
         }
         break;
@@ -2326,7 +2344,7 @@ class PainlessParser extends Parser {
         _localctx = new VariableContext(_localctx);
         enterOuterAlt(_localctx, 4);
         {
-        setState(371);
+        setState(376);
         match(ID);
         }
         break;
@@ -2334,9 +2352,9 @@ class PainlessParser extends Parser {
         _localctx = new CalllocalContext(_localctx);
         enterOuterAlt(_localctx, 5);
         {
-        setState(372);
+        setState(377);
         match(ID);
-        setState(373);
+        setState(378);
         arguments();
         }
         break;
@@ -2344,11 +2362,11 @@ class PainlessParser extends Parser {
         _localctx = new NewobjectContext(_localctx);
         enterOuterAlt(_localctx, 6);
         {
-        setState(374);
+        setState(379);
         match(NEW);
-        setState(375);
+        setState(380);
         match(TYPE);
-        setState(376);
+        setState(381);
         arguments();
         }
         break;
@@ -2390,23 +2408,23 @@ class PainlessParser extends Parser {
     SecondaryContext _localctx = new SecondaryContext(_ctx, getState(), s);
     enterRule(_localctx, 36, RULE_secondary);
     try {
-      setState(383);
-      switch ( getInterpreter().adaptivePredict(_input,29,_ctx) ) {
+      setState(388);
+      switch ( getInterpreter().adaptivePredict(_input,30,_ctx) ) {
       case 1:
         enterOuterAlt(_localctx, 1);
         {
-        setState(379);
+        setState(384);
         if (!( _localctx.s )) throw new FailedPredicateException(this, " $s ");
-        setState(380);
+        setState(385);
         dot();
         }
         break;
       case 2:
         enterOuterAlt(_localctx, 2);
         {
-        setState(381);
+        setState(386);
         if (!( _localctx.s )) throw new FailedPredicateException(this, " $s ");
-        setState(382);
+        setState(387);
         brace();
         }
         break;
@@ -2464,17 +2482,17 @@ class PainlessParser extends Parser {
     enterRule(_localctx, 38, RULE_dot);
     int _la;
     try {
-      setState(390);
-      switch ( getInterpreter().adaptivePredict(_input,30,_ctx) ) {
+      setState(395);
+      switch ( getInterpreter().adaptivePredict(_input,31,_ctx) ) {
       case 1:
         _localctx = new CallinvokeContext(_localctx);
         enterOuterAlt(_localctx, 1);
         {
-        setState(385);
+        setState(390);
         match(DOT);
-        setState(386);
+        setState(391);
         match(DOTID);
-        setState(387);
+        setState(392);
         arguments();
         }
         break;
@@ -2482,9 +2500,9 @@ class PainlessParser extends Parser {
         _localctx = new FieldaccessContext(_localctx);
         enterOuterAlt(_localctx, 2);
         {
-        setState(388);
+        setState(393);
         match(DOT);
-        setState(389);
+        setState(394);
         _la = _input.LA(1);
         if ( !(_la==DOTINTEGER || _la==DOTID) ) {
         _errHandler.recoverInline(this);
@@ -2538,11 +2556,11 @@ class PainlessParser extends Parser {
       _localctx = new BraceaccessContext(_localctx);
       enterOuterAlt(_localctx, 1);
       {
-      setState(392);
+      setState(397);
       match(LBRACE);
-      setState(393);
+      setState(398);
       expression(0);
-      setState(394);
+      setState(399);
       match(RBRACE);
       }
     }
@@ -2589,34 +2607,34 @@ class PainlessParser extends Parser {
       enterOuterAlt(_localctx, 1);
       {
       {
-      setState(396);
+      setState(401);
       match(LP);
-      setState(405);
-      switch ( getInterpreter().adaptivePredict(_input,32,_ctx) ) {
+      setState(410);
+      switch ( getInterpreter().adaptivePredict(_input,33,_ctx) ) {
       case 1:
         {
-        setState(397);
-        argument();
         setState(402);
+        argument();
+        setState(407);
         _errHandler.sync(this);
         _la = _input.LA(1);
         while (_la==COMMA) {
           {
           {
-          setState(398);
+          setState(403);
           match(COMMA);
-          setState(399);
+          setState(404);
           argument();
           }
           }
-          setState(404);
+          setState(409);
           _errHandler.sync(this);
           _la = _input.LA(1);
         }
         }
         break;
       }
-      setState(407);
+      setState(412);
       match(RP);
       }
       }
@@ -2657,26 +2675,26 @@ class PainlessParser extends Parser {
     ArgumentContext _localctx = new ArgumentContext(_ctx, getState());
     enterRule(_localctx, 44, RULE_argument);
     try {
-      setState(412);
-      switch ( getInterpreter().adaptivePredict(_input,33,_ctx) ) {
+      setState(417);
+      switch ( getInterpreter().adaptivePredict(_input,34,_ctx) ) {
       case 1:
         enterOuterAlt(_localctx, 1);
         {
-        setState(409);
+        setState(414);
         expression(0);
         }
         break;
       case 2:
         enterOuterAlt(_localctx, 2);
         {
-        setState(410);
+        setState(415);
         lambda();
         }
         break;
       case 3:
         enterOuterAlt(_localctx, 3);
         {
-        setState(411);
+        setState(416);
         funcref();
         }
         break;
@@ -2728,54 +2746,54 @@ class PainlessParser extends Parser {
     try {
       enterOuterAlt(_localctx, 1);
       {
-      setState(427);
+      setState(432);
       switch (_input.LA(1)) {
       case TYPE:
       case ID:
         {
-        setState(414);
+        setState(419);
         lamtype();
         }
         break;
       case LP:
         {
-        setState(415);
+        setState(420);
         match(LP);
-        setState(424);
+        setState(429);
         _la = _input.LA(1);
         if (_la==TYPE || _la==ID) {
           {
-          setState(416);
-          lamtype();
           setState(421);
+          lamtype();
+          setState(426);
           _errHandler.sync(this);
           _la = _input.LA(1);
           while (_la==COMMA) {
             {
             {
-            setState(417);
+            setState(422);
             match(COMMA);
-            setState(418);
+            setState(423);
             lamtype();
             }
             }
-            setState(423);
+            setState(428);
             _errHandler.sync(this);
             _la = _input.LA(1);
           }
           }
         }
 
-        setState(426);
+        setState(431);
         match(RP);
         }
         break;
       default:
         throw new NoViableAltException(this);
       }
-      setState(429);
+      setState(434);
       match(ARROW);
-      setState(430);
+      setState(435);
       block();
       }
     }
@@ -2813,16 +2831,16 @@ class PainlessParser extends Parser {
     try {
       enterOuterAlt(_localctx, 1);
       {
-      setState(433);
+      setState(438);
       _la = _input.LA(1);
       if (_la==TYPE) {
         {
-        setState(432);
+        setState(437);
         decltype();
         }
       }
 
-      setState(435);
+      setState(440);
       match(ID);
       }
     }
@@ -2861,16 +2879,16 @@ class PainlessParser extends Parser {
     enterRule(_localctx, 50, RULE_funcref);
     int _la;
     try {
-      setState(443);
+      setState(448);
       switch (_input.LA(1)) {
       case TYPE:
         enterOuterAlt(_localctx, 1);
         {
-        setState(437);
+        setState(442);
         match(TYPE);
-        setState(438);
+        setState(443);
         match(REF);
-        setState(439);
+        setState(444);
         _la = _input.LA(1);
         if ( !(_la==NEW || _la==ID) ) {
         _errHandler.recoverInline(this);
@@ -2882,11 +2900,11 @@ class PainlessParser extends Parser {
       case ID:
         enterOuterAlt(_localctx, 2);
         {
-        setState(440);
+        setState(445);
         match(ID);
-        setState(441);
+        setState(446);
         match(REF);
-        setState(442);
+        setState(447);
         match(ID);
         }
         break;
@@ -2995,7 +3013,7 @@ class PainlessParser extends Parser {
   }
 
   public static final String _serializedATN =
-    "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3N\u01c0\4\2\t\2\4"+
+    "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3N\u01c5\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"+
@@ -3010,158 +3028,160 @@ class PainlessParser extends Parser {
     "\7\u00b0\n\7\f\7\16\7\u00b3\13\7\3\7\3\7\3\b\3\b\3\t\3\t\5\t\u00bb\n\t"+
     "\3\n\3\n\3\13\3\13\3\13\3\13\7\13\u00c3\n\13\f\13\16\13\u00c6\13\13\3"+
     "\f\3\f\3\f\7\f\u00cb\n\f\f\f\16\f\u00ce\13\f\3\r\3\r\3\r\5\r\u00d3\n\r"+
-    "\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\20\3\20\3\20\3\20\3\20"+
-    "\3\20\3\20\3\20\3\20\5\20\u00e7\n\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+
+    "\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\5\17\u00e1"+
+    "\n\17\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\5\20\u00ec\n\20\3\20"+
+    "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+
     "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+
     "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+
     "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+
-    "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\7\20\u0122\n\20\f\20\16\20\u0125"+
-    "\13\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21"+
+    "\7\20\u0127\n\20\f\20\16\20\u012a\13\20\3\21\3\21\3\21\3\21\3\21\3\21"+
     "\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21"+
-    "\3\21\3\21\5\21\u0144\n\21\3\22\3\22\7\22\u0148\n\22\f\22\16\22\u014b"+
-    "\13\22\3\22\3\22\3\22\7\22\u0150\n\22\f\22\16\22\u0153\13\22\3\22\3\22"+
-    "\3\22\3\22\3\22\3\22\6\22\u015b\n\22\r\22\16\22\u015c\3\22\3\22\7\22\u0161"+
-    "\n\22\f\22\16\22\u0164\13\22\5\22\u0166\n\22\5\22\u0168\n\22\3\23\3\23"+
-    "\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23"+
-    "\3\23\3\23\5\23\u017c\n\23\3\24\3\24\3\24\3\24\5\24\u0182\n\24\3\25\3"+
-    "\25\3\25\3\25\3\25\5\25\u0189\n\25\3\26\3\26\3\26\3\26\3\27\3\27\3\27"+
-    "\3\27\7\27\u0193\n\27\f\27\16\27\u0196\13\27\5\27\u0198\n\27\3\27\3\27"+
-    "\3\30\3\30\3\30\5\30\u019f\n\30\3\31\3\31\3\31\3\31\3\31\7\31\u01a6\n"+
-    "\31\f\31\16\31\u01a9\13\31\5\31\u01ab\n\31\3\31\5\31\u01ae\n\31\3\31\3"+
-    "\31\3\31\3\32\5\32\u01b4\n\32\3\32\3\32\3\33\3\33\3\33\3\33\3\33\3\33"+
-    "\5\33\u01be\n\33\3\33\2\3\36\34\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36"+
-    " \"$&(*,.\60\62\64\2\16\3\3\r\r\3\2\67B\3\2\34\36\3\2\37 \3\2!#\3\2$\'"+
-    "\3\2(+\3\2\65\66\3\2CF\4\2\32\33\37 \3\2MN\4\2\26\26LL\u01ec\29\3\2\2"+
-    "\2\4D\3\2\2\2\6I\3\2\2\2\b\u00a7\3\2\2\2\n\u00ab\3\2\2\2\f\u00ad\3\2\2"+
-    "\2\16\u00b6\3\2\2\2\20\u00ba\3\2\2\2\22\u00bc\3\2\2\2\24\u00be\3\2\2\2"+
-    "\26\u00c7\3\2\2\2\30\u00cf\3\2\2\2\32\u00d4\3\2\2\2\34\u00db\3\2\2\2\36"+
-    "\u00e6\3\2\2\2 \u0143\3\2\2\2\"\u0167\3\2\2\2$\u017b\3\2\2\2&\u0181\3"+
-    "\2\2\2(\u0188\3\2\2\2*\u018a\3\2\2\2,\u018e\3\2\2\2.\u019e\3\2\2\2\60"+
-    "\u01ad\3\2\2\2\62\u01b3\3\2\2\2\64\u01bd\3\2\2\2\668\5\4\3\2\67\66\3\2"+
-    "\2\28;\3\2\2\29\67\3\2\2\29:\3\2\2\2:?\3\2\2\2;9\3\2\2\2<>\5\b\5\2=<\3"+
-    "\2\2\2>A\3\2\2\2?=\3\2\2\2?@\3\2\2\2@B\3\2\2\2A?\3\2\2\2BC\7\2\2\3C\3"+
-    "\3\2\2\2DE\5\26\f\2EF\7L\2\2FG\5\6\4\2GH\5\f\7\2H\5\3\2\2\2IU\7\t\2\2"+
-    "JK\5\26\f\2KR\7L\2\2LM\7\f\2\2MN\5\26\f\2NO\7L\2\2OQ\3\2\2\2PL\3\2\2\2"+
-    "QT\3\2\2\2RP\3\2\2\2RS\3\2\2\2SV\3\2\2\2TR\3\2\2\2UJ\3\2\2\2UV\3\2\2\2"+
-    "VW\3\2\2\2WX\7\n\2\2X\7\3\2\2\2YZ\7\16\2\2Z[\7\t\2\2[\\\5\36\20\2\\]\7"+
-    "\n\2\2]a\5\n\6\2^_\7\17\2\2_b\5\n\6\2`b\6\5\2\2a^\3\2\2\2a`\3\2\2\2b\u00a8"+
-    "\3\2\2\2cd\7\20\2\2de\7\t\2\2ef\5\36\20\2fi\7\n\2\2gj\5\n\6\2hj\5\16\b"+
-    "\2ig\3\2\2\2ih\3\2\2\2j\u00a8\3\2\2\2kl\7\21\2\2lm\5\f\7\2mn\7\20\2\2"+
-    "no\7\t\2\2op\5\36\20\2pq\7\n\2\2qr\5\34\17\2r\u00a8\3\2\2\2st\7\22\2\2"+
-    "tv\7\t\2\2uw\5\20\t\2vu\3\2\2\2vw\3\2\2\2wx\3\2\2\2xz\7\r\2\2y{\5\36\20"+
-    "\2zy\3\2\2\2z{\3\2\2\2{|\3\2\2\2|~\7\r\2\2}\177\5\22\n\2~}\3\2\2\2~\177"+
-    "\3\2\2\2\177\u0080\3\2\2\2\u0080\u0083\7\n\2\2\u0081\u0084\5\n\6\2\u0082"+
-    "\u0084\5\16\b\2\u0083\u0081\3\2\2\2\u0083\u0082\3\2\2\2\u0084\u00a8\3"+
-    "\2\2\2\u0085\u0086\7\22\2\2\u0086\u0087\7\t\2\2\u0087\u0088\5\26\f\2\u0088"+
-    "\u0089\7L\2\2\u0089\u008a\7\62\2\2\u008a\u008b\5\36\20\2\u008b\u008c\7"+
-    "\n\2\2\u008c\u008d\5\n\6\2\u008d\u00a8\3\2\2\2\u008e\u008f\5\24\13\2\u008f"+
-    "\u0090\5\34\17\2\u0090\u00a8\3\2\2\2\u0091\u0092\7\23\2\2\u0092\u00a8"+
-    "\5\34\17\2\u0093\u0094\7\24\2\2\u0094\u00a8\5\34\17\2\u0095\u0096\7\25"+
-    "\2\2\u0096\u0097\5\36\20\2\u0097\u0098\5\34\17\2\u0098\u00a8\3\2\2\2\u0099"+
-    "\u009a\7\27\2\2\u009a\u009c\5\f\7\2\u009b\u009d\5\32\16\2\u009c\u009b"+
-    "\3\2\2\2\u009d\u009e\3\2\2\2\u009e\u009c\3\2\2\2\u009e\u009f\3\2\2\2\u009f"+
-    "\u00a8\3\2\2\2\u00a0\u00a1\7\31\2\2\u00a1\u00a2\5\36\20\2\u00a2\u00a3"+
-    "\5\34\17\2\u00a3\u00a8\3\2\2\2\u00a4\u00a5\5\36\20\2\u00a5\u00a6\5\34"+
-    "\17\2\u00a6\u00a8\3\2\2\2\u00a7Y\3\2\2\2\u00a7c\3\2\2\2\u00a7k\3\2\2\2"+
-    "\u00a7s\3\2\2\2\u00a7\u0085\3\2\2\2\u00a7\u008e\3\2\2\2\u00a7\u0091\3"+
-    "\2\2\2\u00a7\u0093\3\2\2\2\u00a7\u0095\3\2\2\2\u00a7\u0099\3\2\2\2\u00a7"+
-    "\u00a0\3\2\2\2\u00a7\u00a4\3\2\2\2\u00a8\t\3\2\2\2\u00a9\u00ac\5\f\7\2"+
-    "\u00aa\u00ac\5\b\5\2\u00ab\u00a9\3\2\2\2\u00ab\u00aa\3\2\2\2\u00ac\13"+
-    "\3\2\2\2\u00ad\u00b1\7\5\2\2\u00ae\u00b0\5\b\5\2\u00af\u00ae\3\2\2\2\u00b0"+
-    "\u00b3\3\2\2\2\u00b1\u00af\3\2\2\2\u00b1\u00b2\3\2\2\2\u00b2\u00b4\3\2"+
-    "\2\2\u00b3\u00b1\3\2\2\2\u00b4\u00b5\7\6\2\2\u00b5\r\3\2\2\2\u00b6\u00b7"+
-    "\7\r\2\2\u00b7\17\3\2\2\2\u00b8\u00bb\5\24\13\2\u00b9\u00bb\5\36\20\2"+
-    "\u00ba\u00b8\3\2\2\2\u00ba\u00b9\3\2\2\2\u00bb\21\3\2\2\2\u00bc\u00bd"+
-    "\5\36\20\2\u00bd\23\3\2\2\2\u00be\u00bf\5\26\f\2\u00bf\u00c4\5\30\r\2"+
-    "\u00c0\u00c1\7\f\2\2\u00c1\u00c3\5\30\r\2\u00c2\u00c0\3\2\2\2\u00c3\u00c6"+
-    "\3\2\2\2\u00c4\u00c2\3\2\2\2\u00c4\u00c5\3\2\2\2\u00c5\25\3\2\2\2\u00c6"+
-    "\u00c4\3\2\2\2\u00c7\u00cc\7K\2\2\u00c8\u00c9\7\7\2\2\u00c9\u00cb\7\b"+
-    "\2\2\u00ca\u00c8\3\2\2\2\u00cb\u00ce\3\2\2\2\u00cc\u00ca\3\2\2\2\u00cc"+
-    "\u00cd\3\2\2\2\u00cd\27\3\2\2\2\u00ce\u00cc\3\2\2\2\u00cf\u00d2\7L\2\2"+
-    "\u00d0\u00d1\7\67\2\2\u00d1\u00d3\5\36\20\2\u00d2\u00d0\3\2\2\2\u00d2"+
-    "\u00d3\3\2\2\2\u00d3\31\3\2\2\2\u00d4\u00d5\7\30\2\2\u00d5\u00d6\7\t\2"+
-    "\2\u00d6\u00d7\7K\2\2\u00d7\u00d8\7L\2\2\u00d8\u00d9\7\n\2\2\u00d9\u00da"+
-    "\5\f\7\2\u00da\33\3\2\2\2\u00db\u00dc\t\2\2\2\u00dc\35\3\2\2\2\u00dd\u00de"+
-    "\b\20\1\2\u00de\u00df\5\"\22\2\u00df\u00e0\t\3\2\2\u00e0\u00e1\5\36\20"+
-    "\3\u00e1\u00e2\b\20\1\2\u00e2\u00e7\3\2\2\2\u00e3\u00e4\5 \21\2\u00e4"+
-    "\u00e5\b\20\1\2\u00e5\u00e7\3\2\2\2\u00e6\u00dd\3\2\2\2\u00e6\u00e3\3"+
-    "\2\2\2\u00e7\u0123\3\2\2\2\u00e8\u00e9\f\16\2\2\u00e9\u00ea\t\4\2\2\u00ea"+
-    "\u00eb\5\36\20\17\u00eb\u00ec\b\20\1\2\u00ec\u0122\3\2\2\2\u00ed\u00ee"+
-    "\f\r\2\2\u00ee\u00ef\t\5\2\2\u00ef\u00f0\5\36\20\16\u00f0\u00f1\b\20\1"+
-    "\2\u00f1\u0122\3\2\2\2\u00f2\u00f3\f\f\2\2\u00f3\u00f4\t\6\2\2\u00f4\u00f5"+
-    "\5\36\20\r\u00f5\u00f6\b\20\1\2\u00f6\u0122\3\2\2\2\u00f7\u00f8\f\13\2"+
-    "\2\u00f8\u00f9\t\7\2\2\u00f9\u00fa\5\36\20\f\u00fa\u00fb\b\20\1\2\u00fb"+
-    "\u0122\3\2\2\2\u00fc\u00fd\f\n\2\2\u00fd\u00fe\t\b\2\2\u00fe\u00ff\5\36"+
-    "\20\13\u00ff\u0100\b\20\1\2\u0100\u0122\3\2\2\2\u0101\u0102\f\t\2\2\u0102"+
-    "\u0103\7,\2\2\u0103\u0104\5\36\20\n\u0104\u0105\b\20\1\2\u0105\u0122\3"+
-    "\2\2\2\u0106\u0107\f\b\2\2\u0107\u0108\7-\2\2\u0108\u0109\5\36\20\t\u0109"+
-    "\u010a\b\20\1\2\u010a\u0122\3\2\2\2\u010b\u010c\f\7\2\2\u010c\u010d\7"+
-    ".\2\2\u010d\u010e\5\36\20\b\u010e\u010f\b\20\1\2\u010f\u0122\3\2\2\2\u0110"+
-    "\u0111\f\6\2\2\u0111\u0112\7/\2\2\u0112\u0113\5\36\20\7\u0113\u0114\b"+
-    "\20\1\2\u0114\u0122\3\2\2\2\u0115\u0116\f\5\2\2\u0116\u0117\7\60\2\2\u0117"+
-    "\u0118\5\36\20\6\u0118\u0119\b\20\1\2\u0119\u0122\3\2\2\2\u011a\u011b"+
-    "\f\4\2\2\u011b\u011c\7\61\2\2\u011c\u011d\5\36\20\2\u011d\u011e\7\62\2"+
-    "\2\u011e\u011f\5\36\20\4\u011f\u0120\b\20\1\2\u0120\u0122\3\2\2\2\u0121"+
-    "\u00e8\3\2\2\2\u0121\u00ed\3\2\2\2\u0121\u00f2\3\2\2\2\u0121\u00f7\3\2"+
-    "\2\2\u0121\u00fc\3\2\2\2\u0121\u0101\3\2\2\2\u0121\u0106\3\2\2\2\u0121"+
-    "\u010b\3\2\2\2\u0121\u0110\3\2\2\2\u0121\u0115\3\2\2\2\u0121\u011a\3\2"+
-    "\2\2\u0122\u0125\3\2\2\2\u0123\u0121\3\2\2\2\u0123\u0124\3\2\2\2\u0124"+
-    "\37\3\2\2\2\u0125\u0123\3\2\2\2\u0126\u0127\6\21\16\3\u0127\u0128\t\t"+
-    "\2\2\u0128\u0144\5\"\22\2\u0129\u012a\6\21\17\3\u012a\u012b\5\"\22\2\u012b"+
-    "\u012c\t\t\2\2\u012c\u0144\3\2\2\2\u012d\u012e\6\21\20\3\u012e\u0144\5"+
-    "\"\22\2\u012f\u0130\6\21\21\3\u0130\u0131\t\n\2\2\u0131\u0144\b\21\1\2"+
-    "\u0132\u0133\6\21\22\3\u0133\u0134\7H\2\2\u0134\u0144\b\21\1\2\u0135\u0136"+
-    "\6\21\23\3\u0136\u0137\7I\2\2\u0137\u0144\b\21\1\2\u0138\u0139\6\21\24"+
-    "\3\u0139\u013a\7J\2\2\u013a\u0144\b\21\1\2\u013b\u013c\6\21\25\3\u013c"+
-    "\u013d\t\13\2\2\u013d\u0144\5 \21\2\u013e\u013f\7\t\2\2\u013f\u0140\5"+
-    "\26\f\2\u0140\u0141\7\n\2\2\u0141\u0142\5 \21\2\u0142\u0144\3\2\2\2\u0143"+
-    "\u0126\3\2\2\2\u0143\u0129\3\2\2\2\u0143\u012d\3\2\2\2\u0143\u012f\3\2"+
-    "\2\2\u0143\u0132\3\2\2\2\u0143\u0135\3\2\2\2\u0143\u0138\3\2\2\2\u0143"+
-    "\u013b\3\2\2\2\u0143\u013e\3\2\2\2\u0144!\3\2\2\2\u0145\u0149\5$\23\2"+
-    "\u0146\u0148\5&\24\2\u0147\u0146\3\2\2\2\u0148\u014b\3\2\2\2\u0149\u0147"+
-    "\3\2\2\2\u0149\u014a\3\2\2\2\u014a\u0168\3\2\2\2\u014b\u0149\3\2\2\2\u014c"+
-    "\u014d\5\26\f\2\u014d\u0151\5(\25\2\u014e\u0150\5&\24\2\u014f\u014e\3"+
-    "\2\2\2\u0150\u0153\3\2\2\2\u0151\u014f\3\2\2\2\u0151\u0152\3\2\2\2\u0152"+
-    "\u0168\3\2\2\2\u0153\u0151\3\2\2\2\u0154\u0155\7\26\2\2\u0155\u015a\7"+
-    "K\2\2\u0156\u0157\7\7\2\2\u0157\u0158\5\36\20\2\u0158\u0159\7\b\2\2\u0159"+
-    "\u015b\3\2\2\2\u015a\u0156\3\2\2\2\u015b\u015c\3\2\2\2\u015c\u015a\3\2"+
-    "\2\2\u015c\u015d\3\2\2\2\u015d\u0165\3\2\2\2\u015e\u0162\5(\25\2\u015f"+
-    "\u0161\5&\24\2\u0160\u015f\3\2\2\2\u0161\u0164\3\2\2\2\u0162\u0160\3\2"+
-    "\2\2\u0162\u0163\3\2\2\2\u0163\u0166\3\2\2\2\u0164\u0162\3\2\2\2\u0165"+
-    "\u015e\3\2\2\2\u0165\u0166\3\2\2\2\u0166\u0168\3\2\2\2\u0167\u0145\3\2"+
-    "\2\2\u0167\u014c\3\2\2\2\u0167\u0154\3\2\2\2\u0168#\3\2\2\2\u0169\u016a"+
-    "\6\23\26\3\u016a\u016b\7\t\2\2\u016b\u016c\5\36\20\2\u016c\u016d\7\n\2"+
-    "\2\u016d\u016e\b\23\1\2\u016e\u017c\3\2\2\2\u016f\u0170\6\23\27\3\u0170"+
-    "\u0171\7\t\2\2\u0171\u0172\5 \21\2\u0172\u0173\7\n\2\2\u0173\u017c\3\2"+
-    "\2\2\u0174\u017c\7G\2\2\u0175\u017c\7L\2\2\u0176\u0177\7L\2\2\u0177\u017c"+
-    "\5,\27\2\u0178\u0179\7\26\2\2\u0179\u017a\7K\2\2\u017a\u017c\5,\27\2\u017b"+
-    "\u0169\3\2\2\2\u017b\u016f\3\2\2\2\u017b\u0174\3\2\2\2\u017b\u0175\3\2"+
-    "\2\2\u017b\u0176\3\2\2\2\u017b\u0178\3\2\2\2\u017c%\3\2\2\2\u017d\u017e"+
-    "\6\24\30\3\u017e\u0182\5(\25\2\u017f\u0180\6\24\31\3\u0180\u0182\5*\26"+
-    "\2\u0181\u017d\3\2\2\2\u0181\u017f\3\2\2\2\u0182\'\3\2\2\2\u0183\u0184"+
-    "\7\13\2\2\u0184\u0185\7N\2\2\u0185\u0189\5,\27\2\u0186\u0187\7\13\2\2"+
-    "\u0187\u0189\t\f\2\2\u0188\u0183\3\2\2\2\u0188\u0186\3\2\2\2\u0189)\3"+
-    "\2\2\2\u018a\u018b\7\7\2\2\u018b\u018c\5\36\20\2\u018c\u018d\7\b\2\2\u018d"+
-    "+\3\2\2\2\u018e\u0197\7\t\2\2\u018f\u0194\5.\30\2\u0190\u0191\7\f\2\2"+
-    "\u0191\u0193\5.\30\2\u0192\u0190\3\2\2\2\u0193\u0196\3\2\2\2\u0194\u0192"+
-    "\3\2\2\2\u0194\u0195\3\2\2\2\u0195\u0198\3\2\2\2\u0196\u0194\3\2\2\2\u0197"+
-    "\u018f\3\2\2\2\u0197\u0198\3\2\2\2\u0198\u0199\3\2\2\2\u0199\u019a\7\n"+
-    "\2\2\u019a-\3\2\2\2\u019b\u019f\5\36\20\2\u019c\u019f\5\60\31\2\u019d"+
-    "\u019f\5\64\33\2\u019e\u019b\3\2\2\2\u019e\u019c\3\2\2\2\u019e\u019d\3"+
-    "\2\2\2\u019f/\3\2\2\2\u01a0\u01ae\5\62\32\2\u01a1\u01aa\7\t\2\2\u01a2"+
-    "\u01a7\5\62\32\2\u01a3\u01a4\7\f\2\2\u01a4\u01a6\5\62\32\2\u01a5\u01a3"+
-    "\3\2\2\2\u01a6\u01a9\3\2\2\2\u01a7\u01a5\3\2\2\2\u01a7\u01a8\3\2\2\2\u01a8"+
-    "\u01ab\3\2\2\2\u01a9\u01a7\3\2\2\2\u01aa\u01a2\3\2\2\2\u01aa\u01ab\3\2"+
-    "\2\2\u01ab\u01ac\3\2\2\2\u01ac\u01ae\7\n\2\2\u01ad\u01a0\3\2\2\2\u01ad"+
-    "\u01a1\3\2\2\2\u01ae\u01af\3\2\2\2\u01af\u01b0\7\64\2\2\u01b0\u01b1\5"+
-    "\f\7\2\u01b1\61\3\2\2\2\u01b2\u01b4\5\26\f\2\u01b3\u01b2\3\2\2\2\u01b3"+
-    "\u01b4\3\2\2\2\u01b4\u01b5\3\2\2\2\u01b5\u01b6\7L\2\2\u01b6\63\3\2\2\2"+
-    "\u01b7\u01b8\7K\2\2\u01b8\u01b9\7\63\2\2\u01b9\u01be\t\r\2\2\u01ba\u01bb"+
-    "\7L\2\2\u01bb\u01bc\7\63\2\2\u01bc\u01be\7L\2\2\u01bd\u01b7\3\2\2\2\u01bd"+
-    "\u01ba\3\2\2\2\u01be\65\3\2\2\2)9?RUaivz~\u0083\u009e\u00a7\u00ab\u00b1"+
-    "\u00ba\u00c4\u00cc\u00d2\u00e6\u0121\u0123\u0143\u0149\u0151\u015c\u0162"+
-    "\u0165\u0167\u017b\u0181\u0188\u0194\u0197\u019e\u01a7\u01aa\u01ad\u01b3"+
-    "\u01bd";
+    "\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\5\21\u0149\n\21\3\22\3\22"+
+    "\7\22\u014d\n\22\f\22\16\22\u0150\13\22\3\22\3\22\3\22\7\22\u0155\n\22"+
+    "\f\22\16\22\u0158\13\22\3\22\3\22\3\22\3\22\3\22\3\22\6\22\u0160\n\22"+
+    "\r\22\16\22\u0161\3\22\3\22\7\22\u0166\n\22\f\22\16\22\u0169\13\22\5\22"+
+    "\u016b\n\22\5\22\u016d\n\22\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3"+
+    "\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u0181\n\23\3\24"+
+    "\3\24\3\24\3\24\5\24\u0187\n\24\3\25\3\25\3\25\3\25\3\25\5\25\u018e\n"+
+    "\25\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\7\27\u0198\n\27\f\27\16\27"+
+    "\u019b\13\27\5\27\u019d\n\27\3\27\3\27\3\30\3\30\3\30\5\30\u01a4\n\30"+
+    "\3\31\3\31\3\31\3\31\3\31\7\31\u01ab\n\31\f\31\16\31\u01ae\13\31\5\31"+
+    "\u01b0\n\31\3\31\5\31\u01b3\n\31\3\31\3\31\3\31\3\32\5\32\u01b9\n\32\3"+
+    "\32\3\32\3\33\3\33\3\33\3\33\3\33\3\33\5\33\u01c3\n\33\3\33\2\3\36\34"+
+    "\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\2\r\3\2\67B"+
+    "\3\2\34\36\3\2\37 \3\2!#\3\2$\'\3\2(+\3\2\65\66\3\2CF\4\2\32\33\37 \3"+
+    "\2MN\4\2\26\26LL\u01f3\29\3\2\2\2\4D\3\2\2\2\6I\3\2\2\2\b\u00a7\3\2\2"+
+    "\2\n\u00ab\3\2\2\2\f\u00ad\3\2\2\2\16\u00b6\3\2\2\2\20\u00ba\3\2\2\2\22"+
+    "\u00bc\3\2\2\2\24\u00be\3\2\2\2\26\u00c7\3\2\2\2\30\u00cf\3\2\2\2\32\u00d4"+
+    "\3\2\2\2\34\u00e0\3\2\2\2\36\u00eb\3\2\2\2 \u0148\3\2\2\2\"\u016c\3\2"+
+    "\2\2$\u0180\3\2\2\2&\u0186\3\2\2\2(\u018d\3\2\2\2*\u018f\3\2\2\2,\u0193"+
+    "\3\2\2\2.\u01a3\3\2\2\2\60\u01b2\3\2\2\2\62\u01b8\3\2\2\2\64\u01c2\3\2"+
+    "\2\2\668\5\4\3\2\67\66\3\2\2\28;\3\2\2\29\67\3\2\2\29:\3\2\2\2:?\3\2\2"+
+    "\2;9\3\2\2\2<>\5\b\5\2=<\3\2\2\2>A\3\2\2\2?=\3\2\2\2?@\3\2\2\2@B\3\2\2"+
+    "\2A?\3\2\2\2BC\7\2\2\3C\3\3\2\2\2DE\5\26\f\2EF\7L\2\2FG\5\6\4\2GH\5\f"+
+    "\7\2H\5\3\2\2\2IU\7\t\2\2JK\5\26\f\2KR\7L\2\2LM\7\f\2\2MN\5\26\f\2NO\7"+
+    "L\2\2OQ\3\2\2\2PL\3\2\2\2QT\3\2\2\2RP\3\2\2\2RS\3\2\2\2SV\3\2\2\2TR\3"+
+    "\2\2\2UJ\3\2\2\2UV\3\2\2\2VW\3\2\2\2WX\7\n\2\2X\7\3\2\2\2YZ\7\16\2\2Z"+
+    "[\7\t\2\2[\\\5\36\20\2\\]\7\n\2\2]a\5\n\6\2^_\7\17\2\2_b\5\n\6\2`b\6\5"+
+    "\2\2a^\3\2\2\2a`\3\2\2\2b\u00a8\3\2\2\2cd\7\20\2\2de\7\t\2\2ef\5\36\20"+
+    "\2fi\7\n\2\2gj\5\n\6\2hj\5\16\b\2ig\3\2\2\2ih\3\2\2\2j\u00a8\3\2\2\2k"+
+    "l\7\21\2\2lm\5\f\7\2mn\7\20\2\2no\7\t\2\2op\5\36\20\2pq\7\n\2\2qr\5\34"+
+    "\17\2r\u00a8\3\2\2\2st\7\22\2\2tv\7\t\2\2uw\5\20\t\2vu\3\2\2\2vw\3\2\2"+
+    "\2wx\3\2\2\2xz\7\r\2\2y{\5\36\20\2zy\3\2\2\2z{\3\2\2\2{|\3\2\2\2|~\7\r"+
+    "\2\2}\177\5\22\n\2~}\3\2\2\2~\177\3\2\2\2\177\u0080\3\2\2\2\u0080\u0083"+
+    "\7\n\2\2\u0081\u0084\5\n\6\2\u0082\u0084\5\16\b\2\u0083\u0081\3\2\2\2"+
+    "\u0083\u0082\3\2\2\2\u0084\u00a8\3\2\2\2\u0085\u0086\7\22\2\2\u0086\u0087"+
+    "\7\t\2\2\u0087\u0088\5\26\f\2\u0088\u0089\7L\2\2\u0089\u008a\7\62\2\2"+
+    "\u008a\u008b\5\36\20\2\u008b\u008c\7\n\2\2\u008c\u008d\5\n\6\2\u008d\u00a8"+
+    "\3\2\2\2\u008e\u008f\5\24\13\2\u008f\u0090\5\34\17\2\u0090\u00a8\3\2\2"+
+    "\2\u0091\u0092\7\23\2\2\u0092\u00a8\5\34\17\2\u0093\u0094\7\24\2\2\u0094"+
+    "\u00a8\5\34\17\2\u0095\u0096\7\25\2\2\u0096\u0097\5\36\20\2\u0097\u0098"+
+    "\5\34\17\2\u0098\u00a8\3\2\2\2\u0099\u009a\7\27\2\2\u009a\u009c\5\f\7"+
+    "\2\u009b\u009d\5\32\16\2\u009c\u009b\3\2\2\2\u009d\u009e\3\2\2\2\u009e"+
+    "\u009c\3\2\2\2\u009e\u009f\3\2\2\2\u009f\u00a8\3\2\2\2\u00a0\u00a1\7\31"+
+    "\2\2\u00a1\u00a2\5\36\20\2\u00a2\u00a3\5\34\17\2\u00a3\u00a8\3\2\2\2\u00a4"+
+    "\u00a5\5\36\20\2\u00a5\u00a6\5\34\17\2\u00a6\u00a8\3\2\2\2\u00a7Y\3\2"+
+    "\2\2\u00a7c\3\2\2\2\u00a7k\3\2\2\2\u00a7s\3\2\2\2\u00a7\u0085\3\2\2\2"+
+    "\u00a7\u008e\3\2\2\2\u00a7\u0091\3\2\2\2\u00a7\u0093\3\2\2\2\u00a7\u0095"+
+    "\3\2\2\2\u00a7\u0099\3\2\2\2\u00a7\u00a0\3\2\2\2\u00a7\u00a4\3\2\2\2\u00a8"+
+    "\t\3\2\2\2\u00a9\u00ac\5\f\7\2\u00aa\u00ac\5\b\5\2\u00ab\u00a9\3\2\2\2"+
+    "\u00ab\u00aa\3\2\2\2\u00ac\13\3\2\2\2\u00ad\u00b1\7\5\2\2\u00ae\u00b0"+
+    "\5\b\5\2\u00af\u00ae\3\2\2\2\u00b0\u00b3\3\2\2\2\u00b1\u00af\3\2\2\2\u00b1"+
+    "\u00b2\3\2\2\2\u00b2\u00b4\3\2\2\2\u00b3\u00b1\3\2\2\2\u00b4\u00b5\7\6"+
+    "\2\2\u00b5\r\3\2\2\2\u00b6\u00b7\7\r\2\2\u00b7\17\3\2\2\2\u00b8\u00bb"+
+    "\5\24\13\2\u00b9\u00bb\5\36\20\2\u00ba\u00b8\3\2\2\2\u00ba\u00b9\3\2\2"+
+    "\2\u00bb\21\3\2\2\2\u00bc\u00bd\5\36\20\2\u00bd\23\3\2\2\2\u00be\u00bf"+
+    "\5\26\f\2\u00bf\u00c4\5\30\r\2\u00c0\u00c1\7\f\2\2\u00c1\u00c3\5\30\r"+
+    "\2\u00c2\u00c0\3\2\2\2\u00c3\u00c6\3\2\2\2\u00c4\u00c2\3\2\2\2\u00c4\u00c5"+
+    "\3\2\2\2\u00c5\25\3\2\2\2\u00c6\u00c4\3\2\2\2\u00c7\u00cc\7K\2\2\u00c8"+
+    "\u00c9\7\7\2\2\u00c9\u00cb\7\b\2\2\u00ca\u00c8\3\2\2\2\u00cb\u00ce\3\2"+
+    "\2\2\u00cc\u00ca\3\2\2\2\u00cc\u00cd\3\2\2\2\u00cd\27\3\2\2\2\u00ce\u00cc"+
+    "\3\2\2\2\u00cf\u00d2\7L\2\2\u00d0\u00d1\7\67\2\2\u00d1\u00d3\5\36\20\2"+
+    "\u00d2\u00d0\3\2\2\2\u00d2\u00d3\3\2\2\2\u00d3\31\3\2\2\2\u00d4\u00d5"+
+    "\7\30\2\2\u00d5\u00d6\7\t\2\2\u00d6\u00d7\7K\2\2\u00d7\u00d8\7L\2\2\u00d8"+
+    "\u00d9\7\n\2\2\u00d9\u00da\5\f\7\2\u00da\33\3\2\2\2\u00db\u00e1\7\r\2"+
+    "\2\u00dc\u00e1\7\2\2\3\u00dd\u00de\b\17\1\2\u00de\u00df\7\6\2\2\u00df"+
+    "\u00e1\b\17\1\2\u00e0\u00db\3\2\2\2\u00e0\u00dc\3\2\2\2\u00e0\u00dd\3"+
+    "\2\2\2\u00e1\35\3\2\2\2\u00e2\u00e3\b\20\1\2\u00e3\u00e4\5\"\22\2\u00e4"+
+    "\u00e5\t\2\2\2\u00e5\u00e6\5\36\20\3\u00e6\u00e7\b\20\1\2\u00e7\u00ec"+
+    "\3\2\2\2\u00e8\u00e9\5 \21\2\u00e9\u00ea\b\20\1\2\u00ea\u00ec\3\2\2\2"+
+    "\u00eb\u00e2\3\2\2\2\u00eb\u00e8\3\2\2\2\u00ec\u0128\3\2\2\2\u00ed\u00ee"+
+    "\f\16\2\2\u00ee\u00ef\t\3\2\2\u00ef\u00f0\5\36\20\17\u00f0\u00f1\b\20"+
+    "\1\2\u00f1\u0127\3\2\2\2\u00f2\u00f3\f\r\2\2\u00f3\u00f4\t\4\2\2\u00f4"+
+    "\u00f5\5\36\20\16\u00f5\u00f6\b\20\1\2\u00f6\u0127\3\2\2\2\u00f7\u00f8"+
+    "\f\f\2\2\u00f8\u00f9\t\5\2\2\u00f9\u00fa\5\36\20\r\u00fa\u00fb\b\20\1"+
+    "\2\u00fb\u0127\3\2\2\2\u00fc\u00fd\f\13\2\2\u00fd\u00fe\t\6\2\2\u00fe"+
+    "\u00ff\5\36\20\f\u00ff\u0100\b\20\1\2\u0100\u0127\3\2\2\2\u0101\u0102"+
+    "\f\n\2\2\u0102\u0103\t\7\2\2\u0103\u0104\5\36\20\13\u0104\u0105\b\20\1"+
+    "\2\u0105\u0127\3\2\2\2\u0106\u0107\f\t\2\2\u0107\u0108\7,\2\2\u0108\u0109"+
+    "\5\36\20\n\u0109\u010a\b\20\1\2\u010a\u0127\3\2\2\2\u010b\u010c\f\b\2"+
+    "\2\u010c\u010d\7-\2\2\u010d\u010e\5\36\20\t\u010e\u010f\b\20\1\2\u010f"+
+    "\u0127\3\2\2\2\u0110\u0111\f\7\2\2\u0111\u0112\7.\2\2\u0112\u0113\5\36"+
+    "\20\b\u0113\u0114\b\20\1\2\u0114\u0127\3\2\2\2\u0115\u0116\f\6\2\2\u0116"+
+    "\u0117\7/\2\2\u0117\u0118\5\36\20\7\u0118\u0119\b\20\1\2\u0119\u0127\3"+
+    "\2\2\2\u011a\u011b\f\5\2\2\u011b\u011c\7\60\2\2\u011c\u011d\5\36\20\6"+
+    "\u011d\u011e\b\20\1\2\u011e\u0127\3\2\2\2\u011f\u0120\f\4\2\2\u0120\u0121"+
+    "\7\61\2\2\u0121\u0122\5\36\20\2\u0122\u0123\7\62\2\2\u0123\u0124\5\36"+
+    "\20\4\u0124\u0125\b\20\1\2\u0125\u0127\3\2\2\2\u0126\u00ed\3\2\2\2\u0126"+
+    "\u00f2\3\2\2\2\u0126\u00f7\3\2\2\2\u0126\u00fc\3\2\2\2\u0126\u0101\3\2"+
+    "\2\2\u0126\u0106\3\2\2\2\u0126\u010b\3\2\2\2\u0126\u0110\3\2\2\2\u0126"+
+    "\u0115\3\2\2\2\u0126\u011a\3\2\2\2\u0126\u011f\3\2\2\2\u0127\u012a\3\2"+
+    "\2\2\u0128\u0126\3\2\2\2\u0128\u0129\3\2\2\2\u0129\37\3\2\2\2\u012a\u0128"+
+    "\3\2\2\2\u012b\u012c\6\21\16\3\u012c\u012d\t\b\2\2\u012d\u0149\5\"\22"+
+    "\2\u012e\u012f\6\21\17\3\u012f\u0130\5\"\22\2\u0130\u0131\t\b\2\2\u0131"+
+    "\u0149\3\2\2\2\u0132\u0133\6\21\20\3\u0133\u0149\5\"\22\2\u0134\u0135"+
+    "\6\21\21\3\u0135\u0136\t\t\2\2\u0136\u0149\b\21\1\2\u0137\u0138\6\21\22"+
+    "\3\u0138\u0139\7H\2\2\u0139\u0149\b\21\1\2\u013a\u013b\6\21\23\3\u013b"+
+    "\u013c\7I\2\2\u013c\u0149\b\21\1\2\u013d\u013e\6\21\24\3\u013e\u013f\7"+
+    "J\2\2\u013f\u0149\b\21\1\2\u0140\u0141\6\21\25\3\u0141\u0142\t\n\2\2\u0142"+
+    "\u0149\5 \21\2\u0143\u0144\7\t\2\2\u0144\u0145\5\26\f\2\u0145\u0146\7"+
+    "\n\2\2\u0146\u0147\5 \21\2\u0147\u0149\3\2\2\2\u0148\u012b\3\2\2\2\u0148"+
+    "\u012e\3\2\2\2\u0148\u0132\3\2\2\2\u0148\u0134\3\2\2\2\u0148\u0137\3\2"+
+    "\2\2\u0148\u013a\3\2\2\2\u0148\u013d\3\2\2\2\u0148\u0140\3\2\2\2\u0148"+
+    "\u0143\3\2\2\2\u0149!\3\2\2\2\u014a\u014e\5$\23\2\u014b\u014d\5&\24\2"+
+    "\u014c\u014b\3\2\2\2\u014d\u0150\3\2\2\2\u014e\u014c\3\2\2\2\u014e\u014f"+
+    "\3\2\2\2\u014f\u016d\3\2\2\2\u0150\u014e\3\2\2\2\u0151\u0152\5\26\f\2"+
+    "\u0152\u0156\5(\25\2\u0153\u0155\5&\24\2\u0154\u0153\3\2\2\2\u0155\u0158"+
+    "\3\2\2\2\u0156\u0154\3\2\2\2\u0156\u0157\3\2\2\2\u0157\u016d\3\2\2\2\u0158"+
+    "\u0156\3\2\2\2\u0159\u015a\7\26\2\2\u015a\u015f\7K\2\2\u015b\u015c\7\7"+
+    "\2\2\u015c\u015d\5\36\20\2\u015d\u015e\7\b\2\2\u015e\u0160\3\2\2\2\u015f"+
+    "\u015b\3\2\2\2\u0160\u0161\3\2\2\2\u0161\u015f\3\2\2\2\u0161\u0162\3\2"+
+    "\2\2\u0162\u016a\3\2\2\2\u0163\u0167\5(\25\2\u0164\u0166\5&\24\2\u0165"+
+    "\u0164\3\2\2\2\u0166\u0169\3\2\2\2\u0167\u0165\3\2\2\2\u0167\u0168\3\2"+
+    "\2\2\u0168\u016b\3\2\2\2\u0169\u0167\3\2\2\2\u016a\u0163\3\2\2\2\u016a"+
+    "\u016b\3\2\2\2\u016b\u016d\3\2\2\2\u016c\u014a\3\2\2\2\u016c\u0151\3\2"+
+    "\2\2\u016c\u0159\3\2\2\2\u016d#\3\2\2\2\u016e\u016f\6\23\26\3\u016f\u0170"+
+    "\7\t\2\2\u0170\u0171\5\36\20\2\u0171\u0172\7\n\2\2\u0172\u0173\b\23\1"+
+    "\2\u0173\u0181\3\2\2\2\u0174\u0175\6\23\27\3\u0175\u0176\7\t\2\2\u0176"+
+    "\u0177\5 \21\2\u0177\u0178\7\n\2\2\u0178\u0181\3\2\2\2\u0179\u0181\7G"+
+    "\2\2\u017a\u0181\7L\2\2\u017b\u017c\7L\2\2\u017c\u0181\5,\27\2\u017d\u017e"+
+    "\7\26\2\2\u017e\u017f\7K\2\2\u017f\u0181\5,\27\2\u0180\u016e\3\2\2\2\u0180"+
+    "\u0174\3\2\2\2\u0180\u0179\3\2\2\2\u0180\u017a\3\2\2\2\u0180\u017b\3\2"+
+    "\2\2\u0180\u017d\3\2\2\2\u0181%\3\2\2\2\u0182\u0183\6\24\30\3\u0183\u0187"+
+    "\5(\25\2\u0184\u0185\6\24\31\3\u0185\u0187\5*\26\2\u0186\u0182\3\2\2\2"+
+    "\u0186\u0184\3\2\2\2\u0187\'\3\2\2\2\u0188\u0189\7\13\2\2\u0189\u018a"+
+    "\7N\2\2\u018a\u018e\5,\27\2\u018b\u018c\7\13\2\2\u018c\u018e\t\13\2\2"+
+    "\u018d\u0188\3\2\2\2\u018d\u018b\3\2\2\2\u018e)\3\2\2\2\u018f\u0190\7"+
+    "\7\2\2\u0190\u0191\5\36\20\2\u0191\u0192\7\b\2\2\u0192+\3\2\2\2\u0193"+
+    "\u019c\7\t\2\2\u0194\u0199\5.\30\2\u0195\u0196\7\f\2\2\u0196\u0198\5."+
+    "\30\2\u0197\u0195\3\2\2\2\u0198\u019b\3\2\2\2\u0199\u0197\3\2\2\2\u0199"+
+    "\u019a\3\2\2\2\u019a\u019d\3\2\2\2\u019b\u0199\3\2\2\2\u019c\u0194\3\2"+
+    "\2\2\u019c\u019d\3\2\2\2\u019d\u019e\3\2\2\2\u019e\u019f\7\n\2\2\u019f"+
+    "-\3\2\2\2\u01a0\u01a4\5\36\20\2\u01a1\u01a4\5\60\31\2\u01a2\u01a4\5\64"+
+    "\33\2\u01a3\u01a0\3\2\2\2\u01a3\u01a1\3\2\2\2\u01a3\u01a2\3\2\2\2\u01a4"+
+    "/\3\2\2\2\u01a5\u01b3\5\62\32\2\u01a6\u01af\7\t\2\2\u01a7\u01ac\5\62\32"+
+    "\2\u01a8\u01a9\7\f\2\2\u01a9\u01ab\5\62\32\2\u01aa\u01a8\3\2\2\2\u01ab"+
+    "\u01ae\3\2\2\2\u01ac\u01aa\3\2\2\2\u01ac\u01ad\3\2\2\2\u01ad\u01b0\3\2"+
+    "\2\2\u01ae\u01ac\3\2\2\2\u01af\u01a7\3\2\2\2\u01af\u01b0\3\2\2\2\u01b0"+
+    "\u01b1\3\2\2\2\u01b1\u01b3\7\n\2\2\u01b2\u01a5\3\2\2\2\u01b2\u01a6\3\2"+
+    "\2\2\u01b3\u01b4\3\2\2\2\u01b4\u01b5\7\64\2\2\u01b5\u01b6\5\f\7\2\u01b6"+
+    "\61\3\2\2\2\u01b7\u01b9\5\26\f\2\u01b8\u01b7\3\2\2\2\u01b8\u01b9\3\2\2"+
+    "\2\u01b9\u01ba\3\2\2\2\u01ba\u01bb\7L\2\2\u01bb\63\3\2\2\2\u01bc\u01bd"+
+    "\7K\2\2\u01bd\u01be\7\63\2\2\u01be\u01c3\t\f\2\2\u01bf\u01c0\7L\2\2\u01c0"+
+    "\u01c1\7\63\2\2\u01c1\u01c3\7L\2\2\u01c2\u01bc\3\2\2\2\u01c2\u01bf\3\2"+
+    "\2\2\u01c3\65\3\2\2\2*9?RUaivz~\u0083\u009e\u00a7\u00ab\u00b1\u00ba\u00c4"+
+    "\u00cc\u00d2\u00e0\u00eb\u0126\u0128\u0148\u014e\u0156\u0161\u0167\u016a"+
+    "\u016c\u0180\u0186\u018d\u0199\u019c\u01a3\u01ac\u01af\u01b2\u01b8\u01c2";
   public static final ATN _ATN =
     new ATNDeserializer().deserialize(_serializedATN.toCharArray());
   static {

+ 9 - 0
modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicStatementTests.java

@@ -221,4 +221,13 @@ public class BasicStatementTests extends ScriptTestCase {
         });
         assertTrue(exception.getCause().getMessage().contains("Lambda functions are not supported."));
     }
+
+    public void testLastInBlockDoesntNeedSemi() {
+        // One statement in the block in case that is a special case
+        assertEquals(10, exec("def i = 1; if (i == 1) {return 10}"));
+        assertEquals(10, exec("def i = 1; if (i == 1) {return 10} else {return 12}"));
+        // Two statements in the block, in case that is the general case
+        assertEquals(10, exec("def i = 1; if (i == 1) {i = 2; return 10}"));
+        assertEquals(10, exec("def i = 1; if (i == 1) {i = 2; return 10} else {return 12}"));
+    }
 }

+ 14 - 0
modules/lang-painless/src/test/java/org/elasticsearch/painless/WhenThingsGoWrongTests.java

@@ -23,6 +23,8 @@ import java.lang.invoke.WrongMethodTypeException;
 import java.util.Arrays;
 import java.util.Collections;
 
+import static java.util.Collections.emptyMap;
+
 public class WhenThingsGoWrongTests extends ScriptTestCase {
     public void testNullPointer() {
         expectScriptThrows(NullPointerException.class, () -> {
@@ -197,4 +199,16 @@ public class WhenThingsGoWrongTests extends ScriptTestCase {
             exec("def x = new ArrayList(); x.add('foo'); return x['bogus'];");
         });
     }
+
+    /**
+     * Makes sure that we present a useful error message with a misplaced right-curly. This is important because we do some funky things in
+     * the parser with right-curly brackets to allow statements to be delimited by them at the end of blocks.
+     */
+    public void testRCurlyNotDelim() {
+        IllegalArgumentException e = expectScriptThrows(IllegalArgumentException.class, () -> {
+            // We don't want PICKY here so we get the normal error message
+            exec("def i = 1} return 1", emptyMap(), emptyMap(), null);
+        });
+        assertEquals("invalid sequence of tokens near ['}'].", e.getMessage());
+    }
 }