Browse Source

Add Support for LIKE (LIST) (#129170)

Adds support for LIKE function alternative syntax with a list of patterns.
Examples:

FROM foo
| WHERE bar LIKE ("A*","B*", "C?")
The new syntax is documented as part of the existing LIKE function documentation. We will use the existing WildcardLike java implementation for existing cases using the old syntax and one list argument case to improve mixed cluster compatibility.
Julian Kiryakov 3 months ago
parent
commit
7fb130c53b
28 changed files with 1767 additions and 596 deletions
  1. 5 0
      docs/changelog/129170.yaml
  2. 6 0
      docs/reference/query-languages/esql/_snippets/operators/detailedDescription/like.md
  3. 1 1
      docs/reference/query-languages/esql/kibana/definition/operators/like.json
  4. 1 1
      docs/reference/query-languages/esql/kibana/definition/operators/not like.json
  5. 2 1
      docs/reference/query-languages/esql/kibana/docs/operators/like.md
  6. 2 1
      docs/reference/query-languages/esql/kibana/docs/operators/not like.md
  7. 16 2
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/predicate/regex/WildcardPattern.java
  8. 103 0
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/predicate/regex/WildcardPatternList.java
  9. 36 0
      x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/PushQueriesIT.java
  10. 452 1
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/where-like.csv-spec
  11. 3 2
      x-pack/plugin/esql/src/main/antlr/parser/Expression.g4
  12. 3 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java
  13. 2 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java
  14. 4 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/regex/WildcardLike.java
  15. 121 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/regex/WildcardLikeList.java
  16. 5 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/ReplaceStringCasingWithInsensitiveRegexMatch.java
  17. 0 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp
  18. 674 550
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java
  19. 26 2
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserBaseListener.java
  20. 15 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserBaseVisitor.java
  21. 30 4
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserListener.java
  22. 17 2
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserVisitor.java
  23. 39 24
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/ExpressionBuilder.java
  24. 49 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/WildcardLikeListErrorTests.java
  25. 54 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/WildcardLikeListSerializationTests.java
  26. 99 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/WildcardLikeListTests.java
  27. 1 1
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java
  28. 1 1
      x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/regex/WildcardPattern.java

+ 5 - 0
docs/changelog/129170.yaml

@@ -0,0 +1,5 @@
+pr: 129170
+summary: Add Support for LIKE (LIST)
+area: ES|QL
+type: enhancement
+issues: []

+ 6 - 0
docs/reference/query-languages/esql/_snippets/operators/detailedDescription/like.md

@@ -10,6 +10,12 @@ ROW message = "foo * bar"
 ```
 
 
+```esql
+ROW message = "foobar"
+| WHERE message like ("foo*", "bar?")
+```
+
+
 To reduce the overhead of escaping, we suggest using triple quotes strings `"""`
 
 ```esql

+ 1 - 1
docs/reference/query-languages/esql/kibana/definition/operators/like.json

@@ -3,7 +3,7 @@
   "type" : "operator",
   "operator" : "LIKE",
   "name" : "like",
-  "description" : "Use `LIKE` to filter data based on string patterns using wildcards. `LIKE`\nusually acts on a field placed on the left-hand side of the operator, but it can\nalso act on a constant (literal) expression. The right-hand side of the operator\nrepresents the pattern.\n\nThe following wildcard characters are supported:\n\n* `*` matches zero or more characters.\n* `?` matches one character.",
+  "description" : "Use `LIKE` to filter data based on string patterns using wildcards. `LIKE`\nusually acts on a field placed on the left-hand side of the operator, but it can\nalso act on a constant (literal) expression. The right-hand side of the operator\nrepresents the pattern or a list of patterns. If a list of patterns is provided,\nthe expression will return true if any of the patterns match.\n\nThe following wildcard characters are supported:\n\n* `*` matches zero or more characters.\n* `?` matches one character.",
   "signatures" : [
     {
       "params" : [

+ 1 - 1
docs/reference/query-languages/esql/kibana/definition/operators/not like.json

@@ -3,7 +3,7 @@
   "type" : "operator",
   "operator" : "not like",
   "name" : "not_like",
-  "description" : "Use `LIKE` to filter data based on string patterns using wildcards. `LIKE`\nusually acts on a field placed on the left-hand side of the operator, but it can\nalso act on a constant (literal) expression. The right-hand side of the operator\nrepresents the pattern.\n\nThe following wildcard characters are supported:\n\n* `*` matches zero or more characters.\n* `?` matches one character.",
+  "description" : "Use `LIKE` to filter data based on string patterns using wildcards. `LIKE`\nusually acts on a field placed on the left-hand side of the operator, but it can\nalso act on a constant (literal) expression. The right-hand side of the operator\nrepresents the pattern or a list of patterns. If a list of patterns is provided,\nthe expression will return true if any of the patterns match.\n\nThe following wildcard characters are supported:\n\n* `*` matches zero or more characters.\n* `?` matches one character.",
   "signatures" : [
     {
       "params" : [

+ 2 - 1
docs/reference/query-languages/esql/kibana/docs/operators/like.md

@@ -4,7 +4,8 @@
 Use `LIKE` to filter data based on string patterns using wildcards. `LIKE`
 usually acts on a field placed on the left-hand side of the operator, but it can
 also act on a constant (literal) expression. The right-hand side of the operator
-represents the pattern.
+represents the pattern or a list of patterns. If a list of patterns is provided,
+the expression will return true if any of the patterns match.
 
 The following wildcard characters are supported:
 

+ 2 - 1
docs/reference/query-languages/esql/kibana/docs/operators/not like.md

@@ -4,7 +4,8 @@
 Use `LIKE` to filter data based on string patterns using wildcards. `LIKE`
 usually acts on a field placed on the left-hand side of the operator, but it can
 also act on a constant (literal) expression. The right-hand side of the operator
-represents the pattern.
+represents the pattern or a list of patterns. If a list of patterns is provided,
+the expression will return true if any of the patterns match.
 
 The following wildcard characters are supported:
 

+ 16 - 2
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/predicate/regex/WildcardPattern.java

@@ -11,8 +11,12 @@ import org.apache.lucene.search.WildcardQuery;
 import org.apache.lucene.util.automaton.Automaton;
 import org.apache.lucene.util.automaton.Operations;
 import org.apache.lucene.util.automaton.RegExp;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.io.stream.StreamOutput;
+import org.elasticsearch.common.io.stream.Writeable;
 import org.elasticsearch.xpack.esql.core.util.StringUtils;
 
+import java.io.IOException;
 import java.util.Objects;
 
 import static org.elasticsearch.xpack.esql.core.util.StringUtils.luceneWildcardToRegExp;
@@ -21,10 +25,10 @@ import static org.elasticsearch.xpack.esql.core.util.StringUtils.luceneWildcardT
  * Similar to basic regex, supporting '?' wildcard for single character (same as regex  ".")
  * and '*' wildcard for multiple characters (same as regex ".*")
  * <p>
- * Allows escaping based on a regular char
+ * Allows escaping based on a regular char.
  *
  */
-public class WildcardPattern extends AbstractStringPattern {
+public class WildcardPattern extends AbstractStringPattern implements Writeable {
 
     private final String wildcard;
     private final String regex;
@@ -35,6 +39,15 @@ public class WildcardPattern extends AbstractStringPattern {
         this.regex = StringUtils.wildcardToJavaPattern(pattern, '\\');
     }
 
+    public WildcardPattern(StreamInput in) throws IOException {
+        this(in.readString());
+    }
+
+    @Override
+    public void writeTo(StreamOutput out) throws IOException {
+        out.writeString(wildcard);
+    }
+
     public String pattern() {
         return wildcard;
     }
@@ -87,4 +100,5 @@ public class WildcardPattern extends AbstractStringPattern {
         WildcardPattern other = (WildcardPattern) obj;
         return Objects.equals(wildcard, other.wildcard);
     }
+
 }

+ 103 - 0
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/predicate/regex/WildcardPatternList.java

@@ -0,0 +1,103 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+package org.elasticsearch.xpack.esql.core.expression.predicate.regex;
+
+import org.apache.lucene.util.automaton.Automaton;
+import org.apache.lucene.util.automaton.Operations;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.io.stream.StreamOutput;
+import org.elasticsearch.common.io.stream.Writeable;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * A list of wildcard patterns. Each pattern is a {@link WildcardPattern} that can be used to match strings and is
+ * similar to basic regex, supporting '?' wildcard for single character (same as regex  ".")
+ * and '*' wildcard for multiple characters (same as regex ".*")
+ * <p>
+ * Allows escaping based on a regular char.
+ *
+ */
+public class WildcardPatternList extends AbstractStringPattern implements Writeable {
+    public static final String NAME = "WildcardPatternList";
+    private final List<WildcardPattern> patternList;
+
+    public WildcardPatternList(List<WildcardPattern> patterns) {
+        this.patternList = patterns;
+    }
+
+    public WildcardPatternList(StreamInput in) throws IOException {
+        this(in.readCollectionAsList(WildcardPattern::new));
+    }
+
+    @Override
+    public void writeTo(StreamOutput out) throws IOException {
+        out.writeCollection(patternList, (o, pattern) -> pattern.writeTo(o));
+    }
+
+    public List<WildcardPattern> patternList() {
+        return patternList;
+    }
+
+    /**
+     * Creates an automaton that matches any of the patterns in the list.
+     * We create a single automaton that is the union of all individual automata to improve performance
+     */
+    @Override
+    public Automaton createAutomaton(boolean ignoreCase) {
+        List<Automaton> automatonList = patternList.stream().map(x -> x.createAutomaton(ignoreCase)).toList();
+        Automaton result = Operations.union(automatonList);
+        return Operations.determinize(result, Operations.DEFAULT_DETERMINIZE_WORK_LIMIT);
+    }
+
+    /**
+     * Returns a Java regex that matches any of the patterns in the list.
+     * The patterns are joined with the '|' operator to create a single regex.
+     */
+    @Override
+    public String asJavaRegex() {
+        return patternList.stream().map(WildcardPattern::asJavaRegex).collect(Collectors.joining("|"));
+    }
+
+    /**
+     * Returns a string that matches any of the patterns in the list.
+     * The patterns are joined with the '|' operator to create a single wildcard string.
+     */
+    @Override
+    public String pattern() {
+        if (patternList.isEmpty()) {
+            return "";
+        }
+        if (patternList.size() == 1) {
+            return patternList.getFirst().pattern();
+        }
+        return "(\"" + patternList.stream().map(WildcardPattern::pattern).collect(Collectors.joining("\", \"")) + "\")";
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(patternList);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+
+        WildcardPatternList other = (WildcardPatternList) obj;
+        return patternList.equals(other.patternList);
+    }
+
+}

+ 36 - 0
x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/PushQueriesIT.java

@@ -239,6 +239,42 @@ public class PushQueriesIT extends ESRestTestCase {
         testPushQuery(value, esqlQuery, List.of(luceneQuery), dataNodeSignature, true);
     }
 
+    public void testLike() throws IOException {
+        String value = "v".repeat(between(0, 256));
+        String esqlQuery = """
+            FROM test
+            | WHERE test like "%value*"
+            """;
+        String luceneQuery = switch (type) {
+            case KEYWORD -> "test:%value*";
+            case CONSTANT_KEYWORD, MATCH_ONLY_TEXT_WITH_KEYWORD, AUTO, TEXT_WITH_KEYWORD -> "*:*";
+            case SEMANTIC_TEXT_WITH_KEYWORD -> "FieldExistsQuery [field=_primary_term]";
+        };
+        ComputeSignature dataNodeSignature = switch (type) {
+            case CONSTANT_KEYWORD, KEYWORD -> ComputeSignature.FILTER_IN_QUERY;
+            case AUTO, TEXT_WITH_KEYWORD, MATCH_ONLY_TEXT_WITH_KEYWORD, SEMANTIC_TEXT_WITH_KEYWORD -> ComputeSignature.FILTER_IN_COMPUTE;
+        };
+        testPushQuery(value, esqlQuery, List.of(luceneQuery), dataNodeSignature, true);
+    }
+
+    public void testLikeList() throws IOException {
+        String value = "v".repeat(between(0, 256));
+        String esqlQuery = """
+            FROM test
+            | WHERE test like ("%value*", "abc*")
+            """;
+        String luceneQuery = switch (type) {
+            case KEYWORD, CONSTANT_KEYWORD, MATCH_ONLY_TEXT_WITH_KEYWORD, AUTO, TEXT_WITH_KEYWORD -> "*:*";
+            case SEMANTIC_TEXT_WITH_KEYWORD -> "FieldExistsQuery [field=_primary_term]";
+        };
+        ComputeSignature dataNodeSignature = switch (type) {
+            case CONSTANT_KEYWORD -> ComputeSignature.FILTER_IN_QUERY;
+            case AUTO, KEYWORD, TEXT_WITH_KEYWORD, MATCH_ONLY_TEXT_WITH_KEYWORD, SEMANTIC_TEXT_WITH_KEYWORD ->
+                ComputeSignature.FILTER_IN_COMPUTE;
+        };
+        testPushQuery(value, esqlQuery, List.of(luceneQuery), dataNodeSignature, true);
+    }
+
     enum ComputeSignature {
         FILTER_IN_COMPUTE(
             matchesList().item("LuceneSourceOperator")

+ 452 - 1
x-pack/plugin/esql/qa/testFixtures/src/main/resources/where-like.csv-spec

@@ -74,7 +74,6 @@ emp_no:integer | first_name:keyword
 10013          | Eberhardt      
 ;
 
-
 likeEvalNoWildcard
 from employees | eval x = concat(first_name, "X") | where x like "EberhardtX" | keep emp_no, first_name;
 
@@ -82,6 +81,458 @@ emp_no:integer | first_name:keyword
 10013          | Eberhardt      
 ;
 
+likeListEmptyArgWildcard
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name like ("") 
+| KEEP emp_no, first_name;
+
+emp_no:integer | first_name:keyword    
+;
+
+likeListSingleArgWildcard
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name like ("Eberhardt*") 
+| KEEP emp_no, first_name;
+
+emp_no:integer | first_name:keyword
+10013          | Eberhardt      
+;
+
+likeListTwoArgWildcard
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name like ("Eberhardt*", "testString*") 
+| KEEP emp_no, first_name;
+
+emp_no:integer | first_name:keyword
+10013          | Eberhardt       
+;
+
+likeListDocExample
+required_capability: like_with_list_of_patterns
+// tag::likeListDocExample[]
+ROW message = "foobar" 
+| WHERE message like ("foo*", "bar?")
+// end::likeListDocExample[]
+;
+
+message:string
+foobar   
+;
+
+likeListThreeArgWildcard
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name like ("Eberhardt*", "Ot*", "Part?") 
+| KEEP emp_no, first_name  
+| SORT emp_no;
+
+emp_no:integer | first_name:keyword
+10003          | Parto
+10013          | Eberhardt
+10029          | Otmar     
+;
+
+
+likeListMultipleWhere
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name like ("Eberhardt*", "Ot*", "Part?") 
+| WHERE first_name like ("Eberhard?", "Otm*")
+| KEEP emp_no, first_name
+| SORT emp_no;
+
+emp_no:integer | first_name:keyword
+10013          | Eberhardt
+10029          | Otmar
+;
+
+likeListAllWildcard
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name like ("*") 
+| KEEP emp_no, first_name 
+| SORT emp_no 
+| LIMIT 2;
+
+emp_no:integer | first_name:keyword
+10001          | Georgi
+10002          | Bezalel
+;
+
+likeListOverlappingPatterns
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name like ("Eber*", "Eberhardt") 
+| KEEP emp_no, first_name;
+
+emp_no:integer | first_name:keyword
+10013          | Eberhardt
+;
+
+likeListCaseSensitive
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name like ("eberhardt", "EBERHARDT") 
+| KEEP emp_no, first_name;
+
+emp_no:integer | first_name:keyword
+;
+
+likeListSpecialCharacters
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name like ("*ar*", "?eor*") 
+| KEEP emp_no, first_name 
+| SORT emp_no;
+
+emp_no:integer | first_name:keyword
+10001          | Georgi
+10003          | Parto
+10011          | Mary
+10013          | Eberhardt
+10029          | Otmar
+10055          | Georgy
+10058          | Berhard
+10068          | Charlene
+10069          | Margareta
+10074          | Mokhtar
+10082          | Parviz
+10089          | Sudharsan
+10095          | Hilari
+;
+
+likeListEscapedWildcard
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name like ("Eberhar\\*") 
+| KEEP emp_no, first_name;
+
+emp_no:integer | first_name:keyword
+;
+
+likeListNineOrMoreLetters
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name like ("?????????*") 
+| KEEP emp_no, first_name 
+| SORT emp_no;
+
+emp_no:integer | first_name:keyword
+10004          | Chirstian
+10010          | Duangkaew
+10013          | Eberhardt
+10017          | Cristinel
+10025          | Prasadram
+10059          | Alejandro
+10069          | Margareta
+10089          | Sudharsan
+10092          | Valdiodio
+10098          | Sreekrishna
+;
+
+notLikeListThreeArgWildcardNotOtherFilter
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name not like ("Eberhardt*", "Ot*", "Part?") and emp_no < 10010 
+| KEEP emp_no, first_name
+| SORT emp_no;
+
+emp_no:integer | first_name:keyword
+10001          | Georgi
+10002          | Bezalel
+10004          | Chirstian
+10005          | Kyoichi
+10006          | Anneke
+10007          | Tzvetan
+10008          | Saniya
+10009          | Sumant   
+;
+
+likeListBeginningWithWildcard
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name like ("A*", "B*", "C*") 
+| KEEP emp_no, first_name 
+| SORT emp_no;
+
+emp_no:integer | first_name:keyword
+10002          | Bezalel
+10004          | Chirstian
+10006          | Anneke
+10014          | Berni
+10017          | Cristinel
+10023          | Bojan
+10049          | Basil
+10056          | Brendon
+10058          | Berhard
+10059          | Alejandro
+10060          | Breannda
+10062          | Anoosh
+10067          | Claudi
+10068          | Charlene
+10091          | Amabile
+10094          | Arumugam 
+;
+
+notLikeListThreeArgWildcardOtherFirst
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE emp_no < 10010 and first_name not like ("Eberhardt*", "Ot*", "Part?") 
+| KEEP emp_no, first_name  
+| SORT emp_no;
+
+emp_no:integer | first_name:keyword
+10001          | Georgi
+10002          | Bezalel
+10004          | Chirstian
+10005          | Kyoichi
+10006          | Anneke
+10007          | Tzvetan
+10008          | Saniya
+10009          | Sumant   
+;
+
+notLikeFiveOrLessLetters
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name not like ("??????*") 
+| KEEP emp_no, first_name 
+| SORT emp_no;
+
+emp_no:integer | first_name:keyword
+10003          | Parto
+10011          | Mary
+10014          | Berni
+10021          | Ramzi
+10023          | Bojan
+10029          | Otmar
+10040          | Weiyi
+10041          | Uri
+10042          | Magy
+10045          | Moss
+10049          | Basil
+10057          | Ebbe
+10061          | Tse
+10063          | Gino
+10064          | Udi
+10066          | Kwee
+10071          | Hisao
+10073          | Shir
+10075          | Gao
+10076          | Erez
+10077          | Mona
+10078          | Danel
+10083          | Vishv
+10084          | Tuval
+10097          | Remzi
+;
+
+notLikeListMultipleWhere
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name not like ("Eberhardt*", "Ot*", "Part?", "A*", "B*", "C*", "D*") 
+| WHERE first_name not like ("Eberhard?", "Otm*", "F*", "G*", "H*", "I*", "J*", "K*", "L*")
+| KEEP emp_no, first_name 
+| SORT emp_no;
+
+emp_no:integer | first_name:keyword
+10007          | Tzvetan
+10008          | Saniya
+10009          | Sumant
+10011          | Mary
+10012          | Patricio
+10020          | Mayuko
+10021          | Ramzi
+10022          | Shahaf
+10024          | Suzette
+10025          | Prasadram
+10026          | Yongqiao
+10040          | Weiyi
+10041          | Uri
+10042          | Magy
+10043          | Yishay
+10044          | Mingsen
+10045          | Moss
+10047          | Zvonko
+10050          | Yinghua
+10053          | Sanjiv
+10054          | Mayumi
+10057          | Ebbe
+10061          | Tse
+10064          | Udi
+10065          | Satosi
+10069          | Margareta
+10070          | Reuven
+10073          | Shir
+10074          | Mokhtar
+10076          | Erez
+10077          | Mona
+10080          | Premal
+10081          | Zhongwei
+10082          | Parviz
+10083          | Vishv
+10084          | Tuval
+10086          | Somnath
+10087          | Xinglin
+10089          | Sudharsan
+10092          | Valdiodio
+10093          | Sailaja
+10097          | Remzi
+10098          | Sreekrishna
+10099          | Valter
+;
+
+notLikeListNotField
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE not first_name like ("Eberhardt*", "Ot*", "Part?", "A*", "B*", "C*", "D*") 
+| WHERE first_name not like ("Eberhard?", "Otm*", "F*", "G*", "H*", "I*", "J*", "K*", "L*")
+| KEEP emp_no, first_name 
+| SORT emp_no;
+
+emp_no:integer | first_name:keyword
+10007          | Tzvetan
+10008          | Saniya
+10009          | Sumant
+10011          | Mary
+10012          | Patricio
+10020          | Mayuko
+10021          | Ramzi
+10022          | Shahaf
+10024          | Suzette
+10025          | Prasadram
+10026          | Yongqiao
+10040          | Weiyi
+10041          | Uri
+10042          | Magy
+10043          | Yishay
+10044          | Mingsen
+10045          | Moss
+10047          | Zvonko
+10050          | Yinghua
+10053          | Sanjiv
+10054          | Mayumi
+10057          | Ebbe
+10061          | Tse
+10064          | Udi
+10065          | Satosi
+10069          | Margareta
+10070          | Reuven
+10073          | Shir
+10074          | Mokhtar
+10076          | Erez
+10077          | Mona
+10080          | Premal
+10081          | Zhongwei
+10082          | Parviz
+10083          | Vishv
+10084          | Tuval
+10086          | Somnath
+10087          | Xinglin
+10089          | Sudharsan
+10092          | Valdiodio
+10093          | Sailaja
+10097          | Remzi
+10098          | Sreekrishna
+10099          | Valter
+;
+
+notLikeListAllWildcard
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name not like ("*") 
+| KEEP emp_no, first_name 
+| SORT emp_no 
+| LIMIT 2;
+
+emp_no:integer | first_name:keyword
+10030          | null
+10031          | null
+;
+
+notLikeListWildcard
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE first_name not like ("A*","B*", "C*", "D*","E*", "F*", "G*", "H*", "I*", "J*", "K*") 
+| KEEP emp_no, first_name  
+| SORT emp_no;
+
+emp_no:integer | first_name:keyword
+10003          | Parto
+10007          | Tzvetan
+10008          | Saniya
+10009          | Sumant
+10011          | Mary
+10012          | Patricio
+10019          | Lillian
+10020          | Mayuko
+10021          | Ramzi
+10022          | Shahaf
+10024          | Suzette
+10025          | Prasadram
+10026          | Yongqiao
+10029          | Otmar
+10040          | Weiyi
+10041          | Uri
+10042          | Magy
+10043          | Yishay
+10044          | Mingsen
+10045          | Moss
+10046          | Lucien
+10047          | Zvonko
+10050          | Yinghua
+10053          | Sanjiv
+10054          | Mayumi
+10061          | Tse
+10064          | Udi
+10065          | Satosi
+10069          | Margareta
+10070          | Reuven
+10073          | Shir
+10074          | Mokhtar
+10077          | Mona
+10080          | Premal
+10081          | Zhongwei
+10082          | Parviz
+10083          | Vishv
+10084          | Tuval
+10086          | Somnath
+10087          | Xinglin
+10089          | Sudharsan
+10092          | Valdiodio
+10093          | Sailaja
+10097          | Remzi
+10098          | Sreekrishna
+10099          | Valter
+;
+
+likeListWithUpperTurnedInsensitive
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE TO_UPPER(first_name) LIKE ("GEOR*") 
+| KEEP emp_no, first_name 
+| SORT emp_no;
+
+emp_no:integer | first_name:keyword
+10001          | Georgi
+10055          | Georgy     
+;
+
+likeListWithUpperTurnedInsensitiveMult
+required_capability: like_with_list_of_patterns
+FROM employees 
+| WHERE TO_UPPER(first_name) LIKE ("GEOR*", "WE*")  
+| KEEP emp_no, first_name 
+| SORT emp_no;
+
+emp_no:integer | first_name:keyword
+10001          | Georgi
+10040          | Weiyi
+10055          | Georgy    
+;
 
 likeAll
 from employees | where first_name like "*" and emp_no > 10028 | sort emp_no | keep emp_no, first_name | limit 2;

+ 3 - 2
x-pack/plugin/esql/src/main/antlr/parser/Expression.g4

@@ -18,8 +18,9 @@ booleanExpression
     ;
 
 regexBooleanExpression
-    : valueExpression (NOT)? kind=LIKE pattern=string
-    | valueExpression (NOT)? kind=RLIKE pattern=string
+    : valueExpression (NOT)? LIKE string                               #likeExpression
+    | valueExpression (NOT)? RLIKE string                              #rlikeExpression
+    | valueExpression (NOT)? LIKE LP string  (COMMA string )* RP       #likeListExpression
     ;
 
 matchBooleanExpression

+ 3 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java

@@ -1200,7 +1200,9 @@ public class EsqlCapabilities {
         /**
          * Support knn function
          */
-        KNN_FUNCTION(Build.current().isSnapshot());
+        KNN_FUNCTION(Build.current().isSnapshot()),
+
+        LIKE_WITH_LIST_OF_PATTERNS;
 
         private final boolean enabled;
 

+ 2 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java

@@ -83,6 +83,7 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.string.Space;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.Trim;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.regex.RLike;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.regex.WildcardLike;
+import org.elasticsearch.xpack.esql.expression.function.scalar.string.regex.WildcardLikeList;
 import org.elasticsearch.xpack.esql.expression.function.scalar.util.Delay;
 import org.elasticsearch.xpack.esql.expression.function.vector.Knn;
 import org.elasticsearch.xpack.esql.expression.predicate.logical.Not;
@@ -219,6 +220,7 @@ public class ExpressionWritables {
         entries.add(ToVersion.ENTRY);
         entries.add(Trim.ENTRY);
         entries.add(WildcardLike.ENTRY);
+        entries.add(WildcardLikeList.ENTRY);
         entries.add(Delay.ENTRY);
         // mv functions
         entries.addAll(MvFunctionWritables.getNamedWriteables());

+ 4 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/regex/WildcardLike.java

@@ -38,7 +38,8 @@ public class WildcardLike extends RegexMatch<WildcardPattern> {
         Use `LIKE` to filter data based on string patterns using wildcards. `LIKE`
         usually acts on a field placed on the left-hand side of the operator, but it can
         also act on a constant (literal) expression. The right-hand side of the operator
-        represents the pattern.
+        represents the pattern or a list of patterns. If a list of patterns is provided,
+        the expression will return true if any of the patterns match.
 
         The following wildcard characters are supported:
 
@@ -50,6 +51,8 @@ public class WildcardLike extends RegexMatch<WildcardPattern> {
 
         <<load-esql-example, file=string tag=likeEscapingSingleQuotes>>
 
+        <<load-esql-example, file=where-like tag=likeListDocExample>>
+
         To reduce the overhead of escaping, we suggest using triple quotes strings `\"\"\"`
 
         <<load-esql-example, file=string tag=likeEscapingTripleQuotes>>

+ 121 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/regex/WildcardLikeList.java

@@ -0,0 +1,121 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.string.regex;
+
+import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.io.stream.StreamOutput;
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.expression.FieldAttribute;
+import org.elasticsearch.xpack.esql.core.expression.predicate.regex.WildcardPatternList;
+import org.elasticsearch.xpack.esql.core.querydsl.query.Query;
+import org.elasticsearch.xpack.esql.core.querydsl.query.WildcardQuery;
+import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.expression.function.Param;
+import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput;
+import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.LucenePushdownPredicates;
+import org.elasticsearch.xpack.esql.planner.TranslatorHandler;
+
+import java.io.IOException;
+
+public class WildcardLikeList extends RegexMatch<WildcardPatternList> {
+    public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(
+        Expression.class,
+        "WildcardLikeList",
+        WildcardLikeList::new
+    );
+
+    /**
+     * The documentation for this function is in WildcardLike, and shown to the users `LIKE` in the docs.
+     */
+    public WildcardLikeList(
+        Source source,
+        @Param(name = "str", type = { "keyword", "text" }, description = "A literal expression.") Expression left,
+        @Param(name = "pattern", type = { "keyword", "text" }, description = "Pattern.") WildcardPatternList patterns
+    ) {
+        this(source, left, patterns, false);
+    }
+
+    public WildcardLikeList(Source source, Expression left, WildcardPatternList patterns, boolean caseInsensitive) {
+        super(source, left, patterns, caseInsensitive);
+    }
+
+    public WildcardLikeList(StreamInput in) throws IOException {
+        this(
+            Source.readFrom((PlanStreamInput) in),
+            in.readNamedWriteable(Expression.class),
+            new WildcardPatternList(in),
+            deserializeCaseInsensitivity(in)
+        );
+    }
+
+    @Override
+    public void writeTo(StreamOutput out) throws IOException {
+        source().writeTo(out);
+        out.writeNamedWriteable(field());
+        pattern().writeTo(out);
+        serializeCaseInsensitivity(out);
+    }
+
+    @Override
+    public String name() {
+        return ENTRY.name;
+    }
+
+    @Override
+    public String getWriteableName() {
+        return ENTRY.name;
+    }
+
+    @Override
+    protected NodeInfo<WildcardLikeList> info() {
+        return NodeInfo.create(this, WildcardLikeList::new, field(), pattern(), caseInsensitive());
+    }
+
+    @Override
+    protected WildcardLikeList replaceChild(Expression newLeft) {
+        return new WildcardLikeList(source(), newLeft, pattern(), caseInsensitive());
+    }
+
+    /**
+     * Returns {@link Translatable#YES} if the field is pushable, otherwise {@link Translatable#NO}.
+     * For now, we only support a single pattern in the list for pushdown.
+     */
+    @Override
+    public Translatable translatable(LucenePushdownPredicates pushdownPredicates) {
+        if (pattern().patternList().size() != 1) {
+            // we only support a single pattern in the list for pushdown for now
+            return Translatable.NO;
+        }
+        return pushdownPredicates.isPushableAttribute(field()) ? Translatable.YES : Translatable.NO;
+
+    }
+
+    /**
+     * Returns a {@link Query} that matches the field against the provided patterns.
+     * For now, we only support a single pattern in the list for pushdown.
+     */
+    @Override
+    public Query asQuery(LucenePushdownPredicates pushdownPredicates, TranslatorHandler handler) {
+        var field = field();
+        LucenePushdownPredicates.checkIsPushableAttribute(field);
+        return translateField(handler.nameOf(field instanceof FieldAttribute fa ? fa.exactAttribute() : field));
+    }
+
+    /**
+     * Translates the field to a {@link WildcardQuery} using the first pattern in the list.
+     * Throws an {@link IllegalArgumentException} if the pattern list contains more than one pattern.
+     */
+    private Query translateField(String targetFieldName) {
+        if (pattern().patternList().size() != 1) {
+            throw new IllegalArgumentException("WildcardLikeList can only be translated when it has a single pattern");
+        }
+        return new WildcardQuery(source(), targetFieldName, pattern().patternList().getFirst().asLuceneWildcard(), caseInsensitive());
+    }
+}

+ 5 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/ReplaceStringCasingWithInsensitiveRegexMatch.java

@@ -11,6 +11,7 @@ import org.elasticsearch.xpack.esql.core.expression.Expression;
 import org.elasticsearch.xpack.esql.core.expression.Literal;
 import org.elasticsearch.xpack.esql.core.expression.predicate.regex.RegexMatch;
 import org.elasticsearch.xpack.esql.core.expression.predicate.regex.StringPattern;
+import org.elasticsearch.xpack.esql.core.expression.predicate.regex.WildcardPatternList;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.ChangeCase;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.regex.RLike;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.regex.WildcardLike;
@@ -28,6 +29,10 @@ public class ReplaceStringCasingWithInsensitiveRegexMatch extends OptimizerRules
     @Override
     protected Expression rule(RegexMatch<? extends StringPattern> regexMatch, LogicalOptimizerContext unused) {
         Expression e = regexMatch;
+        if (regexMatch.pattern() instanceof WildcardPatternList) {
+            // This optimization is not supported for WildcardPatternList for now
+            return e;
+        }
         if (regexMatch.field() instanceof ChangeCase changeCase) {
             var pattern = regexMatch.pattern().pattern();
             e = changeCase.caseType().matchesCase(pattern) ? insensitiveRegexMatch(regexMatch) : Literal.of(regexMatch, Boolean.FALSE);

File diff suppressed because it is too large
+ 0 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp


+ 674 - 550
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java

@@ -4938,8 +4938,20 @@ public class EsqlBaseParser extends ParserConfig {
 
   @SuppressWarnings("CheckReturnValue")
   public static class RegexBooleanExpressionContext extends ParserRuleContext {
-    public Token kind;
-    public StringContext pattern;
+    @SuppressWarnings("this-escape")
+    public RegexBooleanExpressionContext(ParserRuleContext parent, int invokingState) {
+      super(parent, invokingState);
+    }
+    @Override public int getRuleIndex() { return RULE_regexBooleanExpression; }
+   
+    @SuppressWarnings("this-escape")
+    public RegexBooleanExpressionContext() { }
+    public void copyFrom(RegexBooleanExpressionContext ctx) {
+      super.copyFrom(ctx);
+    }
+  }
+  @SuppressWarnings("CheckReturnValue")
+  public static class LikeExpressionContext extends RegexBooleanExpressionContext {
     public ValueExpressionContext valueExpression() {
       return getRuleContext(ValueExpressionContext.class,0);
     }
@@ -4948,23 +4960,80 @@ public class EsqlBaseParser extends ParserConfig {
       return getRuleContext(StringContext.class,0);
     }
     public TerminalNode NOT() { return getToken(EsqlBaseParser.NOT, 0); }
-    public TerminalNode RLIKE() { return getToken(EsqlBaseParser.RLIKE, 0); }
     @SuppressWarnings("this-escape")
-    public RegexBooleanExpressionContext(ParserRuleContext parent, int invokingState) {
-      super(parent, invokingState);
+    public LikeExpressionContext(RegexBooleanExpressionContext ctx) { copyFrom(ctx); }
+    @Override
+    public void enterRule(ParseTreeListener listener) {
+      if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).enterLikeExpression(this);
     }
-    @Override public int getRuleIndex() { return RULE_regexBooleanExpression; }
+    @Override
+    public void exitRule(ParseTreeListener listener) {
+      if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).exitLikeExpression(this);
+    }
+    @Override
+    public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+      if ( visitor instanceof EsqlBaseParserVisitor ) return ((EsqlBaseParserVisitor<? extends T>)visitor).visitLikeExpression(this);
+      else return visitor.visitChildren(this);
+    }
+  }
+  @SuppressWarnings("CheckReturnValue")
+  public static class LikeListExpressionContext extends RegexBooleanExpressionContext {
+    public ValueExpressionContext valueExpression() {
+      return getRuleContext(ValueExpressionContext.class,0);
+    }
+    public TerminalNode LIKE() { return getToken(EsqlBaseParser.LIKE, 0); }
+    public TerminalNode LP() { return getToken(EsqlBaseParser.LP, 0); }
+    public List<StringContext> string() {
+      return getRuleContexts(StringContext.class);
+    }
+    public StringContext string(int i) {
+      return getRuleContext(StringContext.class,i);
+    }
+    public TerminalNode RP() { return getToken(EsqlBaseParser.RP, 0); }
+    public TerminalNode NOT() { return getToken(EsqlBaseParser.NOT, 0); }
+    public List<TerminalNode> COMMA() { return getTokens(EsqlBaseParser.COMMA); }
+    public TerminalNode COMMA(int i) {
+      return getToken(EsqlBaseParser.COMMA, i);
+    }
+    @SuppressWarnings("this-escape")
+    public LikeListExpressionContext(RegexBooleanExpressionContext ctx) { copyFrom(ctx); }
     @Override
     public void enterRule(ParseTreeListener listener) {
-      if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).enterRegexBooleanExpression(this);
+      if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).enterLikeListExpression(this);
     }
     @Override
     public void exitRule(ParseTreeListener listener) {
-      if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).exitRegexBooleanExpression(this);
+      if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).exitLikeListExpression(this);
     }
     @Override
     public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
-      if ( visitor instanceof EsqlBaseParserVisitor ) return ((EsqlBaseParserVisitor<? extends T>)visitor).visitRegexBooleanExpression(this);
+      if ( visitor instanceof EsqlBaseParserVisitor ) return ((EsqlBaseParserVisitor<? extends T>)visitor).visitLikeListExpression(this);
+      else return visitor.visitChildren(this);
+    }
+  }
+  @SuppressWarnings("CheckReturnValue")
+  public static class RlikeExpressionContext extends RegexBooleanExpressionContext {
+    public ValueExpressionContext valueExpression() {
+      return getRuleContext(ValueExpressionContext.class,0);
+    }
+    public TerminalNode RLIKE() { return getToken(EsqlBaseParser.RLIKE, 0); }
+    public StringContext string() {
+      return getRuleContext(StringContext.class,0);
+    }
+    public TerminalNode NOT() { return getToken(EsqlBaseParser.NOT, 0); }
+    @SuppressWarnings("this-escape")
+    public RlikeExpressionContext(RegexBooleanExpressionContext ctx) { copyFrom(ctx); }
+    @Override
+    public void enterRule(ParseTreeListener listener) {
+      if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).enterRlikeExpression(this);
+    }
+    @Override
+    public void exitRule(ParseTreeListener listener) {
+      if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).exitRlikeExpression(this);
+    }
+    @Override
+    public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+      if ( visitor instanceof EsqlBaseParserVisitor ) return ((EsqlBaseParserVisitor<? extends T>)visitor).visitRlikeExpression(this);
       else return visitor.visitChildren(this);
     }
   }
@@ -4974,10 +5043,11 @@ public class EsqlBaseParser extends ParserConfig {
     enterRule(_localctx, 124, RULE_regexBooleanExpression);
     int _la;
     try {
-      setState(610);
+      setState(626);
       _errHandler.sync(this);
-      switch ( getInterpreter().adaptivePredict(_input,51,_ctx) ) {
+      switch ( getInterpreter().adaptivePredict(_input,53,_ctx) ) {
       case 1:
+        _localctx = new LikeExpressionContext(_localctx);
         enterOuterAlt(_localctx, 1);
         {
         setState(596);
@@ -4993,12 +5063,13 @@ public class EsqlBaseParser extends ParserConfig {
         }
 
         setState(600);
-        ((RegexBooleanExpressionContext)_localctx).kind = match(LIKE);
+        match(LIKE);
         setState(601);
-        ((RegexBooleanExpressionContext)_localctx).pattern = string();
+        string();
         }
         break;
       case 2:
+        _localctx = new RlikeExpressionContext(_localctx);
         enterOuterAlt(_localctx, 2);
         {
         setState(603);
@@ -5014,9 +5085,51 @@ public class EsqlBaseParser extends ParserConfig {
         }
 
         setState(607);
-        ((RegexBooleanExpressionContext)_localctx).kind = match(RLIKE);
+        match(RLIKE);
         setState(608);
-        ((RegexBooleanExpressionContext)_localctx).pattern = string();
+        string();
+        }
+        break;
+      case 3:
+        _localctx = new LikeListExpressionContext(_localctx);
+        enterOuterAlt(_localctx, 3);
+        {
+        setState(610);
+        valueExpression();
+        setState(612);
+        _errHandler.sync(this);
+        _la = _input.LA(1);
+        if (_la==NOT) {
+          {
+          setState(611);
+          match(NOT);
+          }
+        }
+
+        setState(614);
+        match(LIKE);
+        setState(615);
+        match(LP);
+        setState(616);
+        string();
+        setState(621);
+        _errHandler.sync(this);
+        _la = _input.LA(1);
+        while (_la==COMMA) {
+          {
+          {
+          setState(617);
+          match(COMMA);
+          setState(618);
+          string();
+          }
+          }
+          setState(623);
+          _errHandler.sync(this);
+          _la = _input.LA(1);
+        }
+        setState(624);
+        match(RP);
         }
         break;
       }
@@ -5075,23 +5188,23 @@ public class EsqlBaseParser extends ParserConfig {
     try {
       enterOuterAlt(_localctx, 1);
       {
-      setState(612);
+      setState(628);
       ((MatchBooleanExpressionContext)_localctx).fieldExp = qualifiedName();
-      setState(615);
+      setState(631);
       _errHandler.sync(this);
       _la = _input.LA(1);
       if (_la==CAST_OP) {
         {
-        setState(613);
+        setState(629);
         match(CAST_OP);
-        setState(614);
+        setState(630);
         ((MatchBooleanExpressionContext)_localctx).fieldType = dataType();
         }
       }
 
-      setState(617);
+      setState(633);
       match(COLON);
-      setState(618);
+      setState(634);
       ((MatchBooleanExpressionContext)_localctx).matchQuery = constant();
       }
     }
@@ -5175,14 +5288,14 @@ public class EsqlBaseParser extends ParserConfig {
     ValueExpressionContext _localctx = new ValueExpressionContext(_ctx, getState());
     enterRule(_localctx, 128, RULE_valueExpression);
     try {
-      setState(625);
+      setState(641);
       _errHandler.sync(this);
-      switch ( getInterpreter().adaptivePredict(_input,53,_ctx) ) {
+      switch ( getInterpreter().adaptivePredict(_input,55,_ctx) ) {
       case 1:
         _localctx = new ValueExpressionDefaultContext(_localctx);
         enterOuterAlt(_localctx, 1);
         {
-        setState(620);
+        setState(636);
         operatorExpression(0);
         }
         break;
@@ -5190,11 +5303,11 @@ public class EsqlBaseParser extends ParserConfig {
         _localctx = new ComparisonContext(_localctx);
         enterOuterAlt(_localctx, 2);
         {
-        setState(621);
+        setState(637);
         ((ComparisonContext)_localctx).left = operatorExpression(0);
-        setState(622);
+        setState(638);
         comparisonOperator();
-        setState(623);
+        setState(639);
         ((ComparisonContext)_localctx).right = operatorExpression(0);
         }
         break;
@@ -5319,16 +5432,16 @@ public class EsqlBaseParser extends ParserConfig {
       int _alt;
       enterOuterAlt(_localctx, 1);
       {
-      setState(631);
+      setState(647);
       _errHandler.sync(this);
-      switch ( getInterpreter().adaptivePredict(_input,54,_ctx) ) {
+      switch ( getInterpreter().adaptivePredict(_input,56,_ctx) ) {
       case 1:
         {
         _localctx = new OperatorExpressionDefaultContext(_localctx);
         _ctx = _localctx;
         _prevctx = _localctx;
 
-        setState(628);
+        setState(644);
         primaryExpression(0);
         }
         break;
@@ -5337,7 +5450,7 @@ public class EsqlBaseParser extends ParserConfig {
         _localctx = new ArithmeticUnaryContext(_localctx);
         _ctx = _localctx;
         _prevctx = _localctx;
-        setState(629);
+        setState(645);
         ((ArithmeticUnaryContext)_localctx).operator = _input.LT(1);
         _la = _input.LA(1);
         if ( !(_la==PLUS || _la==MINUS) ) {
@@ -5348,31 +5461,31 @@ public class EsqlBaseParser extends ParserConfig {
           _errHandler.reportMatch(this);
           consume();
         }
-        setState(630);
+        setState(646);
         operatorExpression(3);
         }
         break;
       }
       _ctx.stop = _input.LT(-1);
-      setState(641);
+      setState(657);
       _errHandler.sync(this);
-      _alt = getInterpreter().adaptivePredict(_input,56,_ctx);
+      _alt = getInterpreter().adaptivePredict(_input,58,_ctx);
       while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
         if ( _alt==1 ) {
           if ( _parseListeners!=null ) triggerExitRuleEvent();
           _prevctx = _localctx;
           {
-          setState(639);
+          setState(655);
           _errHandler.sync(this);
-          switch ( getInterpreter().adaptivePredict(_input,55,_ctx) ) {
+          switch ( getInterpreter().adaptivePredict(_input,57,_ctx) ) {
           case 1:
             {
             _localctx = new ArithmeticBinaryContext(new OperatorExpressionContext(_parentctx, _parentState));
             ((ArithmeticBinaryContext)_localctx).left = _prevctx;
             pushNewRecursionContext(_localctx, _startState, RULE_operatorExpression);
-            setState(633);
+            setState(649);
             if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)");
-            setState(634);
+            setState(650);
             ((ArithmeticBinaryContext)_localctx).operator = _input.LT(1);
             _la = _input.LA(1);
             if ( !(((((_la - 89)) & ~0x3f) == 0 && ((1L << (_la - 89)) & 7L) != 0)) ) {
@@ -5383,7 +5496,7 @@ public class EsqlBaseParser extends ParserConfig {
               _errHandler.reportMatch(this);
               consume();
             }
-            setState(635);
+            setState(651);
             ((ArithmeticBinaryContext)_localctx).right = operatorExpression(3);
             }
             break;
@@ -5392,9 +5505,9 @@ public class EsqlBaseParser extends ParserConfig {
             _localctx = new ArithmeticBinaryContext(new OperatorExpressionContext(_parentctx, _parentState));
             ((ArithmeticBinaryContext)_localctx).left = _prevctx;
             pushNewRecursionContext(_localctx, _startState, RULE_operatorExpression);
-            setState(636);
+            setState(652);
             if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)");
-            setState(637);
+            setState(653);
             ((ArithmeticBinaryContext)_localctx).operator = _input.LT(1);
             _la = _input.LA(1);
             if ( !(_la==PLUS || _la==MINUS) ) {
@@ -5405,16 +5518,16 @@ public class EsqlBaseParser extends ParserConfig {
               _errHandler.reportMatch(this);
               consume();
             }
-            setState(638);
+            setState(654);
             ((ArithmeticBinaryContext)_localctx).right = operatorExpression(2);
             }
             break;
           }
           } 
         }
-        setState(643);
+        setState(659);
         _errHandler.sync(this);
-        _alt = getInterpreter().adaptivePredict(_input,56,_ctx);
+        _alt = getInterpreter().adaptivePredict(_input,58,_ctx);
       }
       }
     }
@@ -5570,16 +5683,16 @@ public class EsqlBaseParser extends ParserConfig {
       int _alt;
       enterOuterAlt(_localctx, 1);
       {
-      setState(652);
+      setState(668);
       _errHandler.sync(this);
-      switch ( getInterpreter().adaptivePredict(_input,57,_ctx) ) {
+      switch ( getInterpreter().adaptivePredict(_input,59,_ctx) ) {
       case 1:
         {
         _localctx = new ConstantDefaultContext(_localctx);
         _ctx = _localctx;
         _prevctx = _localctx;
 
-        setState(645);
+        setState(661);
         constant();
         }
         break;
@@ -5588,7 +5701,7 @@ public class EsqlBaseParser extends ParserConfig {
         _localctx = new DereferenceContext(_localctx);
         _ctx = _localctx;
         _prevctx = _localctx;
-        setState(646);
+        setState(662);
         qualifiedName();
         }
         break;
@@ -5597,7 +5710,7 @@ public class EsqlBaseParser extends ParserConfig {
         _localctx = new FunctionContext(_localctx);
         _ctx = _localctx;
         _prevctx = _localctx;
-        setState(647);
+        setState(663);
         functionExpression();
         }
         break;
@@ -5606,19 +5719,19 @@ public class EsqlBaseParser extends ParserConfig {
         _localctx = new ParenthesizedExpressionContext(_localctx);
         _ctx = _localctx;
         _prevctx = _localctx;
-        setState(648);
+        setState(664);
         match(LP);
-        setState(649);
+        setState(665);
         booleanExpression(0);
-        setState(650);
+        setState(666);
         match(RP);
         }
         break;
       }
       _ctx.stop = _input.LT(-1);
-      setState(659);
+      setState(675);
       _errHandler.sync(this);
-      _alt = getInterpreter().adaptivePredict(_input,58,_ctx);
+      _alt = getInterpreter().adaptivePredict(_input,60,_ctx);
       while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
         if ( _alt==1 ) {
           if ( _parseListeners!=null ) triggerExitRuleEvent();
@@ -5627,18 +5740,18 @@ public class EsqlBaseParser extends ParserConfig {
           {
           _localctx = new InlineCastContext(new PrimaryExpressionContext(_parentctx, _parentState));
           pushNewRecursionContext(_localctx, _startState, RULE_primaryExpression);
-          setState(654);
+          setState(670);
           if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)");
-          setState(655);
+          setState(671);
           match(CAST_OP);
-          setState(656);
+          setState(672);
           dataType();
           }
           } 
         }
-        setState(661);
+        setState(677);
         _errHandler.sync(this);
-        _alt = getInterpreter().adaptivePredict(_input,58,_ctx);
+        _alt = getInterpreter().adaptivePredict(_input,60,_ctx);
       }
       }
     }
@@ -5702,16 +5815,16 @@ public class EsqlBaseParser extends ParserConfig {
       int _alt;
       enterOuterAlt(_localctx, 1);
       {
-      setState(662);
+      setState(678);
       functionName();
-      setState(663);
+      setState(679);
       match(LP);
-      setState(677);
+      setState(693);
       _errHandler.sync(this);
       switch (_input.LA(1)) {
       case ASTERISK:
         {
-        setState(664);
+        setState(680);
         match(ASTERISK);
         }
         break;
@@ -5734,34 +5847,34 @@ public class EsqlBaseParser extends ParserConfig {
       case QUOTED_IDENTIFIER:
         {
         {
-        setState(665);
+        setState(681);
         booleanExpression(0);
-        setState(670);
+        setState(686);
         _errHandler.sync(this);
-        _alt = getInterpreter().adaptivePredict(_input,59,_ctx);
+        _alt = getInterpreter().adaptivePredict(_input,61,_ctx);
         while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
           if ( _alt==1 ) {
             {
             {
-            setState(666);
+            setState(682);
             match(COMMA);
-            setState(667);
+            setState(683);
             booleanExpression(0);
             }
             } 
           }
-          setState(672);
+          setState(688);
           _errHandler.sync(this);
-          _alt = getInterpreter().adaptivePredict(_input,59,_ctx);
+          _alt = getInterpreter().adaptivePredict(_input,61,_ctx);
         }
-        setState(675);
+        setState(691);
         _errHandler.sync(this);
         _la = _input.LA(1);
         if (_la==COMMA) {
           {
-          setState(673);
+          setState(689);
           match(COMMA);
-          setState(674);
+          setState(690);
           mapExpression();
           }
         }
@@ -5774,7 +5887,7 @@ public class EsqlBaseParser extends ParserConfig {
       default:
         break;
       }
-      setState(679);
+      setState(695);
       match(RP);
       }
     }
@@ -5820,7 +5933,7 @@ public class EsqlBaseParser extends ParserConfig {
     try {
       enterOuterAlt(_localctx, 1);
       {
-      setState(681);
+      setState(697);
       identifierOrParameter();
       }
     }
@@ -5876,27 +5989,27 @@ public class EsqlBaseParser extends ParserConfig {
     try {
       enterOuterAlt(_localctx, 1);
       {
-      setState(683);
+      setState(699);
       match(LEFT_BRACES);
-      setState(684);
+      setState(700);
       entryExpression();
-      setState(689);
+      setState(705);
       _errHandler.sync(this);
       _la = _input.LA(1);
       while (_la==COMMA) {
         {
         {
-        setState(685);
+        setState(701);
         match(COMMA);
-        setState(686);
+        setState(702);
         entryExpression();
         }
         }
-        setState(691);
+        setState(707);
         _errHandler.sync(this);
         _la = _input.LA(1);
       }
-      setState(692);
+      setState(708);
       match(RIGHT_BRACES);
       }
     }
@@ -5948,11 +6061,11 @@ public class EsqlBaseParser extends ParserConfig {
     try {
       enterOuterAlt(_localctx, 1);
       {
-      setState(694);
+      setState(710);
       ((EntryExpressionContext)_localctx).key = string();
-      setState(695);
+      setState(711);
       match(COLON);
-      setState(696);
+      setState(712);
       ((EntryExpressionContext)_localctx).value = constant();
       }
     }
@@ -6223,14 +6336,14 @@ public class EsqlBaseParser extends ParserConfig {
     enterRule(_localctx, 142, RULE_constant);
     int _la;
     try {
-      setState(740);
+      setState(756);
       _errHandler.sync(this);
-      switch ( getInterpreter().adaptivePredict(_input,66,_ctx) ) {
+      switch ( getInterpreter().adaptivePredict(_input,68,_ctx) ) {
       case 1:
         _localctx = new NullLiteralContext(_localctx);
         enterOuterAlt(_localctx, 1);
         {
-        setState(698);
+        setState(714);
         match(NULL);
         }
         break;
@@ -6238,9 +6351,9 @@ public class EsqlBaseParser extends ParserConfig {
         _localctx = new QualifiedIntegerLiteralContext(_localctx);
         enterOuterAlt(_localctx, 2);
         {
-        setState(699);
+        setState(715);
         integerValue();
-        setState(700);
+        setState(716);
         match(UNQUOTED_IDENTIFIER);
         }
         break;
@@ -6248,7 +6361,7 @@ public class EsqlBaseParser extends ParserConfig {
         _localctx = new DecimalLiteralContext(_localctx);
         enterOuterAlt(_localctx, 3);
         {
-        setState(702);
+        setState(718);
         decimalValue();
         }
         break;
@@ -6256,7 +6369,7 @@ public class EsqlBaseParser extends ParserConfig {
         _localctx = new IntegerLiteralContext(_localctx);
         enterOuterAlt(_localctx, 4);
         {
-        setState(703);
+        setState(719);
         integerValue();
         }
         break;
@@ -6264,7 +6377,7 @@ public class EsqlBaseParser extends ParserConfig {
         _localctx = new BooleanLiteralContext(_localctx);
         enterOuterAlt(_localctx, 5);
         {
-        setState(704);
+        setState(720);
         booleanValue();
         }
         break;
@@ -6272,7 +6385,7 @@ public class EsqlBaseParser extends ParserConfig {
         _localctx = new InputParameterContext(_localctx);
         enterOuterAlt(_localctx, 6);
         {
-        setState(705);
+        setState(721);
         parameter();
         }
         break;
@@ -6280,7 +6393,7 @@ public class EsqlBaseParser extends ParserConfig {
         _localctx = new StringLiteralContext(_localctx);
         enterOuterAlt(_localctx, 7);
         {
-        setState(706);
+        setState(722);
         string();
         }
         break;
@@ -6288,27 +6401,27 @@ public class EsqlBaseParser extends ParserConfig {
         _localctx = new NumericArrayLiteralContext(_localctx);
         enterOuterAlt(_localctx, 8);
         {
-        setState(707);
+        setState(723);
         match(OPENING_BRACKET);
-        setState(708);
+        setState(724);
         numericValue();
-        setState(713);
+        setState(729);
         _errHandler.sync(this);
         _la = _input.LA(1);
         while (_la==COMMA) {
           {
           {
-          setState(709);
+          setState(725);
           match(COMMA);
-          setState(710);
+          setState(726);
           numericValue();
           }
           }
-          setState(715);
+          setState(731);
           _errHandler.sync(this);
           _la = _input.LA(1);
         }
-        setState(716);
+        setState(732);
         match(CLOSING_BRACKET);
         }
         break;
@@ -6316,27 +6429,27 @@ public class EsqlBaseParser extends ParserConfig {
         _localctx = new BooleanArrayLiteralContext(_localctx);
         enterOuterAlt(_localctx, 9);
         {
-        setState(718);
+        setState(734);
         match(OPENING_BRACKET);
-        setState(719);
+        setState(735);
         booleanValue();
-        setState(724);
+        setState(740);
         _errHandler.sync(this);
         _la = _input.LA(1);
         while (_la==COMMA) {
           {
           {
-          setState(720);
+          setState(736);
           match(COMMA);
-          setState(721);
+          setState(737);
           booleanValue();
           }
           }
-          setState(726);
+          setState(742);
           _errHandler.sync(this);
           _la = _input.LA(1);
         }
-        setState(727);
+        setState(743);
         match(CLOSING_BRACKET);
         }
         break;
@@ -6344,27 +6457,27 @@ public class EsqlBaseParser extends ParserConfig {
         _localctx = new StringArrayLiteralContext(_localctx);
         enterOuterAlt(_localctx, 10);
         {
-        setState(729);
+        setState(745);
         match(OPENING_BRACKET);
-        setState(730);
+        setState(746);
         string();
-        setState(735);
+        setState(751);
         _errHandler.sync(this);
         _la = _input.LA(1);
         while (_la==COMMA) {
           {
           {
-          setState(731);
+          setState(747);
           match(COMMA);
-          setState(732);
+          setState(748);
           string();
           }
           }
-          setState(737);
+          setState(753);
           _errHandler.sync(this);
           _la = _input.LA(1);
         }
-        setState(738);
+        setState(754);
         match(CLOSING_BRACKET);
         }
         break;
@@ -6412,7 +6525,7 @@ public class EsqlBaseParser extends ParserConfig {
     try {
       enterOuterAlt(_localctx, 1);
       {
-      setState(742);
+      setState(758);
       _la = _input.LA(1);
       if ( !(_la==FALSE || _la==TRUE) ) {
       _errHandler.recoverInline(this);
@@ -6467,20 +6580,20 @@ public class EsqlBaseParser extends ParserConfig {
     NumericValueContext _localctx = new NumericValueContext(_ctx, getState());
     enterRule(_localctx, 146, RULE_numericValue);
     try {
-      setState(746);
+      setState(762);
       _errHandler.sync(this);
-      switch ( getInterpreter().adaptivePredict(_input,67,_ctx) ) {
+      switch ( getInterpreter().adaptivePredict(_input,69,_ctx) ) {
       case 1:
         enterOuterAlt(_localctx, 1);
         {
-        setState(744);
+        setState(760);
         decimalValue();
         }
         break;
       case 2:
         enterOuterAlt(_localctx, 2);
         {
-        setState(745);
+        setState(761);
         integerValue();
         }
         break;
@@ -6529,12 +6642,12 @@ public class EsqlBaseParser extends ParserConfig {
     try {
       enterOuterAlt(_localctx, 1);
       {
-      setState(749);
+      setState(765);
       _errHandler.sync(this);
       _la = _input.LA(1);
       if (_la==PLUS || _la==MINUS) {
         {
-        setState(748);
+        setState(764);
         _la = _input.LA(1);
         if ( !(_la==PLUS || _la==MINUS) ) {
         _errHandler.recoverInline(this);
@@ -6547,7 +6660,7 @@ public class EsqlBaseParser extends ParserConfig {
         }
       }
 
-      setState(751);
+      setState(767);
       match(DECIMAL_LITERAL);
       }
     }
@@ -6594,12 +6707,12 @@ public class EsqlBaseParser extends ParserConfig {
     try {
       enterOuterAlt(_localctx, 1);
       {
-      setState(754);
+      setState(770);
       _errHandler.sync(this);
       _la = _input.LA(1);
       if (_la==PLUS || _la==MINUS) {
         {
-        setState(753);
+        setState(769);
         _la = _input.LA(1);
         if ( !(_la==PLUS || _la==MINUS) ) {
         _errHandler.recoverInline(this);
@@ -6612,7 +6725,7 @@ public class EsqlBaseParser extends ParserConfig {
         }
       }
 
-      setState(756);
+      setState(772);
       match(INTEGER_LITERAL);
       }
     }
@@ -6656,7 +6769,7 @@ public class EsqlBaseParser extends ParserConfig {
     try {
       enterOuterAlt(_localctx, 1);
       {
-      setState(758);
+      setState(774);
       match(QUOTED_STRING);
       }
     }
@@ -6706,7 +6819,7 @@ public class EsqlBaseParser extends ParserConfig {
     try {
       enterOuterAlt(_localctx, 1);
       {
-      setState(760);
+      setState(776);
       _la = _input.LA(1);
       if ( !(((((_la - 80)) & ~0x3f) == 0 && ((1L << (_la - 80)) & 125L) != 0)) ) {
       _errHandler.recoverInline(this);
@@ -6769,7 +6882,7 @@ public class EsqlBaseParser extends ParserConfig {
     try {
       enterOuterAlt(_localctx, 1);
       {
-      setState(762);
+      setState(778);
       ((JoinCommandContext)_localctx).type = _input.LT(1);
       _la = _input.LA(1);
       if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 54525952L) != 0)) ) {
@@ -6780,11 +6893,11 @@ public class EsqlBaseParser extends ParserConfig {
         _errHandler.reportMatch(this);
         consume();
       }
-      setState(763);
+      setState(779);
       match(JOIN);
-      setState(764);
+      setState(780);
       joinTarget();
-      setState(765);
+      setState(781);
       joinCondition();
       }
     }
@@ -6831,7 +6944,7 @@ public class EsqlBaseParser extends ParserConfig {
     try {
       enterOuterAlt(_localctx, 1);
       {
-      setState(767);
+      setState(783);
       ((JoinTargetContext)_localctx).index = indexPattern();
       }
     }
@@ -6886,27 +6999,27 @@ public class EsqlBaseParser extends ParserConfig {
       int _alt;
       enterOuterAlt(_localctx, 1);
       {
-      setState(769);
+      setState(785);
       match(ON);
-      setState(770);
+      setState(786);
       joinPredicate();
-      setState(775);
+      setState(791);
       _errHandler.sync(this);
-      _alt = getInterpreter().adaptivePredict(_input,70,_ctx);
+      _alt = getInterpreter().adaptivePredict(_input,72,_ctx);
       while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
         if ( _alt==1 ) {
           {
           {
-          setState(771);
+          setState(787);
           match(COMMA);
-          setState(772);
+          setState(788);
           joinPredicate();
           }
           } 
         }
-        setState(777);
+        setState(793);
         _errHandler.sync(this);
-        _alt = getInterpreter().adaptivePredict(_input,70,_ctx);
+        _alt = getInterpreter().adaptivePredict(_input,72,_ctx);
       }
       }
     }
@@ -6952,7 +7065,7 @@ public class EsqlBaseParser extends ParserConfig {
     try {
       enterOuterAlt(_localctx, 1);
       {
-      setState(778);
+      setState(794);
       valueExpression();
       }
     }
@@ -7053,7 +7166,7 @@ public class EsqlBaseParser extends ParserConfig {
   }
 
   public static final String _serializedATN =
-    "\u0004\u0001\u008b\u030d\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001"+
+    "\u0004\u0001\u008b\u031d\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"+
@@ -7129,412 +7242,423 @@ public class EsqlBaseParser extends ParserConfig {
     "=\u0003=\u0243\b=\u0001=\u0001=\u0001=\u0003=\u0248\b=\u0001=\u0001=\u0001"+
     "=\u0001=\u0001=\u0001=\u0005=\u0250\b=\n=\f=\u0253\t=\u0001>\u0001>\u0003"+
     ">\u0257\b>\u0001>\u0001>\u0001>\u0001>\u0001>\u0003>\u025e\b>\u0001>\u0001"+
-    ">\u0001>\u0003>\u0263\b>\u0001?\u0001?\u0001?\u0003?\u0268\b?\u0001?\u0001"+
-    "?\u0001?\u0001@\u0001@\u0001@\u0001@\u0001@\u0003@\u0272\b@\u0001A\u0001"+
-    "A\u0001A\u0001A\u0003A\u0278\bA\u0001A\u0001A\u0001A\u0001A\u0001A\u0001"+
-    "A\u0005A\u0280\bA\nA\fA\u0283\tA\u0001B\u0001B\u0001B\u0001B\u0001B\u0001"+
-    "B\u0001B\u0001B\u0003B\u028d\bB\u0001B\u0001B\u0001B\u0005B\u0292\bB\n"+
-    "B\fB\u0295\tB\u0001C\u0001C\u0001C\u0001C\u0001C\u0001C\u0005C\u029d\b"+
-    "C\nC\fC\u02a0\tC\u0001C\u0001C\u0003C\u02a4\bC\u0003C\u02a6\bC\u0001C"+
-    "\u0001C\u0001D\u0001D\u0001E\u0001E\u0001E\u0001E\u0005E\u02b0\bE\nE\f"+
-    "E\u02b3\tE\u0001E\u0001E\u0001F\u0001F\u0001F\u0001F\u0001G\u0001G\u0001"+
-    "G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001"+
-    "G\u0005G\u02c8\bG\nG\fG\u02cb\tG\u0001G\u0001G\u0001G\u0001G\u0001G\u0001"+
-    "G\u0005G\u02d3\bG\nG\fG\u02d6\tG\u0001G\u0001G\u0001G\u0001G\u0001G\u0001"+
-    "G\u0005G\u02de\bG\nG\fG\u02e1\tG\u0001G\u0001G\u0003G\u02e5\bG\u0001H"+
-    "\u0001H\u0001I\u0001I\u0003I\u02eb\bI\u0001J\u0003J\u02ee\bJ\u0001J\u0001"+
-    "J\u0001K\u0003K\u02f3\bK\u0001K\u0001K\u0001L\u0001L\u0001M\u0001M\u0001"+
-    "N\u0001N\u0001N\u0001N\u0001N\u0001O\u0001O\u0001P\u0001P\u0001P\u0001"+
-    "P\u0005P\u0306\bP\nP\fP\u0309\tP\u0001Q\u0001Q\u0001Q\u0000\u0005\u0002"+
-    "nz\u0082\u0084R\u0000\u0002\u0004\u0006\b\n\f\u000e\u0010\u0012\u0014"+
-    "\u0016\u0018\u001a\u001c\u001e \"$&(*,.02468:<>@BDFHJLNPRTVXZ\\^`bdfh"+
-    "jlnprtvxz|~\u0080\u0082\u0084\u0086\u0088\u008a\u008c\u008e\u0090\u0092"+
-    "\u0094\u0096\u0098\u009a\u009c\u009e\u00a0\u00a2\u0000\t\u0002\u00005"+
-    "5kk\u0001\u0000ef\u0002\u000099??\u0002\u0000BBEE\u0001\u0000WX\u0001"+
-    "\u0000Y[\u0002\u0000AANN\u0002\u0000PPRV\u0002\u0000\u0016\u0016\u0018"+
-    "\u0019\u0330\u0000\u00a4\u0001\u0000\u0000\u0000\u0002\u00a7\u0001\u0000"+
-    "\u0000\u0000\u0004\u00b8\u0001\u0000\u0000\u0000\u0006\u00d7\u0001\u0000"+
-    "\u0000\u0000\b\u00d9\u0001\u0000\u0000\u0000\n\u00dc\u0001\u0000\u0000"+
-    "\u0000\f\u00de\u0001\u0000\u0000\u0000\u000e\u00e1\u0001\u0000\u0000\u0000"+
-    "\u0010\u00ec\u0001\u0000\u0000\u0000\u0012\u00f0\u0001\u0000\u0000\u0000"+
-    "\u0014\u00f8\u0001\u0000\u0000\u0000\u0016\u00fd\u0001\u0000\u0000\u0000"+
-    "\u0018\u0100\u0001\u0000\u0000\u0000\u001a\u0103\u0001\u0000\u0000\u0000"+
-    "\u001c\u0119\u0001\u0000\u0000\u0000\u001e\u011b\u0001\u0000\u0000\u0000"+
-    " \u011d\u0001\u0000\u0000\u0000\"\u011f\u0001\u0000\u0000\u0000$\u0121"+
-    "\u0001\u0000\u0000\u0000&\u012a\u0001\u0000\u0000\u0000(\u012d\u0001\u0000"+
-    "\u0000\u0000*\u0135\u0001\u0000\u0000\u0000,\u013d\u0001\u0000\u0000\u0000"+
-    ".\u0142\u0001\u0000\u0000\u00000\u014a\u0001\u0000\u0000\u00002\u0152"+
-    "\u0001\u0000\u0000\u00004\u015a\u0001\u0000\u0000\u00006\u015f\u0001\u0000"+
-    "\u0000\u00008\u0163\u0001\u0000\u0000\u0000:\u0167\u0001\u0000\u0000\u0000"+
-    "<\u016c\u0001\u0000\u0000\u0000>\u016e\u0001\u0000\u0000\u0000@\u0171"+
-    "\u0001\u0000\u0000\u0000B\u017a\u0001\u0000\u0000\u0000D\u0182\u0001\u0000"+
-    "\u0000\u0000F\u0185\u0001\u0000\u0000\u0000H\u0188\u0001\u0000\u0000\u0000"+
-    "J\u0199\u0001\u0000\u0000\u0000L\u019b\u0001\u0000\u0000\u0000N\u01a1"+
-    "\u0001\u0000\u0000\u0000P\u01a5\u0001\u0000\u0000\u0000R\u01a8\u0001\u0000"+
-    "\u0000\u0000T\u01b0\u0001\u0000\u0000\u0000V\u01b4\u0001\u0000\u0000\u0000"+
-    "X\u01b7\u0001\u0000\u0000\u0000Z\u01bb\u0001\u0000\u0000\u0000\\\u01be"+
-    "\u0001\u0000\u0000\u0000^\u01d2\u0001\u0000\u0000\u0000`\u01d6\u0001\u0000"+
-    "\u0000\u0000b\u01db\u0001\u0000\u0000\u0000d\u01e1\u0001\u0000\u0000\u0000"+
-    "f\u01ee\u0001\u0000\u0000\u0000h\u01f1\u0001\u0000\u0000\u0000j\u01f5"+
-    "\u0001\u0000\u0000\u0000l\u01f9\u0001\u0000\u0000\u0000n\u01fd\u0001\u0000"+
-    "\u0000\u0000p\u0211\u0001\u0000\u0000\u0000r\u0213\u0001\u0000\u0000\u0000"+
-    "t\u0215\u0001\u0000\u0000\u0000v\u021d\u0001\u0000\u0000\u0000x\u0227"+
-    "\u0001\u0000\u0000\u0000z\u0247\u0001\u0000\u0000\u0000|\u0262\u0001\u0000"+
-    "\u0000\u0000~\u0264\u0001\u0000\u0000\u0000\u0080\u0271\u0001\u0000\u0000"+
-    "\u0000\u0082\u0277\u0001\u0000\u0000\u0000\u0084\u028c\u0001\u0000\u0000"+
-    "\u0000\u0086\u0296\u0001\u0000\u0000\u0000\u0088\u02a9\u0001\u0000\u0000"+
-    "\u0000\u008a\u02ab\u0001\u0000\u0000\u0000\u008c\u02b6\u0001\u0000\u0000"+
-    "\u0000\u008e\u02e4\u0001\u0000\u0000\u0000\u0090\u02e6\u0001\u0000\u0000"+
-    "\u0000\u0092\u02ea\u0001\u0000\u0000\u0000\u0094\u02ed\u0001\u0000\u0000"+
-    "\u0000\u0096\u02f2\u0001\u0000\u0000\u0000\u0098\u02f6\u0001\u0000\u0000"+
-    "\u0000\u009a\u02f8\u0001\u0000\u0000\u0000\u009c\u02fa\u0001\u0000\u0000"+
-    "\u0000\u009e\u02ff\u0001\u0000\u0000\u0000\u00a0\u0301\u0001\u0000\u0000"+
-    "\u0000\u00a2\u030a\u0001\u0000\u0000\u0000\u00a4\u00a5\u0003\u0002\u0001"+
-    "\u0000\u00a5\u00a6\u0005\u0000\u0000\u0001\u00a6\u0001\u0001\u0000\u0000"+
-    "\u0000\u00a7\u00a8\u0006\u0001\uffff\uffff\u0000\u00a8\u00a9\u0003\u0004"+
-    "\u0002\u0000\u00a9\u00af\u0001\u0000\u0000\u0000\u00aa\u00ab\n\u0001\u0000"+
-    "\u0000\u00ab\u00ac\u00054\u0000\u0000\u00ac\u00ae\u0003\u0006\u0003\u0000"+
-    "\u00ad\u00aa\u0001\u0000\u0000\u0000\u00ae\u00b1\u0001\u0000\u0000\u0000"+
-    "\u00af\u00ad\u0001\u0000\u0000\u0000\u00af\u00b0\u0001\u0000\u0000\u0000"+
-    "\u00b0\u0003\u0001\u0000\u0000\u0000\u00b1\u00af\u0001\u0000\u0000\u0000"+
-    "\u00b2\u00b9\u0003V+\u0000\u00b3\u00b9\u0003\u0016\u000b\u0000\u00b4\u00b9"+
-    "\u0003\f\u0006\u0000\u00b5\u00b9\u0003Z-\u0000\u00b6\u00b7\u0004\u0002"+
-    "\u0001\u0000\u00b7\u00b9\u0003\u0018\f\u0000\u00b8\u00b2\u0001\u0000\u0000"+
-    "\u0000\u00b8\u00b3\u0001\u0000\u0000\u0000\u00b8\u00b4\u0001\u0000\u0000"+
-    "\u0000\u00b8\u00b5\u0001\u0000\u0000\u0000\u00b8\u00b6\u0001\u0000\u0000"+
-    "\u0000\u00b9\u0005\u0001\u0000\u0000\u0000\u00ba\u00d8\u0003&\u0013\u0000"+
-    "\u00bb\u00d8\u0003\b\u0004\u0000\u00bc\u00d8\u0003D\"\u0000\u00bd\u00d8"+
-    "\u0003>\u001f\u0000\u00be\u00d8\u0003(\u0014\u0000\u00bf\u00d8\u0003@"+
-    " \u0000\u00c0\u00d8\u0003F#\u0000\u00c1\u00d8\u0003H$\u0000\u00c2\u00d8"+
-    "\u0003L&\u0000\u00c3\u00d8\u0003N\'\u0000\u00c4\u00d8\u0003\\.\u0000\u00c5"+
-    "\u00d8\u0003P(\u0000\u00c6\u00d8\u0003\u009cN\u0000\u00c7\u00d8\u0003"+
-    "d2\u0000\u00c8\u00d8\u0003v;\u0000\u00c9\u00ca\u0004\u0003\u0002\u0000"+
-    "\u00ca\u00d8\u0003b1\u0000\u00cb\u00cc\u0004\u0003\u0003\u0000\u00cc\u00d8"+
-    "\u0003`0\u0000\u00cd\u00ce\u0004\u0003\u0004\u0000\u00ce\u00d8\u0003f"+
-    "3\u0000\u00cf\u00d0\u0004\u0003\u0005\u0000\u00d0\u00d8\u0003h4\u0000"+
-    "\u00d1\u00d2\u0004\u0003\u0006\u0000\u00d2\u00d8\u0003t:\u0000\u00d3\u00d4"+
-    "\u0004\u0003\u0007\u0000\u00d4\u00d8\u0003r9\u0000\u00d5\u00d6\u0004\u0003"+
-    "\b\u0000\u00d6\u00d8\u0003x<\u0000\u00d7\u00ba\u0001\u0000\u0000\u0000"+
-    "\u00d7\u00bb\u0001\u0000\u0000\u0000\u00d7\u00bc\u0001\u0000\u0000\u0000"+
-    "\u00d7\u00bd\u0001\u0000\u0000\u0000\u00d7\u00be\u0001\u0000\u0000\u0000"+
-    "\u00d7\u00bf\u0001\u0000\u0000\u0000\u00d7\u00c0\u0001\u0000\u0000\u0000"+
-    "\u00d7\u00c1\u0001\u0000\u0000\u0000\u00d7\u00c2\u0001\u0000\u0000\u0000"+
-    "\u00d7\u00c3\u0001\u0000\u0000\u0000\u00d7\u00c4\u0001\u0000\u0000\u0000"+
-    "\u00d7\u00c5\u0001\u0000\u0000\u0000\u00d7\u00c6\u0001\u0000\u0000\u0000"+
-    "\u00d7\u00c7\u0001\u0000\u0000\u0000\u00d7\u00c8\u0001\u0000\u0000\u0000"+
-    "\u00d7\u00c9\u0001\u0000\u0000\u0000\u00d7\u00cb\u0001\u0000\u0000\u0000"+
-    "\u00d7\u00cd\u0001\u0000\u0000\u0000\u00d7\u00cf\u0001\u0000\u0000\u0000"+
-    "\u00d7\u00d1\u0001\u0000\u0000\u0000\u00d7\u00d3\u0001\u0000\u0000\u0000"+
-    "\u00d7\u00d5\u0001\u0000\u0000\u0000\u00d8\u0007\u0001\u0000\u0000\u0000"+
-    "\u00d9\u00da\u0005\u000f\u0000\u0000\u00da\u00db\u0003z=\u0000\u00db\t"+
-    "\u0001\u0000\u0000\u0000\u00dc\u00dd\u00034\u001a\u0000\u00dd\u000b\u0001"+
-    "\u0000\u0000\u0000\u00de\u00df\u0005\f\u0000\u0000\u00df\u00e0\u0003\u000e"+
-    "\u0007\u0000\u00e0\r\u0001\u0000\u0000\u0000\u00e1\u00e6\u0003\u0010\b"+
-    "\u0000\u00e2\u00e3\u0005>\u0000\u0000\u00e3\u00e5\u0003\u0010\b\u0000"+
-    "\u00e4\u00e2\u0001\u0000\u0000\u0000\u00e5\u00e8\u0001\u0000\u0000\u0000"+
-    "\u00e6\u00e4\u0001\u0000\u0000\u0000\u00e6\u00e7\u0001\u0000\u0000\u0000"+
-    "\u00e7\u000f\u0001\u0000\u0000\u0000\u00e8\u00e6\u0001\u0000\u0000\u0000"+
-    "\u00e9\u00ea\u0003.\u0017\u0000\u00ea\u00eb\u0005:\u0000\u0000\u00eb\u00ed"+
-    "\u0001\u0000\u0000\u0000\u00ec\u00e9\u0001\u0000\u0000\u0000\u00ec\u00ed"+
-    "\u0001\u0000\u0000\u0000\u00ed\u00ee\u0001\u0000\u0000\u0000\u00ee\u00ef"+
-    "\u0003z=\u0000\u00ef\u0011\u0001\u0000\u0000\u0000\u00f0\u00f5\u0003\u0014"+
-    "\n\u0000\u00f1\u00f2\u0005>\u0000\u0000\u00f2\u00f4\u0003\u0014\n\u0000"+
-    "\u00f3\u00f1\u0001\u0000\u0000\u0000\u00f4\u00f7\u0001\u0000\u0000\u0000"+
-    "\u00f5\u00f3\u0001\u0000\u0000\u0000\u00f5\u00f6\u0001\u0000\u0000\u0000"+
-    "\u00f6\u0013\u0001\u0000\u0000\u0000\u00f7\u00f5\u0001\u0000\u0000\u0000"+
-    "\u00f8\u00fb\u0003.\u0017\u0000\u00f9\u00fa\u0005:\u0000\u0000\u00fa\u00fc"+
-    "\u0003z=\u0000\u00fb\u00f9\u0001\u0000\u0000\u0000\u00fb\u00fc\u0001\u0000"+
-    "\u0000\u0000\u00fc\u0015\u0001\u0000\u0000\u0000\u00fd\u00fe\u0005\u0013"+
-    "\u0000\u0000\u00fe\u00ff\u0003\u001a\r\u0000\u00ff\u0017\u0001\u0000\u0000"+
-    "\u0000\u0100\u0101\u0005\u0014\u0000\u0000\u0101\u0102\u0003\u001a\r\u0000"+
-    "\u0102\u0019\u0001\u0000\u0000\u0000\u0103\u0108\u0003\u001c\u000e\u0000"+
-    "\u0104\u0105\u0005>\u0000\u0000\u0105\u0107\u0003\u001c\u000e\u0000\u0106"+
-    "\u0104\u0001\u0000\u0000\u0000\u0107\u010a\u0001\u0000\u0000\u0000\u0108"+
-    "\u0106\u0001\u0000\u0000\u0000\u0108\u0109\u0001\u0000\u0000\u0000\u0109"+
-    "\u010c\u0001\u0000\u0000\u0000\u010a\u0108\u0001\u0000\u0000\u0000\u010b"+
-    "\u010d\u0003$\u0012\u0000\u010c\u010b\u0001\u0000\u0000\u0000\u010c\u010d"+
-    "\u0001\u0000\u0000\u0000\u010d\u001b\u0001\u0000\u0000\u0000\u010e\u010f"+
-    "\u0003\u001e\u000f\u0000\u010f\u0110\u0005=\u0000\u0000\u0110\u0112\u0001"+
-    "\u0000\u0000\u0000\u0111\u010e\u0001\u0000\u0000\u0000\u0111\u0112\u0001"+
-    "\u0000\u0000\u0000\u0112\u0113\u0001\u0000\u0000\u0000\u0113\u011a\u0003"+
-    "\"\u0011\u0000\u0114\u0117\u0003\"\u0011\u0000\u0115\u0116\u0005<\u0000"+
-    "\u0000\u0116\u0118\u0003 \u0010\u0000\u0117\u0115\u0001\u0000\u0000\u0000"+
-    "\u0117\u0118\u0001\u0000\u0000\u0000\u0118\u011a\u0001\u0000\u0000\u0000"+
-    "\u0119\u0111\u0001\u0000\u0000\u0000\u0119\u0114\u0001\u0000\u0000\u0000"+
-    "\u011a\u001d\u0001\u0000\u0000\u0000\u011b\u011c\u0007\u0000\u0000\u0000"+
-    "\u011c\u001f\u0001\u0000\u0000\u0000\u011d\u011e\u0007\u0000\u0000\u0000"+
-    "\u011e!\u0001\u0000\u0000\u0000\u011f\u0120\u0007\u0000\u0000\u0000\u0120"+
-    "#\u0001\u0000\u0000\u0000\u0121\u0122\u0005j\u0000\u0000\u0122\u0127\u0005"+
-    "k\u0000\u0000\u0123\u0124\u0005>\u0000\u0000\u0124\u0126\u0005k\u0000"+
-    "\u0000\u0125\u0123\u0001\u0000\u0000\u0000\u0126\u0129\u0001\u0000\u0000"+
-    "\u0000\u0127\u0125\u0001\u0000\u0000\u0000\u0127\u0128\u0001\u0000\u0000"+
-    "\u0000\u0128%\u0001\u0000\u0000\u0000\u0129\u0127\u0001\u0000\u0000\u0000"+
-    "\u012a\u012b\u0005\t\u0000\u0000\u012b\u012c\u0003\u000e\u0007\u0000\u012c"+
-    "\'\u0001\u0000\u0000\u0000\u012d\u012f\u0005\u000e\u0000\u0000\u012e\u0130"+
-    "\u0003*\u0015\u0000\u012f\u012e\u0001\u0000\u0000\u0000\u012f\u0130\u0001"+
-    "\u0000\u0000\u0000\u0130\u0133\u0001\u0000\u0000\u0000\u0131\u0132\u0005"+
-    ";\u0000\u0000\u0132\u0134\u0003\u000e\u0007\u0000\u0133\u0131\u0001\u0000"+
-    "\u0000\u0000\u0133\u0134\u0001\u0000\u0000\u0000\u0134)\u0001\u0000\u0000"+
-    "\u0000\u0135\u013a\u0003,\u0016\u0000\u0136\u0137\u0005>\u0000\u0000\u0137"+
-    "\u0139\u0003,\u0016\u0000\u0138\u0136\u0001\u0000\u0000\u0000\u0139\u013c"+
-    "\u0001\u0000\u0000\u0000\u013a\u0138\u0001\u0000\u0000\u0000\u013a\u013b"+
-    "\u0001\u0000\u0000\u0000\u013b+\u0001\u0000\u0000\u0000\u013c\u013a\u0001"+
-    "\u0000\u0000\u0000\u013d\u0140\u0003\u0010\b\u0000\u013e\u013f\u0005\u000f"+
-    "\u0000\u0000\u013f\u0141\u0003z=\u0000\u0140\u013e\u0001\u0000\u0000\u0000"+
-    "\u0140\u0141\u0001\u0000\u0000\u0000\u0141-\u0001\u0000\u0000\u0000\u0142"+
-    "\u0147\u0003<\u001e\u0000\u0143\u0144\u0005@\u0000\u0000\u0144\u0146\u0003"+
-    "<\u001e\u0000\u0145\u0143\u0001\u0000\u0000\u0000\u0146\u0149\u0001\u0000"+
-    "\u0000\u0000\u0147\u0145\u0001\u0000\u0000\u0000\u0147\u0148\u0001\u0000"+
-    "\u0000\u0000\u0148/\u0001\u0000\u0000\u0000\u0149\u0147\u0001\u0000\u0000"+
-    "\u0000\u014a\u014f\u00036\u001b\u0000\u014b\u014c\u0005@\u0000\u0000\u014c"+
-    "\u014e\u00036\u001b\u0000\u014d\u014b\u0001\u0000\u0000\u0000\u014e\u0151"+
-    "\u0001\u0000\u0000\u0000\u014f\u014d\u0001\u0000\u0000\u0000\u014f\u0150"+
-    "\u0001\u0000\u0000\u0000\u01501\u0001\u0000\u0000\u0000\u0151\u014f\u0001"+
-    "\u0000\u0000\u0000\u0152\u0157\u00030\u0018\u0000\u0153\u0154\u0005>\u0000"+
-    "\u0000\u0154\u0156\u00030\u0018\u0000\u0155\u0153\u0001\u0000\u0000\u0000"+
-    "\u0156\u0159\u0001\u0000\u0000\u0000\u0157\u0155\u0001\u0000\u0000\u0000"+
-    "\u0157\u0158\u0001\u0000\u0000\u0000\u01583\u0001\u0000\u0000\u0000\u0159"+
-    "\u0157\u0001\u0000\u0000\u0000\u015a\u015b\u0007\u0001\u0000\u0000\u015b"+
-    "5\u0001\u0000\u0000\u0000\u015c\u0160\u0005\u0080\u0000\u0000\u015d\u0160"+
-    "\u00038\u001c\u0000\u015e\u0160\u0003:\u001d\u0000\u015f\u015c\u0001\u0000"+
-    "\u0000\u0000\u015f\u015d\u0001\u0000\u0000\u0000\u015f\u015e\u0001\u0000"+
-    "\u0000\u0000\u01607\u0001\u0000\u0000\u0000\u0161\u0164\u0005L\u0000\u0000"+
-    "\u0162\u0164\u0005_\u0000\u0000\u0163\u0161\u0001\u0000\u0000\u0000\u0163"+
-    "\u0162\u0001\u0000\u0000\u0000\u01649\u0001\u0000\u0000\u0000\u0165\u0168"+
-    "\u0005^\u0000\u0000\u0166\u0168\u0005`\u0000\u0000\u0167\u0165\u0001\u0000"+
-    "\u0000\u0000\u0167\u0166\u0001\u0000\u0000\u0000\u0168;\u0001\u0000\u0000"+
-    "\u0000\u0169\u016d\u00034\u001a\u0000\u016a\u016d\u00038\u001c\u0000\u016b"+
-    "\u016d\u0003:\u001d\u0000\u016c\u0169\u0001\u0000\u0000\u0000\u016c\u016a"+
-    "\u0001\u0000\u0000\u0000\u016c\u016b\u0001\u0000\u0000\u0000\u016d=\u0001"+
-    "\u0000\u0000\u0000\u016e\u016f\u0005\u000b\u0000\u0000\u016f\u0170\u0003"+
-    "\u008eG\u0000\u0170?\u0001\u0000\u0000\u0000\u0171\u0172\u0005\r\u0000"+
-    "\u0000\u0172\u0177\u0003B!\u0000\u0173\u0174\u0005>\u0000\u0000\u0174"+
-    "\u0176\u0003B!\u0000\u0175\u0173\u0001\u0000\u0000\u0000\u0176\u0179\u0001"+
-    "\u0000\u0000\u0000\u0177\u0175\u0001\u0000\u0000\u0000\u0177\u0178\u0001"+
-    "\u0000\u0000\u0000\u0178A\u0001\u0000\u0000\u0000\u0179\u0177\u0001\u0000"+
-    "\u0000\u0000\u017a\u017c\u0003z=\u0000\u017b\u017d\u0007\u0002\u0000\u0000"+
-    "\u017c\u017b\u0001\u0000\u0000\u0000\u017c\u017d\u0001\u0000\u0000\u0000"+
-    "\u017d\u0180\u0001\u0000\u0000\u0000\u017e\u017f\u0005I\u0000\u0000\u017f"+
-    "\u0181\u0007\u0003\u0000\u0000\u0180\u017e\u0001\u0000\u0000\u0000\u0180"+
-    "\u0181\u0001\u0000\u0000\u0000\u0181C\u0001\u0000\u0000\u0000\u0182\u0183"+
-    "\u0005\u001d\u0000\u0000\u0183\u0184\u00032\u0019\u0000\u0184E\u0001\u0000"+
-    "\u0000\u0000\u0185\u0186\u0005\u001c\u0000\u0000\u0186\u0187\u00032\u0019"+
-    "\u0000\u0187G\u0001\u0000\u0000\u0000\u0188\u0189\u0005 \u0000\u0000\u0189"+
-    "\u018e\u0003J%\u0000\u018a\u018b\u0005>\u0000\u0000\u018b\u018d\u0003"+
-    "J%\u0000\u018c\u018a\u0001\u0000\u0000\u0000\u018d\u0190\u0001\u0000\u0000"+
-    "\u0000\u018e\u018c\u0001\u0000\u0000\u0000\u018e\u018f\u0001\u0000\u0000"+
-    "\u0000\u018fI\u0001\u0000\u0000\u0000\u0190\u018e\u0001\u0000\u0000\u0000"+
-    "\u0191\u0192\u00030\u0018\u0000\u0192\u0193\u0005\u0084\u0000\u0000\u0193"+
-    "\u0194\u00030\u0018\u0000\u0194\u019a\u0001\u0000\u0000\u0000\u0195\u0196"+
-    "\u00030\u0018\u0000\u0196\u0197\u0005:\u0000\u0000\u0197\u0198\u00030"+
-    "\u0018\u0000\u0198\u019a\u0001\u0000\u0000\u0000\u0199\u0191\u0001\u0000"+
-    "\u0000\u0000\u0199\u0195\u0001\u0000\u0000\u0000\u019aK\u0001\u0000\u0000"+
-    "\u0000\u019b\u019c\u0005\b\u0000\u0000\u019c\u019d\u0003\u0084B\u0000"+
-    "\u019d\u019f\u0003\u0098L\u0000\u019e\u01a0\u0003R)\u0000\u019f\u019e"+
-    "\u0001\u0000\u0000\u0000\u019f\u01a0\u0001\u0000\u0000\u0000\u01a0M\u0001"+
-    "\u0000\u0000\u0000\u01a1\u01a2\u0005\n\u0000\u0000\u01a2\u01a3\u0003\u0084"+
-    "B\u0000\u01a3\u01a4\u0003\u0098L\u0000\u01a4O\u0001\u0000\u0000\u0000"+
-    "\u01a5\u01a6\u0005\u001b\u0000\u0000\u01a6\u01a7\u0003.\u0017\u0000\u01a7"+
-    "Q\u0001\u0000\u0000\u0000\u01a8\u01ad\u0003T*\u0000\u01a9\u01aa\u0005"+
-    ">\u0000\u0000\u01aa\u01ac\u0003T*\u0000\u01ab\u01a9\u0001\u0000\u0000"+
-    "\u0000\u01ac\u01af\u0001\u0000\u0000\u0000\u01ad\u01ab\u0001\u0000\u0000"+
-    "\u0000\u01ad\u01ae\u0001\u0000\u0000\u0000\u01aeS\u0001\u0000\u0000\u0000"+
-    "\u01af\u01ad\u0001\u0000\u0000\u0000\u01b0\u01b1\u00034\u001a\u0000\u01b1"+
-    "\u01b2\u0005:\u0000\u0000\u01b2\u01b3\u0003\u008eG\u0000\u01b3U\u0001"+
-    "\u0000\u0000\u0000\u01b4\u01b5\u0005\u0006\u0000\u0000\u01b5\u01b6\u0003"+
-    "X,\u0000\u01b6W\u0001\u0000\u0000\u0000\u01b7\u01b8\u0005a\u0000\u0000"+
-    "\u01b8\u01b9\u0003\u0002\u0001\u0000\u01b9\u01ba\u0005b\u0000\u0000\u01ba"+
-    "Y\u0001\u0000\u0000\u0000\u01bb\u01bc\u0005!\u0000\u0000\u01bc\u01bd\u0005"+
-    "\u0088\u0000\u0000\u01bd[\u0001\u0000\u0000\u0000\u01be\u01bf\u0005\u0005"+
-    "\u0000\u0000\u01bf\u01c2\u0005&\u0000\u0000\u01c0\u01c1\u0005J\u0000\u0000"+
-    "\u01c1\u01c3\u00030\u0018\u0000\u01c2\u01c0\u0001\u0000\u0000\u0000\u01c2"+
-    "\u01c3\u0001\u0000\u0000\u0000\u01c3\u01cd\u0001\u0000\u0000\u0000\u01c4"+
-    "\u01c5\u0005O\u0000\u0000\u01c5\u01ca\u0003^/\u0000\u01c6\u01c7\u0005"+
-    ">\u0000\u0000\u01c7\u01c9\u0003^/\u0000\u01c8\u01c6\u0001\u0000\u0000"+
-    "\u0000\u01c9\u01cc\u0001\u0000\u0000\u0000\u01ca\u01c8\u0001\u0000\u0000"+
-    "\u0000\u01ca\u01cb\u0001\u0000\u0000\u0000\u01cb\u01ce\u0001\u0000\u0000"+
-    "\u0000\u01cc\u01ca\u0001\u0000\u0000\u0000\u01cd\u01c4\u0001\u0000\u0000"+
-    "\u0000\u01cd\u01ce\u0001\u0000\u0000\u0000\u01ce]\u0001\u0000\u0000\u0000"+
-    "\u01cf\u01d0\u00030\u0018\u0000\u01d0\u01d1\u0005:\u0000\u0000\u01d1\u01d3"+
-    "\u0001\u0000\u0000\u0000\u01d2\u01cf\u0001\u0000\u0000\u0000\u01d2\u01d3"+
-    "\u0001\u0000\u0000\u0000\u01d3\u01d4\u0001\u0000\u0000\u0000\u01d4\u01d5"+
-    "\u00030\u0018\u0000\u01d5_\u0001\u0000\u0000\u0000\u01d6\u01d7\u0005\u001a"+
-    "\u0000\u0000\u01d7\u01d8\u0003\u001c\u000e\u0000\u01d8\u01d9\u0005J\u0000"+
-    "\u0000\u01d9\u01da\u00032\u0019\u0000\u01daa\u0001\u0000\u0000\u0000\u01db"+
-    "\u01dc\u0005\u0010\u0000\u0000\u01dc\u01df\u0003*\u0015\u0000\u01dd\u01de"+
-    "\u0005;\u0000\u0000\u01de\u01e0\u0003\u000e\u0007\u0000\u01df\u01dd\u0001"+
-    "\u0000\u0000\u0000\u01df\u01e0\u0001\u0000\u0000\u0000\u01e0c\u0001\u0000"+
-    "\u0000\u0000\u01e1\u01e2\u0005\u0004\u0000\u0000\u01e2\u01e5\u0003.\u0017"+
-    "\u0000\u01e3\u01e4\u0005J\u0000\u0000\u01e4\u01e6\u0003.\u0017\u0000\u01e5"+
-    "\u01e3\u0001\u0000\u0000\u0000\u01e5\u01e6\u0001\u0000\u0000\u0000\u01e6"+
-    "\u01ec\u0001\u0000\u0000\u0000\u01e7\u01e8\u0005\u0084\u0000\u0000\u01e8"+
-    "\u01e9\u0003.\u0017\u0000\u01e9\u01ea\u0005>\u0000\u0000\u01ea\u01eb\u0003"+
-    ".\u0017\u0000\u01eb\u01ed\u0001\u0000\u0000\u0000\u01ec\u01e7\u0001\u0000"+
-    "\u0000\u0000\u01ec\u01ed\u0001\u0000\u0000\u0000\u01ede\u0001\u0000\u0000"+
-    "\u0000\u01ee\u01ef\u0005\u001e\u0000\u0000\u01ef\u01f0\u00032\u0019\u0000"+
-    "\u01f0g\u0001\u0000\u0000\u0000\u01f1\u01f2\u0005\u0015\u0000\u0000\u01f2"+
-    "\u01f3\u0003j5\u0000\u01f3i\u0001\u0000\u0000\u0000\u01f4\u01f6\u0003"+
-    "l6\u0000\u01f5\u01f4\u0001\u0000\u0000\u0000\u01f6\u01f7\u0001\u0000\u0000"+
-    "\u0000\u01f7\u01f5\u0001\u0000\u0000\u0000\u01f7\u01f8\u0001\u0000\u0000"+
-    "\u0000\u01f8k\u0001\u0000\u0000\u0000\u01f9\u01fa\u0005c\u0000\u0000\u01fa"+
-    "\u01fb\u0003n7\u0000\u01fb\u01fc\u0005d\u0000\u0000\u01fcm\u0001\u0000"+
-    "\u0000\u0000\u01fd\u01fe\u00067\uffff\uffff\u0000\u01fe\u01ff\u0003p8"+
-    "\u0000\u01ff\u0205\u0001\u0000\u0000\u0000\u0200\u0201\n\u0001\u0000\u0000"+
-    "\u0201\u0202\u00054\u0000\u0000\u0202\u0204\u0003p8\u0000\u0203\u0200"+
-    "\u0001\u0000\u0000\u0000\u0204\u0207\u0001\u0000\u0000\u0000\u0205\u0203"+
-    "\u0001\u0000\u0000\u0000\u0205\u0206\u0001\u0000\u0000\u0000\u0206o\u0001"+
-    "\u0000\u0000\u0000\u0207\u0205\u0001\u0000\u0000\u0000\u0208\u0212\u0003"+
-    "&\u0013\u0000\u0209\u0212\u0003\b\u0004\u0000\u020a\u0212\u0003>\u001f"+
-    "\u0000\u020b\u0212\u0003(\u0014\u0000\u020c\u0212\u0003@ \u0000\u020d"+
-    "\u0212\u0003L&\u0000\u020e\u0212\u0003d2\u0000\u020f\u0212\u0003v;\u0000"+
-    "\u0210\u0212\u0003N\'\u0000\u0211\u0208\u0001\u0000\u0000\u0000\u0211"+
-    "\u0209\u0001\u0000\u0000\u0000\u0211\u020a\u0001\u0000\u0000\u0000\u0211"+
-    "\u020b\u0001\u0000\u0000\u0000\u0211\u020c\u0001\u0000\u0000\u0000\u0211"+
-    "\u020d\u0001\u0000\u0000\u0000\u0211\u020e\u0001\u0000\u0000\u0000\u0211"+
-    "\u020f\u0001\u0000\u0000\u0000\u0211\u0210\u0001\u0000\u0000\u0000\u0212"+
-    "q\u0001\u0000\u0000\u0000\u0213\u0214\u0005\u001f\u0000\u0000\u0214s\u0001"+
-    "\u0000\u0000\u0000\u0215\u0216\u0005\u0011\u0000\u0000\u0216\u0217\u0003"+
-    "\u008eG\u0000\u0217\u0218\u0005J\u0000\u0000\u0218\u021b\u0003\u0012\t"+
-    "\u0000\u0219\u021a\u0005O\u0000\u0000\u021a\u021c\u0003<\u001e\u0000\u021b"+
-    "\u0219\u0001\u0000\u0000\u0000\u021b\u021c\u0001\u0000\u0000\u0000\u021c"+
-    "u\u0001\u0000\u0000\u0000\u021d\u0221\u0005\u0007\u0000\u0000\u021e\u021f"+
-    "\u0003.\u0017\u0000\u021f\u0220\u0005:\u0000\u0000\u0220\u0222\u0001\u0000"+
-    "\u0000\u0000\u0221\u021e\u0001\u0000\u0000\u0000\u0221\u0222\u0001\u0000"+
-    "\u0000\u0000\u0222\u0223\u0001\u0000\u0000\u0000\u0223\u0224\u0003\u0084"+
-    "B\u0000\u0224\u0225\u0005O\u0000\u0000\u0225\u0226\u0003<\u001e\u0000"+
-    "\u0226w\u0001\u0000\u0000\u0000\u0227\u0228\u0005\u0012\u0000\u0000\u0228"+
-    "\u0229\u0003\u0094J\u0000\u0229y\u0001\u0000\u0000\u0000\u022a\u022b\u0006"+
-    "=\uffff\uffff\u0000\u022b\u022c\u0005G\u0000\u0000\u022c\u0248\u0003z"+
-    "=\b\u022d\u0248\u0003\u0080@\u0000\u022e\u0248\u0003|>\u0000\u022f\u0231"+
-    "\u0003\u0080@\u0000\u0230\u0232\u0005G\u0000\u0000\u0231\u0230\u0001\u0000"+
-    "\u0000\u0000\u0231\u0232\u0001\u0000\u0000\u0000\u0232\u0233\u0001\u0000"+
-    "\u0000\u0000\u0233\u0234\u0005C\u0000\u0000\u0234\u0235\u0005c\u0000\u0000"+
-    "\u0235\u023a\u0003\u0080@\u0000\u0236\u0237\u0005>\u0000\u0000\u0237\u0239"+
-    "\u0003\u0080@\u0000\u0238\u0236\u0001\u0000\u0000\u0000\u0239\u023c\u0001"+
-    "\u0000\u0000\u0000\u023a\u0238\u0001\u0000\u0000\u0000\u023a\u023b\u0001"+
-    "\u0000\u0000\u0000\u023b\u023d\u0001\u0000\u0000\u0000\u023c\u023a\u0001"+
-    "\u0000\u0000\u0000\u023d\u023e\u0005d\u0000\u0000\u023e\u0248\u0001\u0000"+
-    "\u0000\u0000\u023f\u0240\u0003\u0080@\u0000\u0240\u0242\u0005D\u0000\u0000"+
-    "\u0241\u0243\u0005G\u0000\u0000\u0242\u0241\u0001\u0000\u0000\u0000\u0242"+
-    "\u0243\u0001\u0000\u0000\u0000\u0243\u0244\u0001\u0000\u0000\u0000\u0244"+
-    "\u0245\u0005H\u0000\u0000\u0245\u0248\u0001\u0000\u0000\u0000\u0246\u0248"+
-    "\u0003~?\u0000\u0247\u022a\u0001\u0000\u0000\u0000\u0247\u022d\u0001\u0000"+
-    "\u0000\u0000\u0247\u022e\u0001\u0000\u0000\u0000\u0247\u022f\u0001\u0000"+
-    "\u0000\u0000\u0247\u023f\u0001\u0000\u0000\u0000\u0247\u0246\u0001\u0000"+
-    "\u0000\u0000\u0248\u0251\u0001\u0000\u0000\u0000\u0249\u024a\n\u0005\u0000"+
-    "\u0000\u024a\u024b\u00058\u0000\u0000\u024b\u0250\u0003z=\u0006\u024c"+
-    "\u024d\n\u0004\u0000\u0000\u024d\u024e\u0005K\u0000\u0000\u024e\u0250"+
-    "\u0003z=\u0005\u024f\u0249\u0001\u0000\u0000\u0000\u024f\u024c\u0001\u0000"+
-    "\u0000\u0000\u0250\u0253\u0001\u0000\u0000\u0000\u0251\u024f\u0001\u0000"+
-    "\u0000\u0000\u0251\u0252\u0001\u0000\u0000\u0000\u0252{\u0001\u0000\u0000"+
-    "\u0000\u0253\u0251\u0001\u0000\u0000\u0000\u0254\u0256\u0003\u0080@\u0000"+
-    "\u0255\u0257\u0005G\u0000\u0000\u0256\u0255\u0001\u0000\u0000\u0000\u0256"+
-    "\u0257\u0001\u0000\u0000\u0000\u0257\u0258\u0001\u0000\u0000\u0000\u0258"+
-    "\u0259\u0005F\u0000\u0000\u0259\u025a\u0003\u0098L\u0000\u025a\u0263\u0001"+
-    "\u0000\u0000\u0000\u025b\u025d\u0003\u0080@\u0000\u025c\u025e\u0005G\u0000"+
-    "\u0000\u025d\u025c\u0001\u0000\u0000\u0000\u025d\u025e\u0001\u0000\u0000"+
-    "\u0000\u025e\u025f\u0001\u0000\u0000\u0000\u025f\u0260\u0005M\u0000\u0000"+
-    "\u0260\u0261\u0003\u0098L\u0000\u0261\u0263\u0001\u0000\u0000\u0000\u0262"+
-    "\u0254\u0001\u0000\u0000\u0000\u0262\u025b\u0001\u0000\u0000\u0000\u0263"+
-    "}\u0001\u0000\u0000\u0000\u0264\u0267\u0003.\u0017\u0000\u0265\u0266\u0005"+
-    "<\u0000\u0000\u0266\u0268\u0003\n\u0005\u0000\u0267\u0265\u0001\u0000"+
-    "\u0000\u0000\u0267\u0268\u0001\u0000\u0000\u0000\u0268\u0269\u0001\u0000"+
-    "\u0000\u0000\u0269\u026a\u0005=\u0000\u0000\u026a\u026b\u0003\u008eG\u0000"+
-    "\u026b\u007f\u0001\u0000\u0000\u0000\u026c\u0272\u0003\u0082A\u0000\u026d"+
-    "\u026e\u0003\u0082A\u0000\u026e\u026f\u0003\u009aM\u0000\u026f\u0270\u0003"+
-    "\u0082A\u0000\u0270\u0272\u0001\u0000\u0000\u0000\u0271\u026c\u0001\u0000"+
-    "\u0000\u0000\u0271\u026d\u0001\u0000\u0000\u0000\u0272\u0081\u0001\u0000"+
-    "\u0000\u0000\u0273\u0274\u0006A\uffff\uffff\u0000\u0274\u0278\u0003\u0084"+
-    "B\u0000\u0275\u0276\u0007\u0004\u0000\u0000\u0276\u0278\u0003\u0082A\u0003"+
-    "\u0277\u0273\u0001\u0000\u0000\u0000\u0277\u0275\u0001\u0000\u0000\u0000"+
-    "\u0278\u0281\u0001\u0000\u0000\u0000\u0279\u027a\n\u0002\u0000\u0000\u027a"+
-    "\u027b\u0007\u0005\u0000\u0000\u027b\u0280\u0003\u0082A\u0003\u027c\u027d"+
-    "\n\u0001\u0000\u0000\u027d\u027e\u0007\u0004\u0000\u0000\u027e\u0280\u0003"+
-    "\u0082A\u0002\u027f\u0279\u0001\u0000\u0000\u0000\u027f\u027c\u0001\u0000"+
-    "\u0000\u0000\u0280\u0283\u0001\u0000\u0000\u0000\u0281\u027f\u0001\u0000"+
-    "\u0000\u0000\u0281\u0282\u0001\u0000\u0000\u0000\u0282\u0083\u0001\u0000"+
-    "\u0000\u0000\u0283\u0281\u0001\u0000\u0000\u0000\u0284\u0285\u0006B\uffff"+
-    "\uffff\u0000\u0285\u028d\u0003\u008eG\u0000\u0286\u028d\u0003.\u0017\u0000"+
-    "\u0287\u028d\u0003\u0086C\u0000\u0288\u0289\u0005c\u0000\u0000\u0289\u028a"+
-    "\u0003z=\u0000\u028a\u028b\u0005d\u0000\u0000\u028b\u028d\u0001\u0000"+
-    "\u0000\u0000\u028c\u0284\u0001\u0000\u0000\u0000\u028c\u0286\u0001\u0000"+
-    "\u0000\u0000\u028c\u0287\u0001\u0000\u0000\u0000\u028c\u0288\u0001\u0000"+
-    "\u0000\u0000\u028d\u0293\u0001\u0000\u0000\u0000\u028e\u028f\n\u0001\u0000"+
-    "\u0000\u028f\u0290\u0005<\u0000\u0000\u0290\u0292\u0003\n\u0005\u0000"+
-    "\u0291\u028e\u0001\u0000\u0000\u0000\u0292\u0295\u0001\u0000\u0000\u0000"+
-    "\u0293\u0291\u0001\u0000\u0000\u0000\u0293\u0294\u0001\u0000\u0000\u0000"+
-    "\u0294\u0085\u0001\u0000\u0000\u0000\u0295\u0293\u0001\u0000\u0000\u0000"+
-    "\u0296\u0297\u0003\u0088D\u0000\u0297\u02a5\u0005c\u0000\u0000\u0298\u02a6"+
-    "\u0005Y\u0000\u0000\u0299\u029e\u0003z=\u0000\u029a\u029b\u0005>\u0000"+
-    "\u0000\u029b\u029d\u0003z=\u0000\u029c\u029a\u0001\u0000\u0000\u0000\u029d"+
-    "\u02a0\u0001\u0000\u0000\u0000\u029e\u029c\u0001\u0000\u0000\u0000\u029e"+
-    "\u029f\u0001\u0000\u0000\u0000\u029f\u02a3\u0001\u0000\u0000\u0000\u02a0"+
-    "\u029e\u0001\u0000\u0000\u0000\u02a1\u02a2\u0005>\u0000\u0000\u02a2\u02a4"+
-    "\u0003\u008aE\u0000\u02a3\u02a1\u0001\u0000\u0000\u0000\u02a3\u02a4\u0001"+
-    "\u0000\u0000\u0000\u02a4\u02a6\u0001\u0000\u0000\u0000\u02a5\u0298\u0001"+
-    "\u0000\u0000\u0000\u02a5\u0299\u0001\u0000\u0000\u0000\u02a5\u02a6\u0001"+
-    "\u0000\u0000\u0000\u02a6\u02a7\u0001\u0000\u0000\u0000\u02a7\u02a8\u0005"+
-    "d\u0000\u0000\u02a8\u0087\u0001\u0000\u0000\u0000\u02a9\u02aa\u0003<\u001e"+
-    "\u0000\u02aa\u0089\u0001\u0000\u0000\u0000\u02ab\u02ac\u0005\\\u0000\u0000"+
-    "\u02ac\u02b1\u0003\u008cF\u0000\u02ad\u02ae\u0005>\u0000\u0000\u02ae\u02b0"+
-    "\u0003\u008cF\u0000\u02af\u02ad\u0001\u0000\u0000\u0000\u02b0\u02b3\u0001"+
-    "\u0000\u0000\u0000\u02b1\u02af\u0001\u0000\u0000\u0000\u02b1\u02b2\u0001"+
-    "\u0000\u0000\u0000\u02b2\u02b4\u0001\u0000\u0000\u0000\u02b3\u02b1\u0001"+
-    "\u0000\u0000\u0000\u02b4\u02b5\u0005]\u0000\u0000\u02b5\u008b\u0001\u0000"+
-    "\u0000\u0000\u02b6\u02b7\u0003\u0098L\u0000\u02b7\u02b8\u0005=\u0000\u0000"+
-    "\u02b8\u02b9\u0003\u008eG\u0000\u02b9\u008d\u0001\u0000\u0000\u0000\u02ba"+
-    "\u02e5\u0005H\u0000\u0000\u02bb\u02bc\u0003\u0096K\u0000\u02bc\u02bd\u0005"+
-    "e\u0000\u0000\u02bd\u02e5\u0001\u0000\u0000\u0000\u02be\u02e5\u0003\u0094"+
-    "J\u0000\u02bf\u02e5\u0003\u0096K\u0000\u02c0\u02e5\u0003\u0090H\u0000"+
-    "\u02c1\u02e5\u00038\u001c\u0000\u02c2\u02e5\u0003\u0098L\u0000\u02c3\u02c4"+
-    "\u0005a\u0000\u0000\u02c4\u02c9\u0003\u0092I\u0000\u02c5\u02c6\u0005>"+
-    "\u0000\u0000\u02c6\u02c8\u0003\u0092I\u0000\u02c7\u02c5\u0001\u0000\u0000"+
-    "\u0000\u02c8\u02cb\u0001\u0000\u0000\u0000\u02c9\u02c7\u0001\u0000\u0000"+
-    "\u0000\u02c9\u02ca\u0001\u0000\u0000\u0000\u02ca\u02cc\u0001\u0000\u0000"+
-    "\u0000\u02cb\u02c9\u0001\u0000\u0000\u0000\u02cc\u02cd\u0005b\u0000\u0000"+
-    "\u02cd\u02e5\u0001\u0000\u0000\u0000\u02ce\u02cf\u0005a\u0000\u0000\u02cf"+
-    "\u02d4\u0003\u0090H\u0000\u02d0\u02d1\u0005>\u0000\u0000\u02d1\u02d3\u0003"+
-    "\u0090H\u0000\u02d2\u02d0\u0001\u0000\u0000\u0000\u02d3\u02d6\u0001\u0000"+
-    "\u0000\u0000\u02d4\u02d2\u0001\u0000\u0000\u0000\u02d4\u02d5\u0001\u0000"+
-    "\u0000\u0000\u02d5\u02d7\u0001\u0000\u0000\u0000\u02d6\u02d4\u0001\u0000"+
-    "\u0000\u0000\u02d7\u02d8\u0005b\u0000\u0000\u02d8\u02e5\u0001\u0000\u0000"+
-    "\u0000\u02d9\u02da\u0005a\u0000\u0000\u02da\u02df\u0003\u0098L\u0000\u02db"+
-    "\u02dc\u0005>\u0000\u0000\u02dc\u02de\u0003\u0098L\u0000\u02dd\u02db\u0001"+
-    "\u0000\u0000\u0000\u02de\u02e1\u0001\u0000\u0000\u0000\u02df\u02dd\u0001"+
-    "\u0000\u0000\u0000\u02df\u02e0\u0001\u0000\u0000\u0000\u02e0\u02e2\u0001"+
-    "\u0000\u0000\u0000\u02e1\u02df\u0001\u0000\u0000\u0000\u02e2\u02e3\u0005"+
-    "b\u0000\u0000\u02e3\u02e5\u0001\u0000\u0000\u0000\u02e4\u02ba\u0001\u0000"+
-    "\u0000\u0000\u02e4\u02bb\u0001\u0000\u0000\u0000\u02e4\u02be\u0001\u0000"+
-    "\u0000\u0000\u02e4\u02bf\u0001\u0000\u0000\u0000\u02e4\u02c0\u0001\u0000"+
-    "\u0000\u0000\u02e4\u02c1\u0001\u0000\u0000\u0000\u02e4\u02c2\u0001\u0000"+
-    "\u0000\u0000\u02e4\u02c3\u0001\u0000\u0000\u0000\u02e4\u02ce\u0001\u0000"+
-    "\u0000\u0000\u02e4\u02d9\u0001\u0000\u0000\u0000\u02e5\u008f\u0001\u0000"+
-    "\u0000\u0000\u02e6\u02e7\u0007\u0006\u0000\u0000\u02e7\u0091\u0001\u0000"+
-    "\u0000\u0000\u02e8\u02eb\u0003\u0094J\u0000\u02e9\u02eb\u0003\u0096K\u0000"+
-    "\u02ea\u02e8\u0001\u0000\u0000\u0000\u02ea\u02e9\u0001\u0000\u0000\u0000"+
-    "\u02eb\u0093\u0001\u0000\u0000\u0000\u02ec\u02ee\u0007\u0004\u0000\u0000"+
-    "\u02ed\u02ec\u0001\u0000\u0000\u0000\u02ed\u02ee\u0001\u0000\u0000\u0000"+
-    "\u02ee\u02ef\u0001\u0000\u0000\u0000\u02ef\u02f0\u00057\u0000\u0000\u02f0"+
-    "\u0095\u0001\u0000\u0000\u0000\u02f1\u02f3\u0007\u0004\u0000\u0000\u02f2"+
-    "\u02f1\u0001\u0000\u0000\u0000\u02f2\u02f3\u0001\u0000\u0000\u0000\u02f3"+
-    "\u02f4\u0001\u0000\u0000\u0000\u02f4\u02f5\u00056\u0000\u0000\u02f5\u0097"+
-    "\u0001\u0000\u0000\u0000\u02f6\u02f7\u00055\u0000\u0000\u02f7\u0099\u0001"+
-    "\u0000\u0000\u0000\u02f8\u02f9\u0007\u0007\u0000\u0000\u02f9\u009b\u0001"+
-    "\u0000\u0000\u0000\u02fa\u02fb\u0007\b\u0000\u0000\u02fb\u02fc\u0005r"+
-    "\u0000\u0000\u02fc\u02fd\u0003\u009eO\u0000\u02fd\u02fe\u0003\u00a0P\u0000"+
-    "\u02fe\u009d\u0001\u0000\u0000\u0000\u02ff\u0300\u0003\u001c\u000e\u0000"+
-    "\u0300\u009f\u0001\u0000\u0000\u0000\u0301\u0302\u0005J\u0000\u0000\u0302"+
-    "\u0307\u0003\u00a2Q\u0000\u0303\u0304\u0005>\u0000\u0000\u0304\u0306\u0003"+
-    "\u00a2Q\u0000\u0305\u0303\u0001\u0000\u0000\u0000\u0306\u0309\u0001\u0000"+
-    "\u0000\u0000\u0307\u0305\u0001\u0000\u0000\u0000\u0307\u0308\u0001\u0000"+
-    "\u0000\u0000\u0308\u00a1\u0001\u0000\u0000\u0000\u0309\u0307\u0001\u0000"+
-    "\u0000\u0000\u030a\u030b\u0003\u0080@\u0000\u030b\u00a3\u0001\u0000\u0000"+
-    "\u0000G\u00af\u00b8\u00d7\u00e6\u00ec\u00f5\u00fb\u0108\u010c\u0111\u0117"+
-    "\u0119\u0127\u012f\u0133\u013a\u0140\u0147\u014f\u0157\u015f\u0163\u0167"+
-    "\u016c\u0177\u017c\u0180\u018e\u0199\u019f\u01ad\u01c2\u01ca\u01cd\u01d2"+
-    "\u01df\u01e5\u01ec\u01f7\u0205\u0211\u021b\u0221\u0231\u023a\u0242\u0247"+
-    "\u024f\u0251\u0256\u025d\u0262\u0267\u0271\u0277\u027f\u0281\u028c\u0293"+
-    "\u029e\u02a3\u02a5\u02b1\u02c9\u02d4\u02df\u02e4\u02ea\u02ed\u02f2\u0307";
+    ">\u0001>\u0001>\u0001>\u0003>\u0265\b>\u0001>\u0001>\u0001>\u0001>\u0001"+
+    ">\u0005>\u026c\b>\n>\f>\u026f\t>\u0001>\u0001>\u0003>\u0273\b>\u0001?"+
+    "\u0001?\u0001?\u0003?\u0278\b?\u0001?\u0001?\u0001?\u0001@\u0001@\u0001"+
+    "@\u0001@\u0001@\u0003@\u0282\b@\u0001A\u0001A\u0001A\u0001A\u0003A\u0288"+
+    "\bA\u0001A\u0001A\u0001A\u0001A\u0001A\u0001A\u0005A\u0290\bA\nA\fA\u0293"+
+    "\tA\u0001B\u0001B\u0001B\u0001B\u0001B\u0001B\u0001B\u0001B\u0003B\u029d"+
+    "\bB\u0001B\u0001B\u0001B\u0005B\u02a2\bB\nB\fB\u02a5\tB\u0001C\u0001C"+
+    "\u0001C\u0001C\u0001C\u0001C\u0005C\u02ad\bC\nC\fC\u02b0\tC\u0001C\u0001"+
+    "C\u0003C\u02b4\bC\u0003C\u02b6\bC\u0001C\u0001C\u0001D\u0001D\u0001E\u0001"+
+    "E\u0001E\u0001E\u0005E\u02c0\bE\nE\fE\u02c3\tE\u0001E\u0001E\u0001F\u0001"+
+    "F\u0001F\u0001F\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001"+
+    "G\u0001G\u0001G\u0001G\u0001G\u0001G\u0005G\u02d8\bG\nG\fG\u02db\tG\u0001"+
+    "G\u0001G\u0001G\u0001G\u0001G\u0001G\u0005G\u02e3\bG\nG\fG\u02e6\tG\u0001"+
+    "G\u0001G\u0001G\u0001G\u0001G\u0001G\u0005G\u02ee\bG\nG\fG\u02f1\tG\u0001"+
+    "G\u0001G\u0003G\u02f5\bG\u0001H\u0001H\u0001I\u0001I\u0003I\u02fb\bI\u0001"+
+    "J\u0003J\u02fe\bJ\u0001J\u0001J\u0001K\u0003K\u0303\bK\u0001K\u0001K\u0001"+
+    "L\u0001L\u0001M\u0001M\u0001N\u0001N\u0001N\u0001N\u0001N\u0001O\u0001"+
+    "O\u0001P\u0001P\u0001P\u0001P\u0005P\u0316\bP\nP\fP\u0319\tP\u0001Q\u0001"+
+    "Q\u0001Q\u0000\u0005\u0002nz\u0082\u0084R\u0000\u0002\u0004\u0006\b\n"+
+    "\f\u000e\u0010\u0012\u0014\u0016\u0018\u001a\u001c\u001e \"$&(*,.0246"+
+    "8:<>@BDFHJLNPRTVXZ\\^`bdfhjlnprtvxz|~\u0080\u0082\u0084\u0086\u0088\u008a"+
+    "\u008c\u008e\u0090\u0092\u0094\u0096\u0098\u009a\u009c\u009e\u00a0\u00a2"+
+    "\u0000\t\u0002\u000055kk\u0001\u0000ef\u0002\u000099??\u0002\u0000BBE"+
+    "E\u0001\u0000WX\u0001\u0000Y[\u0002\u0000AANN\u0002\u0000PPRV\u0002\u0000"+
+    "\u0016\u0016\u0018\u0019\u0343\u0000\u00a4\u0001\u0000\u0000\u0000\u0002"+
+    "\u00a7\u0001\u0000\u0000\u0000\u0004\u00b8\u0001\u0000\u0000\u0000\u0006"+
+    "\u00d7\u0001\u0000\u0000\u0000\b\u00d9\u0001\u0000\u0000\u0000\n\u00dc"+
+    "\u0001\u0000\u0000\u0000\f\u00de\u0001\u0000\u0000\u0000\u000e\u00e1\u0001"+
+    "\u0000\u0000\u0000\u0010\u00ec\u0001\u0000\u0000\u0000\u0012\u00f0\u0001"+
+    "\u0000\u0000\u0000\u0014\u00f8\u0001\u0000\u0000\u0000\u0016\u00fd\u0001"+
+    "\u0000\u0000\u0000\u0018\u0100\u0001\u0000\u0000\u0000\u001a\u0103\u0001"+
+    "\u0000\u0000\u0000\u001c\u0119\u0001\u0000\u0000\u0000\u001e\u011b\u0001"+
+    "\u0000\u0000\u0000 \u011d\u0001\u0000\u0000\u0000\"\u011f\u0001\u0000"+
+    "\u0000\u0000$\u0121\u0001\u0000\u0000\u0000&\u012a\u0001\u0000\u0000\u0000"+
+    "(\u012d\u0001\u0000\u0000\u0000*\u0135\u0001\u0000\u0000\u0000,\u013d"+
+    "\u0001\u0000\u0000\u0000.\u0142\u0001\u0000\u0000\u00000\u014a\u0001\u0000"+
+    "\u0000\u00002\u0152\u0001\u0000\u0000\u00004\u015a\u0001\u0000\u0000\u0000"+
+    "6\u015f\u0001\u0000\u0000\u00008\u0163\u0001\u0000\u0000\u0000:\u0167"+
+    "\u0001\u0000\u0000\u0000<\u016c\u0001\u0000\u0000\u0000>\u016e\u0001\u0000"+
+    "\u0000\u0000@\u0171\u0001\u0000\u0000\u0000B\u017a\u0001\u0000\u0000\u0000"+
+    "D\u0182\u0001\u0000\u0000\u0000F\u0185\u0001\u0000\u0000\u0000H\u0188"+
+    "\u0001\u0000\u0000\u0000J\u0199\u0001\u0000\u0000\u0000L\u019b\u0001\u0000"+
+    "\u0000\u0000N\u01a1\u0001\u0000\u0000\u0000P\u01a5\u0001\u0000\u0000\u0000"+
+    "R\u01a8\u0001\u0000\u0000\u0000T\u01b0\u0001\u0000\u0000\u0000V\u01b4"+
+    "\u0001\u0000\u0000\u0000X\u01b7\u0001\u0000\u0000\u0000Z\u01bb\u0001\u0000"+
+    "\u0000\u0000\\\u01be\u0001\u0000\u0000\u0000^\u01d2\u0001\u0000\u0000"+
+    "\u0000`\u01d6\u0001\u0000\u0000\u0000b\u01db\u0001\u0000\u0000\u0000d"+
+    "\u01e1\u0001\u0000\u0000\u0000f\u01ee\u0001\u0000\u0000\u0000h\u01f1\u0001"+
+    "\u0000\u0000\u0000j\u01f5\u0001\u0000\u0000\u0000l\u01f9\u0001\u0000\u0000"+
+    "\u0000n\u01fd\u0001\u0000\u0000\u0000p\u0211\u0001\u0000\u0000\u0000r"+
+    "\u0213\u0001\u0000\u0000\u0000t\u0215\u0001\u0000\u0000\u0000v\u021d\u0001"+
+    "\u0000\u0000\u0000x\u0227\u0001\u0000\u0000\u0000z\u0247\u0001\u0000\u0000"+
+    "\u0000|\u0272\u0001\u0000\u0000\u0000~\u0274\u0001\u0000\u0000\u0000\u0080"+
+    "\u0281\u0001\u0000\u0000\u0000\u0082\u0287\u0001\u0000\u0000\u0000\u0084"+
+    "\u029c\u0001\u0000\u0000\u0000\u0086\u02a6\u0001\u0000\u0000\u0000\u0088"+
+    "\u02b9\u0001\u0000\u0000\u0000\u008a\u02bb\u0001\u0000\u0000\u0000\u008c"+
+    "\u02c6\u0001\u0000\u0000\u0000\u008e\u02f4\u0001\u0000\u0000\u0000\u0090"+
+    "\u02f6\u0001\u0000\u0000\u0000\u0092\u02fa\u0001\u0000\u0000\u0000\u0094"+
+    "\u02fd\u0001\u0000\u0000\u0000\u0096\u0302\u0001\u0000\u0000\u0000\u0098"+
+    "\u0306\u0001\u0000\u0000\u0000\u009a\u0308\u0001\u0000\u0000\u0000\u009c"+
+    "\u030a\u0001\u0000\u0000\u0000\u009e\u030f\u0001\u0000\u0000\u0000\u00a0"+
+    "\u0311\u0001\u0000\u0000\u0000\u00a2\u031a\u0001\u0000\u0000\u0000\u00a4"+
+    "\u00a5\u0003\u0002\u0001\u0000\u00a5\u00a6\u0005\u0000\u0000\u0001\u00a6"+
+    "\u0001\u0001\u0000\u0000\u0000\u00a7\u00a8\u0006\u0001\uffff\uffff\u0000"+
+    "\u00a8\u00a9\u0003\u0004\u0002\u0000\u00a9\u00af\u0001\u0000\u0000\u0000"+
+    "\u00aa\u00ab\n\u0001\u0000\u0000\u00ab\u00ac\u00054\u0000\u0000\u00ac"+
+    "\u00ae\u0003\u0006\u0003\u0000\u00ad\u00aa\u0001\u0000\u0000\u0000\u00ae"+
+    "\u00b1\u0001\u0000\u0000\u0000\u00af\u00ad\u0001\u0000\u0000\u0000\u00af"+
+    "\u00b0\u0001\u0000\u0000\u0000\u00b0\u0003\u0001\u0000\u0000\u0000\u00b1"+
+    "\u00af\u0001\u0000\u0000\u0000\u00b2\u00b9\u0003V+\u0000\u00b3\u00b9\u0003"+
+    "\u0016\u000b\u0000\u00b4\u00b9\u0003\f\u0006\u0000\u00b5\u00b9\u0003Z"+
+    "-\u0000\u00b6\u00b7\u0004\u0002\u0001\u0000\u00b7\u00b9\u0003\u0018\f"+
+    "\u0000\u00b8\u00b2\u0001\u0000\u0000\u0000\u00b8\u00b3\u0001\u0000\u0000"+
+    "\u0000\u00b8\u00b4\u0001\u0000\u0000\u0000\u00b8\u00b5\u0001\u0000\u0000"+
+    "\u0000\u00b8\u00b6\u0001\u0000\u0000\u0000\u00b9\u0005\u0001\u0000\u0000"+
+    "\u0000\u00ba\u00d8\u0003&\u0013\u0000\u00bb\u00d8\u0003\b\u0004\u0000"+
+    "\u00bc\u00d8\u0003D\"\u0000\u00bd\u00d8\u0003>\u001f\u0000\u00be\u00d8"+
+    "\u0003(\u0014\u0000\u00bf\u00d8\u0003@ \u0000\u00c0\u00d8\u0003F#\u0000"+
+    "\u00c1\u00d8\u0003H$\u0000\u00c2\u00d8\u0003L&\u0000\u00c3\u00d8\u0003"+
+    "N\'\u0000\u00c4\u00d8\u0003\\.\u0000\u00c5\u00d8\u0003P(\u0000\u00c6\u00d8"+
+    "\u0003\u009cN\u0000\u00c7\u00d8\u0003d2\u0000\u00c8\u00d8\u0003v;\u0000"+
+    "\u00c9\u00ca\u0004\u0003\u0002\u0000\u00ca\u00d8\u0003b1\u0000\u00cb\u00cc"+
+    "\u0004\u0003\u0003\u0000\u00cc\u00d8\u0003`0\u0000\u00cd\u00ce\u0004\u0003"+
+    "\u0004\u0000\u00ce\u00d8\u0003f3\u0000\u00cf\u00d0\u0004\u0003\u0005\u0000"+
+    "\u00d0\u00d8\u0003h4\u0000\u00d1\u00d2\u0004\u0003\u0006\u0000\u00d2\u00d8"+
+    "\u0003t:\u0000\u00d3\u00d4\u0004\u0003\u0007\u0000\u00d4\u00d8\u0003r"+
+    "9\u0000\u00d5\u00d6\u0004\u0003\b\u0000\u00d6\u00d8\u0003x<\u0000\u00d7"+
+    "\u00ba\u0001\u0000\u0000\u0000\u00d7\u00bb\u0001\u0000\u0000\u0000\u00d7"+
+    "\u00bc\u0001\u0000\u0000\u0000\u00d7\u00bd\u0001\u0000\u0000\u0000\u00d7"+
+    "\u00be\u0001\u0000\u0000\u0000\u00d7\u00bf\u0001\u0000\u0000\u0000\u00d7"+
+    "\u00c0\u0001\u0000\u0000\u0000\u00d7\u00c1\u0001\u0000\u0000\u0000\u00d7"+
+    "\u00c2\u0001\u0000\u0000\u0000\u00d7\u00c3\u0001\u0000\u0000\u0000\u00d7"+
+    "\u00c4\u0001\u0000\u0000\u0000\u00d7\u00c5\u0001\u0000\u0000\u0000\u00d7"+
+    "\u00c6\u0001\u0000\u0000\u0000\u00d7\u00c7\u0001\u0000\u0000\u0000\u00d7"+
+    "\u00c8\u0001\u0000\u0000\u0000\u00d7\u00c9\u0001\u0000\u0000\u0000\u00d7"+
+    "\u00cb\u0001\u0000\u0000\u0000\u00d7\u00cd\u0001\u0000\u0000\u0000\u00d7"+
+    "\u00cf\u0001\u0000\u0000\u0000\u00d7\u00d1\u0001\u0000\u0000\u0000\u00d7"+
+    "\u00d3\u0001\u0000\u0000\u0000\u00d7\u00d5\u0001\u0000\u0000\u0000\u00d8"+
+    "\u0007\u0001\u0000\u0000\u0000\u00d9\u00da\u0005\u000f\u0000\u0000\u00da"+
+    "\u00db\u0003z=\u0000\u00db\t\u0001\u0000\u0000\u0000\u00dc\u00dd\u0003"+
+    "4\u001a\u0000\u00dd\u000b\u0001\u0000\u0000\u0000\u00de\u00df\u0005\f"+
+    "\u0000\u0000\u00df\u00e0\u0003\u000e\u0007\u0000\u00e0\r\u0001\u0000\u0000"+
+    "\u0000\u00e1\u00e6\u0003\u0010\b\u0000\u00e2\u00e3\u0005>\u0000\u0000"+
+    "\u00e3\u00e5\u0003\u0010\b\u0000\u00e4\u00e2\u0001\u0000\u0000\u0000\u00e5"+
+    "\u00e8\u0001\u0000\u0000\u0000\u00e6\u00e4\u0001\u0000\u0000\u0000\u00e6"+
+    "\u00e7\u0001\u0000\u0000\u0000\u00e7\u000f\u0001\u0000\u0000\u0000\u00e8"+
+    "\u00e6\u0001\u0000\u0000\u0000\u00e9\u00ea\u0003.\u0017\u0000\u00ea\u00eb"+
+    "\u0005:\u0000\u0000\u00eb\u00ed\u0001\u0000\u0000\u0000\u00ec\u00e9\u0001"+
+    "\u0000\u0000\u0000\u00ec\u00ed\u0001\u0000\u0000\u0000\u00ed\u00ee\u0001"+
+    "\u0000\u0000\u0000\u00ee\u00ef\u0003z=\u0000\u00ef\u0011\u0001\u0000\u0000"+
+    "\u0000\u00f0\u00f5\u0003\u0014\n\u0000\u00f1\u00f2\u0005>\u0000\u0000"+
+    "\u00f2\u00f4\u0003\u0014\n\u0000\u00f3\u00f1\u0001\u0000\u0000\u0000\u00f4"+
+    "\u00f7\u0001\u0000\u0000\u0000\u00f5\u00f3\u0001\u0000\u0000\u0000\u00f5"+
+    "\u00f6\u0001\u0000\u0000\u0000\u00f6\u0013\u0001\u0000\u0000\u0000\u00f7"+
+    "\u00f5\u0001\u0000\u0000\u0000\u00f8\u00fb\u0003.\u0017\u0000\u00f9\u00fa"+
+    "\u0005:\u0000\u0000\u00fa\u00fc\u0003z=\u0000\u00fb\u00f9\u0001\u0000"+
+    "\u0000\u0000\u00fb\u00fc\u0001\u0000\u0000\u0000\u00fc\u0015\u0001\u0000"+
+    "\u0000\u0000\u00fd\u00fe\u0005\u0013\u0000\u0000\u00fe\u00ff\u0003\u001a"+
+    "\r\u0000\u00ff\u0017\u0001\u0000\u0000\u0000\u0100\u0101\u0005\u0014\u0000"+
+    "\u0000\u0101\u0102\u0003\u001a\r\u0000\u0102\u0019\u0001\u0000\u0000\u0000"+
+    "\u0103\u0108\u0003\u001c\u000e\u0000\u0104\u0105\u0005>\u0000\u0000\u0105"+
+    "\u0107\u0003\u001c\u000e\u0000\u0106\u0104\u0001\u0000\u0000\u0000\u0107"+
+    "\u010a\u0001\u0000\u0000\u0000\u0108\u0106\u0001\u0000\u0000\u0000\u0108"+
+    "\u0109\u0001\u0000\u0000\u0000\u0109\u010c\u0001\u0000\u0000\u0000\u010a"+
+    "\u0108\u0001\u0000\u0000\u0000\u010b\u010d\u0003$\u0012\u0000\u010c\u010b"+
+    "\u0001\u0000\u0000\u0000\u010c\u010d\u0001\u0000\u0000\u0000\u010d\u001b"+
+    "\u0001\u0000\u0000\u0000\u010e\u010f\u0003\u001e\u000f\u0000\u010f\u0110"+
+    "\u0005=\u0000\u0000\u0110\u0112\u0001\u0000\u0000\u0000\u0111\u010e\u0001"+
+    "\u0000\u0000\u0000\u0111\u0112\u0001\u0000\u0000\u0000\u0112\u0113\u0001"+
+    "\u0000\u0000\u0000\u0113\u011a\u0003\"\u0011\u0000\u0114\u0117\u0003\""+
+    "\u0011\u0000\u0115\u0116\u0005<\u0000\u0000\u0116\u0118\u0003 \u0010\u0000"+
+    "\u0117\u0115\u0001\u0000\u0000\u0000\u0117\u0118\u0001\u0000\u0000\u0000"+
+    "\u0118\u011a\u0001\u0000\u0000\u0000\u0119\u0111\u0001\u0000\u0000\u0000"+
+    "\u0119\u0114\u0001\u0000\u0000\u0000\u011a\u001d\u0001\u0000\u0000\u0000"+
+    "\u011b\u011c\u0007\u0000\u0000\u0000\u011c\u001f\u0001\u0000\u0000\u0000"+
+    "\u011d\u011e\u0007\u0000\u0000\u0000\u011e!\u0001\u0000\u0000\u0000\u011f"+
+    "\u0120\u0007\u0000\u0000\u0000\u0120#\u0001\u0000\u0000\u0000\u0121\u0122"+
+    "\u0005j\u0000\u0000\u0122\u0127\u0005k\u0000\u0000\u0123\u0124\u0005>"+
+    "\u0000\u0000\u0124\u0126\u0005k\u0000\u0000\u0125\u0123\u0001\u0000\u0000"+
+    "\u0000\u0126\u0129\u0001\u0000\u0000\u0000\u0127\u0125\u0001\u0000\u0000"+
+    "\u0000\u0127\u0128\u0001\u0000\u0000\u0000\u0128%\u0001\u0000\u0000\u0000"+
+    "\u0129\u0127\u0001\u0000\u0000\u0000\u012a\u012b\u0005\t\u0000\u0000\u012b"+
+    "\u012c\u0003\u000e\u0007\u0000\u012c\'\u0001\u0000\u0000\u0000\u012d\u012f"+
+    "\u0005\u000e\u0000\u0000\u012e\u0130\u0003*\u0015\u0000\u012f\u012e\u0001"+
+    "\u0000\u0000\u0000\u012f\u0130\u0001\u0000\u0000\u0000\u0130\u0133\u0001"+
+    "\u0000\u0000\u0000\u0131\u0132\u0005;\u0000\u0000\u0132\u0134\u0003\u000e"+
+    "\u0007\u0000\u0133\u0131\u0001\u0000\u0000\u0000\u0133\u0134\u0001\u0000"+
+    "\u0000\u0000\u0134)\u0001\u0000\u0000\u0000\u0135\u013a\u0003,\u0016\u0000"+
+    "\u0136\u0137\u0005>\u0000\u0000\u0137\u0139\u0003,\u0016\u0000\u0138\u0136"+
+    "\u0001\u0000\u0000\u0000\u0139\u013c\u0001\u0000\u0000\u0000\u013a\u0138"+
+    "\u0001\u0000\u0000\u0000\u013a\u013b\u0001\u0000\u0000\u0000\u013b+\u0001"+
+    "\u0000\u0000\u0000\u013c\u013a\u0001\u0000\u0000\u0000\u013d\u0140\u0003"+
+    "\u0010\b\u0000\u013e\u013f\u0005\u000f\u0000\u0000\u013f\u0141\u0003z"+
+    "=\u0000\u0140\u013e\u0001\u0000\u0000\u0000\u0140\u0141\u0001\u0000\u0000"+
+    "\u0000\u0141-\u0001\u0000\u0000\u0000\u0142\u0147\u0003<\u001e\u0000\u0143"+
+    "\u0144\u0005@\u0000\u0000\u0144\u0146\u0003<\u001e\u0000\u0145\u0143\u0001"+
+    "\u0000\u0000\u0000\u0146\u0149\u0001\u0000\u0000\u0000\u0147\u0145\u0001"+
+    "\u0000\u0000\u0000\u0147\u0148\u0001\u0000\u0000\u0000\u0148/\u0001\u0000"+
+    "\u0000\u0000\u0149\u0147\u0001\u0000\u0000\u0000\u014a\u014f\u00036\u001b"+
+    "\u0000\u014b\u014c\u0005@\u0000\u0000\u014c\u014e\u00036\u001b\u0000\u014d"+
+    "\u014b\u0001\u0000\u0000\u0000\u014e\u0151\u0001\u0000\u0000\u0000\u014f"+
+    "\u014d\u0001\u0000\u0000\u0000\u014f\u0150\u0001\u0000\u0000\u0000\u0150"+
+    "1\u0001\u0000\u0000\u0000\u0151\u014f\u0001\u0000\u0000\u0000\u0152\u0157"+
+    "\u00030\u0018\u0000\u0153\u0154\u0005>\u0000\u0000\u0154\u0156\u00030"+
+    "\u0018\u0000\u0155\u0153\u0001\u0000\u0000\u0000\u0156\u0159\u0001\u0000"+
+    "\u0000\u0000\u0157\u0155\u0001\u0000\u0000\u0000\u0157\u0158\u0001\u0000"+
+    "\u0000\u0000\u01583\u0001\u0000\u0000\u0000\u0159\u0157\u0001\u0000\u0000"+
+    "\u0000\u015a\u015b\u0007\u0001\u0000\u0000\u015b5\u0001\u0000\u0000\u0000"+
+    "\u015c\u0160\u0005\u0080\u0000\u0000\u015d\u0160\u00038\u001c\u0000\u015e"+
+    "\u0160\u0003:\u001d\u0000\u015f\u015c\u0001\u0000\u0000\u0000\u015f\u015d"+
+    "\u0001\u0000\u0000\u0000\u015f\u015e\u0001\u0000\u0000\u0000\u01607\u0001"+
+    "\u0000\u0000\u0000\u0161\u0164\u0005L\u0000\u0000\u0162\u0164\u0005_\u0000"+
+    "\u0000\u0163\u0161\u0001\u0000\u0000\u0000\u0163\u0162\u0001\u0000\u0000"+
+    "\u0000\u01649\u0001\u0000\u0000\u0000\u0165\u0168\u0005^\u0000\u0000\u0166"+
+    "\u0168\u0005`\u0000\u0000\u0167\u0165\u0001\u0000\u0000\u0000\u0167\u0166"+
+    "\u0001\u0000\u0000\u0000\u0168;\u0001\u0000\u0000\u0000\u0169\u016d\u0003"+
+    "4\u001a\u0000\u016a\u016d\u00038\u001c\u0000\u016b\u016d\u0003:\u001d"+
+    "\u0000\u016c\u0169\u0001\u0000\u0000\u0000\u016c\u016a\u0001\u0000\u0000"+
+    "\u0000\u016c\u016b\u0001\u0000\u0000\u0000\u016d=\u0001\u0000\u0000\u0000"+
+    "\u016e\u016f\u0005\u000b\u0000\u0000\u016f\u0170\u0003\u008eG\u0000\u0170"+
+    "?\u0001\u0000\u0000\u0000\u0171\u0172\u0005\r\u0000\u0000\u0172\u0177"+
+    "\u0003B!\u0000\u0173\u0174\u0005>\u0000\u0000\u0174\u0176\u0003B!\u0000"+
+    "\u0175\u0173\u0001\u0000\u0000\u0000\u0176\u0179\u0001\u0000\u0000\u0000"+
+    "\u0177\u0175\u0001\u0000\u0000\u0000\u0177\u0178\u0001\u0000\u0000\u0000"+
+    "\u0178A\u0001\u0000\u0000\u0000\u0179\u0177\u0001\u0000\u0000\u0000\u017a"+
+    "\u017c\u0003z=\u0000\u017b\u017d\u0007\u0002\u0000\u0000\u017c\u017b\u0001"+
+    "\u0000\u0000\u0000\u017c\u017d\u0001\u0000\u0000\u0000\u017d\u0180\u0001"+
+    "\u0000\u0000\u0000\u017e\u017f\u0005I\u0000\u0000\u017f\u0181\u0007\u0003"+
+    "\u0000\u0000\u0180\u017e\u0001\u0000\u0000\u0000\u0180\u0181\u0001\u0000"+
+    "\u0000\u0000\u0181C\u0001\u0000\u0000\u0000\u0182\u0183\u0005\u001d\u0000"+
+    "\u0000\u0183\u0184\u00032\u0019\u0000\u0184E\u0001\u0000\u0000\u0000\u0185"+
+    "\u0186\u0005\u001c\u0000\u0000\u0186\u0187\u00032\u0019\u0000\u0187G\u0001"+
+    "\u0000\u0000\u0000\u0188\u0189\u0005 \u0000\u0000\u0189\u018e\u0003J%"+
+    "\u0000\u018a\u018b\u0005>\u0000\u0000\u018b\u018d\u0003J%\u0000\u018c"+
+    "\u018a\u0001\u0000\u0000\u0000\u018d\u0190\u0001\u0000\u0000\u0000\u018e"+
+    "\u018c\u0001\u0000\u0000\u0000\u018e\u018f\u0001\u0000\u0000\u0000\u018f"+
+    "I\u0001\u0000\u0000\u0000\u0190\u018e\u0001\u0000\u0000\u0000\u0191\u0192"+
+    "\u00030\u0018\u0000\u0192\u0193\u0005\u0084\u0000\u0000\u0193\u0194\u0003"+
+    "0\u0018\u0000\u0194\u019a\u0001\u0000\u0000\u0000\u0195\u0196\u00030\u0018"+
+    "\u0000\u0196\u0197\u0005:\u0000\u0000\u0197\u0198\u00030\u0018\u0000\u0198"+
+    "\u019a\u0001\u0000\u0000\u0000\u0199\u0191\u0001\u0000\u0000\u0000\u0199"+
+    "\u0195\u0001\u0000\u0000\u0000\u019aK\u0001\u0000\u0000\u0000\u019b\u019c"+
+    "\u0005\b\u0000\u0000\u019c\u019d\u0003\u0084B\u0000\u019d\u019f\u0003"+
+    "\u0098L\u0000\u019e\u01a0\u0003R)\u0000\u019f\u019e\u0001\u0000\u0000"+
+    "\u0000\u019f\u01a0\u0001\u0000\u0000\u0000\u01a0M\u0001\u0000\u0000\u0000"+
+    "\u01a1\u01a2\u0005\n\u0000\u0000\u01a2\u01a3\u0003\u0084B\u0000\u01a3"+
+    "\u01a4\u0003\u0098L\u0000\u01a4O\u0001\u0000\u0000\u0000\u01a5\u01a6\u0005"+
+    "\u001b\u0000\u0000\u01a6\u01a7\u0003.\u0017\u0000\u01a7Q\u0001\u0000\u0000"+
+    "\u0000\u01a8\u01ad\u0003T*\u0000\u01a9\u01aa\u0005>\u0000\u0000\u01aa"+
+    "\u01ac\u0003T*\u0000\u01ab\u01a9\u0001\u0000\u0000\u0000\u01ac\u01af\u0001"+
+    "\u0000\u0000\u0000\u01ad\u01ab\u0001\u0000\u0000\u0000\u01ad\u01ae\u0001"+
+    "\u0000\u0000\u0000\u01aeS\u0001\u0000\u0000\u0000\u01af\u01ad\u0001\u0000"+
+    "\u0000\u0000\u01b0\u01b1\u00034\u001a\u0000\u01b1\u01b2\u0005:\u0000\u0000"+
+    "\u01b2\u01b3\u0003\u008eG\u0000\u01b3U\u0001\u0000\u0000\u0000\u01b4\u01b5"+
+    "\u0005\u0006\u0000\u0000\u01b5\u01b6\u0003X,\u0000\u01b6W\u0001\u0000"+
+    "\u0000\u0000\u01b7\u01b8\u0005a\u0000\u0000\u01b8\u01b9\u0003\u0002\u0001"+
+    "\u0000\u01b9\u01ba\u0005b\u0000\u0000\u01baY\u0001\u0000\u0000\u0000\u01bb"+
+    "\u01bc\u0005!\u0000\u0000\u01bc\u01bd\u0005\u0088\u0000\u0000\u01bd[\u0001"+
+    "\u0000\u0000\u0000\u01be\u01bf\u0005\u0005\u0000\u0000\u01bf\u01c2\u0005"+
+    "&\u0000\u0000\u01c0\u01c1\u0005J\u0000\u0000\u01c1\u01c3\u00030\u0018"+
+    "\u0000\u01c2\u01c0\u0001\u0000\u0000\u0000\u01c2\u01c3\u0001\u0000\u0000"+
+    "\u0000\u01c3\u01cd\u0001\u0000\u0000\u0000\u01c4\u01c5\u0005O\u0000\u0000"+
+    "\u01c5\u01ca\u0003^/\u0000\u01c6\u01c7\u0005>\u0000\u0000\u01c7\u01c9"+
+    "\u0003^/\u0000\u01c8\u01c6\u0001\u0000\u0000\u0000\u01c9\u01cc\u0001\u0000"+
+    "\u0000\u0000\u01ca\u01c8\u0001\u0000\u0000\u0000\u01ca\u01cb\u0001\u0000"+
+    "\u0000\u0000\u01cb\u01ce\u0001\u0000\u0000\u0000\u01cc\u01ca\u0001\u0000"+
+    "\u0000\u0000\u01cd\u01c4\u0001\u0000\u0000\u0000\u01cd\u01ce\u0001\u0000"+
+    "\u0000\u0000\u01ce]\u0001\u0000\u0000\u0000\u01cf\u01d0\u00030\u0018\u0000"+
+    "\u01d0\u01d1\u0005:\u0000\u0000\u01d1\u01d3\u0001\u0000\u0000\u0000\u01d2"+
+    "\u01cf\u0001\u0000\u0000\u0000\u01d2\u01d3\u0001\u0000\u0000\u0000\u01d3"+
+    "\u01d4\u0001\u0000\u0000\u0000\u01d4\u01d5\u00030\u0018\u0000\u01d5_\u0001"+
+    "\u0000\u0000\u0000\u01d6\u01d7\u0005\u001a\u0000\u0000\u01d7\u01d8\u0003"+
+    "\u001c\u000e\u0000\u01d8\u01d9\u0005J\u0000\u0000\u01d9\u01da\u00032\u0019"+
+    "\u0000\u01daa\u0001\u0000\u0000\u0000\u01db\u01dc\u0005\u0010\u0000\u0000"+
+    "\u01dc\u01df\u0003*\u0015\u0000\u01dd\u01de\u0005;\u0000\u0000\u01de\u01e0"+
+    "\u0003\u000e\u0007\u0000\u01df\u01dd\u0001\u0000\u0000\u0000\u01df\u01e0"+
+    "\u0001\u0000\u0000\u0000\u01e0c\u0001\u0000\u0000\u0000\u01e1\u01e2\u0005"+
+    "\u0004\u0000\u0000\u01e2\u01e5\u0003.\u0017\u0000\u01e3\u01e4\u0005J\u0000"+
+    "\u0000\u01e4\u01e6\u0003.\u0017\u0000\u01e5\u01e3\u0001\u0000\u0000\u0000"+
+    "\u01e5\u01e6\u0001\u0000\u0000\u0000\u01e6\u01ec\u0001\u0000\u0000\u0000"+
+    "\u01e7\u01e8\u0005\u0084\u0000\u0000\u01e8\u01e9\u0003.\u0017\u0000\u01e9"+
+    "\u01ea\u0005>\u0000\u0000\u01ea\u01eb\u0003.\u0017\u0000\u01eb\u01ed\u0001"+
+    "\u0000\u0000\u0000\u01ec\u01e7\u0001\u0000\u0000\u0000\u01ec\u01ed\u0001"+
+    "\u0000\u0000\u0000\u01ede\u0001\u0000\u0000\u0000\u01ee\u01ef\u0005\u001e"+
+    "\u0000\u0000\u01ef\u01f0\u00032\u0019\u0000\u01f0g\u0001\u0000\u0000\u0000"+
+    "\u01f1\u01f2\u0005\u0015\u0000\u0000\u01f2\u01f3\u0003j5\u0000\u01f3i"+
+    "\u0001\u0000\u0000\u0000\u01f4\u01f6\u0003l6\u0000\u01f5\u01f4\u0001\u0000"+
+    "\u0000\u0000\u01f6\u01f7\u0001\u0000\u0000\u0000\u01f7\u01f5\u0001\u0000"+
+    "\u0000\u0000\u01f7\u01f8\u0001\u0000\u0000\u0000\u01f8k\u0001\u0000\u0000"+
+    "\u0000\u01f9\u01fa\u0005c\u0000\u0000\u01fa\u01fb\u0003n7\u0000\u01fb"+
+    "\u01fc\u0005d\u0000\u0000\u01fcm\u0001\u0000\u0000\u0000\u01fd\u01fe\u0006"+
+    "7\uffff\uffff\u0000\u01fe\u01ff\u0003p8\u0000\u01ff\u0205\u0001\u0000"+
+    "\u0000\u0000\u0200\u0201\n\u0001\u0000\u0000\u0201\u0202\u00054\u0000"+
+    "\u0000\u0202\u0204\u0003p8\u0000\u0203\u0200\u0001\u0000\u0000\u0000\u0204"+
+    "\u0207\u0001\u0000\u0000\u0000\u0205\u0203\u0001\u0000\u0000\u0000\u0205"+
+    "\u0206\u0001\u0000\u0000\u0000\u0206o\u0001\u0000\u0000\u0000\u0207\u0205"+
+    "\u0001\u0000\u0000\u0000\u0208\u0212\u0003&\u0013\u0000\u0209\u0212\u0003"+
+    "\b\u0004\u0000\u020a\u0212\u0003>\u001f\u0000\u020b\u0212\u0003(\u0014"+
+    "\u0000\u020c\u0212\u0003@ \u0000\u020d\u0212\u0003L&\u0000\u020e\u0212"+
+    "\u0003d2\u0000\u020f\u0212\u0003v;\u0000\u0210\u0212\u0003N\'\u0000\u0211"+
+    "\u0208\u0001\u0000\u0000\u0000\u0211\u0209\u0001\u0000\u0000\u0000\u0211"+
+    "\u020a\u0001\u0000\u0000\u0000\u0211\u020b\u0001\u0000\u0000\u0000\u0211"+
+    "\u020c\u0001\u0000\u0000\u0000\u0211\u020d\u0001\u0000\u0000\u0000\u0211"+
+    "\u020e\u0001\u0000\u0000\u0000\u0211\u020f\u0001\u0000\u0000\u0000\u0211"+
+    "\u0210\u0001\u0000\u0000\u0000\u0212q\u0001\u0000\u0000\u0000\u0213\u0214"+
+    "\u0005\u001f\u0000\u0000\u0214s\u0001\u0000\u0000\u0000\u0215\u0216\u0005"+
+    "\u0011\u0000\u0000\u0216\u0217\u0003\u008eG\u0000\u0217\u0218\u0005J\u0000"+
+    "\u0000\u0218\u021b\u0003\u0012\t\u0000\u0219\u021a\u0005O\u0000\u0000"+
+    "\u021a\u021c\u0003<\u001e\u0000\u021b\u0219\u0001\u0000\u0000\u0000\u021b"+
+    "\u021c\u0001\u0000\u0000\u0000\u021cu\u0001\u0000\u0000\u0000\u021d\u0221"+
+    "\u0005\u0007\u0000\u0000\u021e\u021f\u0003.\u0017\u0000\u021f\u0220\u0005"+
+    ":\u0000\u0000\u0220\u0222\u0001\u0000\u0000\u0000\u0221\u021e\u0001\u0000"+
+    "\u0000\u0000\u0221\u0222\u0001\u0000\u0000\u0000\u0222\u0223\u0001\u0000"+
+    "\u0000\u0000\u0223\u0224\u0003\u0084B\u0000\u0224\u0225\u0005O\u0000\u0000"+
+    "\u0225\u0226\u0003<\u001e\u0000\u0226w\u0001\u0000\u0000\u0000\u0227\u0228"+
+    "\u0005\u0012\u0000\u0000\u0228\u0229\u0003\u0094J\u0000\u0229y\u0001\u0000"+
+    "\u0000\u0000\u022a\u022b\u0006=\uffff\uffff\u0000\u022b\u022c\u0005G\u0000"+
+    "\u0000\u022c\u0248\u0003z=\b\u022d\u0248\u0003\u0080@\u0000\u022e\u0248"+
+    "\u0003|>\u0000\u022f\u0231\u0003\u0080@\u0000\u0230\u0232\u0005G\u0000"+
+    "\u0000\u0231\u0230\u0001\u0000\u0000\u0000\u0231\u0232\u0001\u0000\u0000"+
+    "\u0000\u0232\u0233\u0001\u0000\u0000\u0000\u0233\u0234\u0005C\u0000\u0000"+
+    "\u0234\u0235\u0005c\u0000\u0000\u0235\u023a\u0003\u0080@\u0000\u0236\u0237"+
+    "\u0005>\u0000\u0000\u0237\u0239\u0003\u0080@\u0000\u0238\u0236\u0001\u0000"+
+    "\u0000\u0000\u0239\u023c\u0001\u0000\u0000\u0000\u023a\u0238\u0001\u0000"+
+    "\u0000\u0000\u023a\u023b\u0001\u0000\u0000\u0000\u023b\u023d\u0001\u0000"+
+    "\u0000\u0000\u023c\u023a\u0001\u0000\u0000\u0000\u023d\u023e\u0005d\u0000"+
+    "\u0000\u023e\u0248\u0001\u0000\u0000\u0000\u023f\u0240\u0003\u0080@\u0000"+
+    "\u0240\u0242\u0005D\u0000\u0000\u0241\u0243\u0005G\u0000\u0000\u0242\u0241"+
+    "\u0001\u0000\u0000\u0000\u0242\u0243\u0001\u0000\u0000\u0000\u0243\u0244"+
+    "\u0001\u0000\u0000\u0000\u0244\u0245\u0005H\u0000\u0000\u0245\u0248\u0001"+
+    "\u0000\u0000\u0000\u0246\u0248\u0003~?\u0000\u0247\u022a\u0001\u0000\u0000"+
+    "\u0000\u0247\u022d\u0001\u0000\u0000\u0000\u0247\u022e\u0001\u0000\u0000"+
+    "\u0000\u0247\u022f\u0001\u0000\u0000\u0000\u0247\u023f\u0001\u0000\u0000"+
+    "\u0000\u0247\u0246\u0001\u0000\u0000\u0000\u0248\u0251\u0001\u0000\u0000"+
+    "\u0000\u0249\u024a\n\u0005\u0000\u0000\u024a\u024b\u00058\u0000\u0000"+
+    "\u024b\u0250\u0003z=\u0006\u024c\u024d\n\u0004\u0000\u0000\u024d\u024e"+
+    "\u0005K\u0000\u0000\u024e\u0250\u0003z=\u0005\u024f\u0249\u0001\u0000"+
+    "\u0000\u0000\u024f\u024c\u0001\u0000\u0000\u0000\u0250\u0253\u0001\u0000"+
+    "\u0000\u0000\u0251\u024f\u0001\u0000\u0000\u0000\u0251\u0252\u0001\u0000"+
+    "\u0000\u0000\u0252{\u0001\u0000\u0000\u0000\u0253\u0251\u0001\u0000\u0000"+
+    "\u0000\u0254\u0256\u0003\u0080@\u0000\u0255\u0257\u0005G\u0000\u0000\u0256"+
+    "\u0255\u0001\u0000\u0000\u0000\u0256\u0257\u0001\u0000\u0000\u0000\u0257"+
+    "\u0258\u0001\u0000\u0000\u0000\u0258\u0259\u0005F\u0000\u0000\u0259\u025a"+
+    "\u0003\u0098L\u0000\u025a\u0273\u0001\u0000\u0000\u0000\u025b\u025d\u0003"+
+    "\u0080@\u0000\u025c\u025e\u0005G\u0000\u0000\u025d\u025c\u0001\u0000\u0000"+
+    "\u0000\u025d\u025e\u0001\u0000\u0000\u0000\u025e\u025f\u0001\u0000\u0000"+
+    "\u0000\u025f\u0260\u0005M\u0000\u0000\u0260\u0261\u0003\u0098L\u0000\u0261"+
+    "\u0273\u0001\u0000\u0000\u0000\u0262\u0264\u0003\u0080@\u0000\u0263\u0265"+
+    "\u0005G\u0000\u0000\u0264\u0263\u0001\u0000\u0000\u0000\u0264\u0265\u0001"+
+    "\u0000\u0000\u0000\u0265\u0266\u0001\u0000\u0000\u0000\u0266\u0267\u0005"+
+    "F\u0000\u0000\u0267\u0268\u0005c\u0000\u0000\u0268\u026d\u0003\u0098L"+
+    "\u0000\u0269\u026a\u0005>\u0000\u0000\u026a\u026c\u0003\u0098L\u0000\u026b"+
+    "\u0269\u0001\u0000\u0000\u0000\u026c\u026f\u0001\u0000\u0000\u0000\u026d"+
+    "\u026b\u0001\u0000\u0000\u0000\u026d\u026e\u0001\u0000\u0000\u0000\u026e"+
+    "\u0270\u0001\u0000\u0000\u0000\u026f\u026d\u0001\u0000\u0000\u0000\u0270"+
+    "\u0271\u0005d\u0000\u0000\u0271\u0273\u0001\u0000\u0000\u0000\u0272\u0254"+
+    "\u0001\u0000\u0000\u0000\u0272\u025b\u0001\u0000\u0000\u0000\u0272\u0262"+
+    "\u0001\u0000\u0000\u0000\u0273}\u0001\u0000\u0000\u0000\u0274\u0277\u0003"+
+    ".\u0017\u0000\u0275\u0276\u0005<\u0000\u0000\u0276\u0278\u0003\n\u0005"+
+    "\u0000\u0277\u0275\u0001\u0000\u0000\u0000\u0277\u0278\u0001\u0000\u0000"+
+    "\u0000\u0278\u0279\u0001\u0000\u0000\u0000\u0279\u027a\u0005=\u0000\u0000"+
+    "\u027a\u027b\u0003\u008eG\u0000\u027b\u007f\u0001\u0000\u0000\u0000\u027c"+
+    "\u0282\u0003\u0082A\u0000\u027d\u027e\u0003\u0082A\u0000\u027e\u027f\u0003"+
+    "\u009aM\u0000\u027f\u0280\u0003\u0082A\u0000\u0280\u0282\u0001\u0000\u0000"+
+    "\u0000\u0281\u027c\u0001\u0000\u0000\u0000\u0281\u027d\u0001\u0000\u0000"+
+    "\u0000\u0282\u0081\u0001\u0000\u0000\u0000\u0283\u0284\u0006A\uffff\uffff"+
+    "\u0000\u0284\u0288\u0003\u0084B\u0000\u0285\u0286\u0007\u0004\u0000\u0000"+
+    "\u0286\u0288\u0003\u0082A\u0003\u0287\u0283\u0001\u0000\u0000\u0000\u0287"+
+    "\u0285\u0001\u0000\u0000\u0000\u0288\u0291\u0001\u0000\u0000\u0000\u0289"+
+    "\u028a\n\u0002\u0000\u0000\u028a\u028b\u0007\u0005\u0000\u0000\u028b\u0290"+
+    "\u0003\u0082A\u0003\u028c\u028d\n\u0001\u0000\u0000\u028d\u028e\u0007"+
+    "\u0004\u0000\u0000\u028e\u0290\u0003\u0082A\u0002\u028f\u0289\u0001\u0000"+
+    "\u0000\u0000\u028f\u028c\u0001\u0000\u0000\u0000\u0290\u0293\u0001\u0000"+
+    "\u0000\u0000\u0291\u028f\u0001\u0000\u0000\u0000\u0291\u0292\u0001\u0000"+
+    "\u0000\u0000\u0292\u0083\u0001\u0000\u0000\u0000\u0293\u0291\u0001\u0000"+
+    "\u0000\u0000\u0294\u0295\u0006B\uffff\uffff\u0000\u0295\u029d\u0003\u008e"+
+    "G\u0000\u0296\u029d\u0003.\u0017\u0000\u0297\u029d\u0003\u0086C\u0000"+
+    "\u0298\u0299\u0005c\u0000\u0000\u0299\u029a\u0003z=\u0000\u029a\u029b"+
+    "\u0005d\u0000\u0000\u029b\u029d\u0001\u0000\u0000\u0000\u029c\u0294\u0001"+
+    "\u0000\u0000\u0000\u029c\u0296\u0001\u0000\u0000\u0000\u029c\u0297\u0001"+
+    "\u0000\u0000\u0000\u029c\u0298\u0001\u0000\u0000\u0000\u029d\u02a3\u0001"+
+    "\u0000\u0000\u0000\u029e\u029f\n\u0001\u0000\u0000\u029f\u02a0\u0005<"+
+    "\u0000\u0000\u02a0\u02a2\u0003\n\u0005\u0000\u02a1\u029e\u0001\u0000\u0000"+
+    "\u0000\u02a2\u02a5\u0001\u0000\u0000\u0000\u02a3\u02a1\u0001\u0000\u0000"+
+    "\u0000\u02a3\u02a4\u0001\u0000\u0000\u0000\u02a4\u0085\u0001\u0000\u0000"+
+    "\u0000\u02a5\u02a3\u0001\u0000\u0000\u0000\u02a6\u02a7\u0003\u0088D\u0000"+
+    "\u02a7\u02b5\u0005c\u0000\u0000\u02a8\u02b6\u0005Y\u0000\u0000\u02a9\u02ae"+
+    "\u0003z=\u0000\u02aa\u02ab\u0005>\u0000\u0000\u02ab\u02ad\u0003z=\u0000"+
+    "\u02ac\u02aa\u0001\u0000\u0000\u0000\u02ad\u02b0\u0001\u0000\u0000\u0000"+
+    "\u02ae\u02ac\u0001\u0000\u0000\u0000\u02ae\u02af\u0001\u0000\u0000\u0000"+
+    "\u02af\u02b3\u0001\u0000\u0000\u0000\u02b0\u02ae\u0001\u0000\u0000\u0000"+
+    "\u02b1\u02b2\u0005>\u0000\u0000\u02b2\u02b4\u0003\u008aE\u0000\u02b3\u02b1"+
+    "\u0001\u0000\u0000\u0000\u02b3\u02b4\u0001\u0000\u0000\u0000\u02b4\u02b6"+
+    "\u0001\u0000\u0000\u0000\u02b5\u02a8\u0001\u0000\u0000\u0000\u02b5\u02a9"+
+    "\u0001\u0000\u0000\u0000\u02b5\u02b6\u0001\u0000\u0000\u0000\u02b6\u02b7"+
+    "\u0001\u0000\u0000\u0000\u02b7\u02b8\u0005d\u0000\u0000\u02b8\u0087\u0001"+
+    "\u0000\u0000\u0000\u02b9\u02ba\u0003<\u001e\u0000\u02ba\u0089\u0001\u0000"+
+    "\u0000\u0000\u02bb\u02bc\u0005\\\u0000\u0000\u02bc\u02c1\u0003\u008cF"+
+    "\u0000\u02bd\u02be\u0005>\u0000\u0000\u02be\u02c0\u0003\u008cF\u0000\u02bf"+
+    "\u02bd\u0001\u0000\u0000\u0000\u02c0\u02c3\u0001\u0000\u0000\u0000\u02c1"+
+    "\u02bf\u0001\u0000\u0000\u0000\u02c1\u02c2\u0001\u0000\u0000\u0000\u02c2"+
+    "\u02c4\u0001\u0000\u0000\u0000\u02c3\u02c1\u0001\u0000\u0000\u0000\u02c4"+
+    "\u02c5\u0005]\u0000\u0000\u02c5\u008b\u0001\u0000\u0000\u0000\u02c6\u02c7"+
+    "\u0003\u0098L\u0000\u02c7\u02c8\u0005=\u0000\u0000\u02c8\u02c9\u0003\u008e"+
+    "G\u0000\u02c9\u008d\u0001\u0000\u0000\u0000\u02ca\u02f5\u0005H\u0000\u0000"+
+    "\u02cb\u02cc\u0003\u0096K\u0000\u02cc\u02cd\u0005e\u0000\u0000\u02cd\u02f5"+
+    "\u0001\u0000\u0000\u0000\u02ce\u02f5\u0003\u0094J\u0000\u02cf\u02f5\u0003"+
+    "\u0096K\u0000\u02d0\u02f5\u0003\u0090H\u0000\u02d1\u02f5\u00038\u001c"+
+    "\u0000\u02d2\u02f5\u0003\u0098L\u0000\u02d3\u02d4\u0005a\u0000\u0000\u02d4"+
+    "\u02d9\u0003\u0092I\u0000\u02d5\u02d6\u0005>\u0000\u0000\u02d6\u02d8\u0003"+
+    "\u0092I\u0000\u02d7\u02d5\u0001\u0000\u0000\u0000\u02d8\u02db\u0001\u0000"+
+    "\u0000\u0000\u02d9\u02d7\u0001\u0000\u0000\u0000\u02d9\u02da\u0001\u0000"+
+    "\u0000\u0000\u02da\u02dc\u0001\u0000\u0000\u0000\u02db\u02d9\u0001\u0000"+
+    "\u0000\u0000\u02dc\u02dd\u0005b\u0000\u0000\u02dd\u02f5\u0001\u0000\u0000"+
+    "\u0000\u02de\u02df\u0005a\u0000\u0000\u02df\u02e4\u0003\u0090H\u0000\u02e0"+
+    "\u02e1\u0005>\u0000\u0000\u02e1\u02e3\u0003\u0090H\u0000\u02e2\u02e0\u0001"+
+    "\u0000\u0000\u0000\u02e3\u02e6\u0001\u0000\u0000\u0000\u02e4\u02e2\u0001"+
+    "\u0000\u0000\u0000\u02e4\u02e5\u0001\u0000\u0000\u0000\u02e5\u02e7\u0001"+
+    "\u0000\u0000\u0000\u02e6\u02e4\u0001\u0000\u0000\u0000\u02e7\u02e8\u0005"+
+    "b\u0000\u0000\u02e8\u02f5\u0001\u0000\u0000\u0000\u02e9\u02ea\u0005a\u0000"+
+    "\u0000\u02ea\u02ef\u0003\u0098L\u0000\u02eb\u02ec\u0005>\u0000\u0000\u02ec"+
+    "\u02ee\u0003\u0098L\u0000\u02ed\u02eb\u0001\u0000\u0000\u0000\u02ee\u02f1"+
+    "\u0001\u0000\u0000\u0000\u02ef\u02ed\u0001\u0000\u0000\u0000\u02ef\u02f0"+
+    "\u0001\u0000\u0000\u0000\u02f0\u02f2\u0001\u0000\u0000\u0000\u02f1\u02ef"+
+    "\u0001\u0000\u0000\u0000\u02f2\u02f3\u0005b\u0000\u0000\u02f3\u02f5\u0001"+
+    "\u0000\u0000\u0000\u02f4\u02ca\u0001\u0000\u0000\u0000\u02f4\u02cb\u0001"+
+    "\u0000\u0000\u0000\u02f4\u02ce\u0001\u0000\u0000\u0000\u02f4\u02cf\u0001"+
+    "\u0000\u0000\u0000\u02f4\u02d0\u0001\u0000\u0000\u0000\u02f4\u02d1\u0001"+
+    "\u0000\u0000\u0000\u02f4\u02d2\u0001\u0000\u0000\u0000\u02f4\u02d3\u0001"+
+    "\u0000\u0000\u0000\u02f4\u02de\u0001\u0000\u0000\u0000\u02f4\u02e9\u0001"+
+    "\u0000\u0000\u0000\u02f5\u008f\u0001\u0000\u0000\u0000\u02f6\u02f7\u0007"+
+    "\u0006\u0000\u0000\u02f7\u0091\u0001\u0000\u0000\u0000\u02f8\u02fb\u0003"+
+    "\u0094J\u0000\u02f9\u02fb\u0003\u0096K\u0000\u02fa\u02f8\u0001\u0000\u0000"+
+    "\u0000\u02fa\u02f9\u0001\u0000\u0000\u0000\u02fb\u0093\u0001\u0000\u0000"+
+    "\u0000\u02fc\u02fe\u0007\u0004\u0000\u0000\u02fd\u02fc\u0001\u0000\u0000"+
+    "\u0000\u02fd\u02fe\u0001\u0000\u0000\u0000\u02fe\u02ff\u0001\u0000\u0000"+
+    "\u0000\u02ff\u0300\u00057\u0000\u0000\u0300\u0095\u0001\u0000\u0000\u0000"+
+    "\u0301\u0303\u0007\u0004\u0000\u0000\u0302\u0301\u0001\u0000\u0000\u0000"+
+    "\u0302\u0303\u0001\u0000\u0000\u0000\u0303\u0304\u0001\u0000\u0000\u0000"+
+    "\u0304\u0305\u00056\u0000\u0000\u0305\u0097\u0001\u0000\u0000\u0000\u0306"+
+    "\u0307\u00055\u0000\u0000\u0307\u0099\u0001\u0000\u0000\u0000\u0308\u0309"+
+    "\u0007\u0007\u0000\u0000\u0309\u009b\u0001\u0000\u0000\u0000\u030a\u030b"+
+    "\u0007\b\u0000\u0000\u030b\u030c\u0005r\u0000\u0000\u030c\u030d\u0003"+
+    "\u009eO\u0000\u030d\u030e\u0003\u00a0P\u0000\u030e\u009d\u0001\u0000\u0000"+
+    "\u0000\u030f\u0310\u0003\u001c\u000e\u0000\u0310\u009f\u0001\u0000\u0000"+
+    "\u0000\u0311\u0312\u0005J\u0000\u0000\u0312\u0317\u0003\u00a2Q\u0000\u0313"+
+    "\u0314\u0005>\u0000\u0000\u0314\u0316\u0003\u00a2Q\u0000\u0315\u0313\u0001"+
+    "\u0000\u0000\u0000\u0316\u0319\u0001\u0000\u0000\u0000\u0317\u0315\u0001"+
+    "\u0000\u0000\u0000\u0317\u0318\u0001\u0000\u0000\u0000\u0318\u00a1\u0001"+
+    "\u0000\u0000\u0000\u0319\u0317\u0001\u0000\u0000\u0000\u031a\u031b\u0003"+
+    "\u0080@\u0000\u031b\u00a3\u0001\u0000\u0000\u0000I\u00af\u00b8\u00d7\u00e6"+
+    "\u00ec\u00f5\u00fb\u0108\u010c\u0111\u0117\u0119\u0127\u012f\u0133\u013a"+
+    "\u0140\u0147\u014f\u0157\u015f\u0163\u0167\u016c\u0177\u017c\u0180\u018e"+
+    "\u0199\u019f\u01ad\u01c2\u01ca\u01cd\u01d2\u01df\u01e5\u01ec\u01f7\u0205"+
+    "\u0211\u021b\u0221\u0231\u023a\u0242\u0247\u024f\u0251\u0256\u025d\u0264"+
+    "\u026d\u0272\u0277\u0281\u0287\u028f\u0291\u029c\u02a3\u02ae\u02b3\u02b5"+
+    "\u02c1\u02d9\u02e4\u02ef\u02f4\u02fa\u02fd\u0302\u0317";
   public static final ATN _ATN =
     new ATNDeserializer().deserialize(_serializedATN.toCharArray());
   static {

+ 26 - 2
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserBaseListener.java

@@ -889,13 +889,37 @@ public class EsqlBaseParserBaseListener implements EsqlBaseParserListener {
    *
    * <p>The default implementation does nothing.</p>
    */
-  @Override public void enterRegexBooleanExpression(EsqlBaseParser.RegexBooleanExpressionContext ctx) { }
+  @Override public void enterLikeExpression(EsqlBaseParser.LikeExpressionContext ctx) { }
   /**
    * {@inheritDoc}
    *
    * <p>The default implementation does nothing.</p>
    */
-  @Override public void exitRegexBooleanExpression(EsqlBaseParser.RegexBooleanExpressionContext ctx) { }
+  @Override public void exitLikeExpression(EsqlBaseParser.LikeExpressionContext ctx) { }
+  /**
+   * {@inheritDoc}
+   *
+   * <p>The default implementation does nothing.</p>
+   */
+  @Override public void enterRlikeExpression(EsqlBaseParser.RlikeExpressionContext ctx) { }
+  /**
+   * {@inheritDoc}
+   *
+   * <p>The default implementation does nothing.</p>
+   */
+  @Override public void exitRlikeExpression(EsqlBaseParser.RlikeExpressionContext ctx) { }
+  /**
+   * {@inheritDoc}
+   *
+   * <p>The default implementation does nothing.</p>
+   */
+  @Override public void enterLikeListExpression(EsqlBaseParser.LikeListExpressionContext ctx) { }
+  /**
+   * {@inheritDoc}
+   *
+   * <p>The default implementation does nothing.</p>
+   */
+  @Override public void exitLikeListExpression(EsqlBaseParser.LikeListExpressionContext ctx) { }
   /**
    * {@inheritDoc}
    *

+ 15 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserBaseVisitor.java

@@ -530,7 +530,21 @@ public class EsqlBaseParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
    * <p>The default implementation returns the result of calling
    * {@link #visitChildren} on {@code ctx}.</p>
    */
-  @Override public T visitRegexBooleanExpression(EsqlBaseParser.RegexBooleanExpressionContext ctx) { return visitChildren(ctx); }
+  @Override public T visitLikeExpression(EsqlBaseParser.LikeExpressionContext ctx) { return visitChildren(ctx); }
+  /**
+   * {@inheritDoc}
+   *
+   * <p>The default implementation returns the result of calling
+   * {@link #visitChildren} on {@code ctx}.</p>
+   */
+  @Override public T visitRlikeExpression(EsqlBaseParser.RlikeExpressionContext ctx) { return visitChildren(ctx); }
+  /**
+   * {@inheritDoc}
+   *
+   * <p>The default implementation returns the result of calling
+   * {@link #visitChildren} on {@code ctx}.</p>
+   */
+  @Override public T visitLikeListExpression(EsqlBaseParser.LikeListExpressionContext ctx) { return visitChildren(ctx); }
   /**
    * {@inheritDoc}
    *

+ 30 - 4
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserListener.java

@@ -770,15 +770,41 @@ public interface EsqlBaseParserListener extends ParseTreeListener {
    */
   void exitLogicalBinary(EsqlBaseParser.LogicalBinaryContext ctx);
   /**
-   * Enter a parse tree produced by {@link EsqlBaseParser#regexBooleanExpression}.
+   * Enter a parse tree produced by the {@code likeExpression}
+   * labeled alternative in {@link EsqlBaseParser#regexBooleanExpression}.
    * @param ctx the parse tree
    */
-  void enterRegexBooleanExpression(EsqlBaseParser.RegexBooleanExpressionContext ctx);
+  void enterLikeExpression(EsqlBaseParser.LikeExpressionContext ctx);
   /**
-   * Exit a parse tree produced by {@link EsqlBaseParser#regexBooleanExpression}.
+   * Exit a parse tree produced by the {@code likeExpression}
+   * labeled alternative in {@link EsqlBaseParser#regexBooleanExpression}.
    * @param ctx the parse tree
    */
-  void exitRegexBooleanExpression(EsqlBaseParser.RegexBooleanExpressionContext ctx);
+  void exitLikeExpression(EsqlBaseParser.LikeExpressionContext ctx);
+  /**
+   * Enter a parse tree produced by the {@code rlikeExpression}
+   * labeled alternative in {@link EsqlBaseParser#regexBooleanExpression}.
+   * @param ctx the parse tree
+   */
+  void enterRlikeExpression(EsqlBaseParser.RlikeExpressionContext ctx);
+  /**
+   * Exit a parse tree produced by the {@code rlikeExpression}
+   * labeled alternative in {@link EsqlBaseParser#regexBooleanExpression}.
+   * @param ctx the parse tree
+   */
+  void exitRlikeExpression(EsqlBaseParser.RlikeExpressionContext ctx);
+  /**
+   * Enter a parse tree produced by the {@code likeListExpression}
+   * labeled alternative in {@link EsqlBaseParser#regexBooleanExpression}.
+   * @param ctx the parse tree
+   */
+  void enterLikeListExpression(EsqlBaseParser.LikeListExpressionContext ctx);
+  /**
+   * Exit a parse tree produced by the {@code likeListExpression}
+   * labeled alternative in {@link EsqlBaseParser#regexBooleanExpression}.
+   * @param ctx the parse tree
+   */
+  void exitLikeListExpression(EsqlBaseParser.LikeListExpressionContext ctx);
   /**
    * Enter a parse tree produced by {@link EsqlBaseParser#matchBooleanExpression}.
    * @param ctx the parse tree

+ 17 - 2
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserVisitor.java

@@ -468,11 +468,26 @@ public interface EsqlBaseParserVisitor<T> extends ParseTreeVisitor<T> {
    */
   T visitLogicalBinary(EsqlBaseParser.LogicalBinaryContext ctx);
   /**
-   * Visit a parse tree produced by {@link EsqlBaseParser#regexBooleanExpression}.
+   * Visit a parse tree produced by the {@code likeExpression}
+   * labeled alternative in {@link EsqlBaseParser#regexBooleanExpression}.
    * @param ctx the parse tree
    * @return the visitor result
    */
-  T visitRegexBooleanExpression(EsqlBaseParser.RegexBooleanExpressionContext ctx);
+  T visitLikeExpression(EsqlBaseParser.LikeExpressionContext ctx);
+  /**
+   * Visit a parse tree produced by the {@code rlikeExpression}
+   * labeled alternative in {@link EsqlBaseParser#regexBooleanExpression}.
+   * @param ctx the parse tree
+   * @return the visitor result
+   */
+  T visitRlikeExpression(EsqlBaseParser.RlikeExpressionContext ctx);
+  /**
+   * Visit a parse tree produced by the {@code likeListExpression}
+   * labeled alternative in {@link EsqlBaseParser#regexBooleanExpression}.
+   * @param ctx the parse tree
+   * @return the visitor result
+   */
+  T visitLikeListExpression(EsqlBaseParser.LikeListExpressionContext ctx);
   /**
    * Visit a parse tree produced by {@link EsqlBaseParser#matchBooleanExpression}.
    * @param ctx the parse tree

+ 39 - 24
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/ExpressionBuilder.java

@@ -29,8 +29,8 @@ import org.elasticsearch.xpack.esql.core.expression.UnresolvedAttribute;
 import org.elasticsearch.xpack.esql.core.expression.UnresolvedStar;
 import org.elasticsearch.xpack.esql.core.expression.function.Function;
 import org.elasticsearch.xpack.esql.core.expression.predicate.regex.RLikePattern;
-import org.elasticsearch.xpack.esql.core.expression.predicate.regex.RegexMatch;
 import org.elasticsearch.xpack.esql.core.expression.predicate.regex.WildcardPattern;
+import org.elasticsearch.xpack.esql.core.expression.predicate.regex.WildcardPatternList;
 import org.elasticsearch.xpack.esql.core.tree.Source;
 import org.elasticsearch.xpack.esql.core.type.DataType;
 import org.elasticsearch.xpack.esql.core.util.DateUtils;
@@ -44,6 +44,7 @@ import org.elasticsearch.xpack.esql.expression.function.aggregate.FilteredExpres
 import org.elasticsearch.xpack.esql.expression.function.fulltext.MatchOperator;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.regex.RLike;
 import org.elasticsearch.xpack.esql.expression.function.scalar.string.regex.WildcardLike;
+import org.elasticsearch.xpack.esql.expression.function.scalar.string.regex.WildcardLikeList;
 import org.elasticsearch.xpack.esql.expression.predicate.logical.And;
 import org.elasticsearch.xpack.esql.expression.predicate.logical.Not;
 import org.elasticsearch.xpack.esql.expression.predicate.logical.Or;
@@ -738,31 +739,45 @@ public abstract class ExpressionBuilder extends IdentifierBuilder {
     }
 
     @Override
-    public Expression visitRegexBooleanExpression(EsqlBaseParser.RegexBooleanExpressionContext ctx) {
-        int type = ctx.kind.getType();
+    public Expression visitRlikeExpression(EsqlBaseParser.RlikeExpressionContext ctx) {
         Source source = source(ctx);
         Expression left = expression(ctx.valueExpression());
-        Literal pattern = visitString(ctx.pattern);
-        RegexMatch<?> result = switch (type) {
-            case EsqlBaseParser.LIKE -> {
-                try {
-                    yield new WildcardLike(
-                        source,
-                        left,
-                        new WildcardPattern(pattern.fold(FoldContext.small() /* TODO remove me */).toString())
-                    );
-                } catch (InvalidArgumentException e) {
-                    throw new ParsingException(source, "Invalid pattern for LIKE [{}]: [{}]", pattern, e.getMessage());
-                }
-            }
-            case EsqlBaseParser.RLIKE -> new RLike(
-                source,
-                left,
-                new RLikePattern(pattern.fold(FoldContext.small() /* TODO remove me */).toString())
-            );
-            default -> throw new ParsingException("Invalid predicate type for [{}]", source.text());
-        };
-        return ctx.NOT() == null ? result : new Not(source, result);
+        Literal patternLiteral = visitString(ctx.string());
+        try {
+            RLike rLike = new RLike(source, left, new RLikePattern(patternLiteral.fold(FoldContext.small()).toString()));
+            return ctx.NOT() == null ? rLike : new Not(source, rLike);
+        } catch (InvalidArgumentException e) {
+            throw new ParsingException(source, "Invalid pattern for LIKE [{}]: [{}]", patternLiteral, e.getMessage());
+        }
+    }
+
+    @Override
+    public Expression visitLikeExpression(EsqlBaseParser.LikeExpressionContext ctx) {
+        Source source = source(ctx);
+        Expression left = expression(ctx.valueExpression());
+        Literal patternLiteral = visitString(ctx.string());
+        try {
+            WildcardPattern pattern = new WildcardPattern(patternLiteral.fold(FoldContext.small()).toString());
+            WildcardLike result = new WildcardLike(source, left, pattern);
+            return ctx.NOT() == null ? result : new Not(source, result);
+        } catch (InvalidArgumentException e) {
+            throw new ParsingException(source, "Invalid pattern for LIKE [{}]: [{}]", patternLiteral, e.getMessage());
+        }
+    }
+
+    @Override
+    public Expression visitLikeListExpression(EsqlBaseParser.LikeListExpressionContext ctx) {
+        Source source = source(ctx);
+        Expression left = expression(ctx.valueExpression());
+        List<WildcardPattern> wildcardPatterns = ctx.string()
+            .stream()
+            .map(x -> new WildcardPattern(visitString(x).fold(FoldContext.small()).toString()))
+            .toList();
+        // for now we will use the old WildcardLike function for one argument case to allow compatibility in mixed version deployments
+        Expression e = wildcardPatterns.size() == 1
+            ? new WildcardLike(source, left, wildcardPatterns.getFirst())
+            : new WildcardLikeList(source, left, new WildcardPatternList(wildcardPatterns));
+        return ctx.NOT() == null ? e : new Not(source, e);
     }
 
     @Override

+ 49 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/WildcardLikeListErrorTests.java

@@ -0,0 +1,49 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.string;
+
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.core.type.DataType;
+import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
+import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
+import org.hamcrest.Matcher;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class WildcardLikeListErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
+    @Override
+    protected List<TestCaseSupplier> cases() {
+        return paramsToSuppliers(WildcardLikeListTests.parameters());
+    }
+
+    @Override
+    protected Stream<List<DataType>> testCandidates(List<TestCaseSupplier> cases, Set<List<DataType>> valid) {
+        /*
+         * We can't support certain signatures, and it's safe not to test them because
+         * you can't even build them.... The building comes directly from the parser
+         * and can only make certain types.
+         */
+        return super.testCandidates(cases, valid).filter(sig -> sig.get(1) == DataType.KEYWORD)
+            .filter(sig -> sig.size() > 2 && sig.get(2) == DataType.BOOLEAN);
+    }
+
+    @Override
+    protected Expression build(Source source, List<Expression> args) {
+        return RLikeTests.buildRLike(logger, source, args);
+    }
+
+    @Override
+    protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
+        return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "string"));
+    }
+}

+ 54 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/WildcardLikeListSerializationTests.java

@@ -0,0 +1,54 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.string;
+
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.expression.predicate.regex.WildcardPattern;
+import org.elasticsearch.xpack.esql.core.expression.predicate.regex.WildcardPatternList;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests;
+import org.elasticsearch.xpack.esql.expression.function.scalar.string.regex.WildcardLikeList;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class WildcardLikeListSerializationTests extends AbstractExpressionSerializationTests<WildcardLikeList> {
+    @Override
+    protected WildcardLikeList createTestInstance() {
+        Source source = randomSource();
+        Expression child = randomChild();
+        return new WildcardLikeList(source, child, generateRandomPatternList());
+    }
+
+    @Override
+    protected WildcardLikeList mutateInstance(WildcardLikeList instance) throws IOException {
+        Source source = instance.source();
+        Expression child = instance.field();
+        List<WildcardPattern> patterns = new ArrayList<>(instance.pattern().patternList());
+        int childToModify = randomIntBetween(0, patterns.size() - 1);
+        WildcardPattern pattern = patterns.get(childToModify);
+        if (randomBoolean()) {
+            child = randomValueOtherThan(child, AbstractExpressionSerializationTests::randomChild);
+        } else {
+            pattern = randomValueOtherThan(pattern, () -> new WildcardPattern(randomAlphaOfLength(4)));
+        }
+        patterns.set(childToModify, pattern);
+        return new WildcardLikeList(source, child, new WildcardPatternList(patterns));
+    }
+
+    private WildcardPatternList generateRandomPatternList() {
+        int numChildren = randomIntBetween(1, 10); // Ensure at least one child
+        List<WildcardPattern> patterns = new ArrayList<>(numChildren);
+        for (int i = 0; i < numChildren; i++) {
+            WildcardPattern pattern = new WildcardPattern(randomAlphaOfLength(4));
+            patterns.add(pattern);
+        }
+        return new WildcardPatternList(patterns);
+    }
+}

+ 99 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/WildcardLikeListTests.java

@@ -0,0 +1,99 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.string;
+
+import com.carrotsearch.randomizedtesting.annotations.Name;
+import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
+
+import org.apache.lucene.util.BytesRef;
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.expression.FoldContext;
+import org.elasticsearch.xpack.esql.core.expression.Literal;
+import org.elasticsearch.xpack.esql.core.expression.predicate.regex.WildcardPattern;
+import org.elasticsearch.xpack.esql.core.expression.predicate.regex.WildcardPatternList;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.core.type.DataType;
+import org.elasticsearch.xpack.esql.expression.function.AbstractScalarFunctionTestCase;
+import org.elasticsearch.xpack.esql.expression.function.FunctionName;
+import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
+import org.elasticsearch.xpack.esql.expression.function.scalar.string.regex.WildcardLikeList;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.startsWith;
+
+@FunctionName("likelist")
+public class WildcardLikeListTests extends AbstractScalarFunctionTestCase {
+    public WildcardLikeListTests(@Name("TestCase") Supplier<TestCaseSupplier.TestCase> testCaseSupplier) {
+        this.testCase = testCaseSupplier.get();
+    }
+
+    @ParametersFactory
+    public static Iterable<Object[]> parameters() {
+        final Function<String, String> escapeString = str -> {
+            for (String syntax : new String[] { "\\", "*", "?" }) {
+                str = str.replace(syntax, "\\" + syntax);
+            }
+            return str;
+        };
+        List<Object[]> cases = (List<Object[]>) RLikeTests.parameters(escapeString, () -> "*");
+
+        List<TestCaseSupplier> suppliers = new ArrayList<>();
+        addCases(suppliers);
+
+        for (TestCaseSupplier supplier : suppliers) {
+            cases.add(new Object[] { supplier });
+        }
+
+        return cases;
+    }
+
+    private static void addCases(List<TestCaseSupplier> suppliers) {
+        for (DataType type : new DataType[] { DataType.KEYWORD, DataType.TEXT }) {
+            suppliers.add(new TestCaseSupplier(" with " + type.esType(), List.of(type, DataType.KEYWORD), () -> {
+                BytesRef str = new BytesRef(randomAlphaOfLength(5));
+                String patternString = randomAlphaOfLength(2);
+                BytesRef pattern = new BytesRef(patternString + "*");
+                Boolean match = str.utf8ToString().startsWith(patternString);
+                return new TestCaseSupplier.TestCase(
+                    List.of(
+                        new TestCaseSupplier.TypedData(str, type, "str"),
+                        new TestCaseSupplier.TypedData(pattern, DataType.KEYWORD, "pattern").forceLiteral()
+                    ),
+                    startsWith("AutomataMatchEvaluator[input=Attribute[channel=0], pattern=digraph Automaton {\n"),
+                    DataType.BOOLEAN,
+                    equalTo(match)
+                );
+            }));
+        }
+    }
+
+    @Override
+    protected Expression build(Source source, List<Expression> args) {
+        return buildWildcardLikeList(source, args);
+    }
+
+    static Expression buildWildcardLikeList(Source source, List<Expression> args) {
+        Expression expression = args.get(0);
+        Literal pattern = (Literal) args.get(1);
+        Literal caseInsensitive = args.size() > 2 ? (Literal) args.get(2) : null;
+        boolean caseInsesitiveBool = caseInsensitive != null && (boolean) caseInsensitive.fold(FoldContext.small());
+
+        WildcardPattern wildcardPattern = new WildcardPattern(((BytesRef) pattern.fold(FoldContext.small())).utf8ToString());
+        WildcardPatternList wildcardPatternList = new WildcardPatternList(List.of(wildcardPattern));
+        return caseInsesitiveBool
+            ? new WildcardLikeList(source, expression, wildcardPatternList, true)
+            : (randomBoolean()
+                ? new WildcardLikeList(source, expression, wildcardPatternList)
+                : new WildcardLikeList(source, expression, wildcardPatternList, false));
+    }
+}

+ 1 - 1
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java

@@ -1158,7 +1158,7 @@ public class StatementParserTests extends AbstractStatementParserTests {
         RLike rlike = (RLike) filter.condition();
         assertEquals(".*bar.*", rlike.pattern().asJavaRegex());
 
-        expectError("from a | where foo like 12", "mismatched input '12'");
+        expectError("from a | where foo like 12", "no viable alternative at input 'foo like 12'");
         expectError("from a | where foo rlike 12", "mismatched input '12'");
 
         expectError(

+ 1 - 1
x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/regex/WildcardPattern.java

@@ -18,7 +18,7 @@ import java.util.Objects;
  * Similar to basic regex, supporting '?' wildcard for single character (same as regex  ".")
  * and '*' wildcard for multiple characters (same as regex ".*")
  * <p>
- * Allows escaping based on a regular char
+ * Allows escaping based on a regular char.
  *
  */
 public class WildcardPattern extends AbstractStringPattern {

Some files were not shown because too many files changed in this diff