You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by rm...@apache.org on 2022/12/16 03:55:11 UTC

[lucene] branch branch_9x updated: Upgrade ANTLR to version 4.11.1 (#12016)

This is an automated email from the ASF dual-hosted git repository.

rmuir pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/lucene.git


The following commit(s) were added to refs/heads/branch_9x by this push:
     new 6700b7e547f Upgrade ANTLR to version 4.11.1 (#12016)
6700b7e547f is described below

commit 6700b7e547f395d0b1f2698250c14edfdb389905
Author: Andriy Redko <an...@aiven.io>
AuthorDate: Thu Dec 15 22:40:35 2022 -0500

    Upgrade ANTLR to version 4.11.1 (#12016)
    
    Drop 3.x compatibility (which was pickier at compile-time and prevented slow things from happening). Instead add paranoia to runtime tests, so that they fail if antlr would do something slow in the parsing. This is needed because antlrv4 is a big performance trap: https://github.com/antlr/antlr4/blob/master/doc/faq/general.md
    
    "Q: What are the main design decisions in ANTLR4?
    Ease-of-use over performance. I will worry about performance later."
    
    It allows us to move forward with newer antlr but hopefully prevent the associated headaches.
    
    Signed-off-by: Andriy Redko <an...@aiven.io>
    Co-authored-by: Robert Muir <rm...@apache.org>
---
 lucene/CHANGES.txt                                 |   2 +
 .../src/generated/checksums/generateAntlr.json     |   6 +-
 lucene/expressions/src/java/module-info.java       |   2 +-
 .../expressions/js/JavascriptBaseVisitor.java      |   1 +
 .../lucene/expressions/js/JavascriptCompiler.java  |  86 +++-
 .../lucene/expressions/js/JavascriptLexer.java     | 438 +++++++++++++--------
 .../lucene/expressions/js/JavascriptParser.java    | 304 ++++++++------
 .../lucene/expressions/js/CompilerTestCase.java    |  48 +++
 .../lucene/expressions/js/TestCustomFunctions.java |  48 ++-
 .../expressions/js/TestJavascriptCompiler.java     |  84 ++--
 .../expressions/js/TestJavascriptFunction.java     |   5 +-
 .../expressions/js/TestJavascriptOperations.java   |   5 +-
 lucene/licenses/antlr4-runtime-4.11.1.jar.sha1     |   1 +
 lucene/licenses/antlr4-runtime-4.5.1-1.jar.sha1    |   1 -
 versions.lock                                      |   2 +-
 versions.props                                     |   2 +-
 16 files changed, 664 insertions(+), 371 deletions(-)

diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index b4c173bd325..842840f1cf4 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -78,6 +78,8 @@ Improvements
 
 * GITHUB#12003: Minor cleanup/improvements to IndexSortSortedNumericDocValuesRangeQuery. (Greg Miller)
 
+* GITHUB#12016: Upgrade lucene/expressions to use antlr 4.11.1 (Andriy Redko)
+
 Bug Fixes
 ---------------------
 * GITHUB#11726: Indexing term vectors on large documents could fail due to
diff --git a/lucene/expressions/src/generated/checksums/generateAntlr.json b/lucene/expressions/src/generated/checksums/generateAntlr.json
index 07c8d018e8a..cc3723b80e1 100644
--- a/lucene/expressions/src/generated/checksums/generateAntlr.json
+++ b/lucene/expressions/src/generated/checksums/generateAntlr.json
@@ -1,7 +1,7 @@
 {
     "lucene/expressions/src/java/org/apache/lucene/expressions/js/Javascript.g4": "818e89aae0b6c7601051802013898c128fe7c1ba",
-    "lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptBaseVisitor.java": "45e3c7093f3e485a07be507efbdefc5e3d112576",
-    "lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptLexer.java": "354e2d7a982fec18a06e552438c2b2e2c13137cf",
-    "lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptParser.java": "6182b6a2e3ade663e6f7a8643ace313e66cbf12a",
+    "lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptBaseVisitor.java": "706c11702149d135fc7ebe13ec1fe01800338260",
+    "lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptLexer.java": "b8d6b259ebbfce09a5379a1a2aa4c1ddd4e378eb",
+    "lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptParser.java": "7a3a7b9de17f4a8d41ef342312eae5c55e483e08",
     "lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptVisitor.java": "ebf033dc72e63203e5d4d85fd57114dd973482dc"
 }
\ No newline at end of file
diff --git a/lucene/expressions/src/java/module-info.java b/lucene/expressions/src/java/module-info.java
index 108f4532483..f950d2dc30e 100644
--- a/lucene/expressions/src/java/module-info.java
+++ b/lucene/expressions/src/java/module-info.java
@@ -19,7 +19,7 @@
 module org.apache.lucene.expressions {
   requires org.objectweb.asm;
   requires org.objectweb.asm.commons;
-  requires antlr4.runtime;
+  requires org.antlr.antlr4.runtime;
   requires org.apache.lucene.core;
   requires org.apache.lucene.codecs;
 
diff --git a/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptBaseVisitor.java b/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptBaseVisitor.java
index b0ea7e68acc..30a2e55d3b4 100644
--- a/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptBaseVisitor.java
+++ b/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptBaseVisitor.java
@@ -10,6 +10,7 @@ import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
  * @param <T> The return type of the visit operation. Use {@link Void} for operations with no return
  *     type.
  */
+@SuppressWarnings("CheckReturnValue")
 class JavascriptBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements JavascriptVisitor<T> {
   /**
    * {@inheritDoc}
diff --git a/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptCompiler.java b/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptCompiler.java
index 06fc8bd5e60..e272eb9eb29 100644
--- a/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptCompiler.java
+++ b/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptCompiler.java
@@ -34,7 +34,12 @@ import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Properties;
 import org.antlr.v4.runtime.ANTLRInputStream;
+import org.antlr.v4.runtime.BaseErrorListener;
 import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.DiagnosticErrorListener;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+import org.antlr.v4.runtime.atn.PredictionMode;
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.apache.lucene.expressions.Expression;
 import org.apache.lucene.expressions.js.JavascriptParser.ExpressionContext;
@@ -120,21 +125,22 @@ public final class JavascriptCompiler {
 
   final String sourceText;
   final Map<String, Method> functions;
+  final boolean picky;
 
   /**
-   * Compiles the given expression.
+   * Compiles the given expression using default compiler settings.
    *
    * @param sourceText The expression to compile
    * @return A new compiled expression
    * @throws ParseException on failure to compile
    */
   public static Expression compile(String sourceText) throws ParseException {
-    return new JavascriptCompiler(sourceText)
-        .compileExpression(JavascriptCompiler.class.getClassLoader());
+    return compile(sourceText, DEFAULT_FUNCTIONS, JavascriptCompiler.class.getClassLoader());
   }
 
   /**
-   * Compiles the given expression with the supplied custom functions.
+   * Compiles the given expression with the supplied custom functions using default compiler
+   * settings.
    *
    * <p>Functions must be {@code public static}, return {@code double} and can take from zero to 256
    * {@code double} parameters.
@@ -148,6 +154,27 @@ public final class JavascriptCompiler {
    */
   public static Expression compile(
       String sourceText, Map<String, Method> functions, ClassLoader parent) throws ParseException {
+    return compile(sourceText, functions, parent, false);
+  }
+
+  /**
+   * Compiles the given expression with the supplied custom functions.
+   *
+   * <p>Functions must be {@code public static}, return {@code double} and can take from zero to 256
+   * {@code double} parameters.
+   *
+   * @param sourceText The expression to compile
+   * @param functions map of String names to functions
+   * @param parent a {@code ClassLoader} that should be used as the parent of the loaded class. It
+   *     must contain all classes referred to by the given {@code functions}.
+   * @param picky whether to throw exception on ambiguity or other internal parsing issues (this
+   *     option makes things slower too, it is only for debugging).
+   * @return A new compiled expression
+   * @throws ParseException on failure to compile
+   */
+  static Expression compile(
+      String sourceText, Map<String, Method> functions, ClassLoader parent, boolean picky)
+      throws ParseException {
     if (parent == null) {
       throw new NullPointerException("A parent ClassLoader must be given.");
     }
@@ -155,7 +182,7 @@ public final class JavascriptCompiler {
       checkFunctionClassLoader(m, parent);
       checkFunction(m);
     }
-    return new JavascriptCompiler(sourceText, functions).compileExpression(parent);
+    return new JavascriptCompiler(sourceText, functions, picky).compileExpression(parent);
   }
 
   /**
@@ -169,26 +196,18 @@ public final class JavascriptCompiler {
     f.doubleValue();
   }
 
-  /**
-   * Constructs a compiler for expressions.
-   *
-   * @param sourceText The expression to compile
-   */
-  private JavascriptCompiler(String sourceText) {
-    this(sourceText, DEFAULT_FUNCTIONS);
-  }
-
   /**
    * Constructs a compiler for expressions with specific set of functions
    *
    * @param sourceText The expression to compile
    */
-  private JavascriptCompiler(String sourceText, Map<String, Method> functions) {
+  private JavascriptCompiler(String sourceText, Map<String, Method> functions, boolean picky) {
     if (sourceText == null) {
       throw new NullPointerException();
     }
     this.sourceText = sourceText;
     this.functions = functions;
+    this.picky = picky;
   }
 
   /**
@@ -238,10 +257,47 @@ public final class JavascriptCompiler {
     final JavascriptParser javascriptParser =
         new JavascriptParser(new CommonTokenStream(javascriptLexer));
     javascriptParser.removeErrorListeners();
+    if (picky) {
+      setupPicky(javascriptParser);
+    }
     javascriptParser.setErrorHandler(new JavascriptParserErrorStrategy());
     return javascriptParser.compile();
   }
 
+  private void setupPicky(JavascriptParser parser) {
+    // Diagnostic listener invokes syntaxError on other listeners for ambiguity issues
+    parser.addErrorListener(new DiagnosticErrorListener(true));
+    // a second listener to fail the test when the above happens.
+    parser.addErrorListener(
+        new BaseErrorListener() {
+          @Override
+          public void syntaxError(
+              final Recognizer<?, ?> recognizer,
+              final Object offendingSymbol,
+              final int line,
+              final int charPositionInLine,
+              final String msg,
+              final RecognitionException e) {
+            throw new RuntimeException(
+                new ParseException(
+                    "line ("
+                        + line
+                        + "), offset ("
+                        + charPositionInLine
+                        + "), symbol ("
+                        + offendingSymbol
+                        + ") "
+                        + msg,
+                    charPositionInLine));
+          }
+        });
+
+    // Enable exact ambiguity detection (costly). we enable exact since its the default for
+    // DiagnosticErrorListener, life is too short to think about what 'inexact ambiguity' might
+    // mean.
+    parser.getInterpreter().setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);
+  }
+
   /** Sends the bytecode of class file to {@link ClassWriter}. */
   private void generateClass(
       final ParseTree parseTree,
diff --git a/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptLexer.java b/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptLexer.java
index 4291bffa88c..e83ffa2cb63 100644
--- a/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptLexer.java
+++ b/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptLexer.java
@@ -8,10 +8,10 @@ import org.antlr.v4.runtime.atn.*;
 import org.antlr.v4.runtime.dfa.DFA;
 import org.antlr.v4.runtime.misc.*;
 
-@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
+@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue"})
 class JavascriptLexer extends Lexer {
   static {
-    RuntimeMetaData.checkVersion("4.5.1", RuntimeMetaData.VERSION);
+    RuntimeMetaData.checkVersion("4.11.1", RuntimeMetaData.VERSION);
   }
 
   protected static final DFA[] _decisionToDFA;
@@ -47,84 +47,99 @@ class JavascriptLexer extends Lexer {
       OCTAL = 29,
       HEX = 30,
       DECIMAL = 31;
+  public static String[] channelNames = {"DEFAULT_TOKEN_CHANNEL", "HIDDEN"};
+
   public static String[] modeNames = {"DEFAULT_MODE"};
 
-  public static final String[] ruleNames = {
-    "LP",
-    "RP",
-    "COMMA",
-    "BOOLNOT",
-    "BWNOT",
-    "MUL",
-    "DIV",
-    "REM",
-    "ADD",
-    "SUB",
-    "LSH",
-    "RSH",
-    "USH",
-    "LT",
-    "LTE",
-    "GT",
-    "GTE",
-    "EQ",
-    "NE",
-    "BWAND",
-    "BWXOR",
-    "BWOR",
-    "BOOLAND",
-    "BOOLOR",
-    "COND",
-    "COLON",
-    "WS",
-    "VARIABLE",
-    "ARRAY",
-    "ID",
-    "STRING",
-    "OCTAL",
-    "HEX",
-    "DECIMAL",
-    "INTEGER"
-  };
+  private static String[] makeRuleNames() {
+    return new String[] {
+      "LP",
+      "RP",
+      "COMMA",
+      "BOOLNOT",
+      "BWNOT",
+      "MUL",
+      "DIV",
+      "REM",
+      "ADD",
+      "SUB",
+      "LSH",
+      "RSH",
+      "USH",
+      "LT",
+      "LTE",
+      "GT",
+      "GTE",
+      "EQ",
+      "NE",
+      "BWAND",
+      "BWXOR",
+      "BWOR",
+      "BOOLAND",
+      "BOOLOR",
+      "COND",
+      "COLON",
+      "WS",
+      "VARIABLE",
+      "ARRAY",
+      "ID",
+      "STRING",
+      "OCTAL",
+      "HEX",
+      "DECIMAL",
+      "INTEGER"
+    };
+  }
+
+  public static final String[] ruleNames = makeRuleNames();
+
+  private static String[] makeLiteralNames() {
+    return new String[] {
+      null, null, null, null, null, null, null, null, null, null, null, "'<<'", "'>>'", "'>>>'",
+      null, "'<='", null, "'>='", "'=='", "'!='", null, null, null, "'&&'", "'||'"
+    };
+  }
+
+  private static final String[] _LITERAL_NAMES = makeLiteralNames();
 
-  private static final String[] _LITERAL_NAMES = {
-    null, null, null, null, null, null, null, null, null, null, null, "'<<'", "'>>'", "'>>>'", null,
-    "'<='", null, "'>='", "'=='", "'!='", null, null, null, "'&&'", "'||'"
-  };
-  private static final String[] _SYMBOLIC_NAMES = {
-    null,
-    "LP",
-    "RP",
-    "COMMA",
-    "BOOLNOT",
-    "BWNOT",
-    "MUL",
-    "DIV",
-    "REM",
-    "ADD",
-    "SUB",
-    "LSH",
-    "RSH",
-    "USH",
-    "LT",
-    "LTE",
-    "GT",
-    "GTE",
-    "EQ",
-    "NE",
-    "BWAND",
-    "BWXOR",
-    "BWOR",
-    "BOOLAND",
-    "BOOLOR",
-    "COND",
-    "COLON",
-    "WS",
-    "VARIABLE",
-    "OCTAL",
-    "HEX",
-    "DECIMAL"
-  };
+  private static String[] makeSymbolicNames() {
+    return new String[] {
+      null,
+      "LP",
+      "RP",
+      "COMMA",
+      "BOOLNOT",
+      "BWNOT",
+      "MUL",
+      "DIV",
+      "REM",
+      "ADD",
+      "SUB",
+      "LSH",
+      "RSH",
+      "USH",
+      "LT",
+      "LTE",
+      "GT",
+      "GTE",
+      "EQ",
+      "NE",
+      "BWAND",
+      "BWXOR",
+      "BWOR",
+      "BOOLAND",
+      "BOOLOR",
+      "COND",
+      "COLON",
+      "WS",
+      "VARIABLE",
+      "OCTAL",
+      "HEX",
+      "DECIMAL"
+    };
+  }
+
+  private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames();
   public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
 
   /**
@@ -177,6 +192,11 @@ class JavascriptLexer extends Lexer {
     return _serializedATN;
   }
 
+  @Override
+  public String[] getChannelNames() {
+    return channelNames;
+  }
+
   @Override
   public String[] getModeNames() {
     return modeNames;
@@ -188,96 +208,180 @@ class JavascriptLexer extends Lexer {
   }
 
   public static final String _serializedATN =
-      "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2!\u00fe\b\1\4\2\t"
-          + "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"
-          + "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"
-          + "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"
-          + "\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"
-          + "\t!\4\"\t\"\4#\t#\4$\t$\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7\3"
-          + "\7\3\b\3\b\3\t\3\t\3\n\3\n\3\13\3\13\3\f\3\f\3\f\3\r\3\r\3\r\3\16\3\16"
-          + "\3\16\3\16\3\17\3\17\3\20\3\20\3\20\3\21\3\21\3\22\3\22\3\22\3\23\3\23"
-          + "\3\23\3\24\3\24\3\24\3\25\3\25\3\26\3\26\3\27\3\27\3\30\3\30\3\30\3\31"
-          + "\3\31\3\31\3\32\3\32\3\33\3\33\3\34\6\34\u0089\n\34\r\34\16\34\u008a\3"
-          + "\34\3\34\3\35\3\35\7\35\u0091\n\35\f\35\16\35\u0094\13\35\3\35\3\35\3"
-          + "\35\7\35\u0099\n\35\f\35\16\35\u009c\13\35\7\35\u009e\n\35\f\35\16\35"
-          + "\u00a1\13\35\3\36\3\36\3\36\5\36\u00a6\n\36\3\36\3\36\3\37\3\37\7\37\u00ac"
-          + "\n\37\f\37\16\37\u00af\13\37\3 \3 \3 \3 \3 \3 \7 \u00b7\n \f \16 \u00ba"
-          + "\13 \3 \3 \3 \3 \3 \3 \3 \7 \u00c3\n \f \16 \u00c6\13 \3 \5 \u00c9\n "
-          + "\3!\3!\6!\u00cd\n!\r!\16!\u00ce\3\"\3\"\3\"\6\"\u00d4\n\"\r\"\16\"\u00d5"
-          + "\3#\3#\3#\7#\u00db\n#\f#\16#\u00de\13#\5#\u00e0\n#\3#\3#\6#\u00e4\n#\r"
-          + "#\16#\u00e5\5#\u00e8\n#\3#\3#\5#\u00ec\n#\3#\6#\u00ef\n#\r#\16#\u00f0"
-          + "\5#\u00f3\n#\3$\3$\3$\7$\u00f8\n$\f$\16$\u00fb\13$\5$\u00fd\n$\4\u00b8"
-          + "\u00c4\2%\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33"
-          + "\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67"
-          + "\359\36;\2=\2?\2A\37C E!G\2\3\2%\3\2**\3\2++\3\2..\3\2##\3\2\u0080\u0080"
-          + "\3\2,,\3\2\61\61\3\2\'\'\3\2--\3\2//\3\2>>\3\2@@\3\2((\3\2``\3\2~~\3\2"
-          + "AA\3\2<<\5\2\13\f\17\17\"\"\3\2\60\60\3\2]]\3\2^_\6\2&&C\\aac|\7\2&&\62"
-          + ";C\\aac|\3\2))\4\2))^^\3\2$$\4\2$$^^\3\2\62\62\3\2\629\4\2ZZzz\5\2\62"
-          + ";CHch\3\2\62;\4\2GGgg\4\2--//\3\2\63;\u0111\2\3\3\2\2\2\2\5\3\2\2\2\2"
-          + "\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2"
-          + "\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2"
-          + "\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2"
-          + "\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2"
-          + "\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2"
-          + "\2\3I\3\2\2\2\5K\3\2\2\2\7M\3\2\2\2\tO\3\2\2\2\13Q\3\2\2\2\rS\3\2\2\2"
-          + "\17U\3\2\2\2\21W\3\2\2\2\23Y\3\2\2\2\25[\3\2\2\2\27]\3\2\2\2\31`\3\2\2"
-          + "\2\33c\3\2\2\2\35g\3\2\2\2\37i\3\2\2\2!l\3\2\2\2#n\3\2\2\2%q\3\2\2\2\'"
-          + "t\3\2\2\2)w\3\2\2\2+y\3\2\2\2-{\3\2\2\2/}\3\2\2\2\61\u0080\3\2\2\2\63"
-          + "\u0083\3\2\2\2\65\u0085\3\2\2\2\67\u0088\3\2\2\29\u008e\3\2\2\2;\u00a2"
-          + "\3\2\2\2=\u00a9\3\2\2\2?\u00c8\3\2\2\2A\u00ca\3\2\2\2C\u00d0\3\2\2\2E"
-          + "\u00e7\3\2\2\2G\u00fc\3\2\2\2IJ\t\2\2\2J\4\3\2\2\2KL\t\3\2\2L\6\3\2\2"
-          + "\2MN\t\4\2\2N\b\3\2\2\2OP\t\5\2\2P\n\3\2\2\2QR\t\6\2\2R\f\3\2\2\2ST\t"
-          + "\7\2\2T\16\3\2\2\2UV\t\b\2\2V\20\3\2\2\2WX\t\t\2\2X\22\3\2\2\2YZ\t\n\2"
-          + "\2Z\24\3\2\2\2[\\\t\13\2\2\\\26\3\2\2\2]^\7>\2\2^_\7>\2\2_\30\3\2\2\2"
-          + "`a\7@\2\2ab\7@\2\2b\32\3\2\2\2cd\7@\2\2de\7@\2\2ef\7@\2\2f\34\3\2\2\2"
-          + "gh\t\f\2\2h\36\3\2\2\2ij\7>\2\2jk\7?\2\2k \3\2\2\2lm\t\r\2\2m\"\3\2\2"
-          + "\2no\7@\2\2op\7?\2\2p$\3\2\2\2qr\7?\2\2rs\7?\2\2s&\3\2\2\2tu\7#\2\2uv"
-          + "\7?\2\2v(\3\2\2\2wx\t\16\2\2x*\3\2\2\2yz\t\17\2\2z,\3\2\2\2{|\t\20\2\2"
-          + "|.\3\2\2\2}~\7(\2\2~\177\7(\2\2\177\60\3\2\2\2\u0080\u0081\7~\2\2\u0081"
-          + "\u0082\7~\2\2\u0082\62\3\2\2\2\u0083\u0084\t\21\2\2\u0084\64\3\2\2\2\u0085"
-          + "\u0086\t\22\2\2\u0086\66\3\2\2\2\u0087\u0089\t\23\2\2\u0088\u0087\3\2"
-          + "\2\2\u0089\u008a\3\2\2\2\u008a\u0088\3\2\2\2\u008a\u008b\3\2\2\2\u008b"
-          + "\u008c\3\2\2\2\u008c\u008d\b\34\2\2\u008d8\3\2\2\2\u008e\u0092\5=\37\2"
-          + "\u008f\u0091\5;\36\2\u0090\u008f\3\2\2\2\u0091\u0094\3\2\2\2\u0092\u0090"
-          + "\3\2\2\2\u0092\u0093\3\2\2\2\u0093\u009f\3\2\2\2\u0094\u0092\3\2\2\2\u0095"
-          + "\u0096\t\24\2\2\u0096\u009a\5=\37\2\u0097\u0099\5;\36\2\u0098\u0097\3"
-          + "\2\2\2\u0099\u009c\3\2\2\2\u009a\u0098\3\2\2\2\u009a\u009b\3\2\2\2\u009b"
-          + "\u009e\3\2\2\2\u009c\u009a\3\2\2\2\u009d\u0095\3\2\2\2\u009e\u00a1\3\2"
-          + "\2\2\u009f\u009d\3\2\2\2\u009f\u00a0\3\2\2\2\u00a0:\3\2\2\2\u00a1\u009f"
-          + "\3\2\2\2\u00a2\u00a5\t\25\2\2\u00a3\u00a6\5? \2\u00a4\u00a6\5G$\2\u00a5"
-          + "\u00a3\3\2\2\2\u00a5\u00a4\3\2\2\2\u00a6\u00a7\3\2\2\2\u00a7\u00a8\t\26"
-          + "\2\2\u00a8<\3\2\2\2\u00a9\u00ad\t\27\2\2\u00aa\u00ac\t\30\2\2\u00ab\u00aa"
-          + "\3\2\2\2\u00ac\u00af\3\2\2\2\u00ad\u00ab\3\2\2\2\u00ad\u00ae\3\2\2\2\u00ae"
-          + ">\3\2\2\2\u00af\u00ad\3\2\2\2\u00b0\u00b8\t\31\2\2\u00b1\u00b2\7^\2\2"
-          + "\u00b2\u00b7\7)\2\2\u00b3\u00b4\7^\2\2\u00b4\u00b7\7^\2\2\u00b5\u00b7"
-          + "\n\32\2\2\u00b6\u00b1\3\2\2\2\u00b6\u00b3\3\2\2\2\u00b6\u00b5\3\2\2\2"
-          + "\u00b7\u00ba\3\2\2\2\u00b8\u00b9\3\2\2\2\u00b8\u00b6\3\2\2\2\u00b9\u00bb"
-          + "\3\2\2\2\u00ba\u00b8\3\2\2\2\u00bb\u00c9\t\31\2\2\u00bc\u00c4\t\33\2\2"
-          + "\u00bd\u00be\7^\2\2\u00be\u00c3\7$\2\2\u00bf\u00c0\7^\2\2\u00c0\u00c3"
-          + "\7^\2\2\u00c1\u00c3\n\34\2\2\u00c2\u00bd\3\2\2\2\u00c2\u00bf\3\2\2\2\u00c2"
-          + "\u00c1\3\2\2\2\u00c3\u00c6\3\2\2\2\u00c4\u00c5\3\2\2\2\u00c4\u00c2\3\2"
-          + "\2\2\u00c5\u00c7\3\2\2\2\u00c6\u00c4\3\2\2\2\u00c7\u00c9\t\33\2\2\u00c8"
-          + "\u00b0\3\2\2\2\u00c8\u00bc\3\2\2\2\u00c9@\3\2\2\2\u00ca\u00cc\t\35\2\2"
-          + "\u00cb\u00cd\t\36\2\2\u00cc\u00cb\3\2\2\2\u00cd\u00ce\3\2\2\2\u00ce\u00cc"
-          + "\3\2\2\2\u00ce\u00cf\3\2\2\2\u00cfB\3\2\2\2\u00d0\u00d1\t\35\2\2\u00d1"
-          + "\u00d3\t\37\2\2\u00d2\u00d4\t \2\2\u00d3\u00d2\3\2\2\2\u00d4\u00d5\3\2"
-          + "\2\2\u00d5\u00d3\3\2\2\2\u00d5\u00d6\3\2\2\2\u00d6D\3\2\2\2\u00d7\u00df"
-          + "\5G$\2\u00d8\u00dc\t\24\2\2\u00d9\u00db\t!\2\2\u00da\u00d9\3\2\2\2\u00db"
-          + "\u00de\3\2\2\2\u00dc\u00da\3\2\2\2\u00dc\u00dd\3\2\2\2\u00dd\u00e0\3\2"
-          + "\2\2\u00de\u00dc\3\2\2\2\u00df\u00d8\3\2\2\2\u00df\u00e0\3\2\2\2\u00e0"
-          + "\u00e8\3\2\2\2\u00e1\u00e3\t\24\2\2\u00e2\u00e4\t!\2\2\u00e3\u00e2\3\2"
-          + "\2\2\u00e4\u00e5\3\2\2\2\u00e5\u00e3\3\2\2\2\u00e5\u00e6\3\2\2\2\u00e6"
-          + "\u00e8\3\2\2\2\u00e7\u00d7\3\2\2\2\u00e7\u00e1\3\2\2\2\u00e8\u00f2\3\2"
-          + "\2\2\u00e9\u00eb\t\"\2\2\u00ea\u00ec\t#\2\2\u00eb\u00ea\3\2\2\2\u00eb"
-          + "\u00ec\3\2\2\2\u00ec\u00ee\3\2\2\2\u00ed\u00ef\t!\2\2\u00ee\u00ed\3\2"
-          + "\2\2\u00ef\u00f0\3\2\2\2\u00f0\u00ee\3\2\2\2\u00f0\u00f1\3\2\2\2\u00f1"
-          + "\u00f3\3\2\2\2\u00f2\u00e9\3\2\2\2\u00f2\u00f3\3\2\2\2\u00f3F\3\2\2\2"
-          + "\u00f4\u00fd\t\35\2\2\u00f5\u00f9\t$\2\2\u00f6\u00f8\t!\2\2\u00f7\u00f6"
-          + "\3\2\2\2\u00f8\u00fb\3\2\2\2\u00f9\u00f7\3\2\2\2\u00f9\u00fa\3\2\2\2\u00fa"
-          + "\u00fd\3\2\2\2\u00fb\u00f9\3\2\2\2\u00fc\u00f4\3\2\2\2\u00fc\u00f5\3\2"
-          + "\2\2\u00fdH\3\2\2\2\31\2\u008a\u0092\u009a\u009f\u00a5\u00ad\u00b6\u00b8"
-          + "\u00c2\u00c4\u00c8\u00ce\u00d5\u00dc\u00df\u00e5\u00e7\u00eb\u00f0\u00f2"
-          + "\u00f9\u00fc\3\b\2\2";
+      "\u0004\u0000\u001f\u00fc\u0006\uffff\uffff\u0002\u0000\u0007\u0000\u0002"
+          + "\u0001\u0007\u0001\u0002\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002"
+          + "\u0004\u0007\u0004\u0002\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002"
+          + "\u0007\u0007\u0007\u0002\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002"
+          + "\u000b\u0007\u000b\u0002\f\u0007\f\u0002\r\u0007\r\u0002\u000e\u0007\u000e"
+          + "\u0002\u000f\u0007\u000f\u0002\u0010\u0007\u0010\u0002\u0011\u0007\u0011"
+          + "\u0002\u0012\u0007\u0012\u0002\u0013\u0007\u0013\u0002\u0014\u0007\u0014"
+          + "\u0002\u0015\u0007\u0015\u0002\u0016\u0007\u0016\u0002\u0017\u0007\u0017"
+          + "\u0002\u0018\u0007\u0018\u0002\u0019\u0007\u0019\u0002\u001a\u0007\u001a"
+          + "\u0002\u001b\u0007\u001b\u0002\u001c\u0007\u001c\u0002\u001d\u0007\u001d"
+          + "\u0002\u001e\u0007\u001e\u0002\u001f\u0007\u001f\u0002 \u0007 \u0002!"
+          + "\u0007!\u0002\"\u0007\"\u0001\u0000\u0001\u0000\u0001\u0001\u0001\u0001"
+          + "\u0001\u0002\u0001\u0002\u0001\u0003\u0001\u0003\u0001\u0004\u0001\u0004"
+          + "\u0001\u0005\u0001\u0005\u0001\u0006\u0001\u0006\u0001\u0007\u0001\u0007"
+          + "\u0001\b\u0001\b\u0001\t\u0001\t\u0001\n\u0001\n\u0001\n\u0001\u000b\u0001"
+          + "\u000b\u0001\u000b\u0001\f\u0001\f\u0001\f\u0001\f\u0001\r\u0001\r\u0001"
+          + "\u000e\u0001\u000e\u0001\u000e\u0001\u000f\u0001\u000f\u0001\u0010\u0001"
+          + "\u0010\u0001\u0010\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0012\u0001"
+          + "\u0012\u0001\u0012\u0001\u0013\u0001\u0013\u0001\u0014\u0001\u0014\u0001"
+          + "\u0015\u0001\u0015\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0017\u0001"
+          + "\u0017\u0001\u0017\u0001\u0018\u0001\u0018\u0001\u0019\u0001\u0019\u0001"
+          + "\u001a\u0004\u001a\u0087\b\u001a\u000b\u001a\f\u001a\u0088\u0001\u001a"
+          + "\u0001\u001a\u0001\u001b\u0001\u001b\u0005\u001b\u008f\b\u001b\n\u001b"
+          + "\f\u001b\u0092\t\u001b\u0001\u001b\u0001\u001b\u0001\u001b\u0005\u001b"
+          + "\u0097\b\u001b\n\u001b\f\u001b\u009a\t\u001b\u0005\u001b\u009c\b\u001b"
+          + "\n\u001b\f\u001b\u009f\t\u001b\u0001\u001c\u0001\u001c\u0001\u001c\u0003"
+          + "\u001c\u00a4\b\u001c\u0001\u001c\u0001\u001c\u0001\u001d\u0001\u001d\u0005"
+          + "\u001d\u00aa\b\u001d\n\u001d\f\u001d\u00ad\t\u001d\u0001\u001e\u0001\u001e"
+          + "\u0001\u001e\u0001\u001e\u0001\u001e\u0001\u001e\u0005\u001e\u00b5\b\u001e"
+          + "\n\u001e\f\u001e\u00b8\t\u001e\u0001\u001e\u0001\u001e\u0001\u001e\u0001"
+          + "\u001e\u0001\u001e\u0001\u001e\u0001\u001e\u0005\u001e\u00c1\b\u001e\n"
+          + "\u001e\f\u001e\u00c4\t\u001e\u0001\u001e\u0003\u001e\u00c7\b\u001e\u0001"
+          + "\u001f\u0001\u001f\u0004\u001f\u00cb\b\u001f\u000b\u001f\f\u001f\u00cc"
+          + "\u0001 \u0001 \u0001 \u0004 \u00d2\b \u000b \f \u00d3\u0001!\u0001!\u0001"
+          + "!\u0005!\u00d9\b!\n!\f!\u00dc\t!\u0003!\u00de\b!\u0001!\u0001!\u0004!"
+          + "\u00e2\b!\u000b!\f!\u00e3\u0003!\u00e6\b!\u0001!\u0001!\u0003!\u00ea\b"
+          + "!\u0001!\u0004!\u00ed\b!\u000b!\f!\u00ee\u0003!\u00f1\b!\u0001\"\u0001"
+          + "\"\u0001\"\u0005\"\u00f6\b\"\n\"\f\"\u00f9\t\"\u0003\"\u00fb\b\"\u0002"
+          + "\u00b6\u00c2\u0000#\u0001\u0001\u0003\u0002\u0005\u0003\u0007\u0004\t"
+          + "\u0005\u000b\u0006\r\u0007\u000f\b\u0011\t\u0013\n\u0015\u000b\u0017\f"
+          + "\u0019\r\u001b\u000e\u001d\u000f\u001f\u0010!\u0011#\u0012%\u0013\'\u0014"
+          + ")\u0015+\u0016-\u0017/\u00181\u00193\u001a5\u001b7\u001c9\u0000;\u0000"
+          + "=\u0000?\u001dA\u001eC\u001fE\u0000\u0001\u0000#\u0001\u0000((\u0001\u0000"
+          + "))\u0001\u0000,,\u0001\u0000!!\u0001\u0000~~\u0001\u0000**\u0001\u0000"
+          + "//\u0001\u0000%%\u0001\u0000++\u0001\u0000--\u0001\u0000<<\u0001\u0000"
+          + ">>\u0001\u0000&&\u0001\u0000^^\u0001\u0000||\u0001\u0000??\u0001\u0000"
+          + "::\u0003\u0000\t\n\r\r  \u0001\u0000..\u0001\u0000[[\u0001\u0000]]\u0004"
+          + "\u0000$$AZ__az\u0005\u0000$$09AZ__az\u0001\u0000\'\'\u0002\u0000\'\'\\"
+          + "\\\u0001\u0000\"\"\u0002\u0000\"\"\\\\\u0001\u000000\u0001\u000007\u0002"
+          + "\u0000XXxx\u0003\u000009AFaf\u0001\u000009\u0002\u0000EEee\u0002\u0000"
+          + "++--\u0001\u000019\u010f\u0000\u0001\u0001\u0000\u0000\u0000\u0000\u0003"
+          + "\u0001\u0000\u0000\u0000\u0000\u0005\u0001\u0000\u0000\u0000\u0000\u0007"
+          + "\u0001\u0000\u0000\u0000\u0000\t\u0001\u0000\u0000\u0000\u0000\u000b\u0001"
+          + "\u0000\u0000\u0000\u0000\r\u0001\u0000\u0000\u0000\u0000\u000f\u0001\u0000"
+          + "\u0000\u0000\u0000\u0011\u0001\u0000\u0000\u0000\u0000\u0013\u0001\u0000"
+          + "\u0000\u0000\u0000\u0015\u0001\u0000\u0000\u0000\u0000\u0017\u0001\u0000"
+          + "\u0000\u0000\u0000\u0019\u0001\u0000\u0000\u0000\u0000\u001b\u0001\u0000"
+          + "\u0000\u0000\u0000\u001d\u0001\u0000\u0000\u0000\u0000\u001f\u0001\u0000"
+          + "\u0000\u0000\u0000!\u0001\u0000\u0000\u0000\u0000#\u0001\u0000\u0000\u0000"
+          + "\u0000%\u0001\u0000\u0000\u0000\u0000\'\u0001\u0000\u0000\u0000\u0000"
+          + ")\u0001\u0000\u0000\u0000\u0000+\u0001\u0000\u0000\u0000\u0000-\u0001"
+          + "\u0000\u0000\u0000\u0000/\u0001\u0000\u0000\u0000\u00001\u0001\u0000\u0000"
+          + "\u0000\u00003\u0001\u0000\u0000\u0000\u00005\u0001\u0000\u0000\u0000\u0000"
+          + "7\u0001\u0000\u0000\u0000\u0000?\u0001\u0000\u0000\u0000\u0000A\u0001"
+          + "\u0000\u0000\u0000\u0000C\u0001\u0000\u0000\u0000\u0001G\u0001\u0000\u0000"
+          + "\u0000\u0003I\u0001\u0000\u0000\u0000\u0005K\u0001\u0000\u0000\u0000\u0007"
+          + "M\u0001\u0000\u0000\u0000\tO\u0001\u0000\u0000\u0000\u000bQ\u0001\u0000"
+          + "\u0000\u0000\rS\u0001\u0000\u0000\u0000\u000fU\u0001\u0000\u0000\u0000"
+          + "\u0011W\u0001\u0000\u0000\u0000\u0013Y\u0001\u0000\u0000\u0000\u0015["
+          + "\u0001\u0000\u0000\u0000\u0017^\u0001\u0000\u0000\u0000\u0019a\u0001\u0000"
+          + "\u0000\u0000\u001be\u0001\u0000\u0000\u0000\u001dg\u0001\u0000\u0000\u0000"
+          + "\u001fj\u0001\u0000\u0000\u0000!l\u0001\u0000\u0000\u0000#o\u0001\u0000"
+          + "\u0000\u0000%r\u0001\u0000\u0000\u0000\'u\u0001\u0000\u0000\u0000)w\u0001"
+          + "\u0000\u0000\u0000+y\u0001\u0000\u0000\u0000-{\u0001\u0000\u0000\u0000"
+          + "/~\u0001\u0000\u0000\u00001\u0081\u0001\u0000\u0000\u00003\u0083\u0001"
+          + "\u0000\u0000\u00005\u0086\u0001\u0000\u0000\u00007\u008c\u0001\u0000\u0000"
+          + "\u00009\u00a0\u0001\u0000\u0000\u0000;\u00a7\u0001\u0000\u0000\u0000="
+          + "\u00c6\u0001\u0000\u0000\u0000?\u00c8\u0001\u0000\u0000\u0000A\u00ce\u0001"
+          + "\u0000\u0000\u0000C\u00e5\u0001\u0000\u0000\u0000E\u00fa\u0001\u0000\u0000"
+          + "\u0000GH\u0007\u0000\u0000\u0000H\u0002\u0001\u0000\u0000\u0000IJ\u0007"
+          + "\u0001\u0000\u0000J\u0004\u0001\u0000\u0000\u0000KL\u0007\u0002\u0000"
+          + "\u0000L\u0006\u0001\u0000\u0000\u0000MN\u0007\u0003\u0000\u0000N\b\u0001"
+          + "\u0000\u0000\u0000OP\u0007\u0004\u0000\u0000P\n\u0001\u0000\u0000\u0000"
+          + "QR\u0007\u0005\u0000\u0000R\f\u0001\u0000\u0000\u0000ST\u0007\u0006\u0000"
+          + "\u0000T\u000e\u0001\u0000\u0000\u0000UV\u0007\u0007\u0000\u0000V\u0010"
+          + "\u0001\u0000\u0000\u0000WX\u0007\b\u0000\u0000X\u0012\u0001\u0000\u0000"
+          + "\u0000YZ\u0007\t\u0000\u0000Z\u0014\u0001\u0000\u0000\u0000[\\\u0005<"
+          + "\u0000\u0000\\]\u0005<\u0000\u0000]\u0016\u0001\u0000\u0000\u0000^_\u0005"
+          + ">\u0000\u0000_`\u0005>\u0000\u0000`\u0018\u0001\u0000\u0000\u0000ab\u0005"
+          + ">\u0000\u0000bc\u0005>\u0000\u0000cd\u0005>\u0000\u0000d\u001a\u0001\u0000"
+          + "\u0000\u0000ef\u0007\n\u0000\u0000f\u001c\u0001\u0000\u0000\u0000gh\u0005"
+          + "<\u0000\u0000hi\u0005=\u0000\u0000i\u001e\u0001\u0000\u0000\u0000jk\u0007"
+          + "\u000b\u0000\u0000k \u0001\u0000\u0000\u0000lm\u0005>\u0000\u0000mn\u0005"
+          + "=\u0000\u0000n\"\u0001\u0000\u0000\u0000op\u0005=\u0000\u0000pq\u0005"
+          + "=\u0000\u0000q$\u0001\u0000\u0000\u0000rs\u0005!\u0000\u0000st\u0005="
+          + "\u0000\u0000t&\u0001\u0000\u0000\u0000uv\u0007\f\u0000\u0000v(\u0001\u0000"
+          + "\u0000\u0000wx\u0007\r\u0000\u0000x*\u0001\u0000\u0000\u0000yz\u0007\u000e"
+          + "\u0000\u0000z,\u0001\u0000\u0000\u0000{|\u0005&\u0000\u0000|}\u0005&\u0000"
+          + "\u0000}.\u0001\u0000\u0000\u0000~\u007f\u0005|\u0000\u0000\u007f\u0080"
+          + "\u0005|\u0000\u0000\u00800\u0001\u0000\u0000\u0000\u0081\u0082\u0007\u000f"
+          + "\u0000\u0000\u00822\u0001\u0000\u0000\u0000\u0083\u0084\u0007\u0010\u0000"
+          + "\u0000\u00844\u0001\u0000\u0000\u0000\u0085\u0087\u0007\u0011\u0000\u0000"
+          + "\u0086\u0085\u0001\u0000\u0000\u0000\u0087\u0088\u0001\u0000\u0000\u0000"
+          + "\u0088\u0086\u0001\u0000\u0000\u0000\u0088\u0089\u0001\u0000\u0000\u0000"
+          + "\u0089\u008a\u0001\u0000\u0000\u0000\u008a\u008b\u0006\u001a\u0000\u0000"
+          + "\u008b6\u0001\u0000\u0000\u0000\u008c\u0090\u0003;\u001d\u0000\u008d\u008f"
+          + "\u00039\u001c\u0000\u008e\u008d\u0001\u0000\u0000\u0000\u008f\u0092\u0001"
+          + "\u0000\u0000\u0000\u0090\u008e\u0001\u0000\u0000\u0000\u0090\u0091\u0001"
+          + "\u0000\u0000\u0000\u0091\u009d\u0001\u0000\u0000\u0000\u0092\u0090\u0001"
+          + "\u0000\u0000\u0000\u0093\u0094\u0007\u0012\u0000\u0000\u0094\u0098\u0003"
+          + ";\u001d\u0000\u0095\u0097\u00039\u001c\u0000\u0096\u0095\u0001\u0000\u0000"
+          + "\u0000\u0097\u009a\u0001\u0000\u0000\u0000\u0098\u0096\u0001\u0000\u0000"
+          + "\u0000\u0098\u0099\u0001\u0000\u0000\u0000\u0099\u009c\u0001\u0000\u0000"
+          + "\u0000\u009a\u0098\u0001\u0000\u0000\u0000\u009b\u0093\u0001\u0000\u0000"
+          + "\u0000\u009c\u009f\u0001\u0000\u0000\u0000\u009d\u009b\u0001\u0000\u0000"
+          + "\u0000\u009d\u009e\u0001\u0000\u0000\u0000\u009e8\u0001\u0000\u0000\u0000"
+          + "\u009f\u009d\u0001\u0000\u0000\u0000\u00a0\u00a3\u0007\u0013\u0000\u0000"
+          + "\u00a1\u00a4\u0003=\u001e\u0000\u00a2\u00a4\u0003E\"\u0000\u00a3\u00a1"
+          + "\u0001\u0000\u0000\u0000\u00a3\u00a2\u0001\u0000\u0000\u0000\u00a4\u00a5"
+          + "\u0001\u0000\u0000\u0000\u00a5\u00a6\u0007\u0014\u0000\u0000\u00a6:\u0001"
+          + "\u0000\u0000\u0000\u00a7\u00ab\u0007\u0015\u0000\u0000\u00a8\u00aa\u0007"
+          + "\u0016\u0000\u0000\u00a9\u00a8\u0001\u0000\u0000\u0000\u00aa\u00ad\u0001"
+          + "\u0000\u0000\u0000\u00ab\u00a9\u0001\u0000\u0000\u0000\u00ab\u00ac\u0001"
+          + "\u0000\u0000\u0000\u00ac<\u0001\u0000\u0000\u0000\u00ad\u00ab\u0001\u0000"
+          + "\u0000\u0000\u00ae\u00b6\u0007\u0017\u0000\u0000\u00af\u00b0\u0005\\\u0000"
+          + "\u0000\u00b0\u00b5\u0005\'\u0000\u0000\u00b1\u00b2\u0005\\\u0000\u0000"
+          + "\u00b2\u00b5\u0005\\\u0000\u0000\u00b3\u00b5\b\u0018\u0000\u0000\u00b4"
+          + "\u00af\u0001\u0000\u0000\u0000\u00b4\u00b1\u0001\u0000\u0000\u0000\u00b4"
+          + "\u00b3\u0001\u0000\u0000\u0000\u00b5\u00b8\u0001\u0000\u0000\u0000\u00b6"
+          + "\u00b7\u0001\u0000\u0000\u0000\u00b6\u00b4\u0001\u0000\u0000\u0000\u00b7"
+          + "\u00b9\u0001\u0000\u0000\u0000\u00b8\u00b6\u0001\u0000\u0000\u0000\u00b9"
+          + "\u00c7\u0007\u0017\u0000\u0000\u00ba\u00c2\u0007\u0019\u0000\u0000\u00bb"
+          + "\u00bc\u0005\\\u0000\u0000\u00bc\u00c1\u0005\"\u0000\u0000\u00bd\u00be"
+          + "\u0005\\\u0000\u0000\u00be\u00c1\u0005\\\u0000\u0000\u00bf\u00c1\b\u001a"
+          + "\u0000\u0000\u00c0\u00bb\u0001\u0000\u0000\u0000\u00c0\u00bd\u0001\u0000"
+          + "\u0000\u0000\u00c0\u00bf\u0001\u0000\u0000\u0000\u00c1\u00c4\u0001\u0000"
+          + "\u0000\u0000\u00c2\u00c3\u0001\u0000\u0000\u0000\u00c2\u00c0\u0001\u0000"
+          + "\u0000\u0000\u00c3\u00c5\u0001\u0000\u0000\u0000\u00c4\u00c2\u0001\u0000"
+          + "\u0000\u0000\u00c5\u00c7\u0007\u0019\u0000\u0000\u00c6\u00ae\u0001\u0000"
+          + "\u0000\u0000\u00c6\u00ba\u0001\u0000\u0000\u0000\u00c7>\u0001\u0000\u0000"
+          + "\u0000\u00c8\u00ca\u0007\u001b\u0000\u0000\u00c9\u00cb\u0007\u001c\u0000"
+          + "\u0000\u00ca\u00c9\u0001\u0000\u0000\u0000\u00cb\u00cc\u0001\u0000\u0000"
+          + "\u0000\u00cc\u00ca\u0001\u0000\u0000\u0000\u00cc\u00cd\u0001\u0000\u0000"
+          + "\u0000\u00cd@\u0001\u0000\u0000\u0000\u00ce\u00cf\u0007\u001b\u0000\u0000"
+          + "\u00cf\u00d1\u0007\u001d\u0000\u0000\u00d0\u00d2\u0007\u001e\u0000\u0000"
+          + "\u00d1\u00d0\u0001\u0000\u0000\u0000\u00d2\u00d3\u0001\u0000\u0000\u0000"
+          + "\u00d3\u00d1\u0001\u0000\u0000\u0000\u00d3\u00d4\u0001\u0000\u0000\u0000"
+          + "\u00d4B\u0001\u0000\u0000\u0000\u00d5\u00dd\u0003E\"\u0000\u00d6\u00da"
+          + "\u0007\u0012\u0000\u0000\u00d7\u00d9\u0007\u001f\u0000\u0000\u00d8\u00d7"
+          + "\u0001\u0000\u0000\u0000\u00d9\u00dc\u0001\u0000\u0000\u0000\u00da\u00d8"
+          + "\u0001\u0000\u0000\u0000\u00da\u00db\u0001\u0000\u0000\u0000\u00db\u00de"
+          + "\u0001\u0000\u0000\u0000\u00dc\u00da\u0001\u0000\u0000\u0000\u00dd\u00d6"
+          + "\u0001\u0000\u0000\u0000\u00dd\u00de\u0001\u0000\u0000\u0000\u00de\u00e6"
+          + "\u0001\u0000\u0000\u0000\u00df\u00e1\u0007\u0012\u0000\u0000\u00e0\u00e2"
+          + "\u0007\u001f\u0000\u0000\u00e1\u00e0\u0001\u0000\u0000\u0000\u00e2\u00e3"
+          + "\u0001\u0000\u0000\u0000\u00e3\u00e1\u0001\u0000\u0000\u0000\u00e3\u00e4"
+          + "\u0001\u0000\u0000\u0000\u00e4\u00e6\u0001\u0000\u0000\u0000\u00e5\u00d5"
+          + "\u0001\u0000\u0000\u0000\u00e5\u00df\u0001\u0000\u0000\u0000\u00e6\u00f0"
+          + "\u0001\u0000\u0000\u0000\u00e7\u00e9\u0007 \u0000\u0000\u00e8\u00ea\u0007"
+          + "!\u0000\u0000\u00e9\u00e8\u0001\u0000\u0000\u0000\u00e9\u00ea\u0001\u0000"
+          + "\u0000\u0000\u00ea\u00ec\u0001\u0000\u0000\u0000\u00eb\u00ed\u0007\u001f"
+          + "\u0000\u0000\u00ec\u00eb\u0001\u0000\u0000\u0000\u00ed\u00ee\u0001\u0000"
+          + "\u0000\u0000\u00ee\u00ec\u0001\u0000\u0000\u0000\u00ee\u00ef\u0001\u0000"
+          + "\u0000\u0000\u00ef\u00f1\u0001\u0000\u0000\u0000\u00f0\u00e7\u0001\u0000"
+          + "\u0000\u0000\u00f0\u00f1\u0001\u0000\u0000\u0000\u00f1D\u0001\u0000\u0000"
+          + "\u0000\u00f2\u00fb\u0007\u001b\u0000\u0000\u00f3\u00f7\u0007\"\u0000\u0000"
+          + "\u00f4\u00f6\u0007\u001f\u0000\u0000\u00f5\u00f4\u0001\u0000\u0000\u0000"
+          + "\u00f6\u00f9\u0001\u0000\u0000\u0000\u00f7\u00f5\u0001\u0000\u0000\u0000"
+          + "\u00f7\u00f8\u0001\u0000\u0000\u0000\u00f8\u00fb\u0001\u0000\u0000\u0000"
+          + "\u00f9\u00f7\u0001\u0000\u0000\u0000\u00fa\u00f2\u0001\u0000\u0000\u0000"
+          + "\u00fa\u00f3\u0001\u0000\u0000\u0000\u00fbF\u0001\u0000\u0000\u0000\u0017"
+          + "\u0000\u0088\u0090\u0098\u009d\u00a3\u00ab\u00b4\u00b6\u00c0\u00c2\u00c6"
+          + "\u00cc\u00d3\u00da\u00dd\u00e3\u00e5\u00e9\u00ee\u00f0\u00f7\u00fa\u0001"
+          + "\u0006\u0000\u0000";
   public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray());
 
   static {
diff --git a/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptParser.java b/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptParser.java
index 267927b5d1b..dbacd6aa75f 100644
--- a/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptParser.java
+++ b/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptParser.java
@@ -8,10 +8,10 @@ import org.antlr.v4.runtime.dfa.DFA;
 import org.antlr.v4.runtime.misc.*;
 import org.antlr.v4.runtime.tree.*;
 
-@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
+@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue"})
 class JavascriptParser extends Parser {
   static {
-    RuntimeMetaData.checkVersion("4.5.1", RuntimeMetaData.VERSION);
+    RuntimeMetaData.checkVersion("4.11.1", RuntimeMetaData.VERSION);
   }
 
   protected static final DFA[] _decisionToDFA;
@@ -48,46 +48,60 @@ class JavascriptParser extends Parser {
       HEX = 30,
       DECIMAL = 31;
   public static final int RULE_compile = 0, RULE_expression = 1;
-  public static final String[] ruleNames = {"compile", "expression"};
-
-  private static final String[] _LITERAL_NAMES = {
-    null, null, null, null, null, null, null, null, null, null, null, "'<<'", "'>>'", "'>>>'", null,
-    "'<='", null, "'>='", "'=='", "'!='", null, null, null, "'&&'", "'||'"
-  };
-  private static final String[] _SYMBOLIC_NAMES = {
-    null,
-    "LP",
-    "RP",
-    "COMMA",
-    "BOOLNOT",
-    "BWNOT",
-    "MUL",
-    "DIV",
-    "REM",
-    "ADD",
-    "SUB",
-    "LSH",
-    "RSH",
-    "USH",
-    "LT",
-    "LTE",
-    "GT",
-    "GTE",
-    "EQ",
-    "NE",
-    "BWAND",
-    "BWXOR",
-    "BWOR",
-    "BOOLAND",
-    "BOOLOR",
-    "COND",
-    "COLON",
-    "WS",
-    "VARIABLE",
-    "OCTAL",
-    "HEX",
-    "DECIMAL"
-  };
+
+  private static String[] makeRuleNames() {
+    return new String[] {"compile", "expression"};
+  }
+
+  public static final String[] ruleNames = makeRuleNames();
+
+  private static String[] makeLiteralNames() {
+    return new String[] {
+      null, null, null, null, null, null, null, null, null, null, null, "'<<'", "'>>'", "'>>>'",
+      null, "'<='", null, "'>='", "'=='", "'!='", null, null, null, "'&&'", "'||'"
+    };
+  }
+
+  private static final String[] _LITERAL_NAMES = makeLiteralNames();
+
+  private static String[] makeSymbolicNames() {
+    return new String[] {
+      null,
+      "LP",
+      "RP",
+      "COMMA",
+      "BOOLNOT",
+      "BWNOT",
+      "MUL",
+      "DIV",
+      "REM",
+      "ADD",
+      "SUB",
+      "LSH",
+      "RSH",
+      "USH",
+      "LT",
+      "LTE",
+      "GT",
+      "GTE",
+      "EQ",
+      "NE",
+      "BWAND",
+      "BWXOR",
+      "BWOR",
+      "BOOLAND",
+      "BOOLOR",
+      "COND",
+      "COLON",
+      "WS",
+      "VARIABLE",
+      "OCTAL",
+      "HEX",
+      "DECIMAL"
+    };
+  }
+
+  private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames();
   public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
 
   /**
@@ -122,7 +136,7 @@ class JavascriptParser extends Parser {
 
   @Override
   public String getGrammarFileName() {
-    return "Javascript.g4";
+    return "java-escape";
   }
 
   @Override
@@ -145,6 +159,7 @@ class JavascriptParser extends Parser {
     _interp = new ParserATNSimulator(this, _ATN, _decisionToDFA, _sharedContextCache);
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class CompileContext extends ParserRuleContext {
     public ExpressionContext expression() {
       return getRuleContext(ExpressionContext.class, 0);
@@ -192,6 +207,7 @@ class JavascriptParser extends Parser {
     return _localctx;
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class ExpressionContext extends ParserRuleContext {
     public ExpressionContext(ParserRuleContext parent, int invokingState) {
       super(parent, invokingState);
@@ -209,6 +225,7 @@ class JavascriptParser extends Parser {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class ConditionalContext extends ExpressionContext {
     public List<ExpressionContext> expression() {
       return getRuleContexts(ExpressionContext.class);
@@ -238,6 +255,7 @@ class JavascriptParser extends Parser {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class BoolorContext extends ExpressionContext {
     public List<ExpressionContext> expression() {
       return getRuleContexts(ExpressionContext.class);
@@ -263,6 +281,7 @@ class JavascriptParser extends Parser {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class BoolcompContext extends ExpressionContext {
     public List<ExpressionContext> expression() {
       return getRuleContexts(ExpressionContext.class);
@@ -300,6 +319,7 @@ class JavascriptParser extends Parser {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class NumericContext extends ExpressionContext {
     public TerminalNode OCTAL() {
       return getToken(JavascriptParser.OCTAL, 0);
@@ -325,6 +345,7 @@ class JavascriptParser extends Parser {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class AddsubContext extends ExpressionContext {
     public List<ExpressionContext> expression() {
       return getRuleContexts(ExpressionContext.class);
@@ -354,6 +375,7 @@ class JavascriptParser extends Parser {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class UnaryContext extends ExpressionContext {
     public ExpressionContext expression() {
       return getRuleContext(ExpressionContext.class, 0);
@@ -387,6 +409,7 @@ class JavascriptParser extends Parser {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class PrecedenceContext extends ExpressionContext {
     public TerminalNode LP() {
       return getToken(JavascriptParser.LP, 0);
@@ -412,6 +435,7 @@ class JavascriptParser extends Parser {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class MuldivContext extends ExpressionContext {
     public List<ExpressionContext> expression() {
       return getRuleContexts(ExpressionContext.class);
@@ -445,6 +469,7 @@ class JavascriptParser extends Parser {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class ExternalContext extends ExpressionContext {
     public TerminalNode VARIABLE() {
       return getToken(JavascriptParser.VARIABLE, 0);
@@ -486,6 +511,7 @@ class JavascriptParser extends Parser {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class BwshiftContext extends ExpressionContext {
     public List<ExpressionContext> expression() {
       return getRuleContexts(ExpressionContext.class);
@@ -519,6 +545,7 @@ class JavascriptParser extends Parser {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class BworContext extends ExpressionContext {
     public List<ExpressionContext> expression() {
       return getRuleContexts(ExpressionContext.class);
@@ -544,6 +571,7 @@ class JavascriptParser extends Parser {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class BoolandContext extends ExpressionContext {
     public List<ExpressionContext> expression() {
       return getRuleContexts(ExpressionContext.class);
@@ -569,6 +597,7 @@ class JavascriptParser extends Parser {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class BwxorContext extends ExpressionContext {
     public List<ExpressionContext> expression() {
       return getRuleContexts(ExpressionContext.class);
@@ -594,6 +623,7 @@ class JavascriptParser extends Parser {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class BwandContext extends ExpressionContext {
     public List<ExpressionContext> expression() {
       return getRuleContexts(ExpressionContext.class);
@@ -619,6 +649,7 @@ class JavascriptParser extends Parser {
     }
   }
 
+  @SuppressWarnings("CheckReturnValue")
   public static class BooleqneContext extends ExpressionContext {
     public List<ExpressionContext> expression() {
       return getRuleContexts(ExpressionContext.class);
@@ -665,39 +696,19 @@ class JavascriptParser extends Parser {
       enterOuterAlt(_localctx, 1);
       {
         setState(30);
+        _errHandler.sync(this);
         switch (_input.LA(1)) {
-          case BOOLNOT:
-          case BWNOT:
-          case ADD:
-          case SUB:
-            {
-              _localctx = new UnaryContext(_localctx);
-              _ctx = _localctx;
-              _prevctx = _localctx;
-
-              setState(8);
-              _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(9);
-              expression(12);
-            }
-            break;
           case LP:
             {
               _localctx = new PrecedenceContext(_localctx);
               _ctx = _localctx;
               _prevctx = _localctx;
-              setState(10);
+
+              setState(8);
               match(LP);
-              setState(11);
+              setState(9);
               expression(0);
-              setState(12);
+              setState(10);
               match(RP);
             }
             break;
@@ -708,12 +719,13 @@ class JavascriptParser extends Parser {
               _localctx = new NumericContext(_localctx);
               _ctx = _localctx;
               _prevctx = _localctx;
-              setState(14);
+              setState(12);
               _la = _input.LA(1);
-              if (!((((_la) & ~0x3f) == 0
-                  && ((1L << _la) & ((1L << OCTAL) | (1L << HEX) | (1L << DECIMAL))) != 0))) {
+              if (!(((_la) & ~0x3f) == 0 && ((1L << _la) & 3758096384L) != 0)) {
                 _errHandler.recoverInline(this);
               } else {
+                if (_input.LA(1) == Token.EOF) matchedEOF = true;
+                _errHandler.reportMatch(this);
                 consume();
               }
             }
@@ -723,57 +735,69 @@ class JavascriptParser extends Parser {
               _localctx = new ExternalContext(_localctx);
               _ctx = _localctx;
               _prevctx = _localctx;
-              setState(15);
+              setState(13);
               match(VARIABLE);
-              setState(28);
+              setState(26);
+              _errHandler.sync(this);
               switch (getInterpreter().adaptivePredict(_input, 2, _ctx)) {
                 case 1:
                   {
-                    setState(16);
+                    setState(14);
                     match(LP);
-                    setState(25);
+                    setState(23);
+                    _errHandler.sync(this);
                     _la = _input.LA(1);
-                    if ((((_la) & ~0x3f) == 0
-                        && ((1L << _la)
-                                & ((1L << LP)
-                                    | (1L << BOOLNOT)
-                                    | (1L << BWNOT)
-                                    | (1L << ADD)
-                                    | (1L << SUB)
-                                    | (1L << VARIABLE)
-                                    | (1L << OCTAL)
-                                    | (1L << HEX)
-                                    | (1L << DECIMAL)))
-                            != 0)) {
+                    if (((_la) & ~0x3f) == 0 && ((1L << _la) & 4026533426L) != 0) {
                       {
-                        setState(17);
+                        setState(15);
                         expression(0);
-                        setState(22);
+                        setState(20);
                         _errHandler.sync(this);
                         _la = _input.LA(1);
                         while (_la == COMMA) {
                           {
                             {
-                              setState(18);
+                              setState(16);
                               match(COMMA);
-                              setState(19);
+                              setState(17);
                               expression(0);
                             }
                           }
-                          setState(24);
+                          setState(22);
                           _errHandler.sync(this);
                           _la = _input.LA(1);
                         }
                       }
                     }
 
-                    setState(27);
+                    setState(25);
                     match(RP);
                   }
                   break;
               }
             }
             break;
+          case BOOLNOT:
+          case BWNOT:
+          case ADD:
+          case SUB:
+            {
+              _localctx = new UnaryContext(_localctx);
+              _ctx = _localctx;
+              _prevctx = _localctx;
+              setState(28);
+              _la = _input.LA(1);
+              if (!(((_la) & ~0x3f) == 0 && ((1L << _la) & 1584L) != 0)) {
+                _errHandler.recoverInline(this);
+              } else {
+                if (_input.LA(1) == Token.EOF) matchedEOF = true;
+                _errHandler.reportMatch(this);
+                consume();
+              }
+              setState(29);
+              expression(12);
+            }
+            break;
           default:
             throw new NoViableAltException(this);
         }
@@ -787,6 +811,7 @@ class JavascriptParser extends Parser {
             _prevctx = _localctx;
             {
               setState(68);
+              _errHandler.sync(this);
               switch (getInterpreter().adaptivePredict(_input, 4, _ctx)) {
                 case 1:
                   {
@@ -797,10 +822,11 @@ class JavascriptParser extends Parser {
                       throw new FailedPredicateException(this, "precpred(_ctx, 11)");
                     setState(33);
                     _la = _input.LA(1);
-                    if (!((((_la) & ~0x3f) == 0
-                        && ((1L << _la) & ((1L << MUL) | (1L << DIV) | (1L << REM))) != 0))) {
+                    if (!(((_la) & ~0x3f) == 0 && ((1L << _la) & 448L) != 0)) {
                       _errHandler.recoverInline(this);
                     } else {
+                      if (_input.LA(1) == Token.EOF) matchedEOF = true;
+                      _errHandler.reportMatch(this);
                       consume();
                     }
                     setState(34);
@@ -819,6 +845,8 @@ class JavascriptParser extends Parser {
                     if (!(_la == ADD || _la == SUB)) {
                       _errHandler.recoverInline(this);
                     } else {
+                      if (_input.LA(1) == Token.EOF) matchedEOF = true;
+                      _errHandler.reportMatch(this);
                       consume();
                     }
                     setState(37);
@@ -834,10 +862,11 @@ class JavascriptParser extends Parser {
                       throw new FailedPredicateException(this, "precpred(_ctx, 9)");
                     setState(39);
                     _la = _input.LA(1);
-                    if (!((((_la) & ~0x3f) == 0
-                        && ((1L << _la) & ((1L << LSH) | (1L << RSH) | (1L << USH))) != 0))) {
+                    if (!(((_la) & ~0x3f) == 0 && ((1L << _la) & 14336L) != 0)) {
                       _errHandler.recoverInline(this);
                     } else {
+                      if (_input.LA(1) == Token.EOF) matchedEOF = true;
+                      _errHandler.reportMatch(this);
                       consume();
                     }
                     setState(40);
@@ -854,11 +883,11 @@ class JavascriptParser extends Parser {
                       throw new FailedPredicateException(this, "precpred(_ctx, 8)");
                     setState(42);
                     _la = _input.LA(1);
-                    if (!((((_la) & ~0x3f) == 0
-                        && ((1L << _la) & ((1L << LT) | (1L << LTE) | (1L << GT) | (1L << GTE)))
-                            != 0))) {
+                    if (!(((_la) & ~0x3f) == 0 && ((1L << _la) & 245760L) != 0)) {
                       _errHandler.recoverInline(this);
                     } else {
+                      if (_input.LA(1) == Token.EOF) matchedEOF = true;
+                      _errHandler.reportMatch(this);
                       consume();
                     }
                     setState(43);
@@ -878,6 +907,8 @@ class JavascriptParser extends Parser {
                     if (!(_la == EQ || _la == NE)) {
                       _errHandler.recoverInline(this);
                     } else {
+                      if (_input.LA(1) == Token.EOF) matchedEOF = true;
+                      _errHandler.reportMatch(this);
                       consume();
                     }
                     setState(46);
@@ -1022,28 +1053,57 @@ class JavascriptParser extends Parser {
   }
 
   public static final String _serializedATN =
-      "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3!L\4\2\t\2\4\3\t\3"
-          + "\3\2\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\7\3\27"
-          + "\n\3\f\3\16\3\32\13\3\5\3\34\n\3\3\3\5\3\37\n\3\5\3!\n\3\3\3\3\3\3\3\3"
-          + "\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3"
-          + "\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\7\3G\n\3"
-          + "\f\3\16\3J\13\3\3\3\2\3\4\4\2\4\2\t\4\2\6\7\13\f\3\2\37!\3\2\b\n\3\2\13"
-          + "\f\3\2\r\17\3\2\20\23\3\2\24\25Z\2\6\3\2\2\2\4 \3\2\2\2\6\7\5\4\3\2\7"
-          + "\b\7\2\2\3\b\3\3\2\2\2\t\n\b\3\1\2\n\13\t\2\2\2\13!\5\4\3\16\f\r\7\3\2"
-          + "\2\r\16\5\4\3\2\16\17\7\4\2\2\17!\3\2\2\2\20!\t\3\2\2\21\36\7\36\2\2\22"
-          + "\33\7\3\2\2\23\30\5\4\3\2\24\25\7\5\2\2\25\27\5\4\3\2\26\24\3\2\2\2\27"
-          + "\32\3\2\2\2\30\26\3\2\2\2\30\31\3\2\2\2\31\34\3\2\2\2\32\30\3\2\2\2\33"
-          + "\23\3\2\2\2\33\34\3\2\2\2\34\35\3\2\2\2\35\37\7\4\2\2\36\22\3\2\2\2\36"
-          + "\37\3\2\2\2\37!\3\2\2\2 \t\3\2\2\2 \f\3\2\2\2 \20\3\2\2\2 \21\3\2\2\2"
-          + "!H\3\2\2\2\"#\f\r\2\2#$\t\4\2\2$G\5\4\3\16%&\f\f\2\2&\'\t\5\2\2\'G\5\4"
-          + "\3\r()\f\13\2\2)*\t\6\2\2*G\5\4\3\f+,\f\n\2\2,-\t\7\2\2-G\5\4\3\13./\f"
-          + "\t\2\2/\60\t\b\2\2\60G\5\4\3\n\61\62\f\b\2\2\62\63\7\26\2\2\63G\5\4\3"
-          + "\t\64\65\f\7\2\2\65\66\7\27\2\2\66G\5\4\3\b\678\f\6\2\289\7\30\2\29G\5"
-          + "\4\3\7:;\f\5\2\2;<\7\31\2\2<G\5\4\3\6=>\f\4\2\2>?\7\32\2\2?G\5\4\3\5@"
-          + "A\f\3\2\2AB\7\33\2\2BC\5\4\3\2CD\7\34\2\2DE\5\4\3\3EG\3\2\2\2F\"\3\2\2"
-          + "\2F%\3\2\2\2F(\3\2\2\2F+\3\2\2\2F.\3\2\2\2F\61\3\2\2\2F\64\3\2\2\2F\67"
-          + "\3\2\2\2F:\3\2\2\2F=\3\2\2\2F@\3\2\2\2GJ\3\2\2\2HF\3\2\2\2HI\3\2\2\2I"
-          + "\5\3\2\2\2JH\3\2\2\2\b\30\33\36 FH";
+      "\u0004\u0001\u001fJ\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001\u0001"
+          + "\u0000\u0001\u0000\u0001\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001"
+          + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"
+          + "\u0001\u0001\u0001\u0005\u0001\u0013\b\u0001\n\u0001\f\u0001\u0016\t\u0001"
+          + "\u0003\u0001\u0018\b\u0001\u0001\u0001\u0003\u0001\u001b\b\u0001\u0001"
+          + "\u0001\u0001\u0001\u0003\u0001\u001f\b\u0001\u0001\u0001\u0001\u0001\u0001"
+          + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"
+          + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"
+          + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"
+          + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"
+          + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"
+          + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u0001E\b\u0001\n\u0001"
+          + "\f\u0001H\t\u0001\u0001\u0001\u0000\u0001\u0002\u0002\u0000\u0002\u0000"
+          + "\u0007\u0001\u0000\u001d\u001f\u0002\u0000\u0004\u0005\t\n\u0001\u0000"
+          + "\u0006\b\u0001\u0000\t\n\u0001\u0000\u000b\r\u0001\u0000\u000e\u0011\u0001"
+          + "\u0000\u0012\u0013X\u0000\u0004\u0001\u0000\u0000\u0000\u0002\u001e\u0001"
+          + "\u0000\u0000\u0000\u0004\u0005\u0003\u0002\u0001\u0000\u0005\u0006\u0005"
+          + "\u0000\u0000\u0001\u0006\u0001\u0001\u0000\u0000\u0000\u0007\b\u0006\u0001"
+          + "\uffff\uffff\u0000\b\t\u0005\u0001\u0000\u0000\t\n\u0003\u0002\u0001\u0000"
+          + "\n\u000b\u0005\u0002\u0000\u0000\u000b\u001f\u0001\u0000\u0000\u0000\f"
+          + "\u001f\u0007\u0000\u0000\u0000\r\u001a\u0005\u001c\u0000\u0000\u000e\u0017"
+          + "\u0005\u0001\u0000\u0000\u000f\u0014\u0003\u0002\u0001\u0000\u0010\u0011"
+          + "\u0005\u0003\u0000\u0000\u0011\u0013\u0003\u0002\u0001\u0000\u0012\u0010"
+          + "\u0001\u0000\u0000\u0000\u0013\u0016\u0001\u0000\u0000\u0000\u0014\u0012"
+          + "\u0001\u0000\u0000\u0000\u0014\u0015\u0001\u0000\u0000\u0000\u0015\u0018"
+          + "\u0001\u0000\u0000\u0000\u0016\u0014\u0001\u0000\u0000\u0000\u0017\u000f"
+          + "\u0001\u0000\u0000\u0000\u0017\u0018\u0001\u0000\u0000\u0000\u0018\u0019"
+          + "\u0001\u0000\u0000\u0000\u0019\u001b\u0005\u0002\u0000\u0000\u001a\u000e"
+          + "\u0001\u0000\u0000\u0000\u001a\u001b\u0001\u0000\u0000\u0000\u001b\u001f"
+          + "\u0001\u0000\u0000\u0000\u001c\u001d\u0007\u0001\u0000\u0000\u001d\u001f"
+          + "\u0003\u0002\u0001\f\u001e\u0007\u0001\u0000\u0000\u0000\u001e\f\u0001"
+          + "\u0000\u0000\u0000\u001e\r\u0001\u0000\u0000\u0000\u001e\u001c\u0001\u0000"
+          + "\u0000\u0000\u001fF\u0001\u0000\u0000\u0000 !\n\u000b\u0000\u0000!\"\u0007"
+          + "\u0002\u0000\u0000\"E\u0003\u0002\u0001\f#$\n\n\u0000\u0000$%\u0007\u0003"
+          + "\u0000\u0000%E\u0003\u0002\u0001\u000b&\'\n\t\u0000\u0000\'(\u0007\u0004"
+          + "\u0000\u0000(E\u0003\u0002\u0001\n)*\n\b\u0000\u0000*+\u0007\u0005\u0000"
+          + "\u0000+E\u0003\u0002\u0001\t,-\n\u0007\u0000\u0000-.\u0007\u0006\u0000"
+          + "\u0000.E\u0003\u0002\u0001\b/0\n\u0006\u0000\u000001\u0005\u0014\u0000"
+          + "\u00001E\u0003\u0002\u0001\u000723\n\u0005\u0000\u000034\u0005\u0015\u0000"
+          + "\u00004E\u0003\u0002\u0001\u000656\n\u0004\u0000\u000067\u0005\u0016\u0000"
+          + "\u00007E\u0003\u0002\u0001\u000589\n\u0003\u0000\u00009:\u0005\u0017\u0000"
+          + "\u0000:E\u0003\u0002\u0001\u0004;<\n\u0002\u0000\u0000<=\u0005\u0018\u0000"
+          + "\u0000=E\u0003\u0002\u0001\u0003>?\n\u0001\u0000\u0000?@\u0005\u0019\u0000"
+          + "\u0000@A\u0003\u0002\u0001\u0000AB\u0005\u001a\u0000\u0000BC\u0003\u0002"
+          + "\u0001\u0001CE\u0001\u0000\u0000\u0000D \u0001\u0000\u0000\u0000D#\u0001"
+          + "\u0000\u0000\u0000D&\u0001\u0000\u0000\u0000D)\u0001\u0000\u0000\u0000"
+          + "D,\u0001\u0000\u0000\u0000D/\u0001\u0000\u0000\u0000D2\u0001\u0000\u0000"
+          + "\u0000D5\u0001\u0000\u0000\u0000D8\u0001\u0000\u0000\u0000D;\u0001\u0000"
+          + "\u0000\u0000D>\u0001\u0000\u0000\u0000EH\u0001\u0000\u0000\u0000FD\u0001"
+          + "\u0000\u0000\u0000FG\u0001\u0000\u0000\u0000G\u0003\u0001\u0000\u0000"
+          + "\u0000HF\u0001\u0000\u0000\u0000\u0006\u0014\u0017\u001a\u001eDF";
   public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray());
 
   static {
diff --git a/lucene/expressions/src/test/org/apache/lucene/expressions/js/CompilerTestCase.java b/lucene/expressions/src/test/org/apache/lucene/expressions/js/CompilerTestCase.java
new file mode 100644
index 00000000000..cc24d24fe1e
--- /dev/null
+++ b/lucene/expressions/src/test/org/apache/lucene/expressions/js/CompilerTestCase.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.lucene.expressions.js;
+
+import java.lang.reflect.Method;
+import java.text.ParseException;
+import java.util.Map;
+import org.apache.lucene.expressions.Expression;
+import org.apache.lucene.tests.util.LuceneTestCase;
+
+/** Base class for testing JS compiler */
+public abstract class CompilerTestCase extends LuceneTestCase {
+
+  /** compiles expression for sourceText with default functions list */
+  protected Expression compile(String sourceText) throws ParseException {
+    return compile(
+        sourceText,
+        JavascriptCompiler.DEFAULT_FUNCTIONS,
+        JavascriptCompiler.class.getClassLoader());
+  }
+
+  /** compiles expression for sourceText with custom functions list */
+  protected Expression compile(String sourceText, Map<String, Method> functions)
+      throws ParseException {
+    return compile(sourceText, functions, JavascriptCompiler.class.getClassLoader());
+  }
+
+  /** compiles expression for sourceText with custom functions list and parent classloader */
+  protected Expression compile(String sourceText, Map<String, Method> functions, ClassLoader parent)
+      throws ParseException {
+    return JavascriptCompiler.compile(sourceText, functions, parent, true);
+  }
+}
diff --git a/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestCustomFunctions.java b/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestCustomFunctions.java
index 0542d7ef4ec..e0273d2df7d 100644
--- a/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestCustomFunctions.java
+++ b/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestCustomFunctions.java
@@ -24,14 +24,13 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import org.apache.lucene.expressions.Expression;
-import org.apache.lucene.tests.util.LuceneTestCase;
 import org.objectweb.asm.ClassWriter;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
 import org.objectweb.asm.commons.GeneratorAdapter;
 
 /** Tests customing the function map */
-public class TestCustomFunctions extends LuceneTestCase {
+public class TestCustomFunctions extends CompilerTestCase {
   private static double DELTA = 0.0000001;
 
   /** empty list of methods */
@@ -41,7 +40,7 @@ public class TestCustomFunctions extends LuceneTestCase {
         expectThrows(
             ParseException.class,
             () -> {
-              JavascriptCompiler.compile("sqrt(20)", functions, getClass().getClassLoader());
+              compile("sqrt(20)", functions);
             });
     assertEquals(
         "Invalid expression 'sqrt(20)': Unrecognized function call (sqrt).", expected.getMessage());
@@ -51,8 +50,7 @@ public class TestCustomFunctions extends LuceneTestCase {
   /** using the default map explicitly */
   public void testDefaultList() throws Exception {
     Map<String, Method> functions = JavascriptCompiler.DEFAULT_FUNCTIONS;
-    Expression expr =
-        JavascriptCompiler.compile("sqrt(20)", functions, getClass().getClassLoader());
+    Expression expr = compile("sqrt(20)", functions);
     assertEquals(Math.sqrt(20), expr.evaluate(null), DELTA);
   }
 
@@ -64,7 +62,7 @@ public class TestCustomFunctions extends LuceneTestCase {
   public void testNoArgMethod() throws Exception {
     Map<String, Method> functions = new HashMap<>();
     functions.put("foo", getClass().getMethod("zeroArgMethod"));
-    Expression expr = JavascriptCompiler.compile("foo()", functions, getClass().getClassLoader());
+    Expression expr = compile("foo()", functions);
     assertEquals(5, expr.evaluate(null), DELTA);
   }
 
@@ -76,7 +74,7 @@ public class TestCustomFunctions extends LuceneTestCase {
   public void testOneArgMethod() throws Exception {
     Map<String, Method> functions = new HashMap<>();
     functions.put("foo", getClass().getMethod("oneArgMethod", double.class));
-    Expression expr = JavascriptCompiler.compile("foo(3)", functions, getClass().getClassLoader());
+    Expression expr = compile("foo(3)", functions);
     assertEquals(6, expr.evaluate(null), DELTA);
   }
 
@@ -89,8 +87,7 @@ public class TestCustomFunctions extends LuceneTestCase {
     Map<String, Method> functions = new HashMap<>();
     functions.put(
         "foo", getClass().getMethod("threeArgMethod", double.class, double.class, double.class));
-    Expression expr =
-        JavascriptCompiler.compile("foo(3, 4, 5)", functions, getClass().getClassLoader());
+    Expression expr = compile("foo(3, 4, 5)", functions);
     assertEquals(12, expr.evaluate(null), DELTA);
   }
 
@@ -99,8 +96,7 @@ public class TestCustomFunctions extends LuceneTestCase {
     Map<String, Method> functions = new HashMap<>();
     functions.put("foo", getClass().getMethod("zeroArgMethod"));
     functions.put("bar", getClass().getMethod("oneArgMethod", double.class));
-    Expression expr =
-        JavascriptCompiler.compile("foo() + bar(3)", functions, getClass().getClassLoader());
+    Expression expr = compile("foo() + bar(3)", functions);
     assertEquals(11, expr.evaluate(null), DELTA);
   }
 
@@ -110,7 +106,7 @@ public class TestCustomFunctions extends LuceneTestCase {
         expectThrows(
             ParseException.class,
             () -> {
-              JavascriptCompiler.compile("method()");
+              compile("method()");
             });
     assertEquals(
         "Invalid expression 'method()': Unrecognized function call (method).",
@@ -121,7 +117,7 @@ public class TestCustomFunctions extends LuceneTestCase {
         expectThrows(
             ParseException.class,
             () -> {
-              JavascriptCompiler.compile("method.method(1)");
+              compile("method.method(1)");
             });
     assertEquals(
         "Invalid expression 'method.method(1)': Unrecognized function call (method.method).",
@@ -132,7 +128,7 @@ public class TestCustomFunctions extends LuceneTestCase {
         expectThrows(
             ParseException.class,
             () -> {
-              JavascriptCompiler.compile("1 + method()");
+              compile("1 + method()");
             });
     assertEquals(
         "Invalid expression '1 + method()': Unrecognized function call (method).",
@@ -152,7 +148,7 @@ public class TestCustomFunctions extends LuceneTestCase {
         expectThrows(
             IllegalArgumentException.class,
             () -> {
-              JavascriptCompiler.compile("foo()", functions, getClass().getClassLoader());
+              compile("foo()", functions);
             });
     assertTrue(expected.getMessage().contains("does not return a double"));
   }
@@ -169,7 +165,7 @@ public class TestCustomFunctions extends LuceneTestCase {
         expectThrows(
             IllegalArgumentException.class,
             () -> {
-              JavascriptCompiler.compile("foo(2)", functions, getClass().getClassLoader());
+              compile("foo(2)", functions);
             });
     assertTrue(expected.getMessage().contains("must take only double parameters"));
   }
@@ -186,7 +182,7 @@ public class TestCustomFunctions extends LuceneTestCase {
         expectThrows(
             IllegalArgumentException.class,
             () -> {
-              JavascriptCompiler.compile("foo()", functions, getClass().getClassLoader());
+              compile("foo()", functions);
             });
     assertTrue(expected.getMessage().contains("is not static"));
   }
@@ -203,7 +199,7 @@ public class TestCustomFunctions extends LuceneTestCase {
         expectThrows(
             IllegalArgumentException.class,
             () -> {
-              JavascriptCompiler.compile("foo()", functions, getClass().getClassLoader());
+              compile("foo()", functions);
             });
     assertTrue(expected.getMessage().contains("not public"));
   }
@@ -222,7 +218,7 @@ public class TestCustomFunctions extends LuceneTestCase {
         expectThrows(
             IllegalArgumentException.class,
             () -> {
-              JavascriptCompiler.compile("foo()", functions, getClass().getClassLoader());
+              compile("foo()", functions);
             });
     assertTrue(expected.getMessage().contains("not public"));
   }
@@ -289,7 +285,7 @@ public class TestCustomFunctions extends LuceneTestCase {
     assertNotSame(thisLoader, barMethod.getDeclaringClass().getClassLoader());
 
     // this should pass:
-    Expression expr = JavascriptCompiler.compile("bar()", functions, childLoader);
+    Expression expr = compile("bar()", functions, childLoader);
     assertEquals(2.0, expr.evaluate(null), DELTA);
 
     // use our classloader, not the foreign one, which should fail!
@@ -297,7 +293,7 @@ public class TestCustomFunctions extends LuceneTestCase {
         expectThrows(
             IllegalArgumentException.class,
             () -> {
-              JavascriptCompiler.compile("bar()", functions, thisLoader);
+              compile("bar()", functions, thisLoader);
             });
     assertTrue(
         expected
@@ -308,9 +304,9 @@ public class TestCustomFunctions extends LuceneTestCase {
     // mix foreign and default functions
     Map<String, Method> mixedFunctions = new HashMap<>(JavascriptCompiler.DEFAULT_FUNCTIONS);
     mixedFunctions.putAll(functions);
-    expr = JavascriptCompiler.compile("bar()", mixedFunctions, childLoader);
+    expr = compile("bar()", mixedFunctions, childLoader);
     assertEquals(2.0, expr.evaluate(null), DELTA);
-    expr = JavascriptCompiler.compile("sqrt(20)", mixedFunctions, childLoader);
+    expr = compile("sqrt(20)", mixedFunctions, childLoader);
     assertEquals(Math.sqrt(20), expr.evaluate(null), DELTA);
 
     // use our classloader, not the foreign one, which should fail!
@@ -318,7 +314,7 @@ public class TestCustomFunctions extends LuceneTestCase {
         expectThrows(
             IllegalArgumentException.class,
             () -> {
-              JavascriptCompiler.compile("bar()", mixedFunctions, thisLoader);
+              compile("bar()", mixedFunctions, thisLoader);
             });
     assertTrue(
         expected
@@ -343,7 +339,7 @@ public class TestCustomFunctions extends LuceneTestCase {
     Map<String, Method> functions = new HashMap<>();
     functions.put("foo", StaticThrowingException.class.getMethod("method"));
     String source = "3 * foo() / 5";
-    Expression expr = JavascriptCompiler.compile(source, functions, getClass().getClassLoader());
+    Expression expr = compile(source, functions);
     ArithmeticException expected =
         expectThrows(
             ArithmeticException.class,
@@ -364,7 +360,7 @@ public class TestCustomFunctions extends LuceneTestCase {
     Map<String, Method> functions = new HashMap<>();
     functions.put("foo.bar", getClass().getMethod("zeroArgMethod"));
     String source = "foo.bar()";
-    Expression expr = JavascriptCompiler.compile(source, functions, getClass().getClassLoader());
+    Expression expr = compile(source, functions);
     assertEquals(5, expr.evaluate(null), DELTA);
   }
 }
diff --git a/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptCompiler.java b/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptCompiler.java
index 6c15afb1239..69eab4cdfc1 100644
--- a/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptCompiler.java
+++ b/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptCompiler.java
@@ -18,15 +18,43 @@ package org.apache.lucene.expressions.js;
 
 import java.text.ParseException;
 import org.apache.lucene.expressions.Expression;
-import org.apache.lucene.tests.util.LuceneTestCase;
 
-public class TestJavascriptCompiler extends LuceneTestCase {
+public class TestJavascriptCompiler extends CompilerTestCase {
+
+  public void testNullExpression() throws Exception {
+    expectThrows(
+        NullPointerException.class,
+        () -> {
+          JavascriptCompiler.compile(null);
+        });
+  }
+
+  public void testNullFunctions() throws Exception {
+    expectThrows(
+        NullPointerException.class,
+        () -> {
+          JavascriptCompiler.compile("100", null, getClass().getClassLoader());
+        });
+  }
+
+  public void testNullLoader() throws Exception {
+    expectThrows(
+        NullPointerException.class,
+        () -> {
+          JavascriptCompiler.compile("100", JavascriptCompiler.DEFAULT_FUNCTIONS, null);
+        });
+  }
+
+  public void testEnormousExpressionSource() throws Exception {
+    String expr = " ".repeat(20000) + "100";
+    assertNotNull(compile(expr));
+  }
 
   public void testValidCompiles() throws Exception {
-    assertNotNull(JavascriptCompiler.compile("100"));
-    assertNotNull(JavascriptCompiler.compile("valid0+100"));
-    assertNotNull(JavascriptCompiler.compile("valid0+\n100"));
-    assertNotNull(JavascriptCompiler.compile("logn(2, 20+10-5.0)"));
+    assertNotNull(compile("100"));
+    assertNotNull(compile("valid0+100"));
+    assertNotNull(compile("valid0+\n100"));
+    assertNotNull(compile("logn(2, 20+10-5.0)"));
   }
 
   public void testValidVariables() throws Exception {
@@ -66,7 +94,7 @@ public class TestJavascriptCompiler extends LuceneTestCase {
   }
 
   void doTestValidVariable(String variable, String output) throws Exception {
-    Expression e = JavascriptCompiler.compile(variable);
+    Expression e = compile(variable);
     assertNotNull(e);
     assertEquals(1, e.variables.length);
     assertEquals(output, e.variables[0]);
@@ -93,7 +121,7 @@ public class TestJavascriptCompiler extends LuceneTestCase {
     expectThrows(
         ParseException.class,
         () -> {
-          JavascriptCompiler.compile(variable);
+          compile(variable);
         });
   }
 
@@ -102,7 +130,7 @@ public class TestJavascriptCompiler extends LuceneTestCase {
         expectThrows(
             ParseException.class,
             () -> {
-              JavascriptCompiler.compile("\n .");
+              compile("\n .");
             });
     assertTrue(expected.getMessage().contains("unexpected character '.' on line (2) position (1)"));
   }
@@ -111,31 +139,31 @@ public class TestJavascriptCompiler extends LuceneTestCase {
     expectThrows(
         ParseException.class,
         () -> {
-          JavascriptCompiler.compile("100 100");
+          compile("100 100");
         });
 
     expectThrows(
         ParseException.class,
         () -> {
-          JavascriptCompiler.compile("7*/-8");
+          compile("7*/-8");
         });
 
     expectThrows(
         ParseException.class,
         () -> {
-          JavascriptCompiler.compile("0y1234");
+          compile("0y1234");
         });
 
     expectThrows(
         ParseException.class,
         () -> {
-          JavascriptCompiler.compile("500EE");
+          compile("500EE");
         });
 
     expectThrows(
         ParseException.class,
         () -> {
-          JavascriptCompiler.compile("500.5EE");
+          compile("500.5EE");
         });
   }
 
@@ -143,19 +171,19 @@ public class TestJavascriptCompiler extends LuceneTestCase {
     expectThrows(
         ParseException.class,
         () -> {
-          JavascriptCompiler.compile("");
+          compile("");
         });
 
     expectThrows(
         ParseException.class,
         () -> {
-          JavascriptCompiler.compile("()");
+          compile("()");
         });
 
     expectThrows(
         ParseException.class,
         () -> {
-          JavascriptCompiler.compile("   \r\n   \n \t");
+          compile("   \r\n   \n \t");
         });
   }
 
@@ -163,7 +191,7 @@ public class TestJavascriptCompiler extends LuceneTestCase {
     expectThrows(
         NullPointerException.class,
         () -> {
-          JavascriptCompiler.compile(null);
+          compile(null);
         });
   }
 
@@ -172,7 +200,7 @@ public class TestJavascriptCompiler extends LuceneTestCase {
         expectThrows(
             ParseException.class,
             () -> {
-              JavascriptCompiler.compile("tan()");
+              compile("tan()");
               fail();
             });
     assertEquals(
@@ -184,7 +212,7 @@ public class TestJavascriptCompiler extends LuceneTestCase {
         expectThrows(
             ParseException.class,
             () -> {
-              JavascriptCompiler.compile("tan(1, 1)");
+              compile("tan(1, 1)");
             });
     assertTrue(expected.getMessage().contains("arguments for function call"));
 
@@ -192,7 +220,7 @@ public class TestJavascriptCompiler extends LuceneTestCase {
         expectThrows(
             ParseException.class,
             () -> {
-              JavascriptCompiler.compile(" tan()");
+              compile(" tan()");
             });
     assertEquals(
         "Invalid expression ' tan()': Expected (1) arguments for function call (tan), but found (0).",
@@ -203,7 +231,7 @@ public class TestJavascriptCompiler extends LuceneTestCase {
         expectThrows(
             ParseException.class,
             () -> {
-              JavascriptCompiler.compile("1 + tan()");
+              compile("1 + tan()");
             });
     assertEquals(
         "Invalid expression '1 + tan()': Expected (1) arguments for function call (tan), but found (0).",
@@ -213,27 +241,27 @@ public class TestJavascriptCompiler extends LuceneTestCase {
 
   public void testVariableNormalization() throws Exception {
     // multiple double quotes
-    Expression x = JavascriptCompiler.compile("foo[\"a\"][\"b\"]");
+    Expression x = compile("foo[\"a\"][\"b\"]");
     assertEquals("foo['a']['b']", x.variables[0]);
 
     // single and double in the same var
-    x = JavascriptCompiler.compile("foo['a'][\"b\"]");
+    x = compile("foo['a'][\"b\"]");
     assertEquals("foo['a']['b']", x.variables[0]);
 
     // escapes remain the same in single quoted strings
-    x = JavascriptCompiler.compile("foo['\\\\\\'\"']");
+    x = compile("foo['\\\\\\'\"']");
     assertEquals("foo['\\\\\\'\"']", x.variables[0]);
 
     // single quotes are escaped
-    x = JavascriptCompiler.compile("foo[\"'\"]");
+    x = compile("foo[\"'\"]");
     assertEquals("foo['\\'']", x.variables[0]);
 
     // double quotes are unescaped
-    x = JavascriptCompiler.compile("foo[\"\\\"\"]");
+    x = compile("foo[\"\\\"\"]");
     assertEquals("foo['\"']", x.variables[0]);
 
     // backslash escapes are kept the same
-    x = JavascriptCompiler.compile("foo['\\\\'][\"\\\\\"]");
+    x = compile("foo['\\\\'][\"\\\\\"]");
     assertEquals("foo['\\\\']['\\\\']", x.variables[0]);
   }
 }
diff --git a/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptFunction.java b/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptFunction.java
index 3976ced9ae1..dbc7c046f01 100644
--- a/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptFunction.java
+++ b/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptFunction.java
@@ -17,13 +17,12 @@
 package org.apache.lucene.expressions.js;
 
 import org.apache.lucene.expressions.Expression;
-import org.apache.lucene.tests.util.LuceneTestCase;
 
-public class TestJavascriptFunction extends LuceneTestCase {
+public class TestJavascriptFunction extends CompilerTestCase {
   private static double DELTA = 0.0000001;
 
   private void assertEvaluatesTo(String expression, double expected) throws Exception {
-    Expression evaluator = JavascriptCompiler.compile(expression);
+    Expression evaluator = compile(expression);
     double actual = evaluator.evaluate(null);
     assertEquals(expected, actual, DELTA);
   }
diff --git a/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptOperations.java b/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptOperations.java
index 22ccc83d0eb..44e86bbaa9f 100644
--- a/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptOperations.java
+++ b/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptOperations.java
@@ -17,11 +17,10 @@
 package org.apache.lucene.expressions.js;
 
 import org.apache.lucene.expressions.Expression;
-import org.apache.lucene.tests.util.LuceneTestCase;
 
-public class TestJavascriptOperations extends LuceneTestCase {
+public class TestJavascriptOperations extends CompilerTestCase {
   private void assertEvaluatesTo(String expression, long expected) throws Exception {
-    Expression evaluator = JavascriptCompiler.compile(expression);
+    Expression evaluator = compile(expression);
     long actual = (long) evaluator.evaluate(null);
     assertEquals(expected, actual);
   }
diff --git a/lucene/licenses/antlr4-runtime-4.11.1.jar.sha1 b/lucene/licenses/antlr4-runtime-4.11.1.jar.sha1
new file mode 100644
index 00000000000..73976600b73
--- /dev/null
+++ b/lucene/licenses/antlr4-runtime-4.11.1.jar.sha1
@@ -0,0 +1 @@
+069214c1de1960040729702eb58deac8827135e7
diff --git a/lucene/licenses/antlr4-runtime-4.5.1-1.jar.sha1 b/lucene/licenses/antlr4-runtime-4.5.1-1.jar.sha1
deleted file mode 100644
index f15e50069ba..00000000000
--- a/lucene/licenses/antlr4-runtime-4.5.1-1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-66144204f9d6d7d3f3f775622c2dd7e9bd511d97
diff --git a/versions.lock b/versions.lock
index d38f82981ed..14035125f8a 100644
--- a/versions.lock
+++ b/versions.lock
@@ -8,7 +8,7 @@ io.sgr:s2-geometry-library-java:1.0.0 (1 constraints: 0305f035)
 javax.servlet:javax.servlet-api:3.1.0 (2 constraints: 88129b22)
 junit:junit:4.13.1 (1 constraints: 3b05453b)
 net.sourceforge.nekohtml:nekohtml:1.9.17 (1 constraints: 4405503b)
-org.antlr:antlr4-runtime:4.5.1-1 (1 constraints: 6a05b240)
+org.antlr:antlr4-runtime:4.11.1 (1 constraints: 39053f3b)
 org.apache.commons:commons-compress:1.19 (1 constraints: df04fa30)
 org.apache.httpcomponents:httpclient:4.5.13 (1 constraints: 3f054e3b)
 org.apache.httpcomponents:httpcore:4.4.13 (1 constraints: 591016a2)
diff --git a/versions.props b/versions.props
index 9218ea5fd8a..1f5341bae6e 100644
--- a/versions.props
+++ b/versions.props
@@ -8,7 +8,7 @@ io.sgr:s2-geometry-library-java=1.0.0
 javax.servlet:javax.servlet-api=3.1.0
 junit:junit=4.13.1
 net.sourceforge.nekohtml:nekohtml=1.9.17
-org.antlr:antlr4*=4.5.1-1
+org.antlr:antlr4*=4.11.1
 org.apache.commons:commons-compress=1.19
 org.apache.httpcomponents:httpclient=4.5.13
 org.apache.opennlp:opennlp-tools=1.9.1