Ver Fonte

[8.19] Backport ES|QL sample (correct transport version) (#129853)

This reverts commit 8e019be0fb9bb3c7687758246d8cb6c851a90444.
Jan Kuipers há 3 meses atrás
pai
commit
fe6c457919
66 ficheiros alterados com 3885 adições e 1827 exclusões
  1. 5 0
      docs/changelog/125570.yaml
  2. 0 5
      docs/changelog/129797.yaml
  3. 2 0
      docs/reference/esql/esql-commands.asciidoc
  4. 1 1
      docs/reference/esql/functions/description/date_trunc.asciidoc
  5. 3 1
      docs/reference/esql/functions/kibana/docs/date_trunc.md
  6. 11 0
      docs/reference/esql/functions/kibana/docs/sample.md
  7. 4 4
      docs/reference/esql/functions/types/to_ip.asciidoc
  8. 30 0
      docs/reference/esql/processing-commands/sample.asciidoc
  9. 2 1
      docs/reference/rest-api/usage.asciidoc
  10. 1 0
      server/src/main/java/org/elasticsearch/TransportVersions.java
  11. 4 0
      server/src/main/java/org/elasticsearch/search/SearchModule.java
  12. 25 5
      server/src/main/java/org/elasticsearch/search/aggregations/bucket/sampler/random/RandomSamplingQuery.java
  13. 149 0
      server/src/main/java/org/elasticsearch/search/aggregations/bucket/sampler/random/RandomSamplingQueryBuilder.java
  14. 1 0
      server/src/test/java/org/elasticsearch/search/SearchModuleTests.java
  15. 75 0
      server/src/test/java/org/elasticsearch/search/aggregations/bucket/sampler/random/RandomSamplingQueryBuilderTests.java
  16. 4 0
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/MetadataAttribute.java
  17. 17 0
      x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/Page.java
  18. 3 3
      x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/ChangePointOperator.java
  19. 1 15
      x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/FilterOperator.java
  20. 242 0
      x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/SampleOperator.java
  21. 74 0
      x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/SampleOperatorTests.java
  22. 26 0
      x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/RestSampleIT.java
  23. 148 0
      x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestSampleTestCase.java
  24. 248 0
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/sample.csv-spec
  25. 204 0
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/stats_sample.csv-spec
  26. 2 0
      x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.g4
  27. 181 179
      x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.tokens
  28. 5 0
      x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.g4
  29. 181 179
      x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.tokens
  30. 17 7
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java
  31. 22 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/capabilities/PostPhysicalOptimizationVerificationAware.java
  32. 3 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Sample.java
  33. 5 4
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizer.java
  34. 2 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizer.java
  35. 3 4
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizer.java
  36. 14 7
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/PhysicalVerifier.java
  37. 82 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PushDownAndCombineSample.java
  38. 43 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/PushSampleToSource.java
  39. 2 2
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/PushTopNToSource.java
  40. 3 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.interp
  41. 1200 1192
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.java
  42. 3 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp
  43. 211 199
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java
  44. 12 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserBaseListener.java
  45. 7 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserBaseVisitor.java
  46. 10 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserListener.java
  47. 6 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserVisitor.java
  48. 14 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/LogicalPlanBuilder.java
  49. 4 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/PlanWritables.java
  50. 88 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/logical/Sample.java
  51. 6 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/physical/EsQueryExec.java
  52. 90 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/physical/SampleExec.java
  53. 11 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlanner.java
  54. 6 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/mapper/LocalMapper.java
  55. 8 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/mapper/Mapper.java
  56. 11 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/mapper/MapperUtils.java
  57. 3 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/telemetry/FeatureMetric.java
  58. 11 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java
  59. 19 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/ParsingTests.java
  60. 147 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java
  61. 39 4
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java
  62. 16 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java
  63. 52 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plan/logical/SampleSerializationTests.java
  64. 45 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plan/physical/SampleExecSerializationTests.java
  65. 16 10
      x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/10_basic.yml
  66. 5 2
      x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml

+ 5 - 0
docs/changelog/125570.yaml

@@ -0,0 +1,5 @@
+pr: 125570
+summary: ES|QL random sampling
+area: Machine Learning
+type: feature
+issues: []

+ 0 - 5
docs/changelog/129797.yaml

@@ -1,5 +0,0 @@
-pr: 129797
-summary: "Revert \"[8.19] Backport ES|QL sample processing command\""
-area: ES|QL
-type: bug
-issues: []

+ 2 - 0
docs/reference/esql/esql-commands.asciidoc

@@ -46,6 +46,7 @@ endif::[]
 * experimental:[] <<esql-lookup-join>>
 * experimental:[] <<esql-mv_expand>>
 * <<esql-rename>>
+* experimental:[] <<esql-sample>>
 * <<esql-sort>>
 * <<esql-stats-by>>
 * <<esql-where>>
@@ -70,6 +71,7 @@ include::processing-commands/limit.asciidoc[]
 include::processing-commands/lookup.asciidoc[]
 include::processing-commands/mv_expand.asciidoc[]
 include::processing-commands/rename.asciidoc[]
+include::processing-commands/sample.asciidoc[]
 include::processing-commands/sort.asciidoc[]
 include::processing-commands/stats.asciidoc[]
 include::processing-commands/where.asciidoc[]

+ 1 - 1
docs/reference/esql/functions/description/date_trunc.asciidoc

@@ -2,4 +2,4 @@
 
 *Description*
 
-Rounds down a date to the closest interval since epoch, which starts at `0001-01-01T00:00:00Z`.
+Rounds down a date to the closest interval.

+ 3 - 1
docs/reference/esql/functions/kibana/docs/date_trunc.md

@@ -3,7 +3,9 @@ This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../READ
 -->
 
 ### DATE_TRUNC
-Rounds down a date to the closest interval since epoch, which starts at `0001-01-01T00:00:00Z`.
+
+Rounds down a date to the closest interval since epoch, which starts
+at `0001-01-01T00:00:00Z`.
 
 ```
 FROM employees

+ 11 - 0
docs/reference/esql/functions/kibana/docs/sample.md

@@ -0,0 +1,11 @@
+<!--
+This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
+-->
+
+### SAMPLE
+Collects sample values for a field.
+
+```
+FROM employees
+| STATS sample = SAMPLE(gender, 5)
+```

+ 4 - 4
docs/reference/esql/functions/types/to_ip.asciidoc

@@ -4,8 +4,8 @@
 
 [%header.monospaced.styled,format=dsv,separator=|]
 |===
-field | options | result
-ip | | ip
-keyword | | ip
-text | | ip
+field | result
+ip | ip
+keyword | ip
+text | ip
 |===

+ 30 - 0
docs/reference/esql/processing-commands/sample.asciidoc

@@ -0,0 +1,30 @@
+[discrete]
+[[esql-sample]]
+=== `SAMPLE`
+
+preview::[]
+
+The `SAMPLE` command samples a fraction of the table rows.
+
+**Syntax**
+
+[source,esql]
+----
+SAMPLE probability
+----
+
+*Parameters*
+
+`probability`::
+The probability that a row is included in the sample. The value must be between 0 and 1, exclusive.
+
+*Example*
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/sample.csv-spec[tag=sampleForDocs]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/sample.csv-spec[tag=sampleForDocs-result]
+|===

+ 2 - 1
docs/reference/rest-api/usage.asciidoc

@@ -249,7 +249,8 @@ GET /_xpack/usage
       "lookup_join" : 0,
       "change_point" : 0,
       "completion": 0,
-      "rerank": 0
+      "rerank": 0,
+      "sample": 0
     },
     "queries" : {
       "rest" : {

+ 1 - 0
server/src/main/java/org/elasticsearch/TransportVersions.java

@@ -246,6 +246,7 @@ public class TransportVersions {
     public static final TransportVersion ML_INFERENCE_CUSTOM_SERVICE_EMBEDDING_BATCH_SIZE_8_19 = def(8_841_0_53);
     public static final TransportVersion STREAMS_LOGS_SUPPORT_8_19 = def(8_841_0_54);
     public static final TransportVersion ML_INFERENCE_CUSTOM_SERVICE_INPUT_TYPE_8_19 = def(8_841_0_55);
+    public static final TransportVersion RANDOM_SAMPLER_QUERY_BUILDER_8_19 = def(8_841_0_56);
 
     /*
      * STOP! READ THIS FIRST! No, really,

+ 4 - 0
server/src/main/java/org/elasticsearch/search/SearchModule.java

@@ -137,6 +137,7 @@ import org.elasticsearch.search.aggregations.bucket.sampler.SamplerAggregationBu
 import org.elasticsearch.search.aggregations.bucket.sampler.UnmappedSampler;
 import org.elasticsearch.search.aggregations.bucket.sampler.random.InternalRandomSampler;
 import org.elasticsearch.search.aggregations.bucket.sampler.random.RandomSamplerAggregationBuilder;
+import org.elasticsearch.search.aggregations.bucket.sampler.random.RandomSamplingQueryBuilder;
 import org.elasticsearch.search.aggregations.bucket.terms.DoubleTerms;
 import org.elasticsearch.search.aggregations.bucket.terms.LongRareTerms;
 import org.elasticsearch.search.aggregations.bucket.terms.LongTerms;
@@ -1209,6 +1210,9 @@ public class SearchModule {
         registerQuery(new QuerySpec<>(ExactKnnQueryBuilder.NAME, ExactKnnQueryBuilder::new, parser -> {
             throw new IllegalArgumentException("[exact_knn] queries cannot be provided directly");
         }));
+        registerQuery(
+            new QuerySpec<>(RandomSamplingQueryBuilder.NAME, RandomSamplingQueryBuilder::new, RandomSamplingQueryBuilder::fromXContent)
+        );
 
         registerFromPlugin(plugins, SearchPlugin::getQueries, this::registerQuery);
 

+ 25 - 5
server/src/main/java/org/elasticsearch/search/aggregations/bucket/sampler/random/RandomSamplingQuery.java

@@ -43,14 +43,34 @@ public final class RandomSamplingQuery extends Query {
      *                  can be generated
      */
     public RandomSamplingQuery(double p, int seed, int hash) {
-        if (p <= 0.0 || p >= 1.0) {
-            throw new IllegalArgumentException("RandomSampling probability must be between 0.0 and 1.0, was [" + p + "]");
-        }
+        checkProbabilityRange(p);
         this.p = p;
         this.seed = seed;
         this.hash = hash;
     }
 
+    /**
+     * Verifies that the probability is within the (0.0, 1.0) range.
+     * @throws IllegalArgumentException in case of an invalid probability.
+     */
+    public static void checkProbabilityRange(double p) throws IllegalArgumentException {
+        if (p <= 0.0 || p >= 1.0) {
+            throw new IllegalArgumentException("RandomSampling probability must be strictly between 0.0 and 1.0, was [" + p + "]");
+        }
+    }
+
+    public double probability() {
+        return p;
+    }
+
+    public int seed() {
+        return seed;
+    }
+
+    public int hash() {
+        return hash;
+    }
+
     @Override
     public String toString(String field) {
         return "RandomSamplingQuery{" + "p=" + p + ", seed=" + seed + ", hash=" + hash + '}';
@@ -97,13 +117,13 @@ public final class RandomSamplingQuery extends Query {
     /**
      * A DocIDSetIter that skips a geometrically random number of documents
      */
-    static class RandomSamplingIterator extends DocIdSetIterator {
+    public static class RandomSamplingIterator extends DocIdSetIterator {
         private final int maxDoc;
         private final double p;
         private final FastGeometric distribution;
         private int doc = -1;
 
-        RandomSamplingIterator(int maxDoc, double p, IntSupplier rng) {
+        public RandomSamplingIterator(int maxDoc, double p, IntSupplier rng) {
             this.maxDoc = maxDoc;
             this.p = p;
             this.distribution = new FastGeometric(rng, p);

+ 149 - 0
server/src/main/java/org/elasticsearch/search/aggregations/bucket/sampler/random/RandomSamplingQueryBuilder.java

@@ -0,0 +1,149 @@
+/*
+ * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
+ * Public License v 1"; you may not use this file except in compliance with, at
+ * your election, the "Elastic License 2.0", the "GNU Affero General Public
+ * License v3.0 only", or the "Server Side Public License, v 1".
+ */
+
+package org.elasticsearch.search.aggregations.bucket.sampler.random;
+
+import org.apache.lucene.search.Query;
+import org.elasticsearch.TransportVersion;
+import org.elasticsearch.TransportVersions;
+import org.elasticsearch.common.Randomness;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.io.stream.StreamOutput;
+import org.elasticsearch.index.query.AbstractQueryBuilder;
+import org.elasticsearch.index.query.SearchExecutionContext;
+import org.elasticsearch.xcontent.ConstructingObjectParser;
+import org.elasticsearch.xcontent.ParseField;
+import org.elasticsearch.xcontent.XContentBuilder;
+import org.elasticsearch.xcontent.XContentParser;
+
+import java.io.IOException;
+import java.util.Objects;
+
+import static org.elasticsearch.search.aggregations.bucket.sampler.random.RandomSamplingQuery.checkProbabilityRange;
+import static org.elasticsearch.xcontent.ConstructingObjectParser.constructorArg;
+import static org.elasticsearch.xcontent.ConstructingObjectParser.optionalConstructorArg;
+
+public class RandomSamplingQueryBuilder extends AbstractQueryBuilder<RandomSamplingQueryBuilder> {
+
+    public static final String NAME = "random_sampling";
+    static final ParseField PROBABILITY = new ParseField("query");
+    static final ParseField SEED = new ParseField("seed");
+    static final ParseField HASH = new ParseField("hash");
+
+    private final double probability;
+    private int seed = Randomness.get().nextInt();
+    private int hash = 0;
+
+    public RandomSamplingQueryBuilder(double probability) {
+        checkProbabilityRange(probability);
+        this.probability = probability;
+    }
+
+    public RandomSamplingQueryBuilder seed(int seed) {
+        checkProbabilityRange(probability);
+        this.seed = seed;
+        return this;
+    }
+
+    public RandomSamplingQueryBuilder(StreamInput in) throws IOException {
+        super(in);
+        this.probability = in.readDouble();
+        this.seed = in.readInt();
+        this.hash = in.readInt();
+    }
+
+    public RandomSamplingQueryBuilder hash(Integer hash) {
+        this.hash = hash;
+        return this;
+    }
+
+    public double probability() {
+        return probability;
+    }
+
+    public int seed() {
+        return seed;
+    }
+
+    public int hash() {
+        return hash;
+    }
+
+    @Override
+    protected void doWriteTo(StreamOutput out) throws IOException {
+        out.writeDouble(probability);
+        out.writeInt(seed);
+        out.writeInt(hash);
+    }
+
+    @Override
+    protected void doXContent(XContentBuilder builder, Params params) throws IOException {
+        builder.startObject(NAME);
+        builder.field(PROBABILITY.getPreferredName(), probability);
+        builder.field(SEED.getPreferredName(), seed);
+        builder.field(HASH.getPreferredName(), hash);
+        builder.endObject();
+    }
+
+    private static final ConstructingObjectParser<RandomSamplingQueryBuilder, Void> PARSER = new ConstructingObjectParser<>(
+        NAME,
+        false,
+        args -> {
+            var randomSamplingQueryBuilder = new RandomSamplingQueryBuilder((double) args[0]);
+            if (args[1] != null) {
+                randomSamplingQueryBuilder.seed((int) args[1]);
+            }
+            if (args[2] != null) {
+                randomSamplingQueryBuilder.hash((int) args[2]);
+            }
+            return randomSamplingQueryBuilder;
+        }
+    );
+
+    static {
+        PARSER.declareDouble(constructorArg(), PROBABILITY);
+        PARSER.declareInt(optionalConstructorArg(), SEED);
+        PARSER.declareInt(optionalConstructorArg(), HASH);
+    }
+
+    public static RandomSamplingQueryBuilder fromXContent(XContentParser parser) throws IOException {
+        return PARSER.apply(parser, null);
+    }
+
+    @Override
+    protected Query doToQuery(SearchExecutionContext context) throws IOException {
+        return new RandomSamplingQuery(probability, seed, hash);
+    }
+
+    @Override
+    protected boolean doEquals(RandomSamplingQueryBuilder other) {
+        return probability == other.probability && seed == other.seed && hash == other.hash;
+    }
+
+    @Override
+    protected int doHashCode() {
+        return Objects.hash(probability, seed, hash);
+    }
+
+    /**
+     * Returns the name of the writeable object
+     */
+    @Override
+    public String getWriteableName() {
+        return NAME;
+    }
+
+    /**
+     * The minimal version of the recipient this object can be sent to
+     */
+    @Override
+    public TransportVersion getMinimalSupportedVersion() {
+        return TransportVersions.RANDOM_SAMPLER_QUERY_BUILDER_8_19;
+    }
+}

+ 1 - 0
server/src/test/java/org/elasticsearch/search/SearchModuleTests.java

@@ -449,6 +449,7 @@ public class SearchModuleTests extends ESTestCase {
         "range",
         "regexp",
         "knn_score_doc",
+        "random_sampling",
         "script",
         "script_score",
         "simple_query_string",

+ 75 - 0
server/src/test/java/org/elasticsearch/search/aggregations/bucket/sampler/random/RandomSamplingQueryBuilderTests.java

@@ -0,0 +1,75 @@
+/*
+ * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
+ * Public License v 1"; you may not use this file except in compliance with, at
+ * your election, the "Elastic License 2.0", the "GNU Affero General Public
+ * License v3.0 only", or the "Server Side Public License, v 1".
+ */
+
+package org.elasticsearch.search.aggregations.bucket.sampler.random;
+
+import org.apache.lucene.search.Query;
+import org.elasticsearch.index.query.SearchExecutionContext;
+import org.elasticsearch.test.AbstractQueryTestCase;
+import org.elasticsearch.xcontent.XContentParseException;
+
+import java.io.IOException;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class RandomSamplingQueryBuilderTests extends AbstractQueryTestCase<RandomSamplingQueryBuilder> {
+
+    @Override
+    protected RandomSamplingQueryBuilder doCreateTestQueryBuilder() {
+        double probability = randomDoubleBetween(0.0, 1.0, false);
+        var builder = new RandomSamplingQueryBuilder(probability);
+        if (randomBoolean()) {
+            builder.seed(randomInt());
+        }
+        if (randomBoolean()) {
+            builder.hash(randomInt());
+        }
+        return builder;
+    }
+
+    @Override
+    protected void doAssertLuceneQuery(RandomSamplingQueryBuilder queryBuilder, Query query, SearchExecutionContext context)
+        throws IOException {
+        var rsQuery = asInstanceOf(RandomSamplingQuery.class, query);
+        assertThat(rsQuery.probability(), equalTo(queryBuilder.probability()));
+        assertThat(rsQuery.seed(), equalTo(queryBuilder.seed()));
+        assertThat(rsQuery.hash(), equalTo(queryBuilder.hash()));
+    }
+
+    @Override
+    protected boolean supportsBoost() {
+        return false;
+    }
+
+    @Override
+    protected boolean supportsQueryName() {
+        return false;
+    }
+
+    @Override
+    public void testUnknownField() {
+        var json = "{ \""
+            + RandomSamplingQueryBuilder.NAME
+            + "\" : {\"bogusField\" : \"someValue\", \""
+            + RandomSamplingQueryBuilder.PROBABILITY.getPreferredName()
+            + "\" : \""
+            + randomBoolean()
+            + "\", \""
+            + RandomSamplingQueryBuilder.SEED.getPreferredName()
+            + "\" : \""
+            + randomInt()
+            + "\", \""
+            + RandomSamplingQueryBuilder.HASH.getPreferredName()
+            + "\" : \""
+            + randomInt()
+            + "\" } }";
+        var e = expectThrows(XContentParseException.class, () -> parseQuery(json));
+        assertTrue(e.getMessage().contains("bogusField"));
+    }
+}

+ 4 - 0
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/MetadataAttribute.java

@@ -172,6 +172,10 @@ public class MetadataAttribute extends TypedAttribute {
         return ATTRIBUTES_MAP.containsKey(name);
     }
 
+    public static boolean isScoreAttribute(Expression a) {
+        return a instanceof MetadataAttribute ma && ma.name().equals(SCORE);
+    }
+
     @Override
     @SuppressWarnings("checkstyle:EqualsHashCode")// equals is implemented in parent. See innerEquals instead
     public int hashCode() {

+ 17 - 0
x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/Page.java

@@ -294,4 +294,21 @@ public final class Page implements Writeable {
             }
         }
     }
+
+    public Page filter(int... positions) {
+        Block[] filteredBlocks = new Block[blocks.length];
+        boolean success = false;
+        try {
+            for (int i = 0; i < blocks.length; i++) {
+                filteredBlocks[i] = getBlock(i).filter(positions);
+            }
+            success = true;
+        } finally {
+            releaseBlocks();
+            if (success == false) {
+                Releasables.closeExpectNoException(filteredBlocks);
+            }
+        }
+        return new Page(filteredBlocks);
+    }
 }

+ 3 - 3
x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/ChangePointOperator.java

@@ -19,9 +19,9 @@ import org.elasticsearch.xpack.ml.aggs.MlAggsHelper;
 import org.elasticsearch.xpack.ml.aggs.changepoint.ChangePointDetector;
 import org.elasticsearch.xpack.ml.aggs.changepoint.ChangeType;
 
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Deque;
-import java.util.LinkedList;
 import java.util.List;
 
 /**
@@ -68,8 +68,8 @@ public class ChangePointOperator implements Operator {
         this.sourceColumn = sourceColumn;
 
         finished = false;
-        inputPages = new LinkedList<>();
-        outputPages = new LinkedList<>();
+        inputPages = new ArrayDeque<>();
+        outputPages = new ArrayDeque<>();
         warnings = null;
     }
 

+ 1 - 15
x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/FilterOperator.java

@@ -7,7 +7,6 @@
 
 package org.elasticsearch.compute.operator;
 
-import org.elasticsearch.compute.data.Block;
 import org.elasticsearch.compute.data.BooleanBlock;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator;
@@ -69,20 +68,7 @@ public class FilterOperator extends AbstractPageMappingOperator {
             }
             positions = Arrays.copyOf(positions, rowCount);
 
-            Block[] filteredBlocks = new Block[page.getBlockCount()];
-            boolean success = false;
-            try {
-                for (int i = 0; i < page.getBlockCount(); i++) {
-                    filteredBlocks[i] = page.getBlock(i).filter(positions);
-                }
-                success = true;
-            } finally {
-                page.releaseBlocks();
-                if (success == false) {
-                    Releasables.closeExpectNoException(filteredBlocks);
-                }
-            }
-            return new Page(filteredBlocks);
+            return page.filter(positions);
         }
     }
 

+ 242 - 0
x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/SampleOperator.java

@@ -0,0 +1,242 @@
+/*
+ * 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.compute.operator;
+
+import org.elasticsearch.TransportVersion;
+import org.elasticsearch.TransportVersions;
+import org.elasticsearch.common.Randomness;
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.io.stream.StreamOutput;
+import org.elasticsearch.compute.data.Page;
+import org.elasticsearch.core.TimeValue;
+import org.elasticsearch.search.aggregations.bucket.sampler.random.RandomSamplingQuery;
+import org.elasticsearch.xcontent.XContentBuilder;
+
+import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.Deque;
+import java.util.Objects;
+import java.util.SplittableRandom;
+
+public class SampleOperator implements Operator {
+
+    public static class Factory implements OperatorFactory {
+
+        private final double probability;
+        private final Integer seed;
+
+        public Factory(double probability) {
+            this(probability, null);
+        }
+
+        // visible for testing
+        Factory(double probability, Integer seed) {
+            this.probability = probability;
+            this.seed = seed;
+        }
+
+        @Override
+        public SampleOperator get(DriverContext driverContext) {
+            return new SampleOperator(probability, seed == null ? Randomness.get().nextInt() : seed);
+        }
+
+        @Override
+        public String describe() {
+            return "SampleOperator[probability = " + probability + "]";
+        }
+    }
+
+    private final Deque<Page> outputPages;
+
+    /**
+     * At any time this iterator will point to be next document that still
+     * needs to be sampled. If this document is on the current page, it's
+     * added to the output and the iterator is advanced. It the document is
+     * not on the current page, the current page is finished and the index
+     * is used for the next page.
+     */
+    private final RandomSamplingQuery.RandomSamplingIterator randomSamplingIterator;
+    private boolean finished;
+
+    private int pagesProcessed = 0;
+    private int rowsReceived = 0;
+    private int rowsEmitted = 0;
+    private long collectNanos;
+    private long emitNanos;
+
+    private SampleOperator(double probability, int seed) {
+        finished = false;
+        outputPages = new ArrayDeque<>();
+        SplittableRandom random = new SplittableRandom(seed);
+        randomSamplingIterator = new RandomSamplingQuery.RandomSamplingIterator(Integer.MAX_VALUE, probability, random::nextInt);
+        // Initialize the iterator to the next document that needs to be sampled.
+        randomSamplingIterator.nextDoc();
+    }
+
+    /**
+     * whether the given operator can accept more input pages
+     */
+    @Override
+    public boolean needsInput() {
+        return finished == false;
+    }
+
+    /**
+     * adds an input page to the operator. only called when needsInput() == true and isFinished() == false
+     *
+     * @param page
+     * @throws UnsupportedOperationException if the operator is a {@link SourceOperator}
+     */
+    @Override
+    public void addInput(Page page) {
+        long startTime = System.nanoTime();
+        createOutputPage(page);
+        rowsReceived += page.getPositionCount();
+        page.releaseBlocks();
+        pagesProcessed++;
+        collectNanos += System.nanoTime() - startTime;
+    }
+
+    private void createOutputPage(Page page) {
+        final int[] sampledPositions = new int[page.getPositionCount()];
+        int sampledIdx = 0;
+        for (int i = randomSamplingIterator.docID(); i - rowsReceived < page.getPositionCount(); i = randomSamplingIterator.nextDoc()) {
+            sampledPositions[sampledIdx++] = i - rowsReceived;
+        }
+        if (sampledIdx > 0) {
+            outputPages.add(page.filter(Arrays.copyOf(sampledPositions, sampledIdx)));
+        }
+    }
+
+    /**
+     * notifies the operator that it won't receive any more input pages
+     */
+    @Override
+    public void finish() {
+        finished = true;
+    }
+
+    /**
+     * whether the operator has finished processing all input pages and made the corresponding output pages available
+     */
+    @Override
+    public boolean isFinished() {
+        return finished && outputPages.isEmpty();
+    }
+
+    @Override
+    public Page getOutput() {
+        final var emitStart = System.nanoTime();
+        Page page;
+        if (outputPages.isEmpty()) {
+            page = null;
+        } else {
+            page = outputPages.removeFirst();
+            rowsEmitted += page.getPositionCount();
+        }
+        emitNanos += System.nanoTime() - emitStart;
+        return page;
+    }
+
+    /**
+     * notifies the operator that it won't be used anymore (i.e. none of the other methods called),
+     * and its resources can be cleaned up
+     */
+    @Override
+    public void close() {
+        for (Page page : outputPages) {
+            page.releaseBlocks();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "SampleOperator[sampled = " + rowsEmitted + "/" + rowsReceived + "]";
+    }
+
+    @Override
+    public Operator.Status status() {
+        return new Status(collectNanos, emitNanos, pagesProcessed, rowsReceived, rowsEmitted);
+    }
+
+    private record Status(long collectNanos, long emitNanos, int pagesProcessed, int rowsReceived, int rowsEmitted)
+        implements
+            Operator.Status {
+
+        public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(
+            Operator.Status.class,
+            "sample",
+            Status::new
+        );
+
+        Status(StreamInput streamInput) throws IOException {
+            this(streamInput.readVLong(), streamInput.readVLong(), streamInput.readVInt(), streamInput.readVInt(), streamInput.readVInt());
+        }
+
+        @Override
+        public void writeTo(StreamOutput out) throws IOException {
+            out.writeVLong(collectNanos);
+            out.writeVLong(emitNanos);
+            out.writeVInt(pagesProcessed);
+            out.writeVInt(rowsReceived);
+            out.writeVInt(rowsEmitted);
+        }
+
+        @Override
+        public String getWriteableName() {
+            return ENTRY.name;
+        }
+
+        @Override
+        public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+            builder.startObject();
+            builder.field("collect_nanos", collectNanos);
+            if (builder.humanReadable()) {
+                builder.field("collect_time", TimeValue.timeValueNanos(collectNanos));
+            }
+            builder.field("emit_nanos", emitNanos);
+            if (builder.humanReadable()) {
+                builder.field("emit_time", TimeValue.timeValueNanos(emitNanos));
+            }
+            builder.field("pages_processed", pagesProcessed);
+            builder.field("rows_received", rowsReceived);
+            builder.field("rows_emitted", rowsEmitted);
+            return builder.endObject();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            Status other = (Status) o;
+            return collectNanos == other.collectNanos
+                && emitNanos == other.emitNanos
+                && pagesProcessed == other.pagesProcessed
+                && rowsReceived == other.rowsReceived
+                && rowsEmitted == other.rowsEmitted;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(collectNanos, emitNanos, pagesProcessed, rowsReceived, rowsEmitted);
+        }
+
+        @Override
+        public String toString() {
+            return Strings.toString(this);
+        }
+
+        @Override
+        public TransportVersion getMinimalSupportedVersion() {
+            return TransportVersions.ZERO;
+        }
+    }
+}

+ 74 - 0
x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/SampleOperatorTests.java

@@ -0,0 +1,74 @@
+/*
+ * 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.compute.operator;
+
+import org.elasticsearch.compute.data.BlockFactory;
+import org.elasticsearch.compute.data.Page;
+import org.elasticsearch.compute.test.OperatorTestCase;
+import org.elasticsearch.compute.test.SequenceLongBlockSourceOperator;
+import org.hamcrest.Matcher;
+
+import java.util.List;
+import java.util.stream.LongStream;
+
+import static org.hamcrest.Matchers.both;
+import static org.hamcrest.Matchers.closeTo;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.lessThan;
+
+public class SampleOperatorTests extends OperatorTestCase {
+
+    @Override
+    protected SourceOperator simpleInput(BlockFactory blockFactory, int size) {
+        return new SequenceLongBlockSourceOperator(blockFactory, LongStream.range(0, size));
+    }
+
+    @Override
+    protected void assertSimpleOutput(List<Page> input, List<Page> results) {
+        int inputCount = input.stream().mapToInt(Page::getPositionCount).sum();
+        int outputCount = results.stream().mapToInt(Page::getPositionCount).sum();
+        double meanExpectedOutputCount = 0.5 * inputCount;
+        double stdDevExpectedOutputCount = Math.sqrt(meanExpectedOutputCount);
+        assertThat((double) outputCount, closeTo(meanExpectedOutputCount, 10 * stdDevExpectedOutputCount));
+    }
+
+    @Override
+    protected SampleOperator.Factory simple() {
+        return new SampleOperator.Factory(0.5, randomInt());
+    }
+
+    @Override
+    protected Matcher<String> expectedDescriptionOfSimple() {
+        return equalTo("SampleOperator[probability = 0.5]");
+    }
+
+    @Override
+    protected Matcher<String> expectedToStringOfSimple() {
+        return equalTo("SampleOperator[sampled = 0/0]");
+    }
+
+    public void testAccuracy() {
+        BlockFactory blockFactory = driverContext().blockFactory();
+        int totalPositionCount = 0;
+
+        for (int iter = 0; iter < 10000; iter++) {
+            SampleOperator operator = simple().get(driverContext());
+            operator.addInput(new Page(blockFactory.newConstantNullBlock(20000)));
+            Page output = operator.getOutput();
+            // 10000 expected rows, stddev=sqrt(10000)=100, so this is 10 stddevs.
+            assertThat(output.getPositionCount(), both(greaterThan(9000)).and(lessThan(11000)));
+            totalPositionCount += output.getPositionCount();
+            output.releaseBlocks();
+        }
+
+        int averagePositionCount = totalPositionCount / 10000;
+        // Running 10000 times, so the stddev is divided by sqrt(10000)=100, so this 10 stddevs again.
+        assertThat(averagePositionCount, both(greaterThan(9990)).and(lessThan(10010)));
+    }
+}

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

@@ -0,0 +1,26 @@
+/*
+ * 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.qa.single_node;
+
+import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;
+
+import org.elasticsearch.test.TestClustersThreadFilter;
+import org.elasticsearch.test.cluster.ElasticsearchCluster;
+import org.elasticsearch.xpack.esql.qa.rest.RestSampleTestCase;
+import org.junit.ClassRule;
+
+@ThreadLeakFilters(filters = TestClustersThreadFilter.class)
+public class RestSampleIT extends RestSampleTestCase {
+    @ClassRule
+    public static ElasticsearchCluster cluster = Clusters.testCluster();
+
+    @Override
+    protected String getTestRestCluster() {
+        return cluster.getHttpAddresses();
+    }
+}

+ 148 - 0
x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestSampleTestCase.java

@@ -0,0 +1,148 @@
+/*
+ * 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.qa.rest;
+
+import org.elasticsearch.client.Request;
+import org.elasticsearch.client.ResponseException;
+import org.elasticsearch.test.rest.ESRestTestCase;
+import org.elasticsearch.xpack.esql.action.EsqlCapabilities;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.After;
+import org.junit.Before;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.IntStream;
+
+import static org.hamcrest.Matchers.both;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.lessThan;
+
+public class RestSampleTestCase extends ESRestTestCase {
+
+    @Before
+    public void skipWhenSampleDisabled() throws IOException {
+        assumeTrue(
+            "Requires SAMPLE capability",
+            EsqlSpecTestCase.hasCapabilities(adminClient(), List.of(EsqlCapabilities.Cap.SAMPLE_V3.capabilityName()))
+        );
+    }
+
+    @Before
+    @After
+    public void assertRequestBreakerEmpty() throws Exception {
+        EsqlSpecTestCase.assertRequestBreakerEmpty();
+    }
+
+    /**
+     * Matcher for the results of sampling 50% of the elements 0,1,2,...,998,999.
+     * The results should consist of unique numbers in [0,999]. Furthermore, the
+     * size should on average be 500. Allowing for 10 stddev deviations, the size
+     * should be in [250,750].
+     */
+    private static final TypeSafeMatcher<List<List<Integer>>> RESULT_MATCHER = new TypeSafeMatcher<>() {
+        @Override
+        public void describeTo(Description description) {
+            description.appendText("a list with between 250 and 750 unique elements in [0,999]");
+        }
+
+        @Override
+        protected boolean matchesSafely(List<List<Integer>> lists) {
+            if (lists.size() < 250 || lists.size() > 750) {
+                return false;
+            }
+            Set<Integer> values = new HashSet<>();
+            for (List<Integer> list : lists) {
+                if (list.size() != 1) {
+                    return false;
+                }
+                Integer value = list.get(0);
+                if (value == null || value < 0 || value >= 1000) {
+                    return false;
+                }
+                values.add(value);
+            }
+            return values.size() == lists.size();
+        }
+    };
+
+    /**
+     * This tests sampling in the Lucene query.
+     */
+    public void testSample_withFrom() throws IOException {
+        createTestIndex();
+        test("FROM sample-test-index | SAMPLE 0.5 | LIMIT 1000");
+        deleteTestIndex();
+    }
+
+    /**
+     * This tests sampling in the ES|QL operator.
+     */
+    public void testSample_withRow() throws IOException {
+        List<Integer> numbers = IntStream.range(0, 999).boxed().toList();
+        test("ROW value = " + numbers + " | MV_EXPAND value | SAMPLE 0.5 | LIMIT 1000");
+    }
+
+    private void test(String query) throws IOException {
+        int iterationCount = 1000;
+        int totalResultSize = 0;
+        for (int iteration = 0; iteration < iterationCount; iteration++) {
+            Map<String, Object> result = runEsqlQuery(query);
+            assertResultMap(result, defaultOutputColumns(), RESULT_MATCHER);
+            totalResultSize += ((List<?>) result.get("values")).size();
+        }
+        // On average there's 500 elements in the results set.
+        // Allowing for 10 stddev deviations, it should be in [490,510].
+        assertThat(totalResultSize / iterationCount, both(greaterThan(490)).and(lessThan(510)));
+    }
+
+    private static List<Map<String, String>> defaultOutputColumns() {
+        return List.of(Map.of("name", "value", "type", "integer"));
+    }
+
+    private Map<String, Object> runEsqlQuery(String query) throws IOException {
+        RestEsqlTestCase.RequestObjectBuilder builder = RestEsqlTestCase.requestObjectBuilder().query(query);
+        return RestEsqlTestCase.runEsqlSync(builder);
+    }
+
+    private void createTestIndex() throws IOException {
+        Request request = new Request("PUT", "/sample-test-index");
+        request.setJsonEntity("""
+            {
+              "mappings": {
+                "properties": {
+                  "value": { "type": "integer" }
+                }
+              }
+            }""");
+        assertEquals(200, client().performRequest(request).getStatusLine().getStatusCode());
+
+        StringBuilder requestJsonEntity = new StringBuilder();
+        for (int i = 0; i < 1000; i++) {
+            requestJsonEntity.append("{ \"index\": {\"_id\": " + i + "} }\n");
+            requestJsonEntity.append("{ \"value\": " + i + " }\n");
+        }
+
+        request = new Request("POST", "/sample-test-index/_bulk");
+        request.addParameter("refresh", "true");
+        request.setJsonEntity(requestJsonEntity.toString());
+        assertEquals(200, client().performRequest(request).getStatusLine().getStatusCode());
+    }
+
+    private void deleteTestIndex() throws IOException {
+        try {
+            adminClient().performRequest(new Request("DELETE", "/sample-test-index"));
+        } catch (ResponseException e) {
+            throw e;
+        }
+    }
+}

+ 248 - 0
x-pack/plugin/esql/qa/testFixtures/src/main/resources/sample.csv-spec

@@ -0,0 +1,248 @@
+// Tests focused on the SAMPLE command
+// Note: this tests only basic behavior, because of limitations of the CSV tests.
+// Most tests assert that the count, average and sum of some values are within a
+// range. These stats should be correctly adjusted for the sampling. Furthermore,
+// they also assert the value of MV_COUNT(VALUES(...)), which is not adjusted for
+// the sampling and therefore gives the size of the sample.
+// All ranges are very loose, so that the tests should practically never fail.
+// The range checks are done in ES|QL, resulting in one boolean value (is_expected),
+// because the CSV tests don't support such assertions.
+
+row
+required_capability: sample_v3
+
+ROW x = 1 | SAMPLE .999999999
+;
+
+x:integer
+1
+;
+
+
+row and mv_expand
+required_capability: sample_v3
+
+ROW x = [1,2,3,4,5] | MV_EXPAND x | SAMPLE .999999999
+;
+
+x:integer
+1
+2
+3
+4
+5
+;
+
+
+adjust stats for sampling
+required_capability: sample_v3
+
+FROM employees
+  | SAMPLE 0.5
+  | STATS count = COUNT(), avg_emp_no = AVG(emp_no), sum_emp_no = SUM(emp_no)
+  | EVAL is_expected = count >= 10 AND count <= 90 AND
+                       avg_emp_no > 10010 AND avg_emp_no < 10090 AND
+                       sum_emp_no > 10*10010 AND sum_emp_no < 90*10090
+  | KEEP is_expected
+;
+
+is_expected:boolean
+true
+;
+
+
+before where
+required_capability: sample_v3
+
+FROM employees
+  | SAMPLE 0.5
+  | WHERE emp_no > 10050 
+  | STATS count = COUNT(), avg_emp_no = AVG(emp_no)
+  | EVAL is_expected = count >= 2 AND count <= 48 AND
+                       avg_emp_no > 10055 AND avg_emp_no < 10095
+  | KEEP is_expected
+;
+
+is_expected:boolean
+true
+;
+
+
+after where
+required_capability: sample_v3
+
+FROM employees
+  | WHERE emp_no <= 10050 
+  | SAMPLE 0.5
+  | STATS count = COUNT(), avg_emp_no = AVG(emp_no)
+  | EVAL is_expected = count >= 2 AND count <= 48 AND
+                       avg_emp_no > 10005 AND avg_emp_no < 10045
+  | KEEP is_expected
+;
+
+is_expected:boolean
+true
+;
+
+
+before sort
+required_capability: sample_v3
+
+FROM employees
+  | SAMPLE 0.5
+  | SORT emp_no
+  | STATS count = COUNT(), avg_emp_no = AVG(emp_no)
+  | EVAL is_expected = count >= 10 AND count <= 90 AND
+                       avg_emp_no > 10010 AND avg_emp_no < 10090
+  | KEEP is_expected
+;
+
+is_expected:boolean
+true
+;
+
+
+after sort
+required_capability: sample_v3
+
+FROM employees
+  | SORT emp_no
+  | SAMPLE 0.5
+  | STATS count = COUNT(), avg_emp_no = AVG(emp_no)
+  | EVAL is_expected = count >= 10 AND count <= 90 AND
+                       avg_emp_no > 10010 AND avg_emp_no < 10090
+  | KEEP is_expected
+;
+
+is_expected:boolean
+true
+;
+
+
+before limit
+required_capability: sample_v3
+
+FROM employees
+  | SAMPLE 0.5
+  | LIMIT 10
+  | STATS count = COUNT(emp_no)
+  | EVAL is_expected = count == 10
+  | KEEP is_expected
+;
+
+is_expected:boolean
+true
+;
+
+
+after limit
+required_capability: sample_v3
+
+FROM employees
+  | LIMIT 50
+  | SAMPLE 0.5
+  | STATS count = COUNT(emp_no)
+  | EVAL is_expected = count >= 2 AND count <= 48
+  | KEEP is_expected
+;
+
+is_expected:boolean
+true
+;
+
+
+before mv_expand
+required_capability: sample_v3
+
+ROW x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50], y = [1,2]
+  | MV_EXPAND x
+  | SAMPLE 0.85
+  | MV_EXPAND y
+  | STATS count = COUNT() BY x
+  | STATS counts = VALUES(count)
+  | EVAL is_expected = MV_COUNT(counts) == 1 AND MV_MIN(counts) == 2
+  | KEEP is_expected
+;
+
+is_expected:boolean 
+true
+;
+
+
+after mv_expand
+required_capability: sample_v3
+
+ROW x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50], y = [1,2]
+  | MV_EXPAND x
+  | MV_EXPAND y
+  | SAMPLE 0.85
+  | STATS count = COUNT() BY x
+  | STATS counts = VALUES(count)
+  | EVAL is_expected = MV_COUNT(counts) == 2 AND MV_MIN(counts) == 1 AND MV_MAX(counts) == 2
+  | KEEP is_expected
+;
+
+is_expected:boolean 
+true
+;
+
+
+multiple samples
+required_capability: sample_v3
+
+FROM employees
+  | SAMPLE 0.7
+  | SAMPLE 0.8
+  | SAMPLE 0.9
+  | STATS count = COUNT(), avg_emp_no = AVG(emp_no)
+  | EVAL is_expected = count >= 10 AND count <= 90 AND
+                       avg_emp_no > 10010 AND avg_emp_no < 10090
+  | KEEP is_expected
+;
+
+is_expected:boolean
+true
+;
+
+
+after stats
+required_capability: sample_v3
+
+FROM employees
+  | SAMPLE 0.5
+  | STATS avg_salary = AVG(salary) BY job_positions
+  | SAMPLE 0.8
+  | STATS count = COUNT(), avg_avg_salary = AVG(avg_salary)
+  | EVAL is_expected = count >= 1 AND count <= 16 AND
+                       avg_avg_salary > 25000 AND avg_avg_salary < 75000
+  | KEEP is_expected
+;
+
+is_expected:boolean
+true
+;
+
+
+example for docs
+required_capability: sample_v3
+
+// tag::sampleForDocs[]
+FROM employees
+| KEEP emp_no
+| SAMPLE 0.05
+// end::sampleForDocs[]
+// Hardcode the sample values to work around the limitations of the CSV tests in the 
+// presence of randomness, and be able to specify an expected result for the docs.
+| STATS emp_no = COUNT()
+| EVAL emp_no = [10018, 10024, 10062, 10081]
+| MV_EXPAND emp_no
+;
+
+// tag::sampleForDocs-result[]
+emp_no:integer
+10018
+10024
+10062
+10081
+// end::sampleForDocs-result[]
+;

+ 204 - 0
x-pack/plugin/esql/qa/testFixtures/src/main/resources/stats_sample.csv-spec

@@ -2,6 +2,26 @@
 // Note: this tests only basic behavior, because of the non-deterministic
 // behavior of SAMPLE and limitations of the CSV tests.
 
+
+documentation
+required_capability: agg_sample
+
+// tag::doc[]
+FROM employees
+| STATS sample = SAMPLE(gender, 5)
+// end::doc[]
+// Hardcode the sample values to work around the limitations of the CSV tests in the 
+// presence of randomness, and be able to specify an expected result for the docs.
+| EVAL sample = ["F", "M", "M", "F", "M"]
+;
+
+// tag::doc-result[]
+sample:keyword
+[F, M, M, F, M]
+// end::doc-result[]
+;
+
+
 sample size
 required_capability: agg_sample
 
@@ -43,3 +63,187 @@ FROM employees
 sample_boolean:boolean | sample_datetime:datetime                                                       | sample_double:double | sample_integer:integer | sample_keyword:keyword   | sample_long:long
 [false, true, true]    | [1985-11-21T00:00:00.000Z, 1986-06-26T00:00:00.000Z, 1986-08-28T00:00:00.000Z] | [1.83, 2.03, 2.08]   | [10001, 10002, 10003]  | [Bezalel, Georgi, Parto] | [2, 4, 5] 
 ;
+
+
+multivalued
+required_capability: agg_sample
+
+FROM mv_sample_data 
+| STATS sample = SAMPLE(message, 20)
+| EVAL sample = MV_SORT(sample)
+;
+
+sample:keyword
+[Banana, Banana, Banana, Banana, Banana, Banana, Banana, Connected to 10.1.0.1, Connected to 10.1.0.2, Connected to 10.1.0.3, Connection error, Connection error, Connection error, Disconnected]
+;
+
+
+some null input
+required_capability: agg_sample
+
+FROM employees
+| SORT emp_no
+| LIMIT 15
+| STATS sample = MV_SORT(SAMPLE(gender, 999)) 
+;
+
+sample:keyword
+[F, F, F, F, M, M, M, M, M]
+;
+
+
+some null output
+required_capability: agg_sample
+
+FROM employees
+| WHERE emp_no >= 10008 AND emp_no <= 10011
+| STATS sample = SAMPLE(gender, 1) BY emp_no
+| SORT emp_no
+;
+
+sample:keyword | emp_no:integer
+M              | 10008
+F              | 10009
+null           | 10010
+null           | 10011
+;
+
+
+stats by
+required_capability: agg_sample
+
+FROM employees 
+| STATS sample_keyword = MV_SORT(SAMPLE(gender, 999)),
+        sample_integer = MV_SORT(SAMPLE(salary, 999)) BY job_positions 
+| SORT job_positions
+;
+
+sample_keyword:keyword                                       | sample_integer:integer                                                                                                                       | job_positions:keyword     
+[F, F, F, F, F, M, M, M, M, M, M, M, M, M, M, M]             | [25976, 31897, 35742, 37691, 39356, 39728, 39878, 43026, 43602, 47411, 47896, 48942, 50128, 57305, 58121, 61358, 66817, 74970]               | Accountant                
+[F, F, F, F, F, F, F, M, M, M, M]                            | [28941, 30404, 31120, 37716, 42716, 43889, 44307, 44817, 45797, 54518, 62233, 62405, 69904]                                                  | Architect                 
+[F, F, F, F, M, M, M, M, M, M, M]                            | [29175, 30404, 35742, 36051, 37853, 39638, 39878, 40612, 41933, 50249, 58121]                                                                | Business Analyst          
+[F, M, M, M, M, M, M, M, M, M, M]                            | [25945, 29175, 31897, 34341, 37137, 39878, 42716, 48233, 50249, 56415, 58715, 67492, 74999]                                                  | Data Scientist            
+[F, F, M, M, M, M]                                           | [25324, 27215, 36174, 37137, 39110, 48942, 49281, 50064, 56415, 58715]                                                                       | Head Human Resources      
+[F, F, F, F, F, F, M, M, M, M, M, M, M, M, M]                | [26436, 30404, 31897, 32272, 39356, 43906, 44817, 46595, 48233, 49281, 50064, 50128, 56415, 66174, 69904]                                    | Internship                
+[F, F, F, F, F, F, F, M, M, M, M, M]                         | [25324, 25976, 30404, 32272, 32568, 41933, 43026, 43602, 43906, 50064, 56760, 62233, 64675, 74970]                                           | Junior Developer          
+[F, F, F, F, F, F, M, M, M, M, M, M, M, M, M, M, M, M, M]    | [25324, 28035, 32568, 36051, 37112, 38376, 39728, 42716, 44307, 45656, 49818, 50064, 50249, 52044, 60335, 65367, 66817, 69904, 74970, 74999] | Principal Support Engineer
+[F, F, F, F, F, F, M, M, M, M, M, M, M, M]                   | [32568, 33956, 37716, 41933, 43906, 44307, 45656, 45797, 47896, 49095, 51956, 58121, 58715, 61358, 62233, 68431, 73717, 74970]               | Purchase Manager          
+[F, F, F, M, M, M, M, M, M, M, M, M]                         | [27215, 32568, 34341, 35222, 36051, 38645, 38992, 39356, 39878, 48233, 54518, 61358, 65030]                                                  | Python Developer          
+[F, M, M, M, M, M, M, M, M, M]                               | [28336, 31120, 36174, 37137, 38645, 39638, 40612, 43026, 43889, 45656, 45797, 48233, 48735, 61358, 71165]                                    | Reporting Analyst         
+[F, F, F, F, F, F, F, M, M, M, M, M, M, M, M, M, M, M, M, M] | [25945, 31897, 35222, 35742, 37691, 37716, 37853, 38992, 43906, 49281, 52833, 57305, 60781, 62233, 62405, 66174, 66817, 68547, 73851, 74999] | Senior Python Developer   
+[F, F, F, F, F, F, F, M, M, M, M, M, M, M]                   | [29175, 31120, 33370, 37716, 40612, 42716, 44307, 44817, 49095, 54518, 56371, 56415, 60335, 65030, 67492]                                    | Senior Team Lead          
+[F, F, F, F, M, M, M, M, M, M]                               | [25324, 34341, 35222, 36174, 39728, 41933, 43026, 47896, 49281, 54462, 60408]                                                                | Support Engineer          
+[F, F, F, F, M, M, M, M, M, M, M, M, M]                      | [31120, 35742, 36174, 37691, 39356, 39638, 39728, 40031, 45656, 45797, 52044, 54518, 60335, 67492, 71165]                                    | Tech Lead                 
+[F, F, F, F, M, M, M, M, M, M, M]                            | [32263, 37702, 44956, 52121, 54329, 55360, 61805, 63528, 70011, 73578, 74572]                                                                | null                      
+;
+
+
+multiple samples are different
+required_capability: agg_sample
+
+FROM employees
+| STATS sample1 = MV_SORT(SAMPLE(last_name, 50)),
+        sample2 = MV_SORT(SAMPLE(last_name, 50))
+| EVAL samples = MV_ZIP(sample1, sample2, "|")
+| KEEP samples
+| MV_EXPAND samples
+| EVAL tokens = SPLIT(samples, "|"),
+       token_different = MV_SLICE(tokens, 0) != MV_SLICE(tokens, 1)
+| WHERE token_different == true
+| STATS token_different_count = COUNT()
+| EVAL samples_different = token_different_count > 0
+| KEEP samples_different
+;
+
+samples_different:boolean
+true
+;
+
+
+sample cartesian_point
+required_capability: agg_sample
+ 
+FROM airports_web | SORT abbrev | LIMIT 3 | STATS sample = SAMPLE(location, 999) | EVAL sample = MV_SORT(sample)
+;
+
+sample:cartesian_point
+[POINT (809321.6344269889 1006514.3393965173), POINT (-1.1868515102256078E7 4170563.5012235222), POINT (-437732.64923689933 585738.5549131387)]
+;
+
+
+sample cartesian_shape
+required_capability: agg_sample
+ 
+FROM cartesian_multipolygons | SORT id | LIMIT 1 | STATS sample = SAMPLE(shape, 999) | MV_EXPAND sample
+;
+
+sample:cartesian_shape
+MULTIPOLYGON (((0.0 0.0, 1.0 0.0, 1.0 1.0, 0.0 1.0, 0.0 0.0)),((2.0 0.0, 3.0 0.0, 3.0 1.0, 2.0 1.0, 2.0 0.0)),((2.0 2.0, 3.0 2.0, 3.0 3.0, 2.0 3.0, 2.0 2.0)),((0.0 2.0, 1.0 2.0, 1.0 3.0, 0.0 3.0, 0.0 2.0)))
+;
+
+
+sample date_nanos
+required_capability: agg_sample
+
+FROM date_nanos | STATS sample = SAMPLE(nanos,999) | EVAL sample = MV_SORT(sample)
+;
+
+sample:date_nanos
+[2023-01-23T13:55:01.543123456Z, 2023-02-23T13:33:34.937193Z, 2023-03-23T12:15:03.360103847Z, 2023-03-23T12:15:03.360103847Z, 2023-03-23T12:15:03.360103847Z, 2023-03-23T12:15:03.360103847Z, 2023-10-23T12:15:03.360103847Z, 2023-10-23T12:15:03.360103847Z, 2023-10-23T12:27:28.948Z, 2023-10-23T13:33:34.937193Z, 2023-10-23T13:51:54.732102837Z, 2023-10-23T13:52:55.015787878Z, 2023-10-23T13:53:55.832987654Z, 2023-10-23T13:55:01.543123456Z]
+;
+
+
+sample geo_point
+required_capability: agg_sample
+ 
+FROM airports | SORT abbrev | LIMIT 2 | STATS sample = SAMPLE(location, 999) | EVAL sample = MV_SORT(sample)
+;
+
+sample:geo_point
+[POINT (-106.6166851616 35.0491578018276), POINT (-3.93221929167636 5.2543984451492)]
+;
+
+
+sample geo_shape
+required_capability: agg_sample
+ 
+FROM countries_bbox | SORT id | LIMIT 1 | STATS sample = SAMPLE(shape, 999)
+;
+
+sample:geo_shape
+BBOX (-70.059664, -69.874864, 12.627773, 12.411109)
+;
+
+
+sample ip
+required_capability: agg_sample
+
+FROM k8s | SORT @timestamp | LIMIT 5 | STATS sample = SAMPLE(client.ip,999) | EVAL sample = MV_SORT(sample)
+;
+
+sample:ip
+[10.10.20.30, 10.10.20.30, 10.10.20.31, 10.10.20.34, 10.10.20.34]
+;
+
+
+sample text
+required_capability: agg_sample
+
+FROM books | SORT book_no | LIMIT 3 | STATS sample = SAMPLE(title,999) | EVAL sample = MV_SORT(sample)
+;
+
+sample:keyword
+[Realms of Tolkien: Images of Middle-earth, Selected Passages from Correspondence with Friends, The brothers Karamazov]
+;
+
+
+
+sample version
+required_capability: agg_sample
+
+FROM apps | STATS sample = SAMPLE(version,999) | EVAL sample = MV_SORT(sample)
+;
+
+sample:version
+[1, 1.2.3.4, 1.2.3.4, 1.11.0, 2.1, 2.3.4, 2.12.0, 5.2.9-SNAPSHOT, 5.2.9, 5.2.9, 5.2.9, bad]
+;

+ 2 - 0
x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.g4

@@ -70,6 +70,7 @@ LIMIT : 'limit'               -> pushMode(EXPRESSION_MODE);
 MV_EXPAND : 'mv_expand'       -> pushMode(MVEXPAND_MODE);
 RENAME : 'rename'             -> pushMode(RENAME_MODE);
 ROW : 'row'                   -> pushMode(EXPRESSION_MODE);
+SAMPLE : 'sample'             -> pushMode(EXPRESSION_MODE);
 SHOW : 'show'                 -> pushMode(SHOW_MODE);
 SORT : 'sort'                 -> pushMode(EXPRESSION_MODE);
 STATS : 'stats'               -> pushMode(EXPRESSION_MODE);
@@ -91,6 +92,7 @@ DEV_INLINESTATS :  {this.isDevVersion()}? 'inlinestats'   -> pushMode(EXPRESSION
 DEV_LOOKUP :       {this.isDevVersion()}? 'lookup_🐔'     -> pushMode(LOOKUP_MODE);
 DEV_METRICS :      {this.isDevVersion()}? 'metrics'       -> pushMode(METRICS_MODE);
 DEV_RERANK :       {this.isDevVersion()}? 'rerank'        -> pushMode(EXPRESSION_MODE);
+
 // list of all JOIN commands
 DEV_JOIN_FULL :    {this.isDevVersion()}? 'full'          -> pushMode(JOIN_MODE);
 DEV_JOIN_LEFT :    {this.isDevVersion()}? 'left'          -> pushMode(JOIN_MODE);

+ 181 - 179
x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.tokens

@@ -11,131 +11,132 @@ LIMIT=10
 MV_EXPAND=11
 RENAME=12
 ROW=13
-SHOW=14
-SORT=15
-STATS=16
-WHERE=17
-JOIN_LOOKUP=18
-CHANGE_POINT=19
-DEV_INLINESTATS=20
-DEV_LOOKUP=21
-DEV_METRICS=22
-DEV_RERANK=23
-DEV_JOIN_FULL=24
-DEV_JOIN_LEFT=25
-DEV_JOIN_RIGHT=26
-UNKNOWN_CMD=27
-LINE_COMMENT=28
-MULTILINE_COMMENT=29
-WS=30
-PIPE=31
-QUOTED_STRING=32
-INTEGER_LITERAL=33
-DECIMAL_LITERAL=34
-AND=35
-ASC=36
-ASSIGN=37
-BY=38
-CAST_OP=39
-COLON=40
-COMMA=41
-DESC=42
-DOT=43
-FALSE=44
-FIRST=45
-IN=46
-IS=47
-LAST=48
-LIKE=49
-LP=50
-NOT=51
-NULL=52
-NULLS=53
-ON=54
-OR=55
-PARAM=56
-RLIKE=57
-RP=58
-TRUE=59
-WITH=60
-EQ=61
-CIEQ=62
-NEQ=63
-LT=64
-LTE=65
-GT=66
-GTE=67
-PLUS=68
-MINUS=69
-ASTERISK=70
-SLASH=71
-PERCENT=72
-LEFT_BRACES=73
-RIGHT_BRACES=74
-DOUBLE_PARAMS=75
-NAMED_OR_POSITIONAL_PARAM=76
-NAMED_OR_POSITIONAL_DOUBLE_PARAMS=77
-OPENING_BRACKET=78
-CLOSING_BRACKET=79
-UNQUOTED_IDENTIFIER=80
-QUOTED_IDENTIFIER=81
-EXPR_LINE_COMMENT=82
-EXPR_MULTILINE_COMMENT=83
-EXPR_WS=84
-EXPLAIN_WS=85
-EXPLAIN_LINE_COMMENT=86
-EXPLAIN_MULTILINE_COMMENT=87
-METADATA=88
-UNQUOTED_SOURCE=89
-FROM_LINE_COMMENT=90
-FROM_MULTILINE_COMMENT=91
-FROM_WS=92
-ID_PATTERN=93
-PROJECT_LINE_COMMENT=94
-PROJECT_MULTILINE_COMMENT=95
-PROJECT_WS=96
-AS=97
-RENAME_LINE_COMMENT=98
-RENAME_MULTILINE_COMMENT=99
-RENAME_WS=100
-ENRICH_POLICY_NAME=101
-ENRICH_LINE_COMMENT=102
-ENRICH_MULTILINE_COMMENT=103
-ENRICH_WS=104
-ENRICH_FIELD_LINE_COMMENT=105
-ENRICH_FIELD_MULTILINE_COMMENT=106
-ENRICH_FIELD_WS=107
-MVEXPAND_LINE_COMMENT=108
-MVEXPAND_MULTILINE_COMMENT=109
-MVEXPAND_WS=110
-INFO=111
-SHOW_LINE_COMMENT=112
-SHOW_MULTILINE_COMMENT=113
-SHOW_WS=114
-SETTING=115
-SETTING_LINE_COMMENT=116
-SETTTING_MULTILINE_COMMENT=117
-SETTING_WS=118
-LOOKUP_LINE_COMMENT=119
-LOOKUP_MULTILINE_COMMENT=120
-LOOKUP_WS=121
-LOOKUP_FIELD_LINE_COMMENT=122
-LOOKUP_FIELD_MULTILINE_COMMENT=123
-LOOKUP_FIELD_WS=124
-JOIN=125
-USING=126
-JOIN_LINE_COMMENT=127
-JOIN_MULTILINE_COMMENT=128
-JOIN_WS=129
-METRICS_LINE_COMMENT=130
-METRICS_MULTILINE_COMMENT=131
-METRICS_WS=132
-CLOSING_METRICS_LINE_COMMENT=133
-CLOSING_METRICS_MULTILINE_COMMENT=134
-CLOSING_METRICS_WS=135
-CHANGE_POINT_LINE_COMMENT=136
-CHANGE_POINT_MULTILINE_COMMENT=137
-CHANGE_POINT_WS=138
+SAMPLE=14
+SHOW=15
+SORT=16
+STATS=17
+WHERE=18
+JOIN_LOOKUP=19
+CHANGE_POINT=20
+DEV_INLINESTATS=21
+DEV_LOOKUP=22
+DEV_METRICS=23
+DEV_RERANK=24
+DEV_JOIN_FULL=25
+DEV_JOIN_LEFT=26
+DEV_JOIN_RIGHT=27
+UNKNOWN_CMD=28
+LINE_COMMENT=29
+MULTILINE_COMMENT=30
+WS=31
+PIPE=32
+QUOTED_STRING=33
+INTEGER_LITERAL=34
+DECIMAL_LITERAL=35
+AND=36
+ASC=37
+ASSIGN=38
+BY=39
+CAST_OP=40
+COLON=41
+COMMA=42
+DESC=43
+DOT=44
+FALSE=45
+FIRST=46
+IN=47
+IS=48
+LAST=49
+LIKE=50
+LP=51
+NOT=52
+NULL=53
+NULLS=54
+ON=55
+OR=56
+PARAM=57
+RLIKE=58
+RP=59
+TRUE=60
+WITH=61
+EQ=62
+CIEQ=63
+NEQ=64
+LT=65
+LTE=66
+GT=67
+GTE=68
+PLUS=69
+MINUS=70
+ASTERISK=71
+SLASH=72
+PERCENT=73
+LEFT_BRACES=74
+RIGHT_BRACES=75
+DOUBLE_PARAMS=76
+NAMED_OR_POSITIONAL_PARAM=77
+NAMED_OR_POSITIONAL_DOUBLE_PARAMS=78
+OPENING_BRACKET=79
+CLOSING_BRACKET=80
+UNQUOTED_IDENTIFIER=81
+QUOTED_IDENTIFIER=82
+EXPR_LINE_COMMENT=83
+EXPR_MULTILINE_COMMENT=84
+EXPR_WS=85
+EXPLAIN_WS=86
+EXPLAIN_LINE_COMMENT=87
+EXPLAIN_MULTILINE_COMMENT=88
+METADATA=89
+UNQUOTED_SOURCE=90
+FROM_LINE_COMMENT=91
+FROM_MULTILINE_COMMENT=92
+FROM_WS=93
+ID_PATTERN=94
+PROJECT_LINE_COMMENT=95
+PROJECT_MULTILINE_COMMENT=96
+PROJECT_WS=97
+AS=98
+RENAME_LINE_COMMENT=99
+RENAME_MULTILINE_COMMENT=100
+RENAME_WS=101
+ENRICH_POLICY_NAME=102
+ENRICH_LINE_COMMENT=103
+ENRICH_MULTILINE_COMMENT=104
+ENRICH_WS=105
+ENRICH_FIELD_LINE_COMMENT=106
+ENRICH_FIELD_MULTILINE_COMMENT=107
+ENRICH_FIELD_WS=108
+MVEXPAND_LINE_COMMENT=109
+MVEXPAND_MULTILINE_COMMENT=110
+MVEXPAND_WS=111
+INFO=112
+SHOW_LINE_COMMENT=113
+SHOW_MULTILINE_COMMENT=114
+SHOW_WS=115
+SETTING=116
+SETTING_LINE_COMMENT=117
+SETTTING_MULTILINE_COMMENT=118
+SETTING_WS=119
+LOOKUP_LINE_COMMENT=120
+LOOKUP_MULTILINE_COMMENT=121
+LOOKUP_WS=122
+LOOKUP_FIELD_LINE_COMMENT=123
+LOOKUP_FIELD_MULTILINE_COMMENT=124
+LOOKUP_FIELD_WS=125
+JOIN=126
+USING=127
+JOIN_LINE_COMMENT=128
+JOIN_MULTILINE_COMMENT=129
+JOIN_WS=130
+METRICS_LINE_COMMENT=131
+METRICS_MULTILINE_COMMENT=132
+METRICS_WS=133
+CLOSING_METRICS_LINE_COMMENT=134
+CLOSING_METRICS_MULTILINE_COMMENT=135
+CLOSING_METRICS_WS=136
+CHANGE_POINT_LINE_COMMENT=137
+CHANGE_POINT_MULTILINE_COMMENT=138
+CHANGE_POINT_WS=139
 'completion'=1
 'dissect'=2
 'drop'=3
@@ -149,57 +150,58 @@ CHANGE_POINT_WS=138
 'mv_expand'=11
 'rename'=12
 'row'=13
-'show'=14
-'sort'=15
-'stats'=16
-'where'=17
-'lookup'=18
-'change_point'=19
-'|'=31
-'and'=35
-'asc'=36
-'='=37
-'by'=38
-'::'=39
-':'=40
-','=41
-'desc'=42
-'.'=43
-'false'=44
-'first'=45
-'in'=46
-'is'=47
-'last'=48
-'like'=49
-'('=50
-'not'=51
-'null'=52
-'nulls'=53
-'on'=54
-'or'=55
-'?'=56
-'rlike'=57
-')'=58
-'true'=59
-'with'=60
-'=='=61
-'=~'=62
-'!='=63
-'<'=64
-'<='=65
-'>'=66
-'>='=67
-'+'=68
-'-'=69
-'*'=70
-'/'=71
-'%'=72
-'{'=73
-'}'=74
-'??'=75
-']'=79
-'metadata'=88
-'as'=97
-'info'=111
-'join'=125
-'USING'=126
+'sample'=14
+'show'=15
+'sort'=16
+'stats'=17
+'where'=18
+'lookup'=19
+'change_point'=20
+'|'=32
+'and'=36
+'asc'=37
+'='=38
+'by'=39
+'::'=40
+':'=41
+','=42
+'desc'=43
+'.'=44
+'false'=45
+'first'=46
+'in'=47
+'is'=48
+'last'=49
+'like'=50
+'('=51
+'not'=52
+'null'=53
+'nulls'=54
+'on'=55
+'or'=56
+'?'=57
+'rlike'=58
+')'=59
+'true'=60
+'with'=61
+'=='=62
+'=~'=63
+'!='=64
+'<'=65
+'<='=66
+'>'=67
+'>='=68
+'+'=69
+'-'=70
+'*'=71
+'/'=72
+'%'=73
+'{'=74
+'}'=75
+'??'=76
+']'=80
+'metadata'=89
+'as'=98
+'info'=112
+'join'=126
+'USING'=127

+ 5 - 0
x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.g4

@@ -54,6 +54,7 @@ processingCommand
     | joinCommand
     | changePointCommand
     | completionCommand
+    | sampleCommand
     // in development
     | {this.isDevVersion()}? inlinestatsCommand
     | {this.isDevVersion()}? lookupCommand
@@ -355,6 +356,10 @@ changePointCommand
     : CHANGE_POINT value=qualifiedName (ON key=qualifiedName)? (AS targetType=qualifiedName COMMA targetPvalue=qualifiedName)?
     ;
 
+sampleCommand
+    : SAMPLE probability=constant
+    ;
+
 //
 // In development
 //

+ 181 - 179
x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.tokens

@@ -11,131 +11,132 @@ LIMIT=10
 MV_EXPAND=11
 RENAME=12
 ROW=13
-SHOW=14
-SORT=15
-STATS=16
-WHERE=17
-JOIN_LOOKUP=18
-CHANGE_POINT=19
-DEV_INLINESTATS=20
-DEV_LOOKUP=21
-DEV_METRICS=22
-DEV_RERANK=23
-DEV_JOIN_FULL=24
-DEV_JOIN_LEFT=25
-DEV_JOIN_RIGHT=26
-UNKNOWN_CMD=27
-LINE_COMMENT=28
-MULTILINE_COMMENT=29
-WS=30
-PIPE=31
-QUOTED_STRING=32
-INTEGER_LITERAL=33
-DECIMAL_LITERAL=34
-AND=35
-ASC=36
-ASSIGN=37
-BY=38
-CAST_OP=39
-COLON=40
-COMMA=41
-DESC=42
-DOT=43
-FALSE=44
-FIRST=45
-IN=46
-IS=47
-LAST=48
-LIKE=49
-LP=50
-NOT=51
-NULL=52
-NULLS=53
-ON=54
-OR=55
-PARAM=56
-RLIKE=57
-RP=58
-TRUE=59
-WITH=60
-EQ=61
-CIEQ=62
-NEQ=63
-LT=64
-LTE=65
-GT=66
-GTE=67
-PLUS=68
-MINUS=69
-ASTERISK=70
-SLASH=71
-PERCENT=72
-LEFT_BRACES=73
-RIGHT_BRACES=74
-DOUBLE_PARAMS=75
-NAMED_OR_POSITIONAL_PARAM=76
-NAMED_OR_POSITIONAL_DOUBLE_PARAMS=77
-OPENING_BRACKET=78
-CLOSING_BRACKET=79
-UNQUOTED_IDENTIFIER=80
-QUOTED_IDENTIFIER=81
-EXPR_LINE_COMMENT=82
-EXPR_MULTILINE_COMMENT=83
-EXPR_WS=84
-EXPLAIN_WS=85
-EXPLAIN_LINE_COMMENT=86
-EXPLAIN_MULTILINE_COMMENT=87
-METADATA=88
-UNQUOTED_SOURCE=89
-FROM_LINE_COMMENT=90
-FROM_MULTILINE_COMMENT=91
-FROM_WS=92
-ID_PATTERN=93
-PROJECT_LINE_COMMENT=94
-PROJECT_MULTILINE_COMMENT=95
-PROJECT_WS=96
-AS=97
-RENAME_LINE_COMMENT=98
-RENAME_MULTILINE_COMMENT=99
-RENAME_WS=100
-ENRICH_POLICY_NAME=101
-ENRICH_LINE_COMMENT=102
-ENRICH_MULTILINE_COMMENT=103
-ENRICH_WS=104
-ENRICH_FIELD_LINE_COMMENT=105
-ENRICH_FIELD_MULTILINE_COMMENT=106
-ENRICH_FIELD_WS=107
-MVEXPAND_LINE_COMMENT=108
-MVEXPAND_MULTILINE_COMMENT=109
-MVEXPAND_WS=110
-INFO=111
-SHOW_LINE_COMMENT=112
-SHOW_MULTILINE_COMMENT=113
-SHOW_WS=114
-SETTING=115
-SETTING_LINE_COMMENT=116
-SETTTING_MULTILINE_COMMENT=117
-SETTING_WS=118
-LOOKUP_LINE_COMMENT=119
-LOOKUP_MULTILINE_COMMENT=120
-LOOKUP_WS=121
-LOOKUP_FIELD_LINE_COMMENT=122
-LOOKUP_FIELD_MULTILINE_COMMENT=123
-LOOKUP_FIELD_WS=124
-JOIN=125
-USING=126
-JOIN_LINE_COMMENT=127
-JOIN_MULTILINE_COMMENT=128
-JOIN_WS=129
-METRICS_LINE_COMMENT=130
-METRICS_MULTILINE_COMMENT=131
-METRICS_WS=132
-CLOSING_METRICS_LINE_COMMENT=133
-CLOSING_METRICS_MULTILINE_COMMENT=134
-CLOSING_METRICS_WS=135
-CHANGE_POINT_LINE_COMMENT=136
-CHANGE_POINT_MULTILINE_COMMENT=137
-CHANGE_POINT_WS=138
+SAMPLE=14
+SHOW=15
+SORT=16
+STATS=17
+WHERE=18
+JOIN_LOOKUP=19
+CHANGE_POINT=20
+DEV_INLINESTATS=21
+DEV_LOOKUP=22
+DEV_METRICS=23
+DEV_RERANK=24
+DEV_JOIN_FULL=25
+DEV_JOIN_LEFT=26
+DEV_JOIN_RIGHT=27
+UNKNOWN_CMD=28
+LINE_COMMENT=29
+MULTILINE_COMMENT=30
+WS=31
+PIPE=32
+QUOTED_STRING=33
+INTEGER_LITERAL=34
+DECIMAL_LITERAL=35
+AND=36
+ASC=37
+ASSIGN=38
+BY=39
+CAST_OP=40
+COLON=41
+COMMA=42
+DESC=43
+DOT=44
+FALSE=45
+FIRST=46
+IN=47
+IS=48
+LAST=49
+LIKE=50
+LP=51
+NOT=52
+NULL=53
+NULLS=54
+ON=55
+OR=56
+PARAM=57
+RLIKE=58
+RP=59
+TRUE=60
+WITH=61
+EQ=62
+CIEQ=63
+NEQ=64
+LT=65
+LTE=66
+GT=67
+GTE=68
+PLUS=69
+MINUS=70
+ASTERISK=71
+SLASH=72
+PERCENT=73
+LEFT_BRACES=74
+RIGHT_BRACES=75
+DOUBLE_PARAMS=76
+NAMED_OR_POSITIONAL_PARAM=77
+NAMED_OR_POSITIONAL_DOUBLE_PARAMS=78
+OPENING_BRACKET=79
+CLOSING_BRACKET=80
+UNQUOTED_IDENTIFIER=81
+QUOTED_IDENTIFIER=82
+EXPR_LINE_COMMENT=83
+EXPR_MULTILINE_COMMENT=84
+EXPR_WS=85
+EXPLAIN_WS=86
+EXPLAIN_LINE_COMMENT=87
+EXPLAIN_MULTILINE_COMMENT=88
+METADATA=89
+UNQUOTED_SOURCE=90
+FROM_LINE_COMMENT=91
+FROM_MULTILINE_COMMENT=92
+FROM_WS=93
+ID_PATTERN=94
+PROJECT_LINE_COMMENT=95
+PROJECT_MULTILINE_COMMENT=96
+PROJECT_WS=97
+AS=98
+RENAME_LINE_COMMENT=99
+RENAME_MULTILINE_COMMENT=100
+RENAME_WS=101
+ENRICH_POLICY_NAME=102
+ENRICH_LINE_COMMENT=103
+ENRICH_MULTILINE_COMMENT=104
+ENRICH_WS=105
+ENRICH_FIELD_LINE_COMMENT=106
+ENRICH_FIELD_MULTILINE_COMMENT=107
+ENRICH_FIELD_WS=108
+MVEXPAND_LINE_COMMENT=109
+MVEXPAND_MULTILINE_COMMENT=110
+MVEXPAND_WS=111
+INFO=112
+SHOW_LINE_COMMENT=113
+SHOW_MULTILINE_COMMENT=114
+SHOW_WS=115
+SETTING=116
+SETTING_LINE_COMMENT=117
+SETTTING_MULTILINE_COMMENT=118
+SETTING_WS=119
+LOOKUP_LINE_COMMENT=120
+LOOKUP_MULTILINE_COMMENT=121
+LOOKUP_WS=122
+LOOKUP_FIELD_LINE_COMMENT=123
+LOOKUP_FIELD_MULTILINE_COMMENT=124
+LOOKUP_FIELD_WS=125
+JOIN=126
+USING=127
+JOIN_LINE_COMMENT=128
+JOIN_MULTILINE_COMMENT=129
+JOIN_WS=130
+METRICS_LINE_COMMENT=131
+METRICS_MULTILINE_COMMENT=132
+METRICS_WS=133
+CLOSING_METRICS_LINE_COMMENT=134
+CLOSING_METRICS_MULTILINE_COMMENT=135
+CLOSING_METRICS_WS=136
+CHANGE_POINT_LINE_COMMENT=137
+CHANGE_POINT_MULTILINE_COMMENT=138
+CHANGE_POINT_WS=139
 'completion'=1
 'dissect'=2
 'drop'=3
@@ -149,57 +150,58 @@ CHANGE_POINT_WS=138
 'mv_expand'=11
 'rename'=12
 'row'=13
-'show'=14
-'sort'=15
-'stats'=16
-'where'=17
-'lookup'=18
-'change_point'=19
-'|'=31
-'and'=35
-'asc'=36
-'='=37
-'by'=38
-'::'=39
-':'=40
-','=41
-'desc'=42
-'.'=43
-'false'=44
-'first'=45
-'in'=46
-'is'=47
-'last'=48
-'like'=49
-'('=50
-'not'=51
-'null'=52
-'nulls'=53
-'on'=54
-'or'=55
-'?'=56
-'rlike'=57
-')'=58
-'true'=59
-'with'=60
-'=='=61
-'=~'=62
-'!='=63
-'<'=64
-'<='=65
-'>'=66
-'>='=67
-'+'=68
-'-'=69
-'*'=70
-'/'=71
-'%'=72
-'{'=73
-'}'=74
-'??'=75
-']'=79
-'metadata'=88
-'as'=97
-'info'=111
-'join'=125
-'USING'=126
+'sample'=14
+'show'=15
+'sort'=16
+'stats'=17
+'where'=18
+'lookup'=19
+'change_point'=20
+'|'=32
+'and'=36
+'asc'=37
+'='=38
+'by'=39
+'::'=40
+':'=41
+','=42
+'desc'=43
+'.'=44
+'false'=45
+'first'=46
+'in'=47
+'is'=48
+'last'=49
+'like'=50
+'('=51
+'not'=52
+'null'=53
+'nulls'=54
+'on'=55
+'or'=56
+'?'=57
+'rlike'=58
+')'=59
+'true'=60
+'with'=61
+'=='=62
+'=~'=63
+'!='=64
+'<'=65
+'<='=66
+'>'=67
+'>='=68
+'+'=69
+'-'=70
+'*'=71
+'/'=72
+'%'=73
+'{'=74
+'}'=75
+'??'=76
+']'=80
+'metadata'=89
+'as'=98
+'info'=112
+'join'=126
+'USING'=127

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

@@ -938,7 +938,7 @@ public class EsqlCapabilities {
         TO_LOWER_EMPTY_STRING,
 
         /**
-         * Support parameters for LiMIT command.
+         * Support parameters for LIMIT command.
          */
         PARAMETER_FOR_LIMIT,
 
@@ -972,18 +972,28 @@ public class EsqlCapabilities {
          */
         LIKE_WITH_LIST_OF_PATTERNS,
 
+        /**
+         * Support for the SAMPLE command
+         */
+        SAMPLE_V3,
+
+        /**
+         * Support parameters for SAMPLE command.
+         */
+        PARAMETER_FOR_SAMPLE,
+
+        /**
+         * Support for the SAMPLE aggregation function
+         */
+        AGG_SAMPLE,
+
         /*
          * From now, Literal only accepts strings as BytesRefs.
          * No java.lang.String anymore.
          *
          * https://github.com/elastic/elasticsearch/issues/129322
          */
-        NO_PLAIN_STRINGS_IN_LITERALS,
-
-        /**
-         * Support for the SAMPLE aggregation function
-         */
-        AGG_SAMPLE;
+        NO_PLAIN_STRINGS_IN_LITERALS;
 
         private final boolean enabled;
 

+ 22 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/capabilities/PostPhysicalOptimizationVerificationAware.java

@@ -0,0 +1,22 @@
+/*
+ * 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.capabilities;
+
+import org.elasticsearch.xpack.esql.common.Failures;
+
+/**
+ * Interface implemented by expressions that require validation post physical optimization.
+ */
+public interface PostPhysicalOptimizationVerificationAware {
+
+    /**
+     * Validates the implementing expression - discovered failures are reported to the given
+     * {@link Failures} class.
+     */
+    void postPhysicalOptimizationVerification(Failures failures);
+}

+ 3 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Sample.java

@@ -23,6 +23,7 @@ import org.elasticsearch.xpack.esql.core.expression.Literal;
 import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
 import org.elasticsearch.xpack.esql.core.tree.Source;
 import org.elasticsearch.xpack.esql.core.type.DataType;
+import org.elasticsearch.xpack.esql.expression.function.Example;
 import org.elasticsearch.xpack.esql.expression.function.FunctionInfo;
 import org.elasticsearch.xpack.esql.expression.function.Param;
 import org.elasticsearch.xpack.esql.planner.PlannerUtils;
@@ -55,7 +56,8 @@ public class Sample extends AggregateFunction implements ToAggregator {
             "keyword",
             "long",
             "version" },
-        description = "Collects sample values for a field."
+        description = "Collects sample values for a field.",
+        examples = @Example(file = "stats_sample", tag = "doc")
     )
     public Sample(
         Source source,

+ 5 - 4
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizer.java

@@ -8,11 +8,12 @@
 package org.elasticsearch.xpack.esql.optimizer;
 
 import org.elasticsearch.xpack.esql.VerificationException;
-import org.elasticsearch.xpack.esql.common.Failure;
+import org.elasticsearch.xpack.esql.common.Failures;
 import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.EnableSpatialDistancePushdown;
 import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.InsertFieldExtraction;
 import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.PushFiltersToSource;
 import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.PushLimitToSource;
+import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.PushSampleToSource;
 import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.PushStatsToSource;
 import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.PushTopNToSource;
 import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.ReplaceSourceAttributes;
@@ -23,7 +24,6 @@ import org.elasticsearch.xpack.esql.rule.ParameterizedRuleExecutor;
 import org.elasticsearch.xpack.esql.rule.Rule;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 
 /**
@@ -45,8 +45,8 @@ public class LocalPhysicalPlanOptimizer extends ParameterizedRuleExecutor<Physic
     }
 
     PhysicalPlan verify(PhysicalPlan plan) {
-        Collection<Failure> failures = verifier.verify(plan);
-        if (failures.isEmpty() == false) {
+        Failures failures = verifier.verify(plan);
+        if (failures.hasFailures()) {
             throw new VerificationException(failures);
         }
         return plan;
@@ -64,6 +64,7 @@ public class LocalPhysicalPlanOptimizer extends ParameterizedRuleExecutor<Physic
             esSourceRules.add(new PushTopNToSource());
             esSourceRules.add(new PushLimitToSource());
             esSourceRules.add(new PushFiltersToSource());
+            esSourceRules.add(new PushSampleToSource());
             esSourceRules.add(new PushStatsToSource());
             esSourceRules.add(new EnableSpatialDistancePushdown());
         }

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

@@ -35,6 +35,7 @@ import org.elasticsearch.xpack.esql.optimizer.rules.logical.PruneRedundantSortCl
 import org.elasticsearch.xpack.esql.optimizer.rules.logical.PushDownAndCombineFilters;
 import org.elasticsearch.xpack.esql.optimizer.rules.logical.PushDownAndCombineLimits;
 import org.elasticsearch.xpack.esql.optimizer.rules.logical.PushDownAndCombineOrderBy;
+import org.elasticsearch.xpack.esql.optimizer.rules.logical.PushDownAndCombineSample;
 import org.elasticsearch.xpack.esql.optimizer.rules.logical.PushDownEnrich;
 import org.elasticsearch.xpack.esql.optimizer.rules.logical.PushDownEval;
 import org.elasticsearch.xpack.esql.optimizer.rules.logical.PushDownInferencePlan;
@@ -186,6 +187,7 @@ public class LogicalPlanOptimizer extends ParameterizedRuleExecutor<LogicalPlan,
             new PruneLiteralsInOrderBy(),
             new PushDownAndCombineLimits(),
             new PushDownAndCombineFilters(),
+            new PushDownAndCombineSample(),
             new PushDownInferencePlan(),
             new PushDownEval(),
             new PushDownRegexExtract(),

+ 3 - 4
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizer.java

@@ -8,14 +8,13 @@
 package org.elasticsearch.xpack.esql.optimizer;
 
 import org.elasticsearch.xpack.esql.VerificationException;
-import org.elasticsearch.xpack.esql.common.Failure;
+import org.elasticsearch.xpack.esql.common.Failures;
 import org.elasticsearch.xpack.esql.optimizer.rules.physical.ProjectAwayColumns;
 import org.elasticsearch.xpack.esql.plan.physical.FragmentExec;
 import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan;
 import org.elasticsearch.xpack.esql.rule.ParameterizedRuleExecutor;
 import org.elasticsearch.xpack.esql.rule.RuleExecutor;
 
-import java.util.Collection;
 import java.util.List;
 
 /**
@@ -39,8 +38,8 @@ public class PhysicalPlanOptimizer extends ParameterizedRuleExecutor<PhysicalPla
     }
 
     PhysicalPlan verify(PhysicalPlan plan) {
-        Collection<Failure> failures = verifier.verify(plan);
-        if (failures.isEmpty() == false) {
+        Failures failures = verifier.verify(plan);
+        if (failures.hasFailures()) {
             throw new VerificationException(failures);
         }
         return plan;

+ 14 - 7
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/PhysicalVerifier.java

@@ -7,7 +7,7 @@
 
 package org.elasticsearch.xpack.esql.optimizer;
 
-import org.elasticsearch.xpack.esql.common.Failure;
+import org.elasticsearch.xpack.esql.capabilities.PostPhysicalOptimizationVerificationAware;
 import org.elasticsearch.xpack.esql.common.Failures;
 import org.elasticsearch.xpack.esql.core.expression.Attribute;
 import org.elasticsearch.xpack.esql.core.expression.Expressions;
@@ -17,10 +17,6 @@ import org.elasticsearch.xpack.esql.plan.physical.EnrichExec;
 import org.elasticsearch.xpack.esql.plan.physical.FieldExtractExec;
 import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan;
 
-import java.util.Collection;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
 import static org.elasticsearch.xpack.esql.common.Failure.fail;
 
 /** Physical plan verifier. */
@@ -31,8 +27,8 @@ public final class PhysicalVerifier {
     private PhysicalVerifier() {}
 
     /** Verifies the physical plan. */
-    public Collection<Failure> verify(PhysicalPlan plan) {
-        Set<Failure> failures = new LinkedHashSet<>();
+    public Failures verify(PhysicalPlan plan) {
+        Failures failures = new Failures();
         Failures depFailures = new Failures();
 
         // AwaitsFix https://github.com/elastic/elasticsearch/issues/118531
@@ -56,6 +52,17 @@ public final class PhysicalVerifier {
                 }
             }
             PlanConsistencyChecker.checkPlan(p, depFailures);
+
+            if (failures.hasFailures() == false) {
+                if (p instanceof PostPhysicalOptimizationVerificationAware va) {
+                    va.postPhysicalOptimizationVerification(failures);
+                }
+                p.forEachExpression(ex -> {
+                    if (ex instanceof PostPhysicalOptimizationVerificationAware va) {
+                        va.postPhysicalOptimizationVerification(failures);
+                    }
+                });
+            }
         });
 
         if (depFailures.hasFailures()) {

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

@@ -0,0 +1,82 @@
+/*
+ * 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.optimizer.rules.logical;
+
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.expression.Foldables;
+import org.elasticsearch.xpack.esql.core.expression.Literal;
+import org.elasticsearch.xpack.esql.optimizer.LogicalOptimizerContext;
+import org.elasticsearch.xpack.esql.plan.logical.Enrich;
+import org.elasticsearch.xpack.esql.plan.logical.Eval;
+import org.elasticsearch.xpack.esql.plan.logical.Filter;
+import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan;
+import org.elasticsearch.xpack.esql.plan.logical.OrderBy;
+import org.elasticsearch.xpack.esql.plan.logical.Project;
+import org.elasticsearch.xpack.esql.plan.logical.RegexExtract;
+import org.elasticsearch.xpack.esql.plan.logical.Sample;
+import org.elasticsearch.xpack.esql.plan.logical.UnaryPlan;
+
+/**
+ * Pushes down the SAMPLE operator. SAMPLE can be pushed down through an
+ * operator if
+ * <p>
+ * <code>| SAMPLE p | OPERATOR</code>
+ * <p>
+ * is equivalent to
+ * <p>
+ * <code>| OPERATOR | SAMPLE p</code>
+ * <p>
+ * statistically (i.e. same possible output with same probabilities).
+ * In that case, we push down sampling to Lucene for efficiency.
+ *  <p>
+ *
+ *  As a rule of thumb, if an operator can be swapped with sampling if it maps:
+ *  <ul>
+ *      <li>
+ *          one row to one row (e.g. <code>DISSECT</code>, <code>DROP</code>, <code>ENRICH</code>,
+ *          <code>EVAL</code>, <code>GROK</code>, <code>KEEP</code>, <code>RENAME</code>)
+ *      </li>
+ *      <li>
+ *          one row to zero or one row (<code>WHERE</code>)
+ *      </li>
+ *      <li>
+ *          reorders the rows (<code>SORT</code>)
+ *      </li>
+ *  </ul>
+ */
+public class PushDownAndCombineSample extends OptimizerRules.ParameterizedOptimizerRule<Sample, LogicalOptimizerContext> {
+
+    public PushDownAndCombineSample() {
+        super(OptimizerRules.TransformDirection.DOWN);
+    }
+
+    @Override
+    protected LogicalPlan rule(Sample sample, LogicalOptimizerContext context) {
+        LogicalPlan plan = sample;
+        var child = sample.child();
+        if (child instanceof Sample sampleChild) {
+            var probability = combinedProbability(context, sample, sampleChild);
+            plan = new Sample(sample.source(), probability, sampleChild.child());
+        } else if (child instanceof Enrich
+            || child instanceof Eval
+            || child instanceof Filter
+            || child instanceof OrderBy
+            || child instanceof Project
+            || child instanceof RegexExtract) {
+                var unaryChild = (UnaryPlan) child;
+                plan = unaryChild.replaceChild(sample.replaceChild(unaryChild.child()));
+            }
+        return plan;
+    }
+
+    private static Expression combinedProbability(LogicalOptimizerContext context, Sample parent, Sample child) {
+        var parentProbability = (double) Foldables.valueOf(context.foldCtx(), parent.probability());
+        var childProbability = (double) Foldables.valueOf(context.foldCtx(), child.probability());
+        return Literal.of(parent.probability(), parentProbability * childProbability);
+    }
+}

+ 43 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/PushSampleToSource.java

@@ -0,0 +1,43 @@
+/*
+ * 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.optimizer.rules.physical.local;
+
+import org.elasticsearch.search.aggregations.bucket.sampler.random.RandomSamplingQueryBuilder;
+import org.elasticsearch.xpack.esql.core.expression.Foldables;
+import org.elasticsearch.xpack.esql.optimizer.LocalPhysicalOptimizerContext;
+import org.elasticsearch.xpack.esql.optimizer.PhysicalOptimizerRules;
+import org.elasticsearch.xpack.esql.plan.physical.EsQueryExec;
+import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan;
+import org.elasticsearch.xpack.esql.plan.physical.SampleExec;
+
+import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
+import static org.elasticsearch.xpack.esql.planner.mapper.MapperUtils.hasScoreAttribute;
+
+public class PushSampleToSource extends PhysicalOptimizerRules.ParameterizedOptimizerRule<SampleExec, LocalPhysicalOptimizerContext> {
+    @Override
+    protected PhysicalPlan rule(SampleExec sample, LocalPhysicalOptimizerContext ctx) {
+        PhysicalPlan plan = sample;
+        if (sample.child() instanceof EsQueryExec queryExec) {
+            var fullQuery = boolQuery();
+            if (queryExec.query() != null) {
+                if (hasScoreAttribute(queryExec.output())) {
+                    fullQuery.must(queryExec.query());
+                } else {
+                    fullQuery.filter(queryExec.query());
+                }
+            }
+
+            var sampleQuery = new RandomSamplingQueryBuilder((double) Foldables.valueOf(ctx.foldCtx(), sample.probability()));
+
+            fullQuery.filter(sampleQuery);
+
+            plan = queryExec.withQuery(fullQuery);
+        }
+        return plan;
+    }
+}

+ 2 - 2
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/PushTopNToSource.java

@@ -200,7 +200,7 @@ public class PushTopNToSource extends PhysicalOptimizerRules.ParameterizedOptimi
         // allow only exact FieldAttributes (no expressions) for sorting
         BiFunction<Expression, LucenePushdownPredicates, Boolean> isSortableAttribute = (exp, lpp) -> lpp.isPushableFieldAttribute(exp)
             // TODO: https://github.com/elastic/elasticsearch/issues/120219
-            || (exp instanceof MetadataAttribute ma && MetadataAttribute.SCORE.equals(ma.name()));
+            || MetadataAttribute.isScoreAttribute(exp);
         return orders.stream().allMatch(o -> isSortableAttribute.apply(o.child(), lucenePushdownPredicates));
     }
 
@@ -209,7 +209,7 @@ public class PushTopNToSource extends PhysicalOptimizerRules.ParameterizedOptimi
         for (Order o : orders) {
             if (o.child() instanceof FieldAttribute fa) {
                 sorts.add(new EsQueryExec.FieldSort(fa.exactAttribute(), o.direction(), o.nullsPosition()));
-            } else if (o.child() instanceof MetadataAttribute ma && MetadataAttribute.SCORE.equals(ma.name())) {
+            } else if (MetadataAttribute.isScoreAttribute(o.child())) {
                 sorts.add(new EsQueryExec.ScoreSort(o.direction()));
             } else {
                 assert false : "unexpected ordering on expression type " + o.child().getClass();

Diff do ficheiro suprimidas por serem muito extensas
+ 3 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.interp


+ 1200 - 1192
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.java

@@ -26,34 +26,35 @@ public class EsqlBaseLexer extends LexerConfig {
     new PredictionContextCache();
   public static final int
     COMPLETION=1, DISSECT=2, DROP=3, ENRICH=4, EVAL=5, EXPLAIN=6, FROM=7, 
-    GROK=8, KEEP=9, LIMIT=10, MV_EXPAND=11, RENAME=12, ROW=13, SHOW=14, SORT=15, 
-    STATS=16, WHERE=17, JOIN_LOOKUP=18, CHANGE_POINT=19, DEV_INLINESTATS=20, 
-    DEV_LOOKUP=21, DEV_METRICS=22, DEV_RERANK=23, DEV_JOIN_FULL=24, DEV_JOIN_LEFT=25, 
-    DEV_JOIN_RIGHT=26, UNKNOWN_CMD=27, LINE_COMMENT=28, MULTILINE_COMMENT=29, 
-    WS=30, PIPE=31, QUOTED_STRING=32, INTEGER_LITERAL=33, DECIMAL_LITERAL=34, 
-    AND=35, ASC=36, ASSIGN=37, BY=38, CAST_OP=39, COLON=40, COMMA=41, DESC=42, 
-    DOT=43, FALSE=44, FIRST=45, IN=46, IS=47, LAST=48, LIKE=49, LP=50, NOT=51, 
-    NULL=52, NULLS=53, ON=54, OR=55, PARAM=56, RLIKE=57, RP=58, TRUE=59, WITH=60, 
-    EQ=61, CIEQ=62, NEQ=63, LT=64, LTE=65, GT=66, GTE=67, PLUS=68, MINUS=69, 
-    ASTERISK=70, SLASH=71, PERCENT=72, LEFT_BRACES=73, RIGHT_BRACES=74, DOUBLE_PARAMS=75, 
-    NAMED_OR_POSITIONAL_PARAM=76, NAMED_OR_POSITIONAL_DOUBLE_PARAMS=77, OPENING_BRACKET=78, 
-    CLOSING_BRACKET=79, UNQUOTED_IDENTIFIER=80, QUOTED_IDENTIFIER=81, EXPR_LINE_COMMENT=82, 
-    EXPR_MULTILINE_COMMENT=83, EXPR_WS=84, EXPLAIN_WS=85, EXPLAIN_LINE_COMMENT=86, 
-    EXPLAIN_MULTILINE_COMMENT=87, METADATA=88, UNQUOTED_SOURCE=89, FROM_LINE_COMMENT=90, 
-    FROM_MULTILINE_COMMENT=91, FROM_WS=92, ID_PATTERN=93, PROJECT_LINE_COMMENT=94, 
-    PROJECT_MULTILINE_COMMENT=95, PROJECT_WS=96, AS=97, RENAME_LINE_COMMENT=98, 
-    RENAME_MULTILINE_COMMENT=99, RENAME_WS=100, ENRICH_POLICY_NAME=101, ENRICH_LINE_COMMENT=102, 
-    ENRICH_MULTILINE_COMMENT=103, ENRICH_WS=104, ENRICH_FIELD_LINE_COMMENT=105, 
-    ENRICH_FIELD_MULTILINE_COMMENT=106, ENRICH_FIELD_WS=107, MVEXPAND_LINE_COMMENT=108, 
-    MVEXPAND_MULTILINE_COMMENT=109, MVEXPAND_WS=110, INFO=111, SHOW_LINE_COMMENT=112, 
-    SHOW_MULTILINE_COMMENT=113, SHOW_WS=114, SETTING=115, SETTING_LINE_COMMENT=116, 
-    SETTTING_MULTILINE_COMMENT=117, SETTING_WS=118, LOOKUP_LINE_COMMENT=119, 
-    LOOKUP_MULTILINE_COMMENT=120, LOOKUP_WS=121, LOOKUP_FIELD_LINE_COMMENT=122, 
-    LOOKUP_FIELD_MULTILINE_COMMENT=123, LOOKUP_FIELD_WS=124, JOIN=125, USING=126, 
-    JOIN_LINE_COMMENT=127, JOIN_MULTILINE_COMMENT=128, JOIN_WS=129, METRICS_LINE_COMMENT=130, 
-    METRICS_MULTILINE_COMMENT=131, METRICS_WS=132, CLOSING_METRICS_LINE_COMMENT=133, 
-    CLOSING_METRICS_MULTILINE_COMMENT=134, CLOSING_METRICS_WS=135, CHANGE_POINT_LINE_COMMENT=136, 
-    CHANGE_POINT_MULTILINE_COMMENT=137, CHANGE_POINT_WS=138;
+    GROK=8, KEEP=9, LIMIT=10, MV_EXPAND=11, RENAME=12, ROW=13, SAMPLE=14, 
+    SHOW=15, SORT=16, STATS=17, WHERE=18, JOIN_LOOKUP=19, CHANGE_POINT=20, 
+    DEV_INLINESTATS=21, DEV_LOOKUP=22, DEV_METRICS=23, DEV_RERANK=24, DEV_JOIN_FULL=25, 
+    DEV_JOIN_LEFT=26, DEV_JOIN_RIGHT=27, UNKNOWN_CMD=28, LINE_COMMENT=29, 
+    MULTILINE_COMMENT=30, WS=31, PIPE=32, QUOTED_STRING=33, INTEGER_LITERAL=34, 
+    DECIMAL_LITERAL=35, AND=36, ASC=37, ASSIGN=38, BY=39, CAST_OP=40, COLON=41, 
+    COMMA=42, DESC=43, DOT=44, FALSE=45, FIRST=46, IN=47, IS=48, LAST=49, 
+    LIKE=50, LP=51, NOT=52, NULL=53, NULLS=54, ON=55, OR=56, PARAM=57, RLIKE=58, 
+    RP=59, TRUE=60, WITH=61, EQ=62, CIEQ=63, NEQ=64, LT=65, LTE=66, GT=67, 
+    GTE=68, PLUS=69, MINUS=70, ASTERISK=71, SLASH=72, PERCENT=73, LEFT_BRACES=74, 
+    RIGHT_BRACES=75, DOUBLE_PARAMS=76, NAMED_OR_POSITIONAL_PARAM=77, NAMED_OR_POSITIONAL_DOUBLE_PARAMS=78, 
+    OPENING_BRACKET=79, CLOSING_BRACKET=80, UNQUOTED_IDENTIFIER=81, QUOTED_IDENTIFIER=82, 
+    EXPR_LINE_COMMENT=83, EXPR_MULTILINE_COMMENT=84, EXPR_WS=85, EXPLAIN_WS=86, 
+    EXPLAIN_LINE_COMMENT=87, EXPLAIN_MULTILINE_COMMENT=88, METADATA=89, UNQUOTED_SOURCE=90, 
+    FROM_LINE_COMMENT=91, FROM_MULTILINE_COMMENT=92, FROM_WS=93, ID_PATTERN=94, 
+    PROJECT_LINE_COMMENT=95, PROJECT_MULTILINE_COMMENT=96, PROJECT_WS=97, 
+    AS=98, RENAME_LINE_COMMENT=99, RENAME_MULTILINE_COMMENT=100, RENAME_WS=101, 
+    ENRICH_POLICY_NAME=102, ENRICH_LINE_COMMENT=103, ENRICH_MULTILINE_COMMENT=104, 
+    ENRICH_WS=105, ENRICH_FIELD_LINE_COMMENT=106, ENRICH_FIELD_MULTILINE_COMMENT=107, 
+    ENRICH_FIELD_WS=108, MVEXPAND_LINE_COMMENT=109, MVEXPAND_MULTILINE_COMMENT=110, 
+    MVEXPAND_WS=111, INFO=112, SHOW_LINE_COMMENT=113, SHOW_MULTILINE_COMMENT=114, 
+    SHOW_WS=115, SETTING=116, SETTING_LINE_COMMENT=117, SETTTING_MULTILINE_COMMENT=118, 
+    SETTING_WS=119, LOOKUP_LINE_COMMENT=120, LOOKUP_MULTILINE_COMMENT=121, 
+    LOOKUP_WS=122, LOOKUP_FIELD_LINE_COMMENT=123, LOOKUP_FIELD_MULTILINE_COMMENT=124, 
+    LOOKUP_FIELD_WS=125, JOIN=126, USING=127, JOIN_LINE_COMMENT=128, JOIN_MULTILINE_COMMENT=129, 
+    JOIN_WS=130, METRICS_LINE_COMMENT=131, METRICS_MULTILINE_COMMENT=132, 
+    METRICS_WS=133, CLOSING_METRICS_LINE_COMMENT=134, CLOSING_METRICS_MULTILINE_COMMENT=135, 
+    CLOSING_METRICS_WS=136, CHANGE_POINT_LINE_COMMENT=137, CHANGE_POINT_MULTILINE_COMMENT=138, 
+    CHANGE_POINT_WS=139;
   public static final int
     EXPRESSION_MODE=1, EXPLAIN_MODE=2, FROM_MODE=3, PROJECT_MODE=4, RENAME_MODE=5, 
     ENRICH_MODE=6, ENRICH_FIELD_MODE=7, MVEXPAND_MODE=8, SHOW_MODE=9, SETTING_MODE=10, 
@@ -73,27 +74,27 @@ public class EsqlBaseLexer extends LexerConfig {
   private static String[] makeRuleNames() {
     return new String[] {
       "COMPLETION", "DISSECT", "DROP", "ENRICH", "EVAL", "EXPLAIN", "FROM", 
-      "GROK", "KEEP", "LIMIT", "MV_EXPAND", "RENAME", "ROW", "SHOW", "SORT", 
-      "STATS", "WHERE", "JOIN_LOOKUP", "CHANGE_POINT", "DEV_INLINESTATS", "DEV_LOOKUP", 
-      "DEV_METRICS", "DEV_RERANK", "DEV_JOIN_FULL", "DEV_JOIN_LEFT", "DEV_JOIN_RIGHT", 
-      "UNKNOWN_CMD", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "PIPE", "DIGIT", 
-      "LETTER", "ESCAPE_SEQUENCE", "UNESCAPED_CHARS", "EXPONENT", "ASPERAND", 
-      "BACKQUOTE", "BACKQUOTE_BLOCK", "UNDERSCORE", "UNQUOTED_ID_BODY", "QUOTED_STRING", 
-      "INTEGER_LITERAL", "DECIMAL_LITERAL", "AND", "ASC", "ASSIGN", "BY", "CAST_OP", 
-      "COLON", "COMMA", "DESC", "DOT", "FALSE", "FIRST", "IN", "IS", "LAST", 
-      "LIKE", "LP", "NOT", "NULL", "NULLS", "ON", "OR", "PARAM", "RLIKE", "RP", 
-      "TRUE", "WITH", "EQ", "CIEQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", 
-      "MINUS", "ASTERISK", "SLASH", "PERCENT", "LEFT_BRACES", "RIGHT_BRACES", 
-      "DOUBLE_PARAMS", "NESTED_WHERE", "NAMED_OR_POSITIONAL_PARAM", "NAMED_OR_POSITIONAL_DOUBLE_PARAMS", 
-      "OPENING_BRACKET", "CLOSING_BRACKET", "UNQUOTED_IDENTIFIER", "QUOTED_ID", 
-      "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", 
-      "EXPLAIN_OPENING_BRACKET", "EXPLAIN_PIPE", "EXPLAIN_WS", "EXPLAIN_LINE_COMMENT", 
-      "EXPLAIN_MULTILINE_COMMENT", "FROM_PIPE", "FROM_OPENING_BRACKET", "FROM_CLOSING_BRACKET", 
-      "FROM_COLON", "FROM_SELECTOR", "FROM_COMMA", "FROM_ASSIGN", "METADATA", 
-      "UNQUOTED_SOURCE_PART", "UNQUOTED_SOURCE", "FROM_UNQUOTED_SOURCE", "FROM_QUOTED_SOURCE", 
-      "FROM_LINE_COMMENT", "FROM_MULTILINE_COMMENT", "FROM_WS", "PROJECT_PIPE", 
-      "PROJECT_DOT", "PROJECT_COMMA", "PROJECT_PARAM", "PROJECT_NAMED_OR_POSITIONAL_PARAM", 
-      "PROJECT_DOUBLE_PARAMS", "PROJECT_NAMED_OR_POSITIONAL_DOUBLE_PARAMS", 
+      "GROK", "KEEP", "LIMIT", "MV_EXPAND", "RENAME", "ROW", "SAMPLE", "SHOW", 
+      "SORT", "STATS", "WHERE", "JOIN_LOOKUP", "CHANGE_POINT", "DEV_INLINESTATS", 
+      "DEV_LOOKUP", "DEV_METRICS", "DEV_RERANK", "DEV_JOIN_FULL", "DEV_JOIN_LEFT", 
+      "DEV_JOIN_RIGHT", "UNKNOWN_CMD", "LINE_COMMENT", "MULTILINE_COMMENT", 
+      "WS", "PIPE", "DIGIT", "LETTER", "ESCAPE_SEQUENCE", "UNESCAPED_CHARS", 
+      "EXPONENT", "ASPERAND", "BACKQUOTE", "BACKQUOTE_BLOCK", "UNDERSCORE", 
+      "UNQUOTED_ID_BODY", "QUOTED_STRING", "INTEGER_LITERAL", "DECIMAL_LITERAL", 
+      "AND", "ASC", "ASSIGN", "BY", "CAST_OP", "COLON", "COMMA", "DESC", "DOT", 
+      "FALSE", "FIRST", "IN", "IS", "LAST", "LIKE", "LP", "NOT", "NULL", "NULLS", 
+      "ON", "OR", "PARAM", "RLIKE", "RP", "TRUE", "WITH", "EQ", "CIEQ", "NEQ", 
+      "LT", "LTE", "GT", "GTE", "PLUS", "MINUS", "ASTERISK", "SLASH", "PERCENT", 
+      "LEFT_BRACES", "RIGHT_BRACES", "DOUBLE_PARAMS", "NESTED_WHERE", "NAMED_OR_POSITIONAL_PARAM", 
+      "NAMED_OR_POSITIONAL_DOUBLE_PARAMS", "OPENING_BRACKET", "CLOSING_BRACKET", 
+      "UNQUOTED_IDENTIFIER", "QUOTED_ID", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", 
+      "EXPR_MULTILINE_COMMENT", "EXPR_WS", "EXPLAIN_OPENING_BRACKET", "EXPLAIN_PIPE", 
+      "EXPLAIN_WS", "EXPLAIN_LINE_COMMENT", "EXPLAIN_MULTILINE_COMMENT", "FROM_PIPE", 
+      "FROM_OPENING_BRACKET", "FROM_CLOSING_BRACKET", "FROM_COLON", "FROM_SELECTOR", 
+      "FROM_COMMA", "FROM_ASSIGN", "METADATA", "UNQUOTED_SOURCE_PART", "UNQUOTED_SOURCE", 
+      "FROM_UNQUOTED_SOURCE", "FROM_QUOTED_SOURCE", "FROM_LINE_COMMENT", "FROM_MULTILINE_COMMENT", 
+      "FROM_WS", "PROJECT_PIPE", "PROJECT_DOT", "PROJECT_COMMA", "PROJECT_PARAM", 
+      "PROJECT_NAMED_OR_POSITIONAL_PARAM", "PROJECT_DOUBLE_PARAMS", "PROJECT_NAMED_OR_POSITIONAL_DOUBLE_PARAMS", 
       "UNQUOTED_ID_BODY_WITH_PATTERN", "UNQUOTED_ID_PATTERN", "ID_PATTERN", 
       "PROJECT_LINE_COMMENT", "PROJECT_MULTILINE_COMMENT", "PROJECT_WS", "RENAME_PIPE", 
       "RENAME_ASSIGN", "RENAME_COMMA", "RENAME_DOT", "RENAME_PARAM", "RENAME_NAMED_OR_POSITIONAL_PARAM", 
@@ -137,7 +138,7 @@ public class EsqlBaseLexer extends LexerConfig {
     return new String[] {
       null, "'completion'", "'dissect'", "'drop'", "'enrich'", "'eval'", "'explain'", 
       "'from'", "'grok'", "'keep'", "'limit'", "'mv_expand'", "'rename'", "'row'", 
-      "'show'", "'sort'", "'stats'", "'where'", "'lookup'", "'change_point'", 
+      "'sample'", "'show'", "'sort'", "'stats'", "'where'", "'lookup'", "'change_point'", 
       null, null, null, null, null, null, null, null, null, null, null, "'|'", 
       null, null, null, "'and'", "'asc'", "'='", "'by'", "'::'", "':'", "','", 
       "'desc'", "'.'", "'false'", "'first'", "'in'", "'is'", "'last'", "'like'", 
@@ -155,33 +156,33 @@ public class EsqlBaseLexer extends LexerConfig {
   private static String[] makeSymbolicNames() {
     return new String[] {
       null, "COMPLETION", "DISSECT", "DROP", "ENRICH", "EVAL", "EXPLAIN", "FROM", 
-      "GROK", "KEEP", "LIMIT", "MV_EXPAND", "RENAME", "ROW", "SHOW", "SORT", 
-      "STATS", "WHERE", "JOIN_LOOKUP", "CHANGE_POINT", "DEV_INLINESTATS", "DEV_LOOKUP", 
-      "DEV_METRICS", "DEV_RERANK", "DEV_JOIN_FULL", "DEV_JOIN_LEFT", "DEV_JOIN_RIGHT", 
-      "UNKNOWN_CMD", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "PIPE", "QUOTED_STRING", 
-      "INTEGER_LITERAL", "DECIMAL_LITERAL", "AND", "ASC", "ASSIGN", "BY", "CAST_OP", 
-      "COLON", "COMMA", "DESC", "DOT", "FALSE", "FIRST", "IN", "IS", "LAST", 
-      "LIKE", "LP", "NOT", "NULL", "NULLS", "ON", "OR", "PARAM", "RLIKE", "RP", 
-      "TRUE", "WITH", "EQ", "CIEQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", 
-      "MINUS", "ASTERISK", "SLASH", "PERCENT", "LEFT_BRACES", "RIGHT_BRACES", 
-      "DOUBLE_PARAMS", "NAMED_OR_POSITIONAL_PARAM", "NAMED_OR_POSITIONAL_DOUBLE_PARAMS", 
-      "OPENING_BRACKET", "CLOSING_BRACKET", "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", 
-      "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", "EXPLAIN_WS", 
-      "EXPLAIN_LINE_COMMENT", "EXPLAIN_MULTILINE_COMMENT", "METADATA", "UNQUOTED_SOURCE", 
-      "FROM_LINE_COMMENT", "FROM_MULTILINE_COMMENT", "FROM_WS", "ID_PATTERN", 
-      "PROJECT_LINE_COMMENT", "PROJECT_MULTILINE_COMMENT", "PROJECT_WS", "AS", 
-      "RENAME_LINE_COMMENT", "RENAME_MULTILINE_COMMENT", "RENAME_WS", "ENRICH_POLICY_NAME", 
-      "ENRICH_LINE_COMMENT", "ENRICH_MULTILINE_COMMENT", "ENRICH_WS", "ENRICH_FIELD_LINE_COMMENT", 
-      "ENRICH_FIELD_MULTILINE_COMMENT", "ENRICH_FIELD_WS", "MVEXPAND_LINE_COMMENT", 
-      "MVEXPAND_MULTILINE_COMMENT", "MVEXPAND_WS", "INFO", "SHOW_LINE_COMMENT", 
-      "SHOW_MULTILINE_COMMENT", "SHOW_WS", "SETTING", "SETTING_LINE_COMMENT", 
-      "SETTTING_MULTILINE_COMMENT", "SETTING_WS", "LOOKUP_LINE_COMMENT", "LOOKUP_MULTILINE_COMMENT", 
-      "LOOKUP_WS", "LOOKUP_FIELD_LINE_COMMENT", "LOOKUP_FIELD_MULTILINE_COMMENT", 
-      "LOOKUP_FIELD_WS", "JOIN", "USING", "JOIN_LINE_COMMENT", "JOIN_MULTILINE_COMMENT", 
-      "JOIN_WS", "METRICS_LINE_COMMENT", "METRICS_MULTILINE_COMMENT", "METRICS_WS", 
-      "CLOSING_METRICS_LINE_COMMENT", "CLOSING_METRICS_MULTILINE_COMMENT", 
-      "CLOSING_METRICS_WS", "CHANGE_POINT_LINE_COMMENT", "CHANGE_POINT_MULTILINE_COMMENT", 
-      "CHANGE_POINT_WS"
+      "GROK", "KEEP", "LIMIT", "MV_EXPAND", "RENAME", "ROW", "SAMPLE", "SHOW", 
+      "SORT", "STATS", "WHERE", "JOIN_LOOKUP", "CHANGE_POINT", "DEV_INLINESTATS", 
+      "DEV_LOOKUP", "DEV_METRICS", "DEV_RERANK", "DEV_JOIN_FULL", "DEV_JOIN_LEFT", 
+      "DEV_JOIN_RIGHT", "UNKNOWN_CMD", "LINE_COMMENT", "MULTILINE_COMMENT", 
+      "WS", "PIPE", "QUOTED_STRING", "INTEGER_LITERAL", "DECIMAL_LITERAL", 
+      "AND", "ASC", "ASSIGN", "BY", "CAST_OP", "COLON", "COMMA", "DESC", "DOT", 
+      "FALSE", "FIRST", "IN", "IS", "LAST", "LIKE", "LP", "NOT", "NULL", "NULLS", 
+      "ON", "OR", "PARAM", "RLIKE", "RP", "TRUE", "WITH", "EQ", "CIEQ", "NEQ", 
+      "LT", "LTE", "GT", "GTE", "PLUS", "MINUS", "ASTERISK", "SLASH", "PERCENT", 
+      "LEFT_BRACES", "RIGHT_BRACES", "DOUBLE_PARAMS", "NAMED_OR_POSITIONAL_PARAM", 
+      "NAMED_OR_POSITIONAL_DOUBLE_PARAMS", "OPENING_BRACKET", "CLOSING_BRACKET", 
+      "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", 
+      "EXPR_WS", "EXPLAIN_WS", "EXPLAIN_LINE_COMMENT", "EXPLAIN_MULTILINE_COMMENT", 
+      "METADATA", "UNQUOTED_SOURCE", "FROM_LINE_COMMENT", "FROM_MULTILINE_COMMENT", 
+      "FROM_WS", "ID_PATTERN", "PROJECT_LINE_COMMENT", "PROJECT_MULTILINE_COMMENT", 
+      "PROJECT_WS", "AS", "RENAME_LINE_COMMENT", "RENAME_MULTILINE_COMMENT", 
+      "RENAME_WS", "ENRICH_POLICY_NAME", "ENRICH_LINE_COMMENT", "ENRICH_MULTILINE_COMMENT", 
+      "ENRICH_WS", "ENRICH_FIELD_LINE_COMMENT", "ENRICH_FIELD_MULTILINE_COMMENT", 
+      "ENRICH_FIELD_WS", "MVEXPAND_LINE_COMMENT", "MVEXPAND_MULTILINE_COMMENT", 
+      "MVEXPAND_WS", "INFO", "SHOW_LINE_COMMENT", "SHOW_MULTILINE_COMMENT", 
+      "SHOW_WS", "SETTING", "SETTING_LINE_COMMENT", "SETTTING_MULTILINE_COMMENT", 
+      "SETTING_WS", "LOOKUP_LINE_COMMENT", "LOOKUP_MULTILINE_COMMENT", "LOOKUP_WS", 
+      "LOOKUP_FIELD_LINE_COMMENT", "LOOKUP_FIELD_MULTILINE_COMMENT", "LOOKUP_FIELD_WS", 
+      "JOIN", "USING", "JOIN_LINE_COMMENT", "JOIN_MULTILINE_COMMENT", "JOIN_WS", 
+      "METRICS_LINE_COMMENT", "METRICS_MULTILINE_COMMENT", "METRICS_WS", "CLOSING_METRICS_LINE_COMMENT", 
+      "CLOSING_METRICS_MULTILINE_COMMENT", "CLOSING_METRICS_WS", "CHANGE_POINT_LINE_COMMENT", 
+      "CHANGE_POINT_MULTILINE_COMMENT", "CHANGE_POINT_WS"
     };
   }
   private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames();
@@ -246,19 +247,19 @@ public class EsqlBaseLexer extends LexerConfig {
   @Override
   public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) {
     switch (ruleIndex) {
-    case 19:
-      return DEV_INLINESTATS_sempred((RuleContext)_localctx, predIndex);
     case 20:
-      return DEV_LOOKUP_sempred((RuleContext)_localctx, predIndex);
+      return DEV_INLINESTATS_sempred((RuleContext)_localctx, predIndex);
     case 21:
-      return DEV_METRICS_sempred((RuleContext)_localctx, predIndex);
+      return DEV_LOOKUP_sempred((RuleContext)_localctx, predIndex);
     case 22:
-      return DEV_RERANK_sempred((RuleContext)_localctx, predIndex);
+      return DEV_METRICS_sempred((RuleContext)_localctx, predIndex);
     case 23:
-      return DEV_JOIN_FULL_sempred((RuleContext)_localctx, predIndex);
+      return DEV_RERANK_sempred((RuleContext)_localctx, predIndex);
     case 24:
-      return DEV_JOIN_LEFT_sempred((RuleContext)_localctx, predIndex);
+      return DEV_JOIN_FULL_sempred((RuleContext)_localctx, predIndex);
     case 25:
+      return DEV_JOIN_LEFT_sempred((RuleContext)_localctx, predIndex);
+    case 26:
       return DEV_JOIN_RIGHT_sempred((RuleContext)_localctx, predIndex);
     }
     return true;
@@ -314,7 +315,7 @@ public class EsqlBaseLexer extends LexerConfig {
   }
 
   public static final String _serializedATN =
-    "\u0004\u0000\u008a\u0715\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff"+
+    "\u0004\u0000\u008b\u0720\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff"+
     "\uffff\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff"+
     "\uffff\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff"+
     "\uffff\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff"+
@@ -386,1119 +387,1126 @@ public class EsqlBaseLexer extends LexerConfig {
     "\u0002\u00e9\u0007\u00e9\u0002\u00ea\u0007\u00ea\u0002\u00eb\u0007\u00eb"+
     "\u0002\u00ec\u0007\u00ec\u0002\u00ed\u0007\u00ed\u0002\u00ee\u0007\u00ee"+
     "\u0002\u00ef\u0007\u00ef\u0002\u00f0\u0007\u00f0\u0002\u00f1\u0007\u00f1"+
-    "\u0002\u00f2\u0007\u00f2\u0002\u00f3\u0007\u00f3\u0001\u0000\u0001\u0000"+
+    "\u0002\u00f2\u0007\u00f2\u0002\u00f3\u0007\u00f3\u0002\u00f4\u0007\u00f4"+
+    "\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000"+
     "\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000"+
-    "\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0001"+
-    "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+
-    "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0001\u0002\u0001\u0002"+
-    "\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0003\u0001\u0003"+
+    "\u0001\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+
+    "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002"+
+    "\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002"+
     "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+
-    "\u0001\u0003\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
-    "\u0001\u0004\u0001\u0004\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005"+
+    "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0004\u0001\u0004\u0001\u0004"+
+    "\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0005\u0001\u0005"+
     "\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005"+
-    "\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006"+
-    "\u0001\u0006\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007"+
-    "\u0001\u0007\u0001\u0007\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001"+
-    "\b\u0001\b\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+
-    "\t\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001"+
-    "\n\u0001\n\u0001\n\u0001\n\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b"+
-    "\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\f\u0001"+
-    "\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\r\u0001\r\u0001\r\u0001\r\u0001"+
-    "\r\u0001\r\u0001\r\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001"+
-    "\u000e\u0001\u000e\u0001\u000e\u0001\u000f\u0001\u000f\u0001\u000f\u0001"+
-    "\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u0010\u0001"+
-    "\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001"+
-    "\u0010\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001"+
-    "\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0012\u0001\u0012\u0001"+
-    "\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001"+
-    "\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001"+
-    "\u0012\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001"+
-    "\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001"+
-    "\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0014\u0001\u0014\u0001"+
-    "\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001"+
-    "\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0015\u0001\u0015\u0001"+
-    "\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001"+
-    "\u0015\u0001\u0015\u0001\u0015\u0001\u0016\u0001\u0016\u0001\u0016\u0001"+
-    "\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001"+
-    "\u0016\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001"+
-    "\u0017\u0001\u0017\u0001\u0017\u0001\u0018\u0001\u0018\u0001\u0018\u0001"+
-    "\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0019\u0001"+
-    "\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001"+
-    "\u0019\u0001\u0019\u0001\u001a\u0004\u001a\u02ea\b\u001a\u000b\u001a\f"+
-    "\u001a\u02eb\u0001\u001a\u0001\u001a\u0001\u001b\u0001\u001b\u0001\u001b"+
-    "\u0001\u001b\u0005\u001b\u02f4\b\u001b\n\u001b\f\u001b\u02f7\t\u001b\u0001"+
-    "\u001b\u0003\u001b\u02fa\b\u001b\u0001\u001b\u0003\u001b\u02fd\b\u001b"+
-    "\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001\u001c\u0001\u001c"+
-    "\u0001\u001c\u0005\u001c\u0306\b\u001c\n\u001c\f\u001c\u0309\t\u001c\u0001"+
-    "\u001c\u0001\u001c\u0001\u001c\u0001\u001c\u0001\u001c\u0001\u001d\u0004"+
-    "\u001d\u0311\b\u001d\u000b\u001d\f\u001d\u0312\u0001\u001d\u0001\u001d"+
-    "\u0001\u001e\u0001\u001e\u0001\u001e\u0001\u001e\u0001\u001f\u0001\u001f"+
-    "\u0001 \u0001 \u0001!\u0001!\u0001!\u0001\"\u0001\"\u0001#\u0001#\u0003"+
-    "#\u0326\b#\u0001#\u0004#\u0329\b#\u000b#\f#\u032a\u0001$\u0001$\u0001"+
-    "%\u0001%\u0001&\u0001&\u0001&\u0003&\u0334\b&\u0001\'\u0001\'\u0001(\u0001"+
-    "(\u0001(\u0003(\u033b\b(\u0001)\u0001)\u0001)\u0005)\u0340\b)\n)\f)\u0343"+
-    "\t)\u0001)\u0001)\u0001)\u0001)\u0001)\u0001)\u0005)\u034b\b)\n)\f)\u034e"+
-    "\t)\u0001)\u0001)\u0001)\u0001)\u0001)\u0003)\u0355\b)\u0001)\u0003)\u0358"+
-    "\b)\u0003)\u035a\b)\u0001*\u0004*\u035d\b*\u000b*\f*\u035e\u0001+\u0004"+
-    "+\u0362\b+\u000b+\f+\u0363\u0001+\u0001+\u0005+\u0368\b+\n+\f+\u036b\t"+
-    "+\u0001+\u0001+\u0004+\u036f\b+\u000b+\f+\u0370\u0001+\u0004+\u0374\b"+
-    "+\u000b+\f+\u0375\u0001+\u0001+\u0005+\u037a\b+\n+\f+\u037d\t+\u0003+"+
-    "\u037f\b+\u0001+\u0001+\u0001+\u0001+\u0004+\u0385\b+\u000b+\f+\u0386"+
-    "\u0001+\u0001+\u0003+\u038b\b+\u0001,\u0001,\u0001,\u0001,\u0001-\u0001"+
-    "-\u0001-\u0001-\u0001.\u0001.\u0001/\u0001/\u0001/\u00010\u00010\u0001"+
-    "0\u00011\u00011\u00012\u00012\u00013\u00013\u00013\u00013\u00013\u0001"+
-    "4\u00014\u00015\u00015\u00015\u00015\u00015\u00015\u00016\u00016\u0001"+
-    "6\u00016\u00016\u00016\u00017\u00017\u00017\u00018\u00018\u00018\u0001"+
-    "9\u00019\u00019\u00019\u00019\u0001:\u0001:\u0001:\u0001:\u0001:\u0001"+
-    ";\u0001;\u0001<\u0001<\u0001<\u0001<\u0001=\u0001=\u0001=\u0001=\u0001"+
-    "=\u0001>\u0001>\u0001>\u0001>\u0001>\u0001>\u0001?\u0001?\u0001?\u0001"+
-    "@\u0001@\u0001@\u0001A\u0001A\u0001B\u0001B\u0001B\u0001B\u0001B\u0001"+
-    "B\u0001C\u0001C\u0001D\u0001D\u0001D\u0001D\u0001D\u0001E\u0001E\u0001"+
-    "E\u0001E\u0001E\u0001F\u0001F\u0001F\u0001G\u0001G\u0001G\u0001H\u0001"+
-    "H\u0001H\u0001I\u0001I\u0001J\u0001J\u0001J\u0001K\u0001K\u0001L\u0001"+
-    "L\u0001L\u0001M\u0001M\u0001N\u0001N\u0001O\u0001O\u0001P\u0001P\u0001"+
-    "Q\u0001Q\u0001R\u0001R\u0001S\u0001S\u0001T\u0001T\u0001T\u0001U\u0001"+
-    "U\u0001U\u0001U\u0001V\u0001V\u0001V\u0003V\u041a\bV\u0001V\u0005V\u041d"+
-    "\bV\nV\fV\u0420\tV\u0001V\u0001V\u0004V\u0424\bV\u000bV\fV\u0425\u0003"+
-    "V\u0428\bV\u0001W\u0001W\u0001W\u0003W\u042d\bW\u0001W\u0005W\u0430\b"+
-    "W\nW\fW\u0433\tW\u0001W\u0001W\u0004W\u0437\bW\u000bW\fW\u0438\u0003W"+
-    "\u043b\bW\u0001X\u0001X\u0001X\u0001X\u0001X\u0001Y\u0001Y\u0001Y\u0001"+
-    "Y\u0001Y\u0001Z\u0001Z\u0005Z\u0449\bZ\nZ\fZ\u044c\tZ\u0001Z\u0001Z\u0003"+
-    "Z\u0450\bZ\u0001Z\u0004Z\u0453\bZ\u000bZ\fZ\u0454\u0003Z\u0457\bZ\u0001"+
-    "[\u0001[\u0004[\u045b\b[\u000b[\f[\u045c\u0001[\u0001[\u0001\\\u0001\\"+
-    "\u0001]\u0001]\u0001]\u0001]\u0001^\u0001^\u0001^\u0001^\u0001_\u0001"+
-    "_\u0001_\u0001_\u0001`\u0001`\u0001`\u0001`\u0001`\u0001a\u0001a\u0001"+
-    "a\u0001a\u0001a\u0001b\u0001b\u0001b\u0001b\u0001c\u0001c\u0001c\u0001"+
-    "c\u0001d\u0001d\u0001d\u0001d\u0001e\u0001e\u0001e\u0001e\u0001e\u0001"+
-    "f\u0001f\u0001f\u0001f\u0001g\u0001g\u0001g\u0001g\u0001h\u0001h\u0001"+
-    "h\u0001h\u0001i\u0001i\u0001i\u0001i\u0001j\u0001j\u0001j\u0001j\u0001"+
-    "k\u0001k\u0001k\u0001k\u0001l\u0001l\u0001l\u0001l\u0001l\u0001l\u0001"+
-    "l\u0001l\u0001l\u0001m\u0001m\u0001m\u0003m\u04ae\bm\u0001n\u0004n\u04b1"+
-    "\bn\u000bn\fn\u04b2\u0001o\u0001o\u0001o\u0001o\u0001p\u0001p\u0001p\u0001"+
-    "p\u0001q\u0001q\u0001q\u0001q\u0001r\u0001r\u0001r\u0001r\u0001s\u0001"+
-    "s\u0001s\u0001s\u0001t\u0001t\u0001t\u0001t\u0001t\u0001u\u0001u\u0001"+
-    "u\u0001u\u0001v\u0001v\u0001v\u0001v\u0001w\u0001w\u0001w\u0001w\u0001"+
-    "x\u0001x\u0001x\u0001x\u0001y\u0001y\u0001y\u0001y\u0001z\u0001z\u0001"+
-    "z\u0001z\u0001{\u0001{\u0001{\u0001{\u0003{\u04ea\b{\u0001|\u0001|\u0003"+
-    "|\u04ee\b|\u0001|\u0005|\u04f1\b|\n|\f|\u04f4\t|\u0001|\u0001|\u0003|"+
-    "\u04f8\b|\u0001|\u0004|\u04fb\b|\u000b|\f|\u04fc\u0003|\u04ff\b|\u0001"+
-    "}\u0001}\u0004}\u0503\b}\u000b}\f}\u0504\u0001~\u0001~\u0001~\u0001~\u0001"+
-    "\u007f\u0001\u007f\u0001\u007f\u0001\u007f\u0001\u0080\u0001\u0080\u0001"+
-    "\u0080\u0001\u0080\u0001\u0081\u0001\u0081\u0001\u0081\u0001\u0081\u0001"+
-    "\u0081\u0001\u0082\u0001\u0082\u0001\u0082\u0001\u0082\u0001\u0083\u0001"+
-    "\u0083\u0001\u0083\u0001\u0083\u0001\u0084\u0001\u0084\u0001\u0084\u0001"+
-    "\u0084\u0001\u0085\u0001\u0085\u0001\u0085\u0001\u0085\u0001\u0086\u0001"+
-    "\u0086\u0001\u0086\u0001\u0086\u0001\u0087\u0001\u0087\u0001\u0087\u0001"+
-    "\u0087\u0001\u0088\u0001\u0088\u0001\u0088\u0001\u0088\u0001\u0089\u0001"+
-    "\u0089\u0001\u0089\u0001\u008a\u0001\u008a\u0001\u008a\u0001\u008a\u0001"+
-    "\u008b\u0001\u008b\u0001\u008b\u0001\u008b\u0001\u008c\u0001\u008c\u0001"+
-    "\u008c\u0001\u008c\u0001\u008d\u0001\u008d\u0001\u008d\u0001\u008d\u0001"+
-    "\u008e\u0001\u008e\u0001\u008e\u0001\u008e\u0001\u008e\u0001\u008f\u0001"+
-    "\u008f\u0001\u008f\u0001\u008f\u0001\u008f\u0001\u0090\u0001\u0090\u0001"+
-    "\u0090\u0001\u0090\u0001\u0090\u0001\u0091\u0001\u0091\u0001\u0091\u0001"+
-    "\u0091\u0001\u0091\u0001\u0092\u0001\u0092\u0001\u0093\u0004\u0093\u055e"+
-    "\b\u0093\u000b\u0093\f\u0093\u055f\u0001\u0093\u0001\u0093\u0003\u0093"+
-    "\u0564\b\u0093\u0001\u0093\u0004\u0093\u0567\b\u0093\u000b\u0093\f\u0093"+
-    "\u0568\u0001\u0094\u0001\u0094\u0001\u0094\u0001\u0094\u0001\u0095\u0001"+
-    "\u0095\u0001\u0095\u0001\u0095\u0001\u0096\u0001\u0096\u0001\u0096\u0001"+
-    "\u0096\u0001\u0097\u0001\u0097\u0001\u0097\u0001\u0097\u0001\u0098\u0001"+
-    "\u0098\u0001\u0098\u0001\u0098\u0001\u0098\u0001\u0098\u0001\u0099\u0001"+
-    "\u0099\u0001\u0099\u0001\u0099\u0001\u009a\u0001\u009a\u0001\u009a\u0001"+
-    "\u009a\u0001\u009b\u0001\u009b\u0001\u009b\u0001\u009b\u0001\u009c\u0001"+
-    "\u009c\u0001\u009c\u0001\u009c\u0001\u009d\u0001\u009d\u0001\u009d\u0001"+
-    "\u009d\u0001\u009e\u0001\u009e\u0001\u009e\u0001\u009e\u0001\u009f\u0001"+
-    "\u009f\u0001\u009f\u0001\u009f\u0001\u00a0\u0001\u00a0\u0001\u00a0\u0001"+
-    "\u00a0\u0001\u00a1\u0001\u00a1\u0001\u00a1\u0001\u00a1\u0001\u00a2\u0001"+
-    "\u00a2\u0001\u00a2\u0001\u00a2\u0001\u00a3\u0001\u00a3\u0001\u00a3\u0001"+
-    "\u00a3\u0001\u00a4\u0001\u00a4\u0001\u00a4\u0001\u00a4\u0001\u00a5\u0001"+
-    "\u00a5\u0001\u00a5\u0001\u00a5\u0001\u00a6\u0001\u00a6\u0001\u00a6\u0001"+
-    "\u00a6\u0001\u00a6\u0001\u00a7\u0001\u00a7\u0001\u00a7\u0001\u00a7\u0001"+
-    "\u00a8\u0001\u00a8\u0001\u00a8\u0001\u00a8\u0001\u00a9\u0001\u00a9\u0001"+
-    "\u00a9\u0001\u00a9\u0001\u00aa\u0001\u00aa\u0001\u00aa\u0001\u00aa\u0001"+
-    "\u00ab\u0001\u00ab\u0001\u00ab\u0001\u00ab\u0001\u00ac\u0001\u00ac\u0001"+
-    "\u00ac\u0001\u00ac\u0001\u00ad\u0001\u00ad\u0001\u00ad\u0001\u00ad\u0001"+
-    "\u00ae\u0001\u00ae\u0001\u00ae\u0001\u00ae\u0001\u00af\u0001\u00af\u0001"+
-    "\u00af\u0001\u00af\u0001\u00b0\u0001\u00b0\u0001\u00b0\u0001\u00b0\u0001"+
-    "\u00b1\u0001\u00b1\u0001\u00b1\u0001\u00b1\u0001\u00b1\u0001\u00b2\u0001"+
-    "\u00b2\u0001\u00b2\u0001\u00b2\u0001\u00b2\u0001\u00b3\u0001\u00b3\u0001"+
-    "\u00b3\u0001\u00b3\u0001\u00b4\u0001\u00b4\u0001\u00b4\u0001\u00b4\u0001"+
-    "\u00b5\u0001\u00b5\u0001\u00b5\u0001\u00b5\u0001\u00b6\u0001\u00b6\u0001"+
-    "\u00b6\u0001\u00b6\u0001\u00b6\u0001\u00b7\u0001\u00b7\u0001\u00b7\u0001"+
-    "\u00b7\u0001\u00b8\u0001\u00b8\u0001\u00b8\u0001\u00b8\u0001\u00b8\u0004"+
-    "\u00b8\u0606\b\u00b8\u000b\u00b8\f\u00b8\u0607\u0001\u00b9\u0001\u00b9"+
-    "\u0001\u00b9\u0001\u00b9\u0001\u00ba\u0001\u00ba\u0001\u00ba\u0001\u00ba"+
-    "\u0001\u00bb\u0001\u00bb\u0001\u00bb\u0001\u00bb\u0001\u00bc\u0001\u00bc"+
-    "\u0001\u00bc\u0001\u00bc\u0001\u00bc\u0001\u00bd\u0001\u00bd\u0001\u00bd"+
-    "\u0001\u00bd\u0001\u00be\u0001\u00be\u0001\u00be\u0001\u00be\u0001\u00bf"+
-    "\u0001\u00bf\u0001\u00bf\u0001\u00bf\u0001\u00c0\u0001\u00c0\u0001\u00c0"+
-    "\u0001\u00c0\u0001\u00c0\u0001\u00c1\u0001\u00c1\u0001\u00c1\u0001\u00c1"+
-    "\u0001\u00c2\u0001\u00c2\u0001\u00c2\u0001\u00c2\u0001\u00c3\u0001\u00c3"+
-    "\u0001\u00c3\u0001\u00c3\u0001\u00c4\u0001\u00c4\u0001\u00c4\u0001\u00c4"+
-    "\u0001\u00c5\u0001\u00c5\u0001\u00c5\u0001\u00c5\u0001\u00c6\u0001\u00c6"+
-    "\u0001\u00c6\u0001\u00c6\u0001\u00c6\u0001\u00c6\u0001\u00c7\u0001\u00c7"+
-    "\u0001\u00c7\u0001\u00c7\u0001\u00c8\u0001\u00c8\u0001\u00c8\u0001\u00c8"+
-    "\u0001\u00c9\u0001\u00c9\u0001\u00c9\u0001\u00c9\u0001\u00ca\u0001\u00ca"+
-    "\u0001\u00ca\u0001\u00ca\u0001\u00cb\u0001\u00cb\u0001\u00cb\u0001\u00cb"+
-    "\u0001\u00cc\u0001\u00cc\u0001\u00cc\u0001\u00cc\u0001\u00cd\u0001\u00cd"+
-    "\u0001\u00cd\u0001\u00cd\u0001\u00cd\u0001\u00ce\u0001\u00ce\u0001\u00ce"+
-    "\u0001\u00ce\u0001\u00ce\u0001\u00cf\u0001\u00cf\u0001\u00cf\u0001\u00cf"+
-    "\u0001\u00d0\u0001\u00d0\u0001\u00d0\u0001\u00d0\u0001\u00d0\u0001\u00d0"+
-    "\u0001\u00d1\u0001\u00d1\u0001\u00d1\u0001\u00d1\u0001\u00d1\u0001\u00d1"+
-    "\u0001\u00d1\u0001\u00d1\u0001\u00d1\u0001\u00d2\u0001\u00d2\u0001\u00d2"+
-    "\u0001\u00d2\u0001\u00d3\u0001\u00d3\u0001\u00d3\u0001\u00d3\u0001\u00d4"+
-    "\u0001\u00d4\u0001\u00d4\u0001\u00d4\u0001\u00d5\u0001\u00d5\u0001\u00d5"+
-    "\u0001\u00d5\u0001\u00d6\u0001\u00d6\u0001\u00d6\u0001\u00d6\u0001\u00d7"+
-    "\u0001\u00d7\u0001\u00d7\u0001\u00d7\u0001\u00d8\u0001\u00d8\u0001\u00d8"+
-    "\u0001\u00d8\u0001\u00d9\u0001\u00d9\u0001\u00d9\u0001\u00d9\u0001\u00da"+
-    "\u0001\u00da\u0001\u00da\u0001\u00da\u0001\u00da\u0001\u00db\u0001\u00db"+
-    "\u0001\u00db\u0001\u00db\u0001\u00db\u0001\u00db\u0001\u00dc\u0001\u00dc"+
-    "\u0001\u00dc\u0001\u00dc\u0001\u00dc\u0001\u00dc\u0001\u00dd\u0001\u00dd"+
-    "\u0001\u00dd\u0001\u00dd\u0001\u00de\u0001\u00de\u0001\u00de\u0001\u00de"+
-    "\u0001\u00df\u0001\u00df\u0001\u00df\u0001\u00df\u0001\u00e0\u0001\u00e0"+
-    "\u0001\u00e0\u0001\u00e0\u0001\u00e0\u0001\u00e0\u0001\u00e1\u0001\u00e1"+
-    "\u0001\u00e1\u0001\u00e1\u0001\u00e1\u0001\u00e1\u0001\u00e2\u0001\u00e2"+
-    "\u0001\u00e2\u0001\u00e2\u0001\u00e2\u0001\u00e2\u0001\u00e3\u0001\u00e3"+
-    "\u0001\u00e3\u0001\u00e3\u0001\u00e4\u0001\u00e4\u0001\u00e4\u0001\u00e4"+
-    "\u0001\u00e5\u0001\u00e5\u0001\u00e5\u0001\u00e5\u0001\u00e6\u0001\u00e6"+
-    "\u0001\u00e6\u0001\u00e6\u0001\u00e6\u0001\u00e6\u0001\u00e7\u0001\u00e7"+
-    "\u0001\u00e7\u0001\u00e7\u0001\u00e7\u0001\u00e7\u0001\u00e8\u0001\u00e8"+
-    "\u0001\u00e8\u0001\u00e8\u0001\u00e8\u0001\u00e8\u0001\u00e9\u0001\u00e9"+
-    "\u0001\u00e9\u0001\u00e9\u0001\u00e9\u0001\u00ea\u0001\u00ea\u0001\u00ea"+
-    "\u0001\u00ea\u0001\u00ea\u0001\u00eb\u0001\u00eb\u0001\u00eb\u0001\u00eb"+
-    "\u0001\u00ec\u0001\u00ec\u0001\u00ec\u0001\u00ec\u0001\u00ed\u0001\u00ed"+
-    "\u0001\u00ed\u0001\u00ed\u0001\u00ee\u0001\u00ee\u0001\u00ee\u0001\u00ee"+
-    "\u0001\u00ef\u0001\u00ef\u0001\u00ef\u0001\u00ef\u0001\u00f0\u0001\u00f0"+
-    "\u0001\u00f0\u0001\u00f0\u0001\u00f1\u0001\u00f1\u0001\u00f1\u0001\u00f1"+
-    "\u0001\u00f2\u0001\u00f2\u0001\u00f2\u0001\u00f2\u0001\u00f3\u0001\u00f3"+
-    "\u0001\u00f3\u0001\u00f3\u0002\u0307\u034c\u0000\u00f4\u0011\u0001\u0013"+
-    "\u0002\u0015\u0003\u0017\u0004\u0019\u0005\u001b\u0006\u001d\u0007\u001f"+
-    "\b!\t#\n%\u000b\'\f)\r+\u000e-\u000f/\u00101\u00113\u00125\u00137\u0014"+
-    "9\u0015;\u0016=\u0017?\u0018A\u0019C\u001aE\u001bG\u001cI\u001dK\u001e"+
-    "M\u001fO\u0000Q\u0000S\u0000U\u0000W\u0000Y\u0000[\u0000]\u0000_\u0000"+
-    "a\u0000c e!g\"i#k$m%o&q\'s(u)w*y+{,}-\u007f.\u0081/\u00830\u00851\u0087"+
-    "2\u00893\u008b4\u008d5\u008f6\u00917\u00938\u00959\u0097:\u0099;\u009b"+
-    "<\u009d=\u009f>\u00a1?\u00a3@\u00a5A\u00a7B\u00a9C\u00abD\u00adE\u00af"+
-    "F\u00b1G\u00b3H\u00b5I\u00b7J\u00b9K\u00bb\u0000\u00bdL\u00bfM\u00c1N"+
-    "\u00c3O\u00c5P\u00c7\u0000\u00c9Q\u00cbR\u00cdS\u00cfT\u00d1\u0000\u00d3"+
-    "\u0000\u00d5U\u00d7V\u00d9W\u00db\u0000\u00dd\u0000\u00df\u0000\u00e1"+
-    "\u0000\u00e3\u0000\u00e5\u0000\u00e7\u0000\u00e9X\u00eb\u0000\u00edY\u00ef"+
-    "\u0000\u00f1\u0000\u00f3Z\u00f5[\u00f7\\\u00f9\u0000\u00fb\u0000\u00fd"+
+    "\u0001\u0005\u0001\u0005\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006"+
+    "\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0007\u0001\u0007\u0001\u0007"+
+    "\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\b\u0001\b\u0001"+
+    "\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+
+    "\t\u0001\t\u0001\t\u0001\t\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001"+
+    "\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\u000b\u0001\u000b"+
+    "\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b"+
+    "\u0001\u000b\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\r\u0001"+
+    "\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\u000e"+
+    "\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e"+
+    "\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f"+
+    "\u0001\u000f\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010"+
+    "\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0011\u0001\u0011\u0001\u0011"+
+    "\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0012"+
+    "\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012"+
+    "\u0001\u0012\u0001\u0012\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013"+
+    "\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013"+
+    "\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0014"+
+    "\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014"+
+    "\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014"+
+    "\u0001\u0014\u0001\u0014\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015"+
+    "\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015"+
+    "\u0001\u0015\u0001\u0015\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016"+
+    "\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016"+
+    "\u0001\u0016\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017"+
+    "\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0018"+
+    "\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018"+
+    "\u0001\u0018\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019"+
+    "\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u001a\u0001\u001a\u0001\u001a"+
+    "\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a"+
+    "\u0001\u001b\u0004\u001b\u02f5\b\u001b\u000b\u001b\f\u001b\u02f6\u0001"+
+    "\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001\u001c\u0001\u001c\u0005"+
+    "\u001c\u02ff\b\u001c\n\u001c\f\u001c\u0302\t\u001c\u0001\u001c\u0003\u001c"+
+    "\u0305\b\u001c\u0001\u001c\u0003\u001c\u0308\b\u001c\u0001\u001c\u0001"+
+    "\u001c\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0005"+
+    "\u001d\u0311\b\u001d\n\u001d\f\u001d\u0314\t\u001d\u0001\u001d\u0001\u001d"+
+    "\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001e\u0004\u001e\u031c\b\u001e"+
+    "\u000b\u001e\f\u001e\u031d\u0001\u001e\u0001\u001e\u0001\u001f\u0001\u001f"+
+    "\u0001\u001f\u0001\u001f\u0001 \u0001 \u0001!\u0001!\u0001\"\u0001\"\u0001"+
+    "\"\u0001#\u0001#\u0001$\u0001$\u0003$\u0331\b$\u0001$\u0004$\u0334\b$"+
+    "\u000b$\f$\u0335\u0001%\u0001%\u0001&\u0001&\u0001\'\u0001\'\u0001\'\u0003"+
+    "\'\u033f\b\'\u0001(\u0001(\u0001)\u0001)\u0001)\u0003)\u0346\b)\u0001"+
+    "*\u0001*\u0001*\u0005*\u034b\b*\n*\f*\u034e\t*\u0001*\u0001*\u0001*\u0001"+
+    "*\u0001*\u0001*\u0005*\u0356\b*\n*\f*\u0359\t*\u0001*\u0001*\u0001*\u0001"+
+    "*\u0001*\u0003*\u0360\b*\u0001*\u0003*\u0363\b*\u0003*\u0365\b*\u0001"+
+    "+\u0004+\u0368\b+\u000b+\f+\u0369\u0001,\u0004,\u036d\b,\u000b,\f,\u036e"+
+    "\u0001,\u0001,\u0005,\u0373\b,\n,\f,\u0376\t,\u0001,\u0001,\u0004,\u037a"+
+    "\b,\u000b,\f,\u037b\u0001,\u0004,\u037f\b,\u000b,\f,\u0380\u0001,\u0001"+
+    ",\u0005,\u0385\b,\n,\f,\u0388\t,\u0003,\u038a\b,\u0001,\u0001,\u0001,"+
+    "\u0001,\u0004,\u0390\b,\u000b,\f,\u0391\u0001,\u0001,\u0003,\u0396\b,"+
+    "\u0001-\u0001-\u0001-\u0001-\u0001.\u0001.\u0001.\u0001.\u0001/\u0001"+
+    "/\u00010\u00010\u00010\u00011\u00011\u00011\u00012\u00012\u00013\u0001"+
+    "3\u00014\u00014\u00014\u00014\u00014\u00015\u00015\u00016\u00016\u0001"+
+    "6\u00016\u00016\u00016\u00017\u00017\u00017\u00017\u00017\u00017\u0001"+
+    "8\u00018\u00018\u00019\u00019\u00019\u0001:\u0001:\u0001:\u0001:\u0001"+
+    ":\u0001;\u0001;\u0001;\u0001;\u0001;\u0001<\u0001<\u0001=\u0001=\u0001"+
+    "=\u0001=\u0001>\u0001>\u0001>\u0001>\u0001>\u0001?\u0001?\u0001?\u0001"+
+    "?\u0001?\u0001?\u0001@\u0001@\u0001@\u0001A\u0001A\u0001A\u0001B\u0001"+
+    "B\u0001C\u0001C\u0001C\u0001C\u0001C\u0001C\u0001D\u0001D\u0001E\u0001"+
+    "E\u0001E\u0001E\u0001E\u0001F\u0001F\u0001F\u0001F\u0001F\u0001G\u0001"+
+    "G\u0001G\u0001H\u0001H\u0001H\u0001I\u0001I\u0001I\u0001J\u0001J\u0001"+
+    "K\u0001K\u0001K\u0001L\u0001L\u0001M\u0001M\u0001M\u0001N\u0001N\u0001"+
+    "O\u0001O\u0001P\u0001P\u0001Q\u0001Q\u0001R\u0001R\u0001S\u0001S\u0001"+
+    "T\u0001T\u0001U\u0001U\u0001U\u0001V\u0001V\u0001V\u0001V\u0001W\u0001"+
+    "W\u0001W\u0003W\u0425\bW\u0001W\u0005W\u0428\bW\nW\fW\u042b\tW\u0001W"+
+    "\u0001W\u0004W\u042f\bW\u000bW\fW\u0430\u0003W\u0433\bW\u0001X\u0001X"+
+    "\u0001X\u0003X\u0438\bX\u0001X\u0005X\u043b\bX\nX\fX\u043e\tX\u0001X\u0001"+
+    "X\u0004X\u0442\bX\u000bX\fX\u0443\u0003X\u0446\bX\u0001Y\u0001Y\u0001"+
+    "Y\u0001Y\u0001Y\u0001Z\u0001Z\u0001Z\u0001Z\u0001Z\u0001[\u0001[\u0005"+
+    "[\u0454\b[\n[\f[\u0457\t[\u0001[\u0001[\u0003[\u045b\b[\u0001[\u0004["+
+    "\u045e\b[\u000b[\f[\u045f\u0003[\u0462\b[\u0001\\\u0001\\\u0004\\\u0466"+
+    "\b\\\u000b\\\f\\\u0467\u0001\\\u0001\\\u0001]\u0001]\u0001^\u0001^\u0001"+
+    "^\u0001^\u0001_\u0001_\u0001_\u0001_\u0001`\u0001`\u0001`\u0001`\u0001"+
+    "a\u0001a\u0001a\u0001a\u0001a\u0001b\u0001b\u0001b\u0001b\u0001b\u0001"+
+    "c\u0001c\u0001c\u0001c\u0001d\u0001d\u0001d\u0001d\u0001e\u0001e\u0001"+
+    "e\u0001e\u0001f\u0001f\u0001f\u0001f\u0001f\u0001g\u0001g\u0001g\u0001"+
+    "g\u0001h\u0001h\u0001h\u0001h\u0001i\u0001i\u0001i\u0001i\u0001j\u0001"+
+    "j\u0001j\u0001j\u0001k\u0001k\u0001k\u0001k\u0001l\u0001l\u0001l\u0001"+
+    "l\u0001m\u0001m\u0001m\u0001m\u0001m\u0001m\u0001m\u0001m\u0001m\u0001"+
+    "n\u0001n\u0001n\u0003n\u04b9\bn\u0001o\u0004o\u04bc\bo\u000bo\fo\u04bd"+
+    "\u0001p\u0001p\u0001p\u0001p\u0001q\u0001q\u0001q\u0001q\u0001r\u0001"+
+    "r\u0001r\u0001r\u0001s\u0001s\u0001s\u0001s\u0001t\u0001t\u0001t\u0001"+
+    "t\u0001u\u0001u\u0001u\u0001u\u0001u\u0001v\u0001v\u0001v\u0001v\u0001"+
+    "w\u0001w\u0001w\u0001w\u0001x\u0001x\u0001x\u0001x\u0001y\u0001y\u0001"+
+    "y\u0001y\u0001z\u0001z\u0001z\u0001z\u0001{\u0001{\u0001{\u0001{\u0001"+
+    "|\u0001|\u0001|\u0001|\u0003|\u04f5\b|\u0001}\u0001}\u0003}\u04f9\b}\u0001"+
+    "}\u0005}\u04fc\b}\n}\f}\u04ff\t}\u0001}\u0001}\u0003}\u0503\b}\u0001}"+
+    "\u0004}\u0506\b}\u000b}\f}\u0507\u0003}\u050a\b}\u0001~\u0001~\u0004~"+
+    "\u050e\b~\u000b~\f~\u050f\u0001\u007f\u0001\u007f\u0001\u007f\u0001\u007f"+
+    "\u0001\u0080\u0001\u0080\u0001\u0080\u0001\u0080\u0001\u0081\u0001\u0081"+
+    "\u0001\u0081\u0001\u0081\u0001\u0082\u0001\u0082\u0001\u0082\u0001\u0082"+
+    "\u0001\u0082\u0001\u0083\u0001\u0083\u0001\u0083\u0001\u0083\u0001\u0084"+
+    "\u0001\u0084\u0001\u0084\u0001\u0084\u0001\u0085\u0001\u0085\u0001\u0085"+
+    "\u0001\u0085\u0001\u0086\u0001\u0086\u0001\u0086\u0001\u0086\u0001\u0087"+
+    "\u0001\u0087\u0001\u0087\u0001\u0087\u0001\u0088\u0001\u0088\u0001\u0088"+
+    "\u0001\u0088\u0001\u0089\u0001\u0089\u0001\u0089\u0001\u0089\u0001\u008a"+
+    "\u0001\u008a\u0001\u008a\u0001\u008b\u0001\u008b\u0001\u008b\u0001\u008b"+
+    "\u0001\u008c\u0001\u008c\u0001\u008c\u0001\u008c\u0001\u008d\u0001\u008d"+
+    "\u0001\u008d\u0001\u008d\u0001\u008e\u0001\u008e\u0001\u008e\u0001\u008e"+
+    "\u0001\u008f\u0001\u008f\u0001\u008f\u0001\u008f\u0001\u008f\u0001\u0090"+
+    "\u0001\u0090\u0001\u0090\u0001\u0090\u0001\u0090\u0001\u0091\u0001\u0091"+
+    "\u0001\u0091\u0001\u0091\u0001\u0091\u0001\u0092\u0001\u0092\u0001\u0092"+
+    "\u0001\u0092\u0001\u0092\u0001\u0093\u0001\u0093\u0001\u0094\u0004\u0094"+
+    "\u0569\b\u0094\u000b\u0094\f\u0094\u056a\u0001\u0094\u0001\u0094\u0003"+
+    "\u0094\u056f\b\u0094\u0001\u0094\u0004\u0094\u0572\b\u0094\u000b\u0094"+
+    "\f\u0094\u0573\u0001\u0095\u0001\u0095\u0001\u0095\u0001\u0095\u0001\u0096"+
+    "\u0001\u0096\u0001\u0096\u0001\u0096\u0001\u0097\u0001\u0097\u0001\u0097"+
+    "\u0001\u0097\u0001\u0098\u0001\u0098\u0001\u0098\u0001\u0098\u0001\u0099"+
+    "\u0001\u0099\u0001\u0099\u0001\u0099\u0001\u0099\u0001\u0099\u0001\u009a"+
+    "\u0001\u009a\u0001\u009a\u0001\u009a\u0001\u009b\u0001\u009b\u0001\u009b"+
+    "\u0001\u009b\u0001\u009c\u0001\u009c\u0001\u009c\u0001\u009c\u0001\u009d"+
+    "\u0001\u009d\u0001\u009d\u0001\u009d\u0001\u009e\u0001\u009e\u0001\u009e"+
+    "\u0001\u009e\u0001\u009f\u0001\u009f\u0001\u009f\u0001\u009f\u0001\u00a0"+
+    "\u0001\u00a0\u0001\u00a0\u0001\u00a0\u0001\u00a1\u0001\u00a1\u0001\u00a1"+
+    "\u0001\u00a1\u0001\u00a2\u0001\u00a2\u0001\u00a2\u0001\u00a2\u0001\u00a3"+
+    "\u0001\u00a3\u0001\u00a3\u0001\u00a3\u0001\u00a4\u0001\u00a4\u0001\u00a4"+
+    "\u0001\u00a4\u0001\u00a5\u0001\u00a5\u0001\u00a5\u0001\u00a5\u0001\u00a6"+
+    "\u0001\u00a6\u0001\u00a6\u0001\u00a6\u0001\u00a7\u0001\u00a7\u0001\u00a7"+
+    "\u0001\u00a7\u0001\u00a7\u0001\u00a8\u0001\u00a8\u0001\u00a8\u0001\u00a8"+
+    "\u0001\u00a9\u0001\u00a9\u0001\u00a9\u0001\u00a9\u0001\u00aa\u0001\u00aa"+
+    "\u0001\u00aa\u0001\u00aa\u0001\u00ab\u0001\u00ab\u0001\u00ab\u0001\u00ab"+
+    "\u0001\u00ac\u0001\u00ac\u0001\u00ac\u0001\u00ac\u0001\u00ad\u0001\u00ad"+
+    "\u0001\u00ad\u0001\u00ad\u0001\u00ae\u0001\u00ae\u0001\u00ae\u0001\u00ae"+
+    "\u0001\u00af\u0001\u00af\u0001\u00af\u0001\u00af\u0001\u00b0\u0001\u00b0"+
+    "\u0001\u00b0\u0001\u00b0\u0001\u00b1\u0001\u00b1\u0001\u00b1\u0001\u00b1"+
+    "\u0001\u00b2\u0001\u00b2\u0001\u00b2\u0001\u00b2\u0001\u00b2\u0001\u00b3"+
+    "\u0001\u00b3\u0001\u00b3\u0001\u00b3\u0001\u00b3\u0001\u00b4\u0001\u00b4"+
+    "\u0001\u00b4\u0001\u00b4\u0001\u00b5\u0001\u00b5\u0001\u00b5\u0001\u00b5"+
+    "\u0001\u00b6\u0001\u00b6\u0001\u00b6\u0001\u00b6\u0001\u00b7\u0001\u00b7"+
+    "\u0001\u00b7\u0001\u00b7\u0001\u00b7\u0001\u00b8\u0001\u00b8\u0001\u00b8"+
+    "\u0001\u00b8\u0001\u00b9\u0001\u00b9\u0001\u00b9\u0001\u00b9\u0001\u00b9"+
+    "\u0004\u00b9\u0611\b\u00b9\u000b\u00b9\f\u00b9\u0612\u0001\u00ba\u0001"+
+    "\u00ba\u0001\u00ba\u0001\u00ba\u0001\u00bb\u0001\u00bb\u0001\u00bb\u0001"+
+    "\u00bb\u0001\u00bc\u0001\u00bc\u0001\u00bc\u0001\u00bc\u0001\u00bd\u0001"+
+    "\u00bd\u0001\u00bd\u0001\u00bd\u0001\u00bd\u0001\u00be\u0001\u00be\u0001"+
+    "\u00be\u0001\u00be\u0001\u00bf\u0001\u00bf\u0001\u00bf\u0001\u00bf\u0001"+
+    "\u00c0\u0001\u00c0\u0001\u00c0\u0001\u00c0\u0001\u00c1\u0001\u00c1\u0001"+
+    "\u00c1\u0001\u00c1\u0001\u00c1\u0001\u00c2\u0001\u00c2\u0001\u00c2\u0001"+
+    "\u00c2\u0001\u00c3\u0001\u00c3\u0001\u00c3\u0001\u00c3\u0001\u00c4\u0001"+
+    "\u00c4\u0001\u00c4\u0001\u00c4\u0001\u00c5\u0001\u00c5\u0001\u00c5\u0001"+
+    "\u00c5\u0001\u00c6\u0001\u00c6\u0001\u00c6\u0001\u00c6\u0001\u00c7\u0001"+
+    "\u00c7\u0001\u00c7\u0001\u00c7\u0001\u00c7\u0001\u00c7\u0001\u00c8\u0001"+
+    "\u00c8\u0001\u00c8\u0001\u00c8\u0001\u00c9\u0001\u00c9\u0001\u00c9\u0001"+
+    "\u00c9\u0001\u00ca\u0001\u00ca\u0001\u00ca\u0001\u00ca\u0001\u00cb\u0001"+
+    "\u00cb\u0001\u00cb\u0001\u00cb\u0001\u00cc\u0001\u00cc\u0001\u00cc\u0001"+
+    "\u00cc\u0001\u00cd\u0001\u00cd\u0001\u00cd\u0001\u00cd\u0001\u00ce\u0001"+
+    "\u00ce\u0001\u00ce\u0001\u00ce\u0001\u00ce\u0001\u00cf\u0001\u00cf\u0001"+
+    "\u00cf\u0001\u00cf\u0001\u00cf\u0001\u00d0\u0001\u00d0\u0001\u00d0\u0001"+
+    "\u00d0\u0001\u00d1\u0001\u00d1\u0001\u00d1\u0001\u00d1\u0001\u00d1\u0001"+
+    "\u00d1\u0001\u00d2\u0001\u00d2\u0001\u00d2\u0001\u00d2\u0001\u00d2\u0001"+
+    "\u00d2\u0001\u00d2\u0001\u00d2\u0001\u00d2\u0001\u00d3\u0001\u00d3\u0001"+
+    "\u00d3\u0001\u00d3\u0001\u00d4\u0001\u00d4\u0001\u00d4\u0001\u00d4\u0001"+
+    "\u00d5\u0001\u00d5\u0001\u00d5\u0001\u00d5\u0001\u00d6\u0001\u00d6\u0001"+
+    "\u00d6\u0001\u00d6\u0001\u00d7\u0001\u00d7\u0001\u00d7\u0001\u00d7\u0001"+
+    "\u00d8\u0001\u00d8\u0001\u00d8\u0001\u00d8\u0001\u00d9\u0001\u00d9\u0001"+
+    "\u00d9\u0001\u00d9\u0001\u00da\u0001\u00da\u0001\u00da\u0001\u00da\u0001"+
+    "\u00db\u0001\u00db\u0001\u00db\u0001\u00db\u0001\u00db\u0001\u00dc\u0001"+
+    "\u00dc\u0001\u00dc\u0001\u00dc\u0001\u00dc\u0001\u00dc\u0001\u00dd\u0001"+
+    "\u00dd\u0001\u00dd\u0001\u00dd\u0001\u00dd\u0001\u00dd\u0001\u00de\u0001"+
+    "\u00de\u0001\u00de\u0001\u00de\u0001\u00df\u0001\u00df\u0001\u00df\u0001"+
+    "\u00df\u0001\u00e0\u0001\u00e0\u0001\u00e0\u0001\u00e0\u0001\u00e1\u0001"+
+    "\u00e1\u0001\u00e1\u0001\u00e1\u0001\u00e1\u0001\u00e1\u0001\u00e2\u0001"+
+    "\u00e2\u0001\u00e2\u0001\u00e2\u0001\u00e2\u0001\u00e2\u0001\u00e3\u0001"+
+    "\u00e3\u0001\u00e3\u0001\u00e3\u0001\u00e3\u0001\u00e3\u0001\u00e4\u0001"+
+    "\u00e4\u0001\u00e4\u0001\u00e4\u0001\u00e5\u0001\u00e5\u0001\u00e5\u0001"+
+    "\u00e5\u0001\u00e6\u0001\u00e6\u0001\u00e6\u0001\u00e6\u0001\u00e7\u0001"+
+    "\u00e7\u0001\u00e7\u0001\u00e7\u0001\u00e7\u0001\u00e7\u0001\u00e8\u0001"+
+    "\u00e8\u0001\u00e8\u0001\u00e8\u0001\u00e8\u0001\u00e8\u0001\u00e9\u0001"+
+    "\u00e9\u0001\u00e9\u0001\u00e9\u0001\u00e9\u0001\u00e9\u0001\u00ea\u0001"+
+    "\u00ea\u0001\u00ea\u0001\u00ea\u0001\u00ea\u0001\u00eb\u0001\u00eb\u0001"+
+    "\u00eb\u0001\u00eb\u0001\u00eb\u0001\u00ec\u0001\u00ec\u0001\u00ec\u0001"+
+    "\u00ec\u0001\u00ed\u0001\u00ed\u0001\u00ed\u0001\u00ed\u0001\u00ee\u0001"+
+    "\u00ee\u0001\u00ee\u0001\u00ee\u0001\u00ef\u0001\u00ef\u0001\u00ef\u0001"+
+    "\u00ef\u0001\u00f0\u0001\u00f0\u0001\u00f0\u0001\u00f0\u0001\u00f1\u0001"+
+    "\u00f1\u0001\u00f1\u0001\u00f1\u0001\u00f2\u0001\u00f2\u0001\u00f2\u0001"+
+    "\u00f2\u0001\u00f3\u0001\u00f3\u0001\u00f3\u0001\u00f3\u0001\u00f4\u0001"+
+    "\u00f4\u0001\u00f4\u0001\u00f4\u0002\u0312\u0357\u0000\u00f5\u0011\u0001"+
+    "\u0013\u0002\u0015\u0003\u0017\u0004\u0019\u0005\u001b\u0006\u001d\u0007"+
+    "\u001f\b!\t#\n%\u000b\'\f)\r+\u000e-\u000f/\u00101\u00113\u00125\u0013"+
+    "7\u00149\u0015;\u0016=\u0017?\u0018A\u0019C\u001aE\u001bG\u001cI\u001d"+
+    "K\u001eM\u001fO Q\u0000S\u0000U\u0000W\u0000Y\u0000[\u0000]\u0000_\u0000"+
+    "a\u0000c\u0000e!g\"i#k$m%o&q\'s(u)w*y+{,}-\u007f.\u0081/\u00830\u0085"+
+    "1\u00872\u00893\u008b4\u008d5\u008f6\u00917\u00938\u00959\u0097:\u0099"+
+    ";\u009b<\u009d=\u009f>\u00a1?\u00a3@\u00a5A\u00a7B\u00a9C\u00abD\u00ad"+
+    "E\u00afF\u00b1G\u00b3H\u00b5I\u00b7J\u00b9K\u00bbL\u00bd\u0000\u00bfM"+
+    "\u00c1N\u00c3O\u00c5P\u00c7Q\u00c9\u0000\u00cbR\u00cdS\u00cfT\u00d1U\u00d3"+
+    "\u0000\u00d5\u0000\u00d7V\u00d9W\u00dbX\u00dd\u0000\u00df\u0000\u00e1"+
+    "\u0000\u00e3\u0000\u00e5\u0000\u00e7\u0000\u00e9\u0000\u00ebY\u00ed\u0000"+
+    "\u00efZ\u00f1\u0000\u00f3\u0000\u00f5[\u00f7\\\u00f9]\u00fb\u0000\u00fd"+
     "\u0000\u00ff\u0000\u0101\u0000\u0103\u0000\u0105\u0000\u0107\u0000\u0109"+
-    "\u0000\u010b]\u010d^\u010f_\u0111`\u0113\u0000\u0115\u0000\u0117\u0000"+
-    "\u0119\u0000\u011b\u0000\u011d\u0000\u011f\u0000\u0121\u0000\u0123a\u0125"+
-    "\u0000\u0127b\u0129c\u012bd\u012d\u0000\u012f\u0000\u0131\u0000\u0133"+
-    "\u0000\u0135\u0000\u0137e\u0139\u0000\u013bf\u013dg\u013fh\u0141\u0000"+
-    "\u0143\u0000\u0145\u0000\u0147\u0000\u0149\u0000\u014b\u0000\u014d\u0000"+
-    "\u014f\u0000\u0151\u0000\u0153\u0000\u0155\u0000\u0157i\u0159j\u015bk"+
-    "\u015d\u0000\u015f\u0000\u0161\u0000\u0163\u0000\u0165\u0000\u0167\u0000"+
-    "\u0169\u0000\u016b\u0000\u016dl\u016fm\u0171n\u0173\u0000\u0175o\u0177"+
-    "p\u0179q\u017br\u017d\u0000\u017f\u0000\u0181s\u0183t\u0185u\u0187v\u0189"+
-    "\u0000\u018b\u0000\u018d\u0000\u018f\u0000\u0191\u0000\u0193\u0000\u0195"+
-    "\u0000\u0197w\u0199x\u019by\u019d\u0000\u019f\u0000\u01a1\u0000\u01a3"+
-    "\u0000\u01a5z\u01a7{\u01a9|\u01ab\u0000\u01ad}\u01af\u0000\u01b1\u0000"+
-    "\u01b3~\u01b5\u0000\u01b7\u0000\u01b9\u0000\u01bb\u0000\u01bd\u0000\u01bf"+
-    "\u007f\u01c1\u0080\u01c3\u0081\u01c5\u0000\u01c7\u0000\u01c9\u0000\u01cb"+
-    "\u0082\u01cd\u0083\u01cf\u0084\u01d1\u0000\u01d3\u0000\u01d5\u0000\u01d7"+
-    "\u0085\u01d9\u0086\u01db\u0087\u01dd\u0000\u01df\u0000\u01e1\u0000\u01e3"+
+    "\u0000\u010b\u0000\u010d^\u010f_\u0111`\u0113a\u0115\u0000\u0117\u0000"+
+    "\u0119\u0000\u011b\u0000\u011d\u0000\u011f\u0000\u0121\u0000\u0123\u0000"+
+    "\u0125b\u0127\u0000\u0129c\u012bd\u012de\u012f\u0000\u0131\u0000\u0133"+
+    "\u0000\u0135\u0000\u0137\u0000\u0139f\u013b\u0000\u013dg\u013fh\u0141"+
+    "i\u0143\u0000\u0145\u0000\u0147\u0000\u0149\u0000\u014b\u0000\u014d\u0000"+
+    "\u014f\u0000\u0151\u0000\u0153\u0000\u0155\u0000\u0157\u0000\u0159j\u015b"+
+    "k\u015dl\u015f\u0000\u0161\u0000\u0163\u0000\u0165\u0000\u0167\u0000\u0169"+
+    "\u0000\u016b\u0000\u016d\u0000\u016fm\u0171n\u0173o\u0175\u0000\u0177"+
+    "p\u0179q\u017br\u017ds\u017f\u0000\u0181\u0000\u0183t\u0185u\u0187v\u0189"+
+    "w\u018b\u0000\u018d\u0000\u018f\u0000\u0191\u0000\u0193\u0000\u0195\u0000"+
+    "\u0197\u0000\u0199x\u019by\u019dz\u019f\u0000\u01a1\u0000\u01a3\u0000"+
+    "\u01a5\u0000\u01a7{\u01a9|\u01ab}\u01ad\u0000\u01af~\u01b1\u0000\u01b3"+
+    "\u0000\u01b5\u007f\u01b7\u0000\u01b9\u0000\u01bb\u0000\u01bd\u0000\u01bf"+
+    "\u0000\u01c1\u0080\u01c3\u0081\u01c5\u0082\u01c7\u0000\u01c9\u0000\u01cb"+
+    "\u0000\u01cd\u0083\u01cf\u0084\u01d1\u0085\u01d3\u0000\u01d5\u0000\u01d7"+
+    "\u0000\u01d9\u0086\u01db\u0087\u01dd\u0088\u01df\u0000\u01e1\u0000\u01e3"+
     "\u0000\u01e5\u0000\u01e7\u0000\u01e9\u0000\u01eb\u0000\u01ed\u0000\u01ef"+
-    "\u0000\u01f1\u0000\u01f3\u0088\u01f5\u0089\u01f7\u008a\u0011\u0000\u0001"+
-    "\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010"+
-    "$\u0002\u0000CCcc\u0002\u0000OOoo\u0002\u0000MMmm\u0002\u0000PPpp\u0002"+
-    "\u0000LLll\u0002\u0000EEee\u0002\u0000TTtt\u0002\u0000IIii\u0002\u0000"+
-    "NNnn\u0002\u0000DDdd\u0002\u0000SSss\u0002\u0000RRrr\u0002\u0000HHhh\u0002"+
-    "\u0000VVvv\u0002\u0000AAaa\u0002\u0000XXxx\u0002\u0000FFff\u0002\u0000"+
-    "GGgg\u0002\u0000KKkk\u0002\u0000WWww\u0002\u0000UUuu\u0006\u0000\t\n\r"+
-    "\r  //[[]]\u0002\u0000\n\n\r\r\u0003\u0000\t\n\r\r  \u0001\u000009\u0002"+
-    "\u0000AZaz\b\u0000\"\"NNRRTT\\\\nnrrtt\u0004\u0000\n\n\r\r\"\"\\\\\u0002"+
-    "\u0000++--\u0001\u0000``\u0002\u0000BBbb\u0002\u0000YYyy\u000b\u0000\t"+
-    "\n\r\r  \"\",,//::==[[]]||\u0002\u0000**//\u000b\u0000\t\n\r\r  \"#,,"+
-    "//::<<>?\\\\||\u0002\u0000JJjj\u0733\u0000\u0011\u0001\u0000\u0000\u0000"+
-    "\u0000\u0013\u0001\u0000\u0000\u0000\u0000\u0015\u0001\u0000\u0000\u0000"+
-    "\u0000\u0017\u0001\u0000\u0000\u0000\u0000\u0019\u0001\u0000\u0000\u0000"+
-    "\u0000\u001b\u0001\u0000\u0000\u0000\u0000\u001d\u0001\u0000\u0000\u0000"+
-    "\u0000\u001f\u0001\u0000\u0000\u0000\u0000!\u0001\u0000\u0000\u0000\u0000"+
-    "#\u0001\u0000\u0000\u0000\u0000%\u0001\u0000\u0000\u0000\u0000\'\u0001"+
-    "\u0000\u0000\u0000\u0000)\u0001\u0000\u0000\u0000\u0000+\u0001\u0000\u0000"+
-    "\u0000\u0000-\u0001\u0000\u0000\u0000\u0000/\u0001\u0000\u0000\u0000\u0000"+
-    "1\u0001\u0000\u0000\u0000\u00003\u0001\u0000\u0000\u0000\u00005\u0001"+
-    "\u0000\u0000\u0000\u00007\u0001\u0000\u0000\u0000\u00009\u0001\u0000\u0000"+
-    "\u0000\u0000;\u0001\u0000\u0000\u0000\u0000=\u0001\u0000\u0000\u0000\u0000"+
-    "?\u0001\u0000\u0000\u0000\u0000A\u0001\u0000\u0000\u0000\u0000C\u0001"+
-    "\u0000\u0000\u0000\u0000E\u0001\u0000\u0000\u0000\u0000G\u0001\u0000\u0000"+
-    "\u0000\u0000I\u0001\u0000\u0000\u0000\u0000K\u0001\u0000\u0000\u0000\u0001"+
-    "M\u0001\u0000\u0000\u0000\u0001c\u0001\u0000\u0000\u0000\u0001e\u0001"+
-    "\u0000\u0000\u0000\u0001g\u0001\u0000\u0000\u0000\u0001i\u0001\u0000\u0000"+
-    "\u0000\u0001k\u0001\u0000\u0000\u0000\u0001m\u0001\u0000\u0000\u0000\u0001"+
-    "o\u0001\u0000\u0000\u0000\u0001q\u0001\u0000\u0000\u0000\u0001s\u0001"+
-    "\u0000\u0000\u0000\u0001u\u0001\u0000\u0000\u0000\u0001w\u0001\u0000\u0000"+
-    "\u0000\u0001y\u0001\u0000\u0000\u0000\u0001{\u0001\u0000\u0000\u0000\u0001"+
-    "}\u0001\u0000\u0000\u0000\u0001\u007f\u0001\u0000\u0000\u0000\u0001\u0081"+
-    "\u0001\u0000\u0000\u0000\u0001\u0083\u0001\u0000\u0000\u0000\u0001\u0085"+
-    "\u0001\u0000\u0000\u0000\u0001\u0087\u0001\u0000\u0000\u0000\u0001\u0089"+
-    "\u0001\u0000\u0000\u0000\u0001\u008b\u0001\u0000\u0000\u0000\u0001\u008d"+
-    "\u0001\u0000\u0000\u0000\u0001\u008f\u0001\u0000\u0000\u0000\u0001\u0091"+
-    "\u0001\u0000\u0000\u0000\u0001\u0093\u0001\u0000\u0000\u0000\u0001\u0095"+
-    "\u0001\u0000\u0000\u0000\u0001\u0097\u0001\u0000\u0000\u0000\u0001\u0099"+
-    "\u0001\u0000\u0000\u0000\u0001\u009b\u0001\u0000\u0000\u0000\u0001\u009d"+
-    "\u0001\u0000\u0000\u0000\u0001\u009f\u0001\u0000\u0000\u0000\u0001\u00a1"+
-    "\u0001\u0000\u0000\u0000\u0001\u00a3\u0001\u0000\u0000\u0000\u0001\u00a5"+
-    "\u0001\u0000\u0000\u0000\u0001\u00a7\u0001\u0000\u0000\u0000\u0001\u00a9"+
-    "\u0001\u0000\u0000\u0000\u0001\u00ab\u0001\u0000\u0000\u0000\u0001\u00ad"+
-    "\u0001\u0000\u0000\u0000\u0001\u00af\u0001\u0000\u0000\u0000\u0001\u00b1"+
-    "\u0001\u0000\u0000\u0000\u0001\u00b3\u0001\u0000\u0000\u0000\u0001\u00b5"+
-    "\u0001\u0000\u0000\u0000\u0001\u00b7\u0001\u0000\u0000\u0000\u0001\u00b9"+
-    "\u0001\u0000\u0000\u0000\u0001\u00bb\u0001\u0000\u0000\u0000\u0001\u00bd"+
-    "\u0001\u0000\u0000\u0000\u0001\u00bf\u0001\u0000\u0000\u0000\u0001\u00c1"+
-    "\u0001\u0000\u0000\u0000\u0001\u00c3\u0001\u0000\u0000\u0000\u0001\u00c5"+
-    "\u0001\u0000\u0000\u0000\u0001\u00c9\u0001\u0000\u0000\u0000\u0001\u00cb"+
-    "\u0001\u0000\u0000\u0000\u0001\u00cd\u0001\u0000\u0000\u0000\u0001\u00cf"+
-    "\u0001\u0000\u0000\u0000\u0002\u00d1\u0001\u0000\u0000\u0000\u0002\u00d3"+
-    "\u0001\u0000\u0000\u0000\u0002\u00d5\u0001\u0000\u0000\u0000\u0002\u00d7"+
-    "\u0001\u0000\u0000\u0000\u0002\u00d9\u0001\u0000\u0000\u0000\u0003\u00db"+
-    "\u0001\u0000\u0000\u0000\u0003\u00dd\u0001\u0000\u0000\u0000\u0003\u00df"+
-    "\u0001\u0000\u0000\u0000\u0003\u00e1\u0001\u0000\u0000\u0000\u0003\u00e3"+
-    "\u0001\u0000\u0000\u0000\u0003\u00e5\u0001\u0000\u0000\u0000\u0003\u00e7"+
-    "\u0001\u0000\u0000\u0000\u0003\u00e9\u0001\u0000\u0000\u0000\u0003\u00ed"+
-    "\u0001\u0000\u0000\u0000\u0003\u00ef\u0001\u0000\u0000\u0000\u0003\u00f1"+
-    "\u0001\u0000\u0000\u0000\u0003\u00f3\u0001\u0000\u0000\u0000\u0003\u00f5"+
-    "\u0001\u0000\u0000\u0000\u0003\u00f7\u0001\u0000\u0000\u0000\u0004\u00f9"+
-    "\u0001\u0000\u0000\u0000\u0004\u00fb\u0001\u0000\u0000\u0000\u0004\u00fd"+
-    "\u0001\u0000\u0000\u0000\u0004\u00ff\u0001\u0000\u0000\u0000\u0004\u0101"+
-    "\u0001\u0000\u0000\u0000\u0004\u0103\u0001\u0000\u0000\u0000\u0004\u0105"+
-    "\u0001\u0000\u0000\u0000\u0004\u010b\u0001\u0000\u0000\u0000\u0004\u010d"+
-    "\u0001\u0000\u0000\u0000\u0004\u010f\u0001\u0000\u0000\u0000\u0004\u0111"+
-    "\u0001\u0000\u0000\u0000\u0005\u0113\u0001\u0000\u0000\u0000\u0005\u0115"+
-    "\u0001\u0000\u0000\u0000\u0005\u0117\u0001\u0000\u0000\u0000\u0005\u0119"+
-    "\u0001\u0000\u0000\u0000\u0005\u011b\u0001\u0000\u0000\u0000\u0005\u011d"+
-    "\u0001\u0000\u0000\u0000\u0005\u011f\u0001\u0000\u0000\u0000\u0005\u0121"+
-    "\u0001\u0000\u0000\u0000\u0005\u0123\u0001\u0000\u0000\u0000\u0005\u0125"+
-    "\u0001\u0000\u0000\u0000\u0005\u0127\u0001\u0000\u0000\u0000\u0005\u0129"+
-    "\u0001\u0000\u0000\u0000\u0005\u012b\u0001\u0000\u0000\u0000\u0006\u012d"+
-    "\u0001\u0000\u0000\u0000\u0006\u012f\u0001\u0000\u0000\u0000\u0006\u0131"+
-    "\u0001\u0000\u0000\u0000\u0006\u0133\u0001\u0000\u0000\u0000\u0006\u0137"+
-    "\u0001\u0000\u0000\u0000\u0006\u0139\u0001\u0000\u0000\u0000\u0006\u013b"+
-    "\u0001\u0000\u0000\u0000\u0006\u013d\u0001\u0000\u0000\u0000\u0006\u013f"+
-    "\u0001\u0000\u0000\u0000\u0007\u0141\u0001\u0000\u0000\u0000\u0007\u0143"+
-    "\u0001\u0000\u0000\u0000\u0007\u0145\u0001\u0000\u0000\u0000\u0007\u0147"+
-    "\u0001\u0000\u0000\u0000\u0007\u0149\u0001\u0000\u0000\u0000\u0007\u014b"+
-    "\u0001\u0000\u0000\u0000\u0007\u014d\u0001\u0000\u0000\u0000\u0007\u014f"+
-    "\u0001\u0000\u0000\u0000\u0007\u0151\u0001\u0000\u0000\u0000\u0007\u0153"+
-    "\u0001\u0000\u0000\u0000\u0007\u0155\u0001\u0000\u0000\u0000\u0007\u0157"+
-    "\u0001\u0000\u0000\u0000\u0007\u0159\u0001\u0000\u0000\u0000\u0007\u015b"+
-    "\u0001\u0000\u0000\u0000\b\u015d\u0001\u0000\u0000\u0000\b\u015f\u0001"+
-    "\u0000\u0000\u0000\b\u0161\u0001\u0000\u0000\u0000\b\u0163\u0001\u0000"+
-    "\u0000\u0000\b\u0165\u0001\u0000\u0000\u0000\b\u0167\u0001\u0000\u0000"+
-    "\u0000\b\u0169\u0001\u0000\u0000\u0000\b\u016b\u0001\u0000\u0000\u0000"+
-    "\b\u016d\u0001\u0000\u0000\u0000\b\u016f\u0001\u0000\u0000\u0000\b\u0171"+
-    "\u0001\u0000\u0000\u0000\t\u0173\u0001\u0000\u0000\u0000\t\u0175\u0001"+
-    "\u0000\u0000\u0000\t\u0177\u0001\u0000\u0000\u0000\t\u0179\u0001\u0000"+
-    "\u0000\u0000\t\u017b\u0001\u0000\u0000\u0000\n\u017d\u0001\u0000\u0000"+
-    "\u0000\n\u017f\u0001\u0000\u0000\u0000\n\u0181\u0001\u0000\u0000\u0000"+
-    "\n\u0183\u0001\u0000\u0000\u0000\n\u0185\u0001\u0000\u0000\u0000\n\u0187"+
-    "\u0001\u0000\u0000\u0000\u000b\u0189\u0001\u0000\u0000\u0000\u000b\u018b"+
-    "\u0001\u0000\u0000\u0000\u000b\u018d\u0001\u0000\u0000\u0000\u000b\u018f"+
-    "\u0001\u0000\u0000\u0000\u000b\u0191\u0001\u0000\u0000\u0000\u000b\u0193"+
-    "\u0001\u0000\u0000\u0000\u000b\u0195\u0001\u0000\u0000\u0000\u000b\u0197"+
-    "\u0001\u0000\u0000\u0000\u000b\u0199\u0001\u0000\u0000\u0000\u000b\u019b"+
-    "\u0001\u0000\u0000\u0000\f\u019d\u0001\u0000\u0000\u0000\f\u019f\u0001"+
-    "\u0000\u0000\u0000\f\u01a1\u0001\u0000\u0000\u0000\f\u01a3\u0001\u0000"+
-    "\u0000\u0000\f\u01a5\u0001\u0000\u0000\u0000\f\u01a7\u0001\u0000\u0000"+
-    "\u0000\f\u01a9\u0001\u0000\u0000\u0000\r\u01ab\u0001\u0000\u0000\u0000"+
-    "\r\u01ad\u0001\u0000\u0000\u0000\r\u01af\u0001\u0000\u0000\u0000\r\u01b1"+
-    "\u0001\u0000\u0000\u0000\r\u01b3\u0001\u0000\u0000\u0000\r\u01b5\u0001"+
-    "\u0000\u0000\u0000\r\u01b7\u0001\u0000\u0000\u0000\r\u01b9\u0001\u0000"+
-    "\u0000\u0000\r\u01bb\u0001\u0000\u0000\u0000\r\u01bd\u0001\u0000\u0000"+
-    "\u0000\r\u01bf\u0001\u0000\u0000\u0000\r\u01c1\u0001\u0000\u0000\u0000"+
-    "\r\u01c3\u0001\u0000\u0000\u0000\u000e\u01c5\u0001\u0000\u0000\u0000\u000e"+
-    "\u01c7\u0001\u0000\u0000\u0000\u000e\u01c9\u0001\u0000\u0000\u0000\u000e"+
-    "\u01cb\u0001\u0000\u0000\u0000\u000e\u01cd\u0001\u0000\u0000\u0000\u000e"+
-    "\u01cf\u0001\u0000\u0000\u0000\u000f\u01d1\u0001\u0000\u0000\u0000\u000f"+
-    "\u01d3\u0001\u0000\u0000\u0000\u000f\u01d5\u0001\u0000\u0000\u0000\u000f"+
-    "\u01d7\u0001\u0000\u0000\u0000\u000f\u01d9\u0001\u0000\u0000\u0000\u000f"+
-    "\u01db\u0001\u0000\u0000\u0000\u000f\u01dd\u0001\u0000\u0000\u0000\u000f"+
-    "\u01df\u0001\u0000\u0000\u0000\u000f\u01e1\u0001\u0000\u0000\u0000\u000f"+
-    "\u01e3\u0001\u0000\u0000\u0000\u0010\u01e5\u0001\u0000\u0000\u0000\u0010"+
-    "\u01e7\u0001\u0000\u0000\u0000\u0010\u01e9\u0001\u0000\u0000\u0000\u0010"+
-    "\u01eb\u0001\u0000\u0000\u0000\u0010\u01ed\u0001\u0000\u0000\u0000\u0010"+
-    "\u01ef\u0001\u0000\u0000\u0000\u0010\u01f1\u0001\u0000\u0000\u0000\u0010"+
-    "\u01f3\u0001\u0000\u0000\u0000\u0010\u01f5\u0001\u0000\u0000\u0000\u0010"+
-    "\u01f7\u0001\u0000\u0000\u0000\u0011\u01f9\u0001\u0000\u0000\u0000\u0013"+
-    "\u0206\u0001\u0000\u0000\u0000\u0015\u0210\u0001\u0000\u0000\u0000\u0017"+
-    "\u0217\u0001\u0000\u0000\u0000\u0019\u0220\u0001\u0000\u0000\u0000\u001b"+
-    "\u0227\u0001\u0000\u0000\u0000\u001d\u0231\u0001\u0000\u0000\u0000\u001f"+
-    "\u0238\u0001\u0000\u0000\u0000!\u023f\u0001\u0000\u0000\u0000#\u0246\u0001"+
-    "\u0000\u0000\u0000%\u024e\u0001\u0000\u0000\u0000\'\u025a\u0001\u0000"+
-    "\u0000\u0000)\u0263\u0001\u0000\u0000\u0000+\u0269\u0001\u0000\u0000\u0000"+
-    "-\u0270\u0001\u0000\u0000\u0000/\u0277\u0001\u0000\u0000\u00001\u027f"+
-    "\u0001\u0000\u0000\u00003\u0287\u0001\u0000\u0000\u00005\u0290\u0001\u0000"+
-    "\u0000\u00007\u029f\u0001\u0000\u0000\u00009\u02ae\u0001\u0000\u0000\u0000"+
-    ";\u02ba\u0001\u0000\u0000\u0000=\u02c5\u0001\u0000\u0000\u0000?\u02cf"+
-    "\u0001\u0000\u0000\u0000A\u02d7\u0001\u0000\u0000\u0000C\u02df\u0001\u0000"+
-    "\u0000\u0000E\u02e9\u0001\u0000\u0000\u0000G\u02ef\u0001\u0000\u0000\u0000"+
-    "I\u0300\u0001\u0000\u0000\u0000K\u0310\u0001\u0000\u0000\u0000M\u0316"+
-    "\u0001\u0000\u0000\u0000O\u031a\u0001\u0000\u0000\u0000Q\u031c\u0001\u0000"+
-    "\u0000\u0000S\u031e\u0001\u0000\u0000\u0000U\u0321\u0001\u0000\u0000\u0000"+
-    "W\u0323\u0001\u0000\u0000\u0000Y\u032c\u0001\u0000\u0000\u0000[\u032e"+
-    "\u0001\u0000\u0000\u0000]\u0333\u0001\u0000\u0000\u0000_\u0335\u0001\u0000"+
-    "\u0000\u0000a\u033a\u0001\u0000\u0000\u0000c\u0359\u0001\u0000\u0000\u0000"+
-    "e\u035c\u0001\u0000\u0000\u0000g\u038a\u0001\u0000\u0000\u0000i\u038c"+
-    "\u0001\u0000\u0000\u0000k\u0390\u0001\u0000\u0000\u0000m\u0394\u0001\u0000"+
-    "\u0000\u0000o\u0396\u0001\u0000\u0000\u0000q\u0399\u0001\u0000\u0000\u0000"+
-    "s\u039c\u0001\u0000\u0000\u0000u\u039e\u0001\u0000\u0000\u0000w\u03a0"+
-    "\u0001\u0000\u0000\u0000y\u03a5\u0001\u0000\u0000\u0000{\u03a7\u0001\u0000"+
-    "\u0000\u0000}\u03ad\u0001\u0000\u0000\u0000\u007f\u03b3\u0001\u0000\u0000"+
-    "\u0000\u0081\u03b6\u0001\u0000\u0000\u0000\u0083\u03b9\u0001\u0000\u0000"+
-    "\u0000\u0085\u03be\u0001\u0000\u0000\u0000\u0087\u03c3\u0001\u0000\u0000"+
-    "\u0000\u0089\u03c5\u0001\u0000\u0000\u0000\u008b\u03c9\u0001\u0000\u0000"+
-    "\u0000\u008d\u03ce\u0001\u0000\u0000\u0000\u008f\u03d4\u0001\u0000\u0000"+
-    "\u0000\u0091\u03d7\u0001\u0000\u0000\u0000\u0093\u03da\u0001\u0000\u0000"+
-    "\u0000\u0095\u03dc\u0001\u0000\u0000\u0000\u0097\u03e2\u0001\u0000\u0000"+
-    "\u0000\u0099\u03e4\u0001\u0000\u0000\u0000\u009b\u03e9\u0001\u0000\u0000"+
-    "\u0000\u009d\u03ee\u0001\u0000\u0000\u0000\u009f\u03f1\u0001\u0000\u0000"+
-    "\u0000\u00a1\u03f4\u0001\u0000\u0000\u0000\u00a3\u03f7\u0001\u0000\u0000"+
-    "\u0000\u00a5\u03f9\u0001\u0000\u0000\u0000\u00a7\u03fc\u0001\u0000\u0000"+
-    "\u0000\u00a9\u03fe\u0001\u0000\u0000\u0000\u00ab\u0401\u0001\u0000\u0000"+
-    "\u0000\u00ad\u0403\u0001\u0000\u0000\u0000\u00af\u0405\u0001\u0000\u0000"+
-    "\u0000\u00b1\u0407\u0001\u0000\u0000\u0000\u00b3\u0409\u0001\u0000\u0000"+
-    "\u0000\u00b5\u040b\u0001\u0000\u0000\u0000\u00b7\u040d\u0001\u0000\u0000"+
-    "\u0000\u00b9\u040f\u0001\u0000\u0000\u0000\u00bb\u0412\u0001\u0000\u0000"+
-    "\u0000\u00bd\u0427\u0001\u0000\u0000\u0000\u00bf\u043a\u0001\u0000\u0000"+
-    "\u0000\u00c1\u043c\u0001\u0000\u0000\u0000\u00c3\u0441\u0001\u0000\u0000"+
-    "\u0000\u00c5\u0456\u0001\u0000\u0000\u0000\u00c7\u0458\u0001\u0000\u0000"+
-    "\u0000\u00c9\u0460\u0001\u0000\u0000\u0000\u00cb\u0462\u0001\u0000\u0000"+
-    "\u0000\u00cd\u0466\u0001\u0000\u0000\u0000\u00cf\u046a\u0001\u0000\u0000"+
-    "\u0000\u00d1\u046e\u0001\u0000\u0000\u0000\u00d3\u0473\u0001\u0000\u0000"+
-    "\u0000\u00d5\u0478\u0001\u0000\u0000\u0000\u00d7\u047c\u0001\u0000\u0000"+
-    "\u0000\u00d9\u0480\u0001\u0000\u0000\u0000\u00db\u0484\u0001\u0000\u0000"+
-    "\u0000\u00dd\u0489\u0001\u0000\u0000\u0000\u00df\u048d\u0001\u0000\u0000"+
-    "\u0000\u00e1\u0491\u0001\u0000\u0000\u0000\u00e3\u0495\u0001\u0000\u0000"+
-    "\u0000\u00e5\u0499\u0001\u0000\u0000\u0000\u00e7\u049d\u0001\u0000\u0000"+
-    "\u0000\u00e9\u04a1\u0001\u0000\u0000\u0000\u00eb\u04ad\u0001\u0000\u0000"+
-    "\u0000\u00ed\u04b0\u0001\u0000\u0000\u0000\u00ef\u04b4\u0001\u0000\u0000"+
-    "\u0000\u00f1\u04b8\u0001\u0000\u0000\u0000\u00f3\u04bc\u0001\u0000\u0000"+
-    "\u0000\u00f5\u04c0\u0001\u0000\u0000\u0000\u00f7\u04c4\u0001\u0000\u0000"+
-    "\u0000\u00f9\u04c8\u0001\u0000\u0000\u0000\u00fb\u04cd\u0001\u0000\u0000"+
-    "\u0000\u00fd\u04d1\u0001\u0000\u0000\u0000\u00ff\u04d5\u0001\u0000\u0000"+
-    "\u0000\u0101\u04d9\u0001\u0000\u0000\u0000\u0103\u04dd\u0001\u0000\u0000"+
-    "\u0000\u0105\u04e1\u0001\u0000\u0000\u0000\u0107\u04e9\u0001\u0000\u0000"+
-    "\u0000\u0109\u04fe\u0001\u0000\u0000\u0000\u010b\u0502\u0001\u0000\u0000"+
-    "\u0000\u010d\u0506\u0001\u0000\u0000\u0000\u010f\u050a\u0001\u0000\u0000"+
-    "\u0000\u0111\u050e\u0001\u0000\u0000\u0000\u0113\u0512\u0001\u0000\u0000"+
-    "\u0000\u0115\u0517\u0001\u0000\u0000\u0000\u0117\u051b\u0001\u0000\u0000"+
-    "\u0000\u0119\u051f\u0001\u0000\u0000\u0000\u011b\u0523\u0001\u0000\u0000"+
-    "\u0000\u011d\u0527\u0001\u0000\u0000\u0000\u011f\u052b\u0001\u0000\u0000"+
-    "\u0000\u0121\u052f\u0001\u0000\u0000\u0000\u0123\u0533\u0001\u0000\u0000"+
-    "\u0000\u0125\u0536\u0001\u0000\u0000\u0000\u0127\u053a\u0001\u0000\u0000"+
-    "\u0000\u0129\u053e\u0001\u0000\u0000\u0000\u012b\u0542\u0001\u0000\u0000"+
-    "\u0000\u012d\u0546\u0001\u0000\u0000\u0000\u012f\u054b\u0001\u0000\u0000"+
-    "\u0000\u0131\u0550\u0001\u0000\u0000\u0000\u0133\u0555\u0001\u0000\u0000"+
-    "\u0000\u0135\u055a\u0001\u0000\u0000\u0000\u0137\u0563\u0001\u0000\u0000"+
-    "\u0000\u0139\u056a\u0001\u0000\u0000\u0000\u013b\u056e\u0001\u0000\u0000"+
-    "\u0000\u013d\u0572\u0001\u0000\u0000\u0000\u013f\u0576\u0001\u0000\u0000"+
-    "\u0000\u0141\u057a\u0001\u0000\u0000\u0000\u0143\u0580\u0001\u0000\u0000"+
-    "\u0000\u0145\u0584\u0001\u0000\u0000\u0000\u0147\u0588\u0001\u0000\u0000"+
-    "\u0000\u0149\u058c\u0001\u0000\u0000\u0000\u014b\u0590\u0001\u0000\u0000"+
-    "\u0000\u014d\u0594\u0001\u0000\u0000\u0000\u014f\u0598\u0001\u0000\u0000"+
-    "\u0000\u0151\u059c\u0001\u0000\u0000\u0000\u0153\u05a0\u0001\u0000\u0000"+
-    "\u0000\u0155\u05a4\u0001\u0000\u0000\u0000\u0157\u05a8\u0001\u0000\u0000"+
-    "\u0000\u0159\u05ac\u0001\u0000\u0000\u0000\u015b\u05b0\u0001\u0000\u0000"+
-    "\u0000\u015d\u05b4\u0001\u0000\u0000\u0000\u015f\u05b9\u0001\u0000\u0000"+
-    "\u0000\u0161\u05bd\u0001\u0000\u0000\u0000\u0163\u05c1\u0001\u0000\u0000"+
-    "\u0000\u0165\u05c5\u0001\u0000\u0000\u0000\u0167\u05c9\u0001\u0000\u0000"+
-    "\u0000\u0169\u05cd\u0001\u0000\u0000\u0000\u016b\u05d1\u0001\u0000\u0000"+
-    "\u0000\u016d\u05d5\u0001\u0000\u0000\u0000\u016f\u05d9\u0001\u0000\u0000"+
-    "\u0000\u0171\u05dd\u0001\u0000\u0000\u0000\u0173\u05e1\u0001\u0000\u0000"+
-    "\u0000\u0175\u05e6\u0001\u0000\u0000\u0000\u0177\u05eb\u0001\u0000\u0000"+
-    "\u0000\u0179\u05ef\u0001\u0000\u0000\u0000\u017b\u05f3\u0001\u0000\u0000"+
-    "\u0000\u017d\u05f7\u0001\u0000\u0000\u0000\u017f\u05fc\u0001\u0000\u0000"+
-    "\u0000\u0181\u0605\u0001\u0000\u0000\u0000\u0183\u0609\u0001\u0000\u0000"+
-    "\u0000\u0185\u060d\u0001\u0000\u0000\u0000\u0187\u0611\u0001\u0000\u0000"+
-    "\u0000\u0189\u0615\u0001\u0000\u0000\u0000\u018b\u061a\u0001\u0000\u0000"+
-    "\u0000\u018d\u061e\u0001\u0000\u0000\u0000\u018f\u0622\u0001\u0000\u0000"+
-    "\u0000\u0191\u0626\u0001\u0000\u0000\u0000\u0193\u062b\u0001\u0000\u0000"+
-    "\u0000\u0195\u062f\u0001\u0000\u0000\u0000\u0197\u0633\u0001\u0000\u0000"+
-    "\u0000\u0199\u0637\u0001\u0000\u0000\u0000\u019b\u063b\u0001\u0000\u0000"+
-    "\u0000\u019d\u063f\u0001\u0000\u0000\u0000\u019f\u0645\u0001\u0000\u0000"+
-    "\u0000\u01a1\u0649\u0001\u0000\u0000\u0000\u01a3\u064d\u0001\u0000\u0000"+
-    "\u0000\u01a5\u0651\u0001\u0000\u0000\u0000\u01a7\u0655\u0001\u0000\u0000"+
-    "\u0000\u01a9\u0659\u0001\u0000\u0000\u0000\u01ab\u065d\u0001\u0000\u0000"+
-    "\u0000\u01ad\u0662\u0001\u0000\u0000\u0000\u01af\u0667\u0001\u0000\u0000"+
-    "\u0000\u01b1\u066b\u0001\u0000\u0000\u0000\u01b3\u0671\u0001\u0000\u0000"+
-    "\u0000\u01b5\u067a\u0001\u0000\u0000\u0000\u01b7\u067e\u0001\u0000\u0000"+
-    "\u0000\u01b9\u0682\u0001\u0000\u0000\u0000\u01bb\u0686\u0001\u0000\u0000"+
-    "\u0000\u01bd\u068a\u0001\u0000\u0000\u0000\u01bf\u068e\u0001\u0000\u0000"+
-    "\u0000\u01c1\u0692\u0001\u0000\u0000\u0000\u01c3\u0696\u0001\u0000\u0000"+
-    "\u0000\u01c5\u069a\u0001\u0000\u0000\u0000\u01c7\u069f\u0001\u0000\u0000"+
-    "\u0000\u01c9\u06a5\u0001\u0000\u0000\u0000\u01cb\u06ab\u0001\u0000\u0000"+
-    "\u0000\u01cd\u06af\u0001\u0000\u0000\u0000\u01cf\u06b3\u0001\u0000\u0000"+
-    "\u0000\u01d1\u06b7\u0001\u0000\u0000\u0000\u01d3\u06bd\u0001\u0000\u0000"+
-    "\u0000\u01d5\u06c3\u0001\u0000\u0000\u0000\u01d7\u06c9\u0001\u0000\u0000"+
-    "\u0000\u01d9\u06cd\u0001\u0000\u0000\u0000\u01db\u06d1\u0001\u0000\u0000"+
-    "\u0000\u01dd\u06d5\u0001\u0000\u0000\u0000\u01df\u06db\u0001\u0000\u0000"+
-    "\u0000\u01e1\u06e1\u0001\u0000\u0000\u0000\u01e3\u06e7\u0001\u0000\u0000"+
-    "\u0000\u01e5\u06ec\u0001\u0000\u0000\u0000\u01e7\u06f1\u0001\u0000\u0000"+
-    "\u0000\u01e9\u06f5\u0001\u0000\u0000\u0000\u01eb\u06f9\u0001\u0000\u0000"+
-    "\u0000\u01ed\u06fd\u0001\u0000\u0000\u0000\u01ef\u0701\u0001\u0000\u0000"+
-    "\u0000\u01f1\u0705\u0001\u0000\u0000\u0000\u01f3\u0709\u0001\u0000\u0000"+
-    "\u0000\u01f5\u070d\u0001\u0000\u0000\u0000\u01f7\u0711\u0001\u0000\u0000"+
-    "\u0000\u01f9\u01fa\u0007\u0000\u0000\u0000\u01fa\u01fb\u0007\u0001\u0000"+
-    "\u0000\u01fb\u01fc\u0007\u0002\u0000\u0000\u01fc\u01fd\u0007\u0003\u0000"+
-    "\u0000\u01fd\u01fe\u0007\u0004\u0000\u0000\u01fe\u01ff\u0007\u0005\u0000"+
-    "\u0000\u01ff\u0200\u0007\u0006\u0000\u0000\u0200\u0201\u0007\u0007\u0000"+
-    "\u0000\u0201\u0202\u0007\u0001\u0000\u0000\u0202\u0203\u0007\b\u0000\u0000"+
-    "\u0203\u0204\u0001\u0000\u0000\u0000\u0204\u0205\u0006\u0000\u0000\u0000"+
-    "\u0205\u0012\u0001\u0000\u0000\u0000\u0206\u0207\u0007\t\u0000\u0000\u0207"+
-    "\u0208\u0007\u0007\u0000\u0000\u0208\u0209\u0007\n\u0000\u0000\u0209\u020a"+
-    "\u0007\n\u0000\u0000\u020a\u020b\u0007\u0005\u0000\u0000\u020b\u020c\u0007"+
-    "\u0000\u0000\u0000\u020c\u020d\u0007\u0006\u0000\u0000\u020d\u020e\u0001"+
-    "\u0000\u0000\u0000\u020e\u020f\u0006\u0001\u0000\u0000\u020f\u0014\u0001"+
-    "\u0000\u0000\u0000\u0210\u0211\u0007\t\u0000\u0000\u0211\u0212\u0007\u000b"+
-    "\u0000\u0000\u0212\u0213\u0007\u0001\u0000\u0000\u0213\u0214\u0007\u0003"+
-    "\u0000\u0000\u0214\u0215\u0001\u0000\u0000\u0000\u0215\u0216\u0006\u0002"+
-    "\u0001\u0000\u0216\u0016\u0001\u0000\u0000\u0000\u0217\u0218\u0007\u0005"+
-    "\u0000\u0000\u0218\u0219\u0007\b\u0000\u0000\u0219\u021a\u0007\u000b\u0000"+
-    "\u0000\u021a\u021b\u0007\u0007\u0000\u0000\u021b\u021c\u0007\u0000\u0000"+
-    "\u0000\u021c\u021d\u0007\f\u0000\u0000\u021d\u021e\u0001\u0000\u0000\u0000"+
-    "\u021e\u021f\u0006\u0003\u0002\u0000\u021f\u0018\u0001\u0000\u0000\u0000"+
-    "\u0220\u0221\u0007\u0005\u0000\u0000\u0221\u0222\u0007\r\u0000\u0000\u0222"+
-    "\u0223\u0007\u000e\u0000\u0000\u0223\u0224\u0007\u0004\u0000\u0000\u0224"+
-    "\u0225\u0001\u0000\u0000\u0000\u0225\u0226\u0006\u0004\u0000\u0000\u0226"+
-    "\u001a\u0001\u0000\u0000\u0000\u0227\u0228\u0007\u0005\u0000\u0000\u0228"+
-    "\u0229\u0007\u000f\u0000\u0000\u0229\u022a\u0007\u0003\u0000\u0000\u022a"+
-    "\u022b\u0007\u0004\u0000\u0000\u022b\u022c\u0007\u000e\u0000\u0000\u022c"+
-    "\u022d\u0007\u0007\u0000\u0000\u022d\u022e\u0007\b\u0000\u0000\u022e\u022f"+
-    "\u0001\u0000\u0000\u0000\u022f\u0230\u0006\u0005\u0003\u0000\u0230\u001c"+
-    "\u0001\u0000\u0000\u0000\u0231\u0232\u0007\u0010\u0000\u0000\u0232\u0233"+
-    "\u0007\u000b\u0000\u0000\u0233\u0234\u0007\u0001\u0000\u0000\u0234\u0235"+
-    "\u0007\u0002\u0000\u0000\u0235\u0236\u0001\u0000\u0000\u0000\u0236\u0237"+
-    "\u0006\u0006\u0004\u0000\u0237\u001e\u0001\u0000\u0000\u0000\u0238\u0239"+
-    "\u0007\u0011\u0000\u0000\u0239\u023a\u0007\u000b\u0000\u0000\u023a\u023b"+
-    "\u0007\u0001\u0000\u0000\u023b\u023c\u0007\u0012\u0000\u0000\u023c\u023d"+
-    "\u0001\u0000\u0000\u0000\u023d\u023e\u0006\u0007\u0000\u0000\u023e \u0001"+
-    "\u0000\u0000\u0000\u023f\u0240\u0007\u0012\u0000\u0000\u0240\u0241\u0007"+
-    "\u0005\u0000\u0000\u0241\u0242\u0007\u0005\u0000\u0000\u0242\u0243\u0007"+
-    "\u0003\u0000\u0000\u0243\u0244\u0001\u0000\u0000\u0000\u0244\u0245\u0006"+
-    "\b\u0001\u0000\u0245\"\u0001\u0000\u0000\u0000\u0246\u0247\u0007\u0004"+
-    "\u0000\u0000\u0247\u0248\u0007\u0007\u0000\u0000\u0248\u0249\u0007\u0002"+
-    "\u0000\u0000\u0249\u024a\u0007\u0007\u0000\u0000\u024a\u024b\u0007\u0006"+
-    "\u0000\u0000\u024b\u024c\u0001\u0000\u0000\u0000\u024c\u024d\u0006\t\u0000"+
-    "\u0000\u024d$\u0001\u0000\u0000\u0000\u024e\u024f\u0007\u0002\u0000\u0000"+
-    "\u024f\u0250\u0007\r\u0000\u0000\u0250\u0251\u0005_\u0000\u0000\u0251"+
-    "\u0252\u0007\u0005\u0000\u0000\u0252\u0253\u0007\u000f\u0000\u0000\u0253"+
-    "\u0254\u0007\u0003\u0000\u0000\u0254\u0255\u0007\u000e\u0000\u0000\u0255"+
-    "\u0256\u0007\b\u0000\u0000\u0256\u0257\u0007\t\u0000\u0000\u0257\u0258"+
-    "\u0001\u0000\u0000\u0000\u0258\u0259\u0006\n\u0005\u0000\u0259&\u0001"+
-    "\u0000\u0000\u0000\u025a\u025b\u0007\u000b\u0000\u0000\u025b\u025c\u0007"+
-    "\u0005\u0000\u0000\u025c\u025d\u0007\b\u0000\u0000\u025d\u025e\u0007\u000e"+
-    "\u0000\u0000\u025e\u025f\u0007\u0002\u0000\u0000\u025f\u0260\u0007\u0005"+
-    "\u0000\u0000\u0260\u0261\u0001\u0000\u0000\u0000\u0261\u0262\u0006\u000b"+
-    "\u0006\u0000\u0262(\u0001\u0000\u0000\u0000\u0263\u0264\u0007\u000b\u0000"+
-    "\u0000\u0264\u0265\u0007\u0001\u0000\u0000\u0265\u0266\u0007\u0013\u0000"+
-    "\u0000\u0266\u0267\u0001\u0000\u0000\u0000\u0267\u0268\u0006\f\u0000\u0000"+
-    "\u0268*\u0001\u0000\u0000\u0000\u0269\u026a\u0007\n\u0000\u0000\u026a"+
-    "\u026b\u0007\f\u0000\u0000\u026b\u026c\u0007\u0001\u0000\u0000\u026c\u026d"+
-    "\u0007\u0013\u0000\u0000\u026d\u026e\u0001\u0000\u0000\u0000\u026e\u026f"+
-    "\u0006\r\u0007\u0000\u026f,\u0001\u0000\u0000\u0000\u0270\u0271\u0007"+
-    "\n\u0000\u0000\u0271\u0272\u0007\u0001\u0000\u0000\u0272\u0273\u0007\u000b"+
-    "\u0000\u0000\u0273\u0274\u0007\u0006\u0000\u0000\u0274\u0275\u0001\u0000"+
-    "\u0000\u0000\u0275\u0276\u0006\u000e\u0000\u0000\u0276.\u0001\u0000\u0000"+
-    "\u0000\u0277\u0278\u0007\n\u0000\u0000\u0278\u0279\u0007\u0006\u0000\u0000"+
-    "\u0279\u027a\u0007\u000e\u0000\u0000\u027a\u027b\u0007\u0006\u0000\u0000"+
-    "\u027b\u027c\u0007\n\u0000\u0000\u027c\u027d\u0001\u0000\u0000\u0000\u027d"+
-    "\u027e\u0006\u000f\u0000\u0000\u027e0\u0001\u0000\u0000\u0000\u027f\u0280"+
-    "\u0007\u0013\u0000\u0000\u0280\u0281\u0007\f\u0000\u0000\u0281\u0282\u0007"+
-    "\u0005\u0000\u0000\u0282\u0283\u0007\u000b\u0000\u0000\u0283\u0284\u0007"+
-    "\u0005\u0000\u0000\u0284\u0285\u0001\u0000\u0000\u0000\u0285\u0286\u0006"+
-    "\u0010\u0000\u0000\u02862\u0001\u0000\u0000\u0000\u0287\u0288\u0007\u0004"+
-    "\u0000\u0000\u0288\u0289\u0007\u0001\u0000\u0000\u0289\u028a\u0007\u0001"+
-    "\u0000\u0000\u028a\u028b\u0007\u0012\u0000\u0000\u028b\u028c\u0007\u0014"+
-    "\u0000\u0000\u028c\u028d\u0007\u0003\u0000\u0000\u028d\u028e\u0001\u0000"+
-    "\u0000\u0000\u028e\u028f\u0006\u0011\b\u0000\u028f4\u0001\u0000\u0000"+
-    "\u0000\u0290\u0291\u0007\u0000\u0000\u0000\u0291\u0292\u0007\f\u0000\u0000"+
-    "\u0292\u0293\u0007\u000e\u0000\u0000\u0293\u0294\u0007\b\u0000\u0000\u0294"+
-    "\u0295\u0007\u0011\u0000\u0000\u0295\u0296\u0007\u0005\u0000\u0000\u0296"+
-    "\u0297\u0005_\u0000\u0000\u0297\u0298\u0007\u0003\u0000\u0000\u0298\u0299"+
-    "\u0007\u0001\u0000\u0000\u0299\u029a\u0007\u0007\u0000\u0000\u029a\u029b"+
-    "\u0007\b\u0000\u0000\u029b\u029c\u0007\u0006\u0000\u0000\u029c\u029d\u0001"+
-    "\u0000\u0000\u0000\u029d\u029e\u0006\u0012\t\u0000\u029e6\u0001\u0000"+
-    "\u0000\u0000\u029f\u02a0\u0004\u0013\u0000\u0000\u02a0\u02a1\u0007\u0007"+
-    "\u0000\u0000\u02a1\u02a2\u0007\b\u0000\u0000\u02a2\u02a3\u0007\u0004\u0000"+
-    "\u0000\u02a3\u02a4\u0007\u0007\u0000\u0000\u02a4\u02a5\u0007\b\u0000\u0000"+
-    "\u02a5\u02a6\u0007\u0005\u0000\u0000\u02a6\u02a7\u0007\n\u0000\u0000\u02a7"+
-    "\u02a8\u0007\u0006\u0000\u0000\u02a8\u02a9\u0007\u000e\u0000\u0000\u02a9"+
-    "\u02aa\u0007\u0006\u0000\u0000\u02aa\u02ab\u0007\n\u0000\u0000\u02ab\u02ac"+
-    "\u0001\u0000\u0000\u0000\u02ac\u02ad\u0006\u0013\u0000\u0000\u02ad8\u0001"+
-    "\u0000\u0000\u0000\u02ae\u02af\u0004\u0014\u0001\u0000\u02af\u02b0\u0007"+
-    "\u0004\u0000\u0000\u02b0\u02b1\u0007\u0001\u0000\u0000\u02b1\u02b2\u0007"+
-    "\u0001\u0000\u0000\u02b2\u02b3\u0007\u0012\u0000\u0000\u02b3\u02b4\u0007"+
-    "\u0014\u0000\u0000\u02b4\u02b5\u0007\u0003\u0000\u0000\u02b5\u02b6\u0005"+
-    "_\u0000\u0000\u02b6\u02b7\u0005\u8001\uf414\u0000\u0000\u02b7\u02b8\u0001"+
-    "\u0000\u0000\u0000\u02b8\u02b9\u0006\u0014\n\u0000\u02b9:\u0001\u0000"+
-    "\u0000\u0000\u02ba\u02bb\u0004\u0015\u0002\u0000\u02bb\u02bc\u0007\u0002"+
-    "\u0000\u0000\u02bc\u02bd\u0007\u0005\u0000\u0000\u02bd\u02be\u0007\u0006"+
-    "\u0000\u0000\u02be\u02bf\u0007\u000b\u0000\u0000\u02bf\u02c0\u0007\u0007"+
-    "\u0000\u0000\u02c0\u02c1\u0007\u0000\u0000\u0000\u02c1\u02c2\u0007\n\u0000"+
-    "\u0000\u02c2\u02c3\u0001\u0000\u0000\u0000\u02c3\u02c4\u0006\u0015\u000b"+
-    "\u0000\u02c4<\u0001\u0000\u0000\u0000\u02c5\u02c6\u0004\u0016\u0003\u0000"+
-    "\u02c6\u02c7\u0007\u000b\u0000\u0000\u02c7\u02c8\u0007\u0005\u0000\u0000"+
-    "\u02c8\u02c9\u0007\u000b\u0000\u0000\u02c9\u02ca\u0007\u000e\u0000\u0000"+
-    "\u02ca\u02cb\u0007\b\u0000\u0000\u02cb\u02cc\u0007\u0012\u0000\u0000\u02cc"+
-    "\u02cd\u0001\u0000\u0000\u0000\u02cd\u02ce\u0006\u0016\u0000\u0000\u02ce"+
-    ">\u0001\u0000\u0000\u0000\u02cf\u02d0\u0004\u0017\u0004\u0000\u02d0\u02d1"+
-    "\u0007\u0010\u0000\u0000\u02d1\u02d2\u0007\u0014\u0000\u0000\u02d2\u02d3"+
-    "\u0007\u0004\u0000\u0000\u02d3\u02d4\u0007\u0004\u0000\u0000\u02d4\u02d5"+
-    "\u0001\u0000\u0000\u0000\u02d5\u02d6\u0006\u0017\b\u0000\u02d6@\u0001"+
-    "\u0000\u0000\u0000\u02d7\u02d8\u0004\u0018\u0005\u0000\u02d8\u02d9\u0007"+
-    "\u0004\u0000\u0000\u02d9\u02da\u0007\u0005\u0000\u0000\u02da\u02db\u0007"+
-    "\u0010\u0000\u0000\u02db\u02dc\u0007\u0006\u0000\u0000\u02dc\u02dd\u0001"+
-    "\u0000\u0000\u0000\u02dd\u02de\u0006\u0018\b\u0000\u02deB\u0001\u0000"+
-    "\u0000\u0000\u02df\u02e0\u0004\u0019\u0006\u0000\u02e0\u02e1\u0007\u000b"+
-    "\u0000\u0000\u02e1\u02e2\u0007\u0007\u0000\u0000\u02e2\u02e3\u0007\u0011"+
-    "\u0000\u0000\u02e3\u02e4\u0007\f\u0000\u0000\u02e4\u02e5\u0007\u0006\u0000"+
-    "\u0000\u02e5\u02e6\u0001\u0000\u0000\u0000\u02e6\u02e7\u0006\u0019\b\u0000"+
-    "\u02e7D\u0001\u0000\u0000\u0000\u02e8\u02ea\b\u0015\u0000\u0000\u02e9"+
-    "\u02e8\u0001\u0000\u0000\u0000\u02ea\u02eb\u0001\u0000\u0000\u0000\u02eb"+
-    "\u02e9\u0001\u0000\u0000\u0000\u02eb\u02ec\u0001\u0000\u0000\u0000\u02ec"+
-    "\u02ed\u0001\u0000\u0000\u0000\u02ed\u02ee\u0006\u001a\u0000\u0000\u02ee"+
-    "F\u0001\u0000\u0000\u0000\u02ef\u02f0\u0005/\u0000\u0000\u02f0\u02f1\u0005"+
-    "/\u0000\u0000\u02f1\u02f5\u0001\u0000\u0000\u0000\u02f2\u02f4\b\u0016"+
-    "\u0000\u0000\u02f3\u02f2\u0001\u0000\u0000\u0000\u02f4\u02f7\u0001\u0000"+
-    "\u0000\u0000\u02f5\u02f3\u0001\u0000\u0000\u0000\u02f5\u02f6\u0001\u0000"+
-    "\u0000\u0000\u02f6\u02f9\u0001\u0000\u0000\u0000\u02f7\u02f5\u0001\u0000"+
-    "\u0000\u0000\u02f8\u02fa\u0005\r\u0000\u0000\u02f9\u02f8\u0001\u0000\u0000"+
-    "\u0000\u02f9\u02fa\u0001\u0000\u0000\u0000\u02fa\u02fc\u0001\u0000\u0000"+
-    "\u0000\u02fb\u02fd\u0005\n\u0000\u0000\u02fc\u02fb\u0001\u0000\u0000\u0000"+
-    "\u02fc\u02fd\u0001\u0000\u0000\u0000\u02fd\u02fe\u0001\u0000\u0000\u0000"+
-    "\u02fe\u02ff\u0006\u001b\f\u0000\u02ffH\u0001\u0000\u0000\u0000\u0300"+
-    "\u0301\u0005/\u0000\u0000\u0301\u0302\u0005*\u0000\u0000\u0302\u0307\u0001"+
-    "\u0000\u0000\u0000\u0303\u0306\u0003I\u001c\u0000\u0304\u0306\t\u0000"+
-    "\u0000\u0000\u0305\u0303\u0001\u0000\u0000\u0000\u0305\u0304\u0001\u0000"+
-    "\u0000\u0000\u0306\u0309\u0001\u0000\u0000\u0000\u0307\u0308\u0001\u0000"+
-    "\u0000\u0000\u0307\u0305\u0001\u0000\u0000\u0000\u0308\u030a\u0001\u0000"+
-    "\u0000\u0000\u0309\u0307\u0001\u0000\u0000\u0000\u030a\u030b\u0005*\u0000"+
-    "\u0000\u030b\u030c\u0005/\u0000\u0000\u030c\u030d\u0001\u0000\u0000\u0000"+
-    "\u030d\u030e\u0006\u001c\f\u0000\u030eJ\u0001\u0000\u0000\u0000\u030f"+
-    "\u0311\u0007\u0017\u0000\u0000\u0310\u030f\u0001\u0000\u0000\u0000\u0311"+
-    "\u0312\u0001\u0000\u0000\u0000\u0312\u0310\u0001\u0000\u0000\u0000\u0312"+
-    "\u0313\u0001\u0000\u0000\u0000\u0313\u0314\u0001\u0000\u0000\u0000\u0314"+
-    "\u0315\u0006\u001d\f\u0000\u0315L\u0001\u0000\u0000\u0000\u0316\u0317"+
-    "\u0005|\u0000\u0000\u0317\u0318\u0001\u0000\u0000\u0000\u0318\u0319\u0006"+
-    "\u001e\r\u0000\u0319N\u0001\u0000\u0000\u0000\u031a\u031b\u0007\u0018"+
-    "\u0000\u0000\u031bP\u0001\u0000\u0000\u0000\u031c\u031d\u0007\u0019\u0000"+
-    "\u0000\u031dR\u0001\u0000\u0000\u0000\u031e\u031f\u0005\\\u0000\u0000"+
-    "\u031f\u0320\u0007\u001a\u0000\u0000\u0320T\u0001\u0000\u0000\u0000\u0321"+
-    "\u0322\b\u001b\u0000\u0000\u0322V\u0001\u0000\u0000\u0000\u0323\u0325"+
-    "\u0007\u0005\u0000\u0000\u0324\u0326\u0007\u001c\u0000\u0000\u0325\u0324"+
-    "\u0001\u0000\u0000\u0000\u0325\u0326\u0001\u0000\u0000\u0000\u0326\u0328"+
-    "\u0001\u0000\u0000\u0000\u0327\u0329\u0003O\u001f\u0000\u0328\u0327\u0001"+
-    "\u0000\u0000\u0000\u0329\u032a\u0001\u0000\u0000\u0000\u032a\u0328\u0001"+
-    "\u0000\u0000\u0000\u032a\u032b\u0001\u0000\u0000\u0000\u032bX\u0001\u0000"+
-    "\u0000\u0000\u032c\u032d\u0005@\u0000\u0000\u032dZ\u0001\u0000\u0000\u0000"+
-    "\u032e\u032f\u0005`\u0000\u0000\u032f\\\u0001\u0000\u0000\u0000\u0330"+
-    "\u0334\b\u001d\u0000\u0000\u0331\u0332\u0005`\u0000\u0000\u0332\u0334"+
-    "\u0005`\u0000\u0000\u0333\u0330\u0001\u0000\u0000\u0000\u0333\u0331\u0001"+
-    "\u0000\u0000\u0000\u0334^\u0001\u0000\u0000\u0000\u0335\u0336\u0005_\u0000"+
-    "\u0000\u0336`\u0001\u0000\u0000\u0000\u0337\u033b\u0003Q \u0000\u0338"+
-    "\u033b\u0003O\u001f\u0000\u0339\u033b\u0003_\'\u0000\u033a\u0337\u0001"+
-    "\u0000\u0000\u0000\u033a\u0338\u0001\u0000\u0000\u0000\u033a\u0339\u0001"+
-    "\u0000\u0000\u0000\u033bb\u0001\u0000\u0000\u0000\u033c\u0341\u0005\""+
-    "\u0000\u0000\u033d\u0340\u0003S!\u0000\u033e\u0340\u0003U\"\u0000\u033f"+
-    "\u033d\u0001\u0000\u0000\u0000\u033f\u033e\u0001\u0000\u0000\u0000\u0340"+
-    "\u0343\u0001\u0000\u0000\u0000\u0341\u033f\u0001\u0000\u0000\u0000\u0341"+
-    "\u0342\u0001\u0000\u0000\u0000\u0342\u0344\u0001\u0000\u0000\u0000\u0343"+
-    "\u0341\u0001\u0000\u0000\u0000\u0344\u035a\u0005\"\u0000\u0000\u0345\u0346"+
-    "\u0005\"\u0000\u0000\u0346\u0347\u0005\"\u0000\u0000\u0347\u0348\u0005"+
-    "\"\u0000\u0000\u0348\u034c\u0001\u0000\u0000\u0000\u0349\u034b\b\u0016"+
-    "\u0000\u0000\u034a\u0349\u0001\u0000\u0000\u0000\u034b\u034e\u0001\u0000"+
-    "\u0000\u0000\u034c\u034d\u0001\u0000\u0000\u0000\u034c\u034a\u0001\u0000"+
-    "\u0000\u0000\u034d\u034f\u0001\u0000\u0000\u0000\u034e\u034c\u0001\u0000"+
-    "\u0000\u0000\u034f\u0350\u0005\"\u0000\u0000\u0350\u0351\u0005\"\u0000"+
-    "\u0000\u0351\u0352\u0005\"\u0000\u0000\u0352\u0354\u0001\u0000\u0000\u0000"+
-    "\u0353\u0355\u0005\"\u0000\u0000\u0354\u0353\u0001\u0000\u0000\u0000\u0354"+
-    "\u0355\u0001\u0000\u0000\u0000\u0355\u0357\u0001\u0000\u0000\u0000\u0356"+
-    "\u0358\u0005\"\u0000\u0000\u0357\u0356\u0001\u0000\u0000\u0000\u0357\u0358"+
-    "\u0001\u0000\u0000\u0000\u0358\u035a\u0001\u0000\u0000\u0000\u0359\u033c"+
-    "\u0001\u0000\u0000\u0000\u0359\u0345\u0001\u0000\u0000\u0000\u035ad\u0001"+
-    "\u0000\u0000\u0000\u035b\u035d\u0003O\u001f\u0000\u035c\u035b\u0001\u0000"+
-    "\u0000\u0000\u035d\u035e\u0001\u0000\u0000\u0000\u035e\u035c\u0001\u0000"+
-    "\u0000\u0000\u035e\u035f\u0001\u0000\u0000\u0000\u035ff\u0001\u0000\u0000"+
-    "\u0000\u0360\u0362\u0003O\u001f\u0000\u0361\u0360\u0001\u0000\u0000\u0000"+
-    "\u0362\u0363\u0001\u0000\u0000\u0000\u0363\u0361\u0001\u0000\u0000\u0000"+
-    "\u0363\u0364\u0001\u0000\u0000\u0000\u0364\u0365\u0001\u0000\u0000\u0000"+
-    "\u0365\u0369\u0003y4\u0000\u0366\u0368\u0003O\u001f\u0000\u0367\u0366"+
-    "\u0001\u0000\u0000\u0000\u0368\u036b\u0001\u0000\u0000\u0000\u0369\u0367"+
-    "\u0001\u0000\u0000\u0000\u0369\u036a\u0001\u0000\u0000\u0000\u036a\u038b"+
-    "\u0001\u0000\u0000\u0000\u036b\u0369\u0001\u0000\u0000\u0000\u036c\u036e"+
-    "\u0003y4\u0000\u036d\u036f\u0003O\u001f\u0000\u036e\u036d\u0001\u0000"+
-    "\u0000\u0000\u036f\u0370\u0001\u0000\u0000\u0000\u0370\u036e\u0001\u0000"+
-    "\u0000\u0000\u0370\u0371\u0001\u0000\u0000\u0000\u0371\u038b\u0001\u0000"+
-    "\u0000\u0000\u0372\u0374\u0003O\u001f\u0000\u0373\u0372\u0001\u0000\u0000"+
-    "\u0000\u0374\u0375\u0001\u0000\u0000\u0000\u0375\u0373\u0001\u0000\u0000"+
-    "\u0000\u0375\u0376\u0001\u0000\u0000\u0000\u0376\u037e\u0001\u0000\u0000"+
-    "\u0000\u0377\u037b\u0003y4\u0000\u0378\u037a\u0003O\u001f\u0000\u0379"+
-    "\u0378\u0001\u0000\u0000\u0000\u037a\u037d\u0001\u0000\u0000\u0000\u037b"+
-    "\u0379\u0001\u0000\u0000\u0000\u037b\u037c\u0001\u0000\u0000\u0000\u037c"+
-    "\u037f\u0001\u0000\u0000\u0000\u037d\u037b\u0001\u0000\u0000\u0000\u037e"+
-    "\u0377\u0001\u0000\u0000\u0000\u037e\u037f\u0001\u0000\u0000\u0000\u037f"+
-    "\u0380\u0001\u0000\u0000\u0000\u0380\u0381\u0003W#\u0000\u0381\u038b\u0001"+
-    "\u0000\u0000\u0000\u0382\u0384\u0003y4\u0000\u0383\u0385\u0003O\u001f"+
-    "\u0000\u0384\u0383\u0001\u0000\u0000\u0000\u0385\u0386\u0001\u0000\u0000"+
-    "\u0000\u0386\u0384\u0001\u0000\u0000\u0000\u0386\u0387\u0001\u0000\u0000"+
-    "\u0000\u0387\u0388\u0001\u0000\u0000\u0000\u0388\u0389\u0003W#\u0000\u0389"+
-    "\u038b\u0001\u0000\u0000\u0000\u038a\u0361\u0001\u0000\u0000\u0000\u038a"+
-    "\u036c\u0001\u0000\u0000\u0000\u038a\u0373\u0001\u0000\u0000\u0000\u038a"+
-    "\u0382\u0001\u0000\u0000\u0000\u038bh\u0001\u0000\u0000\u0000\u038c\u038d"+
-    "\u0007\u000e\u0000\u0000\u038d\u038e\u0007\b\u0000\u0000\u038e\u038f\u0007"+
-    "\t\u0000\u0000\u038fj\u0001\u0000\u0000\u0000\u0390\u0391\u0007\u000e"+
-    "\u0000\u0000\u0391\u0392\u0007\n\u0000\u0000\u0392\u0393\u0007\u0000\u0000"+
-    "\u0000\u0393l\u0001\u0000\u0000\u0000\u0394\u0395\u0005=\u0000\u0000\u0395"+
-    "n\u0001\u0000\u0000\u0000\u0396\u0397\u0007\u001e\u0000\u0000\u0397\u0398"+
-    "\u0007\u001f\u0000\u0000\u0398p\u0001\u0000\u0000\u0000\u0399\u039a\u0005"+
-    ":\u0000\u0000\u039a\u039b\u0005:\u0000\u0000\u039br\u0001\u0000\u0000"+
-    "\u0000\u039c\u039d\u0005:\u0000\u0000\u039dt\u0001\u0000\u0000\u0000\u039e"+
-    "\u039f\u0005,\u0000\u0000\u039fv\u0001\u0000\u0000\u0000\u03a0\u03a1\u0007"+
-    "\t\u0000\u0000\u03a1\u03a2\u0007\u0005\u0000\u0000\u03a2\u03a3\u0007\n"+
-    "\u0000\u0000\u03a3\u03a4\u0007\u0000\u0000\u0000\u03a4x\u0001\u0000\u0000"+
-    "\u0000\u03a5\u03a6\u0005.\u0000\u0000\u03a6z\u0001\u0000\u0000\u0000\u03a7"+
-    "\u03a8\u0007\u0010\u0000\u0000\u03a8\u03a9\u0007\u000e\u0000\u0000\u03a9"+
-    "\u03aa\u0007\u0004\u0000\u0000\u03aa\u03ab\u0007\n\u0000\u0000\u03ab\u03ac"+
-    "\u0007\u0005\u0000\u0000\u03ac|\u0001\u0000\u0000\u0000\u03ad\u03ae\u0007"+
-    "\u0010\u0000\u0000\u03ae\u03af\u0007\u0007\u0000\u0000\u03af\u03b0\u0007"+
-    "\u000b\u0000\u0000\u03b0\u03b1\u0007\n\u0000\u0000\u03b1\u03b2\u0007\u0006"+
-    "\u0000\u0000\u03b2~\u0001\u0000\u0000\u0000\u03b3\u03b4\u0007\u0007\u0000"+
-    "\u0000\u03b4\u03b5\u0007\b\u0000\u0000\u03b5\u0080\u0001\u0000\u0000\u0000"+
-    "\u03b6\u03b7\u0007\u0007\u0000\u0000\u03b7\u03b8\u0007\n\u0000\u0000\u03b8"+
-    "\u0082\u0001\u0000\u0000\u0000\u03b9\u03ba\u0007\u0004\u0000\u0000\u03ba"+
-    "\u03bb\u0007\u000e\u0000\u0000\u03bb\u03bc\u0007\n\u0000\u0000\u03bc\u03bd"+
-    "\u0007\u0006\u0000\u0000\u03bd\u0084\u0001\u0000\u0000\u0000\u03be\u03bf"+
-    "\u0007\u0004\u0000\u0000\u03bf\u03c0\u0007\u0007\u0000\u0000\u03c0\u03c1"+
-    "\u0007\u0012\u0000\u0000\u03c1\u03c2\u0007\u0005\u0000\u0000\u03c2\u0086"+
-    "\u0001\u0000\u0000\u0000\u03c3\u03c4\u0005(\u0000\u0000\u03c4\u0088\u0001"+
-    "\u0000\u0000\u0000\u03c5\u03c6\u0007\b\u0000\u0000\u03c6\u03c7\u0007\u0001"+
-    "\u0000\u0000\u03c7\u03c8\u0007\u0006\u0000\u0000\u03c8\u008a\u0001\u0000"+
-    "\u0000\u0000\u03c9\u03ca\u0007\b\u0000\u0000\u03ca\u03cb\u0007\u0014\u0000"+
-    "\u0000\u03cb\u03cc\u0007\u0004\u0000\u0000\u03cc\u03cd\u0007\u0004\u0000"+
-    "\u0000\u03cd\u008c\u0001\u0000\u0000\u0000\u03ce\u03cf\u0007\b\u0000\u0000"+
-    "\u03cf\u03d0\u0007\u0014\u0000\u0000\u03d0\u03d1\u0007\u0004\u0000\u0000"+
-    "\u03d1\u03d2\u0007\u0004\u0000\u0000\u03d2\u03d3\u0007\n\u0000\u0000\u03d3"+
-    "\u008e\u0001\u0000\u0000\u0000\u03d4\u03d5\u0007\u0001\u0000\u0000\u03d5"+
-    "\u03d6\u0007\b\u0000\u0000\u03d6\u0090\u0001\u0000\u0000\u0000\u03d7\u03d8"+
-    "\u0007\u0001\u0000\u0000\u03d8\u03d9\u0007\u000b\u0000\u0000\u03d9\u0092"+
-    "\u0001\u0000\u0000\u0000\u03da\u03db\u0005?\u0000\u0000\u03db\u0094\u0001"+
-    "\u0000\u0000\u0000\u03dc\u03dd\u0007\u000b\u0000\u0000\u03dd\u03de\u0007"+
-    "\u0004\u0000\u0000\u03de\u03df\u0007\u0007\u0000\u0000\u03df\u03e0\u0007"+
-    "\u0012\u0000\u0000\u03e0\u03e1\u0007\u0005\u0000\u0000\u03e1\u0096\u0001"+
-    "\u0000\u0000\u0000\u03e2\u03e3\u0005)\u0000\u0000\u03e3\u0098\u0001\u0000"+
-    "\u0000\u0000\u03e4\u03e5\u0007\u0006\u0000\u0000\u03e5\u03e6\u0007\u000b"+
-    "\u0000\u0000\u03e6\u03e7\u0007\u0014\u0000\u0000\u03e7\u03e8\u0007\u0005"+
-    "\u0000\u0000\u03e8\u009a\u0001\u0000\u0000\u0000\u03e9\u03ea\u0007\u0013"+
-    "\u0000\u0000\u03ea\u03eb\u0007\u0007\u0000\u0000\u03eb\u03ec\u0007\u0006"+
-    "\u0000\u0000\u03ec\u03ed\u0007\f\u0000\u0000\u03ed\u009c\u0001\u0000\u0000"+
-    "\u0000\u03ee\u03ef\u0005=\u0000\u0000\u03ef\u03f0\u0005=\u0000\u0000\u03f0"+
-    "\u009e\u0001\u0000\u0000\u0000\u03f1\u03f2\u0005=\u0000\u0000\u03f2\u03f3"+
-    "\u0005~\u0000\u0000\u03f3\u00a0\u0001\u0000\u0000\u0000\u03f4\u03f5\u0005"+
-    "!\u0000\u0000\u03f5\u03f6\u0005=\u0000\u0000\u03f6\u00a2\u0001\u0000\u0000"+
-    "\u0000\u03f7\u03f8\u0005<\u0000\u0000\u03f8\u00a4\u0001\u0000\u0000\u0000"+
-    "\u03f9\u03fa\u0005<\u0000\u0000\u03fa\u03fb\u0005=\u0000\u0000\u03fb\u00a6"+
-    "\u0001\u0000\u0000\u0000\u03fc\u03fd\u0005>\u0000\u0000\u03fd\u00a8\u0001"+
-    "\u0000\u0000\u0000\u03fe\u03ff\u0005>\u0000\u0000\u03ff\u0400\u0005=\u0000"+
-    "\u0000\u0400\u00aa\u0001\u0000\u0000\u0000\u0401\u0402\u0005+\u0000\u0000"+
-    "\u0402\u00ac\u0001\u0000\u0000\u0000\u0403\u0404\u0005-\u0000\u0000\u0404"+
-    "\u00ae\u0001\u0000\u0000\u0000\u0405\u0406\u0005*\u0000\u0000\u0406\u00b0"+
-    "\u0001\u0000\u0000\u0000\u0407\u0408\u0005/\u0000\u0000\u0408\u00b2\u0001"+
-    "\u0000\u0000\u0000\u0409\u040a\u0005%\u0000\u0000\u040a\u00b4\u0001\u0000"+
-    "\u0000\u0000\u040b\u040c\u0005{\u0000\u0000\u040c\u00b6\u0001\u0000\u0000"+
-    "\u0000\u040d\u040e\u0005}\u0000\u0000\u040e\u00b8\u0001\u0000\u0000\u0000"+
-    "\u040f\u0410\u0005?\u0000\u0000\u0410\u0411\u0005?\u0000\u0000\u0411\u00ba"+
-    "\u0001\u0000\u0000\u0000\u0412\u0413\u00031\u0010\u0000\u0413\u0414\u0001"+
-    "\u0000\u0000\u0000\u0414\u0415\u0006U\u000e\u0000\u0415\u00bc\u0001\u0000"+
-    "\u0000\u0000\u0416\u0419\u0003\u0093A\u0000\u0417\u041a\u0003Q \u0000"+
-    "\u0418\u041a\u0003_\'\u0000\u0419\u0417\u0001\u0000\u0000\u0000\u0419"+
-    "\u0418\u0001\u0000\u0000\u0000\u041a\u041e\u0001\u0000\u0000\u0000\u041b"+
-    "\u041d\u0003a(\u0000\u041c\u041b\u0001\u0000\u0000\u0000\u041d\u0420\u0001"+
-    "\u0000\u0000\u0000\u041e\u041c\u0001\u0000\u0000\u0000\u041e\u041f\u0001"+
-    "\u0000\u0000\u0000\u041f\u0428\u0001\u0000\u0000\u0000\u0420\u041e\u0001"+
-    "\u0000\u0000\u0000\u0421\u0423\u0003\u0093A\u0000\u0422\u0424\u0003O\u001f"+
-    "\u0000\u0423\u0422\u0001\u0000\u0000\u0000\u0424\u0425\u0001\u0000\u0000"+
-    "\u0000\u0425\u0423\u0001\u0000\u0000\u0000\u0425\u0426\u0001\u0000\u0000"+
-    "\u0000\u0426\u0428\u0001\u0000\u0000\u0000\u0427\u0416\u0001\u0000\u0000"+
-    "\u0000\u0427\u0421\u0001\u0000\u0000\u0000\u0428\u00be\u0001\u0000\u0000"+
-    "\u0000\u0429\u042c\u0003\u00b9T\u0000\u042a\u042d\u0003Q \u0000\u042b"+
-    "\u042d\u0003_\'\u0000\u042c\u042a\u0001\u0000\u0000\u0000\u042c\u042b"+
-    "\u0001\u0000\u0000\u0000\u042d\u0431\u0001\u0000\u0000\u0000\u042e\u0430"+
-    "\u0003a(\u0000\u042f\u042e\u0001\u0000\u0000\u0000\u0430\u0433\u0001\u0000"+
-    "\u0000\u0000\u0431\u042f\u0001\u0000\u0000\u0000\u0431\u0432\u0001\u0000"+
-    "\u0000\u0000\u0432\u043b\u0001\u0000\u0000\u0000\u0433\u0431\u0001\u0000"+
-    "\u0000\u0000\u0434\u0436\u0003\u00b9T\u0000\u0435\u0437\u0003O\u001f\u0000"+
-    "\u0436\u0435\u0001\u0000\u0000\u0000\u0437\u0438\u0001\u0000\u0000\u0000"+
-    "\u0438\u0436\u0001\u0000\u0000\u0000\u0438\u0439\u0001\u0000\u0000\u0000"+
-    "\u0439\u043b\u0001\u0000\u0000\u0000\u043a\u0429\u0001\u0000\u0000\u0000"+
-    "\u043a\u0434\u0001\u0000\u0000\u0000\u043b\u00c0\u0001\u0000\u0000\u0000"+
-    "\u043c\u043d\u0005[\u0000\u0000\u043d\u043e\u0001\u0000\u0000\u0000\u043e"+
-    "\u043f\u0006X\u0000\u0000\u043f\u0440\u0006X\u0000\u0000\u0440\u00c2\u0001"+
-    "\u0000\u0000\u0000\u0441\u0442\u0005]\u0000\u0000\u0442\u0443\u0001\u0000"+
-    "\u0000\u0000\u0443\u0444\u0006Y\r\u0000\u0444\u0445\u0006Y\r\u0000\u0445"+
-    "\u00c4\u0001\u0000\u0000\u0000\u0446\u044a\u0003Q \u0000\u0447\u0449\u0003"+
-    "a(\u0000\u0448\u0447\u0001\u0000\u0000\u0000\u0449\u044c\u0001\u0000\u0000"+
-    "\u0000\u044a\u0448\u0001\u0000\u0000\u0000\u044a\u044b\u0001\u0000\u0000"+
-    "\u0000\u044b\u0457\u0001\u0000\u0000\u0000\u044c\u044a\u0001\u0000\u0000"+
-    "\u0000\u044d\u0450\u0003_\'\u0000\u044e\u0450\u0003Y$\u0000\u044f\u044d"+
-    "\u0001\u0000\u0000\u0000\u044f\u044e\u0001\u0000\u0000\u0000\u0450\u0452"+
-    "\u0001\u0000\u0000\u0000\u0451\u0453\u0003a(\u0000\u0452\u0451\u0001\u0000"+
-    "\u0000\u0000\u0453\u0454\u0001\u0000\u0000\u0000\u0454\u0452\u0001\u0000"+
-    "\u0000\u0000\u0454\u0455\u0001\u0000\u0000\u0000\u0455\u0457\u0001\u0000"+
-    "\u0000\u0000\u0456\u0446\u0001\u0000\u0000\u0000\u0456\u044f\u0001\u0000"+
-    "\u0000\u0000\u0457\u00c6\u0001\u0000\u0000\u0000\u0458\u045a\u0003[%\u0000"+
-    "\u0459\u045b\u0003]&\u0000\u045a\u0459\u0001\u0000\u0000\u0000\u045b\u045c"+
-    "\u0001\u0000\u0000\u0000\u045c\u045a\u0001\u0000\u0000\u0000\u045c\u045d"+
-    "\u0001\u0000\u0000\u0000\u045d\u045e\u0001\u0000\u0000\u0000\u045e\u045f"+
-    "\u0003[%\u0000\u045f\u00c8\u0001\u0000\u0000\u0000\u0460\u0461\u0003\u00c7"+
-    "[\u0000\u0461\u00ca\u0001\u0000\u0000\u0000\u0462\u0463\u0003G\u001b\u0000"+
-    "\u0463\u0464\u0001\u0000\u0000\u0000\u0464\u0465\u0006]\f\u0000\u0465"+
-    "\u00cc\u0001\u0000\u0000\u0000\u0466\u0467\u0003I\u001c\u0000\u0467\u0468"+
-    "\u0001\u0000\u0000\u0000\u0468\u0469\u0006^\f\u0000\u0469\u00ce\u0001"+
-    "\u0000\u0000\u0000\u046a\u046b\u0003K\u001d\u0000\u046b\u046c\u0001\u0000"+
-    "\u0000\u0000\u046c\u046d\u0006_\f\u0000\u046d\u00d0\u0001\u0000\u0000"+
-    "\u0000\u046e\u046f\u0003\u00c1X\u0000\u046f\u0470\u0001\u0000\u0000\u0000"+
-    "\u0470\u0471\u0006`\u000f\u0000\u0471\u0472\u0006`\u0010\u0000\u0472\u00d2"+
-    "\u0001\u0000\u0000\u0000\u0473\u0474\u0003M\u001e\u0000\u0474\u0475\u0001"+
-    "\u0000\u0000\u0000\u0475\u0476\u0006a\u0011\u0000\u0476\u0477\u0006a\r"+
-    "\u0000\u0477\u00d4\u0001\u0000\u0000\u0000\u0478\u0479\u0003K\u001d\u0000"+
-    "\u0479\u047a\u0001\u0000\u0000\u0000\u047a\u047b\u0006b\f\u0000\u047b"+
-    "\u00d6\u0001\u0000\u0000\u0000\u047c\u047d\u0003G\u001b\u0000\u047d\u047e"+
-    "\u0001\u0000\u0000\u0000\u047e\u047f\u0006c\f\u0000\u047f\u00d8\u0001"+
-    "\u0000\u0000\u0000\u0480\u0481\u0003I\u001c\u0000\u0481\u0482\u0001\u0000"+
-    "\u0000\u0000\u0482\u0483\u0006d\f\u0000\u0483\u00da\u0001\u0000\u0000"+
-    "\u0000\u0484\u0485\u0003M\u001e\u0000\u0485\u0486\u0001\u0000\u0000\u0000"+
-    "\u0486\u0487\u0006e\u0011\u0000\u0487\u0488\u0006e\r\u0000\u0488\u00dc"+
-    "\u0001\u0000\u0000\u0000\u0489\u048a\u0003\u00c1X\u0000\u048a\u048b\u0001"+
-    "\u0000\u0000\u0000\u048b\u048c\u0006f\u000f\u0000\u048c\u00de\u0001\u0000"+
-    "\u0000\u0000\u048d\u048e\u0003\u00c3Y\u0000\u048e\u048f\u0001\u0000\u0000"+
-    "\u0000\u048f\u0490\u0006g\u0012\u0000\u0490\u00e0\u0001\u0000\u0000\u0000"+
-    "\u0491\u0492\u0003s1\u0000\u0492\u0493\u0001\u0000\u0000\u0000\u0493\u0494"+
-    "\u0006h\u0013\u0000\u0494\u00e2\u0001\u0000\u0000\u0000\u0495\u0496\u0003"+
-    "q0\u0000\u0496\u0497\u0001\u0000\u0000\u0000\u0497\u0498\u0006i\u0014"+
-    "\u0000\u0498\u00e4\u0001\u0000\u0000\u0000\u0499\u049a\u0003u2\u0000\u049a"+
-    "\u049b\u0001\u0000\u0000\u0000\u049b\u049c\u0006j\u0015\u0000\u049c\u00e6"+
-    "\u0001\u0000\u0000\u0000\u049d\u049e\u0003m.\u0000\u049e\u049f\u0001\u0000"+
-    "\u0000\u0000\u049f\u04a0\u0006k\u0016\u0000\u04a0\u00e8\u0001\u0000\u0000"+
-    "\u0000\u04a1\u04a2\u0007\u0002\u0000\u0000\u04a2\u04a3\u0007\u0005\u0000"+
-    "\u0000\u04a3\u04a4\u0007\u0006\u0000\u0000\u04a4\u04a5\u0007\u000e\u0000"+
-    "\u0000\u04a5\u04a6\u0007\t\u0000\u0000\u04a6\u04a7\u0007\u000e\u0000\u0000"+
-    "\u04a7\u04a8\u0007\u0006\u0000\u0000\u04a8\u04a9\u0007\u000e\u0000\u0000"+
-    "\u04a9\u00ea\u0001\u0000\u0000\u0000\u04aa\u04ae\b \u0000\u0000\u04ab"+
-    "\u04ac\u0005/\u0000\u0000\u04ac\u04ae\b!\u0000\u0000\u04ad\u04aa\u0001"+
-    "\u0000\u0000\u0000\u04ad\u04ab\u0001\u0000\u0000\u0000\u04ae\u00ec\u0001"+
-    "\u0000\u0000\u0000\u04af\u04b1\u0003\u00ebm\u0000\u04b0\u04af\u0001\u0000"+
-    "\u0000\u0000\u04b1\u04b2\u0001\u0000\u0000\u0000\u04b2\u04b0\u0001\u0000"+
-    "\u0000\u0000\u04b2\u04b3\u0001\u0000\u0000\u0000\u04b3\u00ee\u0001\u0000"+
-    "\u0000\u0000\u04b4\u04b5\u0003\u00edn\u0000\u04b5\u04b6\u0001\u0000\u0000"+
-    "\u0000\u04b6\u04b7\u0006o\u0017\u0000\u04b7\u00f0\u0001\u0000\u0000\u0000"+
-    "\u04b8\u04b9\u0003c)\u0000\u04b9\u04ba\u0001\u0000\u0000\u0000\u04ba\u04bb"+
-    "\u0006p\u0018\u0000\u04bb\u00f2\u0001\u0000\u0000\u0000\u04bc\u04bd\u0003"+
-    "G\u001b\u0000\u04bd\u04be\u0001\u0000\u0000\u0000\u04be\u04bf\u0006q\f"+
-    "\u0000\u04bf\u00f4\u0001\u0000\u0000\u0000\u04c0\u04c1\u0003I\u001c\u0000"+
-    "\u04c1\u04c2\u0001\u0000\u0000\u0000\u04c2\u04c3\u0006r\f\u0000\u04c3"+
-    "\u00f6\u0001\u0000\u0000\u0000\u04c4\u04c5\u0003K\u001d\u0000\u04c5\u04c6"+
-    "\u0001\u0000\u0000\u0000\u04c6\u04c7\u0006s\f\u0000\u04c7\u00f8\u0001"+
-    "\u0000\u0000\u0000\u04c8\u04c9\u0003M\u001e\u0000\u04c9\u04ca\u0001\u0000"+
-    "\u0000\u0000\u04ca\u04cb\u0006t\u0011\u0000\u04cb\u04cc\u0006t\r\u0000"+
-    "\u04cc\u00fa\u0001\u0000\u0000\u0000\u04cd\u04ce\u0003y4\u0000\u04ce\u04cf"+
-    "\u0001\u0000\u0000\u0000\u04cf\u04d0\u0006u\u0019\u0000\u04d0\u00fc\u0001"+
-    "\u0000\u0000\u0000\u04d1\u04d2\u0003u2\u0000\u04d2\u04d3\u0001\u0000\u0000"+
-    "\u0000\u04d3\u04d4\u0006v\u0015\u0000\u04d4\u00fe\u0001\u0000\u0000\u0000"+
-    "\u04d5\u04d6\u0003\u0093A\u0000\u04d6\u04d7\u0001\u0000\u0000\u0000\u04d7"+
-    "\u04d8\u0006w\u001a\u0000\u04d8\u0100\u0001\u0000\u0000\u0000\u04d9\u04da"+
-    "\u0003\u00bdV\u0000\u04da\u04db\u0001\u0000\u0000\u0000\u04db\u04dc\u0006"+
-    "x\u001b\u0000\u04dc\u0102\u0001\u0000\u0000\u0000\u04dd\u04de\u0003\u00b9"+
-    "T\u0000\u04de\u04df\u0001\u0000\u0000\u0000\u04df\u04e0\u0006y\u001c\u0000"+
-    "\u04e0\u0104\u0001\u0000\u0000\u0000\u04e1\u04e2\u0003\u00bfW\u0000\u04e2"+
-    "\u04e3\u0001\u0000\u0000\u0000\u04e3\u04e4\u0006z\u001d\u0000\u04e4\u0106"+
-    "\u0001\u0000\u0000\u0000\u04e5\u04ea\u0003Q \u0000\u04e6\u04ea\u0003O"+
-    "\u001f\u0000\u04e7\u04ea\u0003_\'\u0000\u04e8\u04ea\u0003\u00afO\u0000"+
-    "\u04e9\u04e5\u0001\u0000\u0000\u0000\u04e9\u04e6\u0001\u0000\u0000\u0000"+
-    "\u04e9\u04e7\u0001\u0000\u0000\u0000\u04e9\u04e8\u0001\u0000\u0000\u0000"+
-    "\u04ea\u0108\u0001\u0000\u0000\u0000\u04eb\u04ee\u0003Q \u0000\u04ec\u04ee"+
-    "\u0003\u00afO\u0000\u04ed\u04eb\u0001\u0000\u0000\u0000\u04ed\u04ec\u0001"+
-    "\u0000\u0000\u0000\u04ee\u04f2\u0001\u0000\u0000\u0000\u04ef\u04f1\u0003"+
-    "\u0107{\u0000\u04f0\u04ef\u0001\u0000\u0000\u0000\u04f1\u04f4\u0001\u0000"+
-    "\u0000\u0000\u04f2\u04f0\u0001\u0000\u0000\u0000\u04f2\u04f3\u0001\u0000"+
-    "\u0000\u0000\u04f3\u04ff\u0001\u0000\u0000\u0000\u04f4\u04f2\u0001\u0000"+
-    "\u0000\u0000\u04f5\u04f8\u0003_\'\u0000\u04f6\u04f8\u0003Y$\u0000\u04f7"+
-    "\u04f5\u0001\u0000\u0000\u0000\u04f7\u04f6\u0001\u0000\u0000\u0000\u04f8"+
-    "\u04fa\u0001\u0000\u0000\u0000\u04f9\u04fb\u0003\u0107{\u0000\u04fa\u04f9"+
-    "\u0001\u0000\u0000\u0000\u04fb\u04fc\u0001\u0000\u0000\u0000\u04fc\u04fa"+
-    "\u0001\u0000\u0000\u0000\u04fc\u04fd\u0001\u0000\u0000\u0000\u04fd\u04ff"+
-    "\u0001\u0000\u0000\u0000\u04fe\u04ed\u0001\u0000\u0000\u0000\u04fe\u04f7"+
-    "\u0001\u0000\u0000\u0000\u04ff\u010a\u0001\u0000\u0000\u0000\u0500\u0503"+
-    "\u0003\u0109|\u0000\u0501\u0503\u0003\u00c7[\u0000\u0502\u0500\u0001\u0000"+
-    "\u0000\u0000\u0502\u0501\u0001\u0000\u0000\u0000\u0503\u0504\u0001\u0000"+
-    "\u0000\u0000\u0504\u0502\u0001\u0000\u0000\u0000\u0504\u0505\u0001\u0000"+
-    "\u0000\u0000\u0505\u010c\u0001\u0000\u0000\u0000\u0506\u0507\u0003G\u001b"+
-    "\u0000\u0507\u0508\u0001\u0000\u0000\u0000\u0508\u0509\u0006~\f\u0000"+
-    "\u0509\u010e\u0001\u0000\u0000\u0000\u050a\u050b\u0003I\u001c\u0000\u050b"+
-    "\u050c\u0001\u0000\u0000\u0000\u050c\u050d\u0006\u007f\f\u0000\u050d\u0110"+
-    "\u0001\u0000\u0000\u0000\u050e\u050f\u0003K\u001d\u0000\u050f\u0510\u0001"+
-    "\u0000\u0000\u0000\u0510\u0511\u0006\u0080\f\u0000\u0511\u0112\u0001\u0000"+
-    "\u0000\u0000\u0512\u0513\u0003M\u001e\u0000\u0513\u0514\u0001\u0000\u0000"+
-    "\u0000\u0514\u0515\u0006\u0081\u0011\u0000\u0515\u0516\u0006\u0081\r\u0000"+
-    "\u0516\u0114\u0001\u0000\u0000\u0000\u0517\u0518\u0003m.\u0000\u0518\u0519"+
-    "\u0001\u0000\u0000\u0000\u0519\u051a\u0006\u0082\u0016\u0000\u051a\u0116"+
-    "\u0001\u0000\u0000\u0000\u051b\u051c\u0003u2\u0000\u051c\u051d\u0001\u0000"+
-    "\u0000\u0000\u051d\u051e\u0006\u0083\u0015\u0000\u051e\u0118\u0001\u0000"+
-    "\u0000\u0000\u051f\u0520\u0003y4\u0000\u0520\u0521\u0001\u0000\u0000\u0000"+
-    "\u0521\u0522\u0006\u0084\u0019\u0000\u0522\u011a\u0001\u0000\u0000\u0000"+
-    "\u0523\u0524\u0003\u0093A\u0000\u0524\u0525\u0001\u0000\u0000\u0000\u0525"+
-    "\u0526\u0006\u0085\u001a\u0000\u0526\u011c\u0001\u0000\u0000\u0000\u0527"+
-    "\u0528\u0003\u00bdV\u0000\u0528\u0529\u0001\u0000\u0000\u0000\u0529\u052a"+
-    "\u0006\u0086\u001b\u0000\u052a\u011e\u0001\u0000\u0000\u0000\u052b\u052c"+
-    "\u0003\u00b9T\u0000\u052c\u052d\u0001\u0000\u0000\u0000\u052d\u052e\u0006"+
-    "\u0087\u001c\u0000\u052e\u0120\u0001\u0000\u0000\u0000\u052f\u0530\u0003"+
-    "\u00bfW\u0000\u0530\u0531\u0001\u0000\u0000\u0000\u0531\u0532\u0006\u0088"+
-    "\u001d\u0000\u0532\u0122\u0001\u0000\u0000\u0000\u0533\u0534\u0007\u000e"+
-    "\u0000\u0000\u0534\u0535\u0007\n\u0000\u0000\u0535\u0124\u0001\u0000\u0000"+
-    "\u0000\u0536\u0537\u0003\u010b}\u0000\u0537\u0538\u0001\u0000\u0000\u0000"+
-    "\u0538\u0539\u0006\u008a\u001e\u0000\u0539\u0126\u0001\u0000\u0000\u0000"+
-    "\u053a\u053b\u0003G\u001b\u0000\u053b\u053c\u0001\u0000\u0000\u0000\u053c"+
-    "\u053d\u0006\u008b\f\u0000\u053d\u0128\u0001\u0000\u0000\u0000\u053e\u053f"+
-    "\u0003I\u001c\u0000\u053f\u0540\u0001\u0000\u0000\u0000\u0540\u0541\u0006"+
-    "\u008c\f\u0000\u0541\u012a\u0001\u0000\u0000\u0000\u0542\u0543\u0003K"+
-    "\u001d\u0000\u0543\u0544\u0001\u0000\u0000\u0000\u0544\u0545\u0006\u008d"+
-    "\f\u0000\u0545\u012c\u0001\u0000\u0000\u0000\u0546\u0547\u0003M\u001e"+
-    "\u0000\u0547\u0548\u0001\u0000\u0000\u0000\u0548\u0549\u0006\u008e\u0011"+
-    "\u0000\u0549\u054a\u0006\u008e\r\u0000\u054a\u012e\u0001\u0000\u0000\u0000"+
-    "\u054b\u054c\u0003\u00c1X\u0000\u054c\u054d\u0001\u0000\u0000\u0000\u054d"+
-    "\u054e\u0006\u008f\u000f\u0000\u054e\u054f\u0006\u008f\u001f\u0000\u054f"+
-    "\u0130\u0001\u0000\u0000\u0000\u0550\u0551\u0003\u008f?\u0000\u0551\u0552"+
-    "\u0001\u0000\u0000\u0000\u0552\u0553\u0006\u0090 \u0000\u0553\u0554\u0006"+
-    "\u0090!\u0000\u0554\u0132\u0001\u0000\u0000\u0000\u0555\u0556\u0003\u009b"+
-    "E\u0000\u0556\u0557\u0001\u0000\u0000\u0000\u0557\u0558\u0006\u0091\""+
-    "\u0000\u0558\u0559\u0006\u0091!\u0000\u0559\u0134\u0001\u0000\u0000\u0000"+
-    "\u055a\u055b\b\"\u0000\u0000\u055b\u0136\u0001\u0000\u0000\u0000\u055c"+
-    "\u055e\u0003\u0135\u0092\u0000\u055d\u055c\u0001\u0000\u0000\u0000\u055e"+
-    "\u055f\u0001\u0000\u0000\u0000\u055f\u055d\u0001\u0000\u0000\u0000\u055f"+
-    "\u0560\u0001\u0000\u0000\u0000\u0560\u0561\u0001\u0000\u0000\u0000\u0561"+
-    "\u0562\u0003s1\u0000\u0562\u0564\u0001\u0000\u0000\u0000\u0563\u055d\u0001"+
-    "\u0000\u0000\u0000\u0563\u0564\u0001\u0000\u0000\u0000\u0564\u0566\u0001"+
-    "\u0000\u0000\u0000\u0565\u0567\u0003\u0135\u0092\u0000\u0566\u0565\u0001"+
-    "\u0000\u0000\u0000\u0567\u0568\u0001\u0000\u0000\u0000\u0568\u0566\u0001"+
-    "\u0000\u0000\u0000\u0568\u0569\u0001\u0000\u0000\u0000\u0569\u0138\u0001"+
-    "\u0000\u0000\u0000\u056a\u056b\u0003\u0137\u0093\u0000\u056b\u056c\u0001"+
-    "\u0000\u0000\u0000\u056c\u056d\u0006\u0094#\u0000\u056d\u013a\u0001\u0000"+
-    "\u0000\u0000\u056e\u056f\u0003G\u001b\u0000\u056f\u0570\u0001\u0000\u0000"+
-    "\u0000\u0570\u0571\u0006\u0095\f\u0000\u0571\u013c\u0001\u0000\u0000\u0000"+
-    "\u0572\u0573\u0003I\u001c\u0000\u0573\u0574\u0001\u0000\u0000\u0000\u0574"+
-    "\u0575\u0006\u0096\f\u0000\u0575\u013e\u0001\u0000\u0000\u0000\u0576\u0577"+
-    "\u0003K\u001d\u0000\u0577\u0578\u0001\u0000\u0000\u0000\u0578\u0579\u0006"+
-    "\u0097\f\u0000\u0579\u0140\u0001\u0000\u0000\u0000\u057a\u057b\u0003M"+
-    "\u001e\u0000\u057b\u057c\u0001\u0000\u0000\u0000\u057c\u057d\u0006\u0098"+
-    "\u0011\u0000\u057d\u057e\u0006\u0098\r\u0000\u057e\u057f\u0006\u0098\r"+
-    "\u0000\u057f\u0142\u0001\u0000\u0000\u0000\u0580\u0581\u0003m.\u0000\u0581"+
-    "\u0582\u0001\u0000\u0000\u0000\u0582\u0583\u0006\u0099\u0016\u0000\u0583"+
-    "\u0144\u0001\u0000\u0000\u0000\u0584\u0585\u0003u2\u0000\u0585\u0586\u0001"+
-    "\u0000\u0000\u0000\u0586\u0587\u0006\u009a\u0015\u0000\u0587\u0146\u0001"+
-    "\u0000\u0000\u0000\u0588\u0589\u0003y4\u0000\u0589\u058a\u0001\u0000\u0000"+
-    "\u0000\u058a\u058b\u0006\u009b\u0019\u0000\u058b\u0148\u0001\u0000\u0000"+
-    "\u0000\u058c\u058d\u0003\u009bE\u0000\u058d\u058e\u0001\u0000\u0000\u0000"+
-    "\u058e\u058f\u0006\u009c\"\u0000\u058f\u014a\u0001\u0000\u0000\u0000\u0590"+
-    "\u0591\u0003\u010b}\u0000\u0591\u0592\u0001\u0000\u0000\u0000\u0592\u0593"+
-    "\u0006\u009d\u001e\u0000\u0593\u014c\u0001\u0000\u0000\u0000\u0594\u0595"+
-    "\u0003\u00c9\\\u0000\u0595\u0596\u0001\u0000\u0000\u0000\u0596\u0597\u0006"+
-    "\u009e$\u0000\u0597\u014e\u0001\u0000\u0000\u0000\u0598\u0599\u0003\u0093"+
-    "A\u0000\u0599\u059a\u0001\u0000\u0000\u0000\u059a\u059b\u0006\u009f\u001a"+
-    "\u0000\u059b\u0150\u0001\u0000\u0000\u0000\u059c\u059d\u0003\u00bdV\u0000"+
-    "\u059d\u059e\u0001\u0000\u0000\u0000\u059e\u059f\u0006\u00a0\u001b\u0000"+
-    "\u059f\u0152\u0001\u0000\u0000\u0000\u05a0\u05a1\u0003\u00b9T\u0000\u05a1"+
-    "\u05a2\u0001\u0000\u0000\u0000\u05a2\u05a3\u0006\u00a1\u001c\u0000\u05a3"+
-    "\u0154\u0001\u0000\u0000\u0000\u05a4\u05a5\u0003\u00bfW\u0000\u05a5\u05a6"+
-    "\u0001\u0000\u0000\u0000\u05a6\u05a7\u0006\u00a2\u001d\u0000\u05a7\u0156"+
-    "\u0001\u0000\u0000\u0000\u05a8\u05a9\u0003G\u001b\u0000\u05a9\u05aa\u0001"+
-    "\u0000\u0000\u0000\u05aa\u05ab\u0006\u00a3\f\u0000\u05ab\u0158\u0001\u0000"+
-    "\u0000\u0000\u05ac\u05ad\u0003I\u001c\u0000\u05ad\u05ae\u0001\u0000\u0000"+
-    "\u0000\u05ae\u05af\u0006\u00a4\f\u0000\u05af\u015a\u0001\u0000\u0000\u0000"+
-    "\u05b0\u05b1\u0003K\u001d\u0000\u05b1\u05b2\u0001\u0000\u0000\u0000\u05b2"+
-    "\u05b3\u0006\u00a5\f\u0000\u05b3\u015c\u0001\u0000\u0000\u0000\u05b4\u05b5"+
-    "\u0003M\u001e\u0000\u05b5\u05b6\u0001\u0000\u0000\u0000\u05b6\u05b7\u0006"+
-    "\u00a6\u0011\u0000\u05b7\u05b8\u0006\u00a6\r\u0000\u05b8\u015e\u0001\u0000"+
-    "\u0000\u0000\u05b9\u05ba\u0003y4\u0000\u05ba\u05bb\u0001\u0000\u0000\u0000"+
-    "\u05bb\u05bc\u0006\u00a7\u0019\u0000\u05bc\u0160\u0001\u0000\u0000\u0000"+
-    "\u05bd\u05be\u0003\u0093A\u0000\u05be\u05bf\u0001\u0000\u0000\u0000\u05bf"+
-    "\u05c0\u0006\u00a8\u001a\u0000\u05c0\u0162\u0001\u0000\u0000\u0000\u05c1"+
-    "\u05c2\u0003\u00bdV\u0000\u05c2\u05c3\u0001\u0000\u0000\u0000\u05c3\u05c4"+
-    "\u0006\u00a9\u001b\u0000\u05c4\u0164\u0001\u0000\u0000\u0000\u05c5\u05c6"+
-    "\u0003\u00b9T\u0000\u05c6\u05c7\u0001\u0000\u0000\u0000\u05c7\u05c8\u0006"+
-    "\u00aa\u001c\u0000\u05c8\u0166\u0001\u0000\u0000\u0000\u05c9\u05ca\u0003"+
-    "\u00bfW\u0000\u05ca\u05cb\u0001\u0000\u0000\u0000\u05cb\u05cc\u0006\u00ab"+
-    "\u001d\u0000\u05cc\u0168\u0001\u0000\u0000\u0000\u05cd\u05ce\u0003\u00c9"+
-    "\\\u0000\u05ce\u05cf\u0001\u0000\u0000\u0000\u05cf\u05d0\u0006\u00ac$"+
-    "\u0000\u05d0\u016a\u0001\u0000\u0000\u0000\u05d1\u05d2\u0003\u00c5Z\u0000"+
-    "\u05d2\u05d3\u0001\u0000\u0000\u0000\u05d3\u05d4\u0006\u00ad%\u0000\u05d4"+
-    "\u016c\u0001\u0000\u0000\u0000\u05d5\u05d6\u0003G\u001b\u0000\u05d6\u05d7"+
-    "\u0001\u0000\u0000\u0000\u05d7\u05d8\u0006\u00ae\f\u0000\u05d8\u016e\u0001"+
-    "\u0000\u0000\u0000\u05d9\u05da\u0003I\u001c\u0000\u05da\u05db\u0001\u0000"+
-    "\u0000\u0000\u05db\u05dc\u0006\u00af\f\u0000\u05dc\u0170\u0001\u0000\u0000"+
-    "\u0000\u05dd\u05de\u0003K\u001d\u0000\u05de\u05df\u0001\u0000\u0000\u0000"+
-    "\u05df\u05e0\u0006\u00b0\f\u0000\u05e0\u0172\u0001\u0000\u0000\u0000\u05e1"+
-    "\u05e2\u0003M\u001e\u0000\u05e2\u05e3\u0001\u0000\u0000\u0000\u05e3\u05e4"+
-    "\u0006\u00b1\u0011\u0000\u05e4\u05e5\u0006\u00b1\r\u0000\u05e5\u0174\u0001"+
-    "\u0000\u0000\u0000\u05e6\u05e7\u0007\u0007\u0000\u0000\u05e7\u05e8\u0007"+
-    "\b\u0000\u0000\u05e8\u05e9\u0007\u0010\u0000\u0000\u05e9\u05ea\u0007\u0001"+
-    "\u0000\u0000\u05ea\u0176\u0001\u0000\u0000\u0000\u05eb\u05ec\u0003G\u001b"+
-    "\u0000\u05ec\u05ed\u0001\u0000\u0000\u0000\u05ed\u05ee\u0006\u00b3\f\u0000"+
-    "\u05ee\u0178\u0001\u0000\u0000\u0000\u05ef\u05f0\u0003I\u001c\u0000\u05f0"+
-    "\u05f1\u0001\u0000\u0000\u0000\u05f1\u05f2\u0006\u00b4\f\u0000\u05f2\u017a"+
-    "\u0001\u0000\u0000\u0000\u05f3\u05f4\u0003K\u001d\u0000\u05f4\u05f5\u0001"+
-    "\u0000\u0000\u0000\u05f5\u05f6\u0006\u00b5\f\u0000\u05f6\u017c\u0001\u0000"+
-    "\u0000\u0000\u05f7\u05f8\u0003\u00c3Y\u0000\u05f8\u05f9\u0001\u0000\u0000"+
-    "\u0000\u05f9\u05fa\u0006\u00b6\u0012\u0000\u05fa\u05fb\u0006\u00b6\r\u0000"+
-    "\u05fb\u017e\u0001\u0000\u0000\u0000\u05fc\u05fd\u0003s1\u0000\u05fd\u05fe"+
-    "\u0001\u0000\u0000\u0000\u05fe\u05ff\u0006\u00b7\u0013\u0000\u05ff\u0180"+
-    "\u0001\u0000\u0000\u0000\u0600\u0606\u0003Y$\u0000\u0601\u0606\u0003O"+
-    "\u001f\u0000\u0602\u0606\u0003y4\u0000\u0603\u0606\u0003Q \u0000\u0604"+
-    "\u0606\u0003_\'\u0000\u0605\u0600\u0001\u0000\u0000\u0000\u0605\u0601"+
-    "\u0001\u0000\u0000\u0000\u0605\u0602\u0001\u0000\u0000\u0000\u0605\u0603"+
-    "\u0001\u0000\u0000\u0000\u0605\u0604\u0001\u0000\u0000\u0000\u0606\u0607"+
-    "\u0001\u0000\u0000\u0000\u0607\u0605\u0001\u0000\u0000\u0000\u0607\u0608"+
-    "\u0001\u0000\u0000\u0000\u0608\u0182\u0001\u0000\u0000\u0000\u0609\u060a"+
-    "\u0003G\u001b\u0000\u060a\u060b\u0001\u0000\u0000\u0000\u060b\u060c\u0006"+
-    "\u00b9\f\u0000\u060c\u0184\u0001\u0000\u0000\u0000\u060d\u060e\u0003I"+
-    "\u001c\u0000\u060e\u060f\u0001\u0000\u0000\u0000\u060f\u0610\u0006\u00ba"+
-    "\f\u0000\u0610\u0186\u0001\u0000\u0000\u0000\u0611\u0612\u0003K\u001d"+
-    "\u0000\u0612\u0613\u0001\u0000\u0000\u0000\u0613\u0614\u0006\u00bb\f\u0000"+
-    "\u0614\u0188\u0001\u0000\u0000\u0000\u0615\u0616\u0003M\u001e\u0000\u0616"+
-    "\u0617\u0001\u0000\u0000\u0000\u0617\u0618\u0006\u00bc\u0011\u0000\u0618"+
-    "\u0619\u0006\u00bc\r\u0000\u0619\u018a\u0001\u0000\u0000\u0000\u061a\u061b"+
-    "\u0003s1\u0000\u061b\u061c\u0001\u0000\u0000\u0000\u061c\u061d\u0006\u00bd"+
-    "\u0013\u0000\u061d\u018c\u0001\u0000\u0000\u0000\u061e\u061f\u0003u2\u0000"+
-    "\u061f\u0620\u0001\u0000\u0000\u0000\u0620\u0621\u0006\u00be\u0015\u0000"+
-    "\u0621\u018e\u0001\u0000\u0000\u0000\u0622\u0623\u0003y4\u0000\u0623\u0624"+
-    "\u0001\u0000\u0000\u0000\u0624\u0625\u0006\u00bf\u0019\u0000\u0625\u0190"+
-    "\u0001\u0000\u0000\u0000\u0626\u0627\u0003\u008f?\u0000\u0627\u0628\u0001"+
-    "\u0000\u0000\u0000\u0628\u0629\u0006\u00c0 \u0000\u0629\u062a\u0006\u00c0"+
-    "&\u0000\u062a\u0192\u0001\u0000\u0000\u0000\u062b\u062c\u0003\u00edn\u0000"+
-    "\u062c\u062d\u0001\u0000\u0000\u0000\u062d\u062e\u0006\u00c1\u0017\u0000"+
-    "\u062e\u0194\u0001\u0000\u0000\u0000\u062f\u0630\u0003c)\u0000\u0630\u0631"+
-    "\u0001\u0000\u0000\u0000\u0631\u0632\u0006\u00c2\u0018\u0000\u0632\u0196"+
-    "\u0001\u0000\u0000\u0000\u0633\u0634\u0003G\u001b\u0000\u0634\u0635\u0001"+
-    "\u0000\u0000\u0000\u0635\u0636\u0006\u00c3\f\u0000\u0636\u0198\u0001\u0000"+
-    "\u0000\u0000\u0637\u0638\u0003I\u001c\u0000\u0638\u0639\u0001\u0000\u0000"+
-    "\u0000\u0639\u063a\u0006\u00c4\f\u0000\u063a\u019a\u0001\u0000\u0000\u0000"+
-    "\u063b\u063c\u0003K\u001d\u0000\u063c\u063d\u0001\u0000\u0000\u0000\u063d"+
-    "\u063e\u0006\u00c5\f\u0000\u063e\u019c\u0001\u0000\u0000\u0000\u063f\u0640"+
-    "\u0003M\u001e\u0000\u0640\u0641\u0001\u0000\u0000\u0000\u0641\u0642\u0006"+
-    "\u00c6\u0011\u0000\u0642\u0643\u0006\u00c6\r\u0000\u0643\u0644\u0006\u00c6"+
-    "\r\u0000\u0644\u019e\u0001\u0000\u0000\u0000\u0645\u0646\u0003u2\u0000"+
-    "\u0646\u0647\u0001\u0000\u0000\u0000\u0647\u0648\u0006\u00c7\u0015\u0000"+
-    "\u0648\u01a0\u0001\u0000\u0000\u0000\u0649\u064a\u0003y4\u0000\u064a\u064b"+
-    "\u0001\u0000\u0000\u0000\u064b\u064c\u0006\u00c8\u0019\u0000\u064c\u01a2"+
-    "\u0001\u0000\u0000\u0000\u064d\u064e\u0003\u010b}\u0000\u064e\u064f\u0001"+
-    "\u0000\u0000\u0000\u064f\u0650\u0006\u00c9\u001e\u0000\u0650\u01a4\u0001"+
-    "\u0000\u0000\u0000\u0651\u0652\u0003G\u001b\u0000\u0652\u0653\u0001\u0000"+
-    "\u0000\u0000\u0653\u0654\u0006\u00ca\f\u0000\u0654\u01a6\u0001\u0000\u0000"+
-    "\u0000\u0655\u0656\u0003I\u001c\u0000\u0656\u0657\u0001\u0000\u0000\u0000"+
-    "\u0657\u0658\u0006\u00cb\f\u0000\u0658\u01a8\u0001\u0000\u0000\u0000\u0659"+
-    "\u065a\u0003K\u001d\u0000\u065a\u065b\u0001\u0000\u0000\u0000\u065b\u065c"+
-    "\u0006\u00cc\f\u0000\u065c\u01aa\u0001\u0000\u0000\u0000\u065d\u065e\u0003"+
-    "M\u001e\u0000\u065e\u065f\u0001\u0000\u0000\u0000\u065f\u0660\u0006\u00cd"+
-    "\u0011\u0000\u0660\u0661\u0006\u00cd\r\u0000\u0661\u01ac\u0001\u0000\u0000"+
-    "\u0000\u0662\u0663\u0007#\u0000\u0000\u0663\u0664\u0007\u0001\u0000\u0000"+
-    "\u0664\u0665\u0007\u0007\u0000\u0000\u0665\u0666\u0007\b\u0000\u0000\u0666"+
-    "\u01ae\u0001\u0000\u0000\u0000\u0667\u0668\u0003\u0123\u0089\u0000\u0668"+
-    "\u0669\u0001\u0000\u0000\u0000\u0669\u066a\u0006\u00cf\'\u0000\u066a\u01b0"+
-    "\u0001\u0000\u0000\u0000\u066b\u066c\u0003\u008f?\u0000\u066c\u066d\u0001"+
-    "\u0000\u0000\u0000\u066d\u066e\u0006\u00d0 \u0000\u066e\u066f\u0006\u00d0"+
-    "\r\u0000\u066f\u0670\u0006\u00d0\u0000\u0000\u0670\u01b2\u0001\u0000\u0000"+
-    "\u0000\u0671\u0672\u0007\u0014\u0000\u0000\u0672\u0673\u0007\n\u0000\u0000"+
-    "\u0673\u0674\u0007\u0007\u0000\u0000\u0674\u0675\u0007\b\u0000\u0000\u0675"+
-    "\u0676\u0007\u0011\u0000\u0000\u0676\u0677\u0001\u0000\u0000\u0000\u0677"+
-    "\u0678\u0006\u00d1\r\u0000\u0678\u0679\u0006\u00d1\u0000\u0000\u0679\u01b4"+
-    "\u0001\u0000\u0000\u0000\u067a\u067b\u0003\u00edn\u0000\u067b\u067c\u0001"+
-    "\u0000\u0000\u0000\u067c\u067d\u0006\u00d2\u0017\u0000\u067d\u01b6\u0001"+
-    "\u0000\u0000\u0000\u067e\u067f\u0003c)\u0000\u067f\u0680\u0001\u0000\u0000"+
-    "\u0000\u0680\u0681\u0006\u00d3\u0018\u0000\u0681\u01b8\u0001\u0000\u0000"+
-    "\u0000\u0682\u0683\u0003s1\u0000\u0683\u0684\u0001\u0000\u0000\u0000\u0684"+
-    "\u0685\u0006\u00d4\u0013\u0000\u0685\u01ba\u0001\u0000\u0000\u0000\u0686"+
-    "\u0687\u0003\u00c5Z\u0000\u0687\u0688\u0001\u0000\u0000\u0000\u0688\u0689"+
-    "\u0006\u00d5%\u0000\u0689\u01bc\u0001\u0000\u0000\u0000\u068a\u068b\u0003"+
-    "\u00c9\\\u0000\u068b\u068c\u0001\u0000\u0000\u0000\u068c\u068d\u0006\u00d6"+
-    "$\u0000\u068d\u01be\u0001\u0000\u0000\u0000\u068e\u068f\u0003G\u001b\u0000"+
-    "\u068f\u0690\u0001\u0000\u0000\u0000\u0690\u0691\u0006\u00d7\f\u0000\u0691"+
-    "\u01c0\u0001\u0000\u0000\u0000\u0692\u0693\u0003I\u001c\u0000\u0693\u0694"+
-    "\u0001\u0000\u0000\u0000\u0694\u0695\u0006\u00d8\f\u0000\u0695\u01c2\u0001"+
-    "\u0000\u0000\u0000\u0696\u0697\u0003K\u001d\u0000\u0697\u0698\u0001\u0000"+
-    "\u0000\u0000\u0698\u0699\u0006\u00d9\f\u0000\u0699\u01c4\u0001\u0000\u0000"+
-    "\u0000\u069a\u069b\u0003M\u001e\u0000\u069b\u069c\u0001\u0000\u0000\u0000"+
-    "\u069c\u069d\u0006\u00da\u0011\u0000\u069d\u069e\u0006\u00da\r\u0000\u069e"+
-    "\u01c6\u0001\u0000\u0000\u0000\u069f\u06a0\u0003\u00edn\u0000\u06a0\u06a1"+
-    "\u0001\u0000\u0000\u0000\u06a1\u06a2\u0006\u00db\u0017\u0000\u06a2\u06a3"+
-    "\u0006\u00db\r\u0000\u06a3\u06a4\u0006\u00db(\u0000\u06a4\u01c8\u0001"+
-    "\u0000\u0000\u0000\u06a5\u06a6\u0003c)\u0000\u06a6\u06a7\u0001\u0000\u0000"+
-    "\u0000\u06a7\u06a8\u0006\u00dc\u0018\u0000\u06a8\u06a9\u0006\u00dc\r\u0000"+
-    "\u06a9\u06aa\u0006\u00dc(\u0000\u06aa\u01ca\u0001\u0000\u0000\u0000\u06ab"+
-    "\u06ac\u0003G\u001b\u0000\u06ac\u06ad\u0001\u0000\u0000\u0000\u06ad\u06ae"+
-    "\u0006\u00dd\f\u0000\u06ae\u01cc\u0001\u0000\u0000\u0000\u06af\u06b0\u0003"+
-    "I\u001c\u0000\u06b0\u06b1\u0001\u0000\u0000\u0000\u06b1\u06b2\u0006\u00de"+
-    "\f\u0000\u06b2\u01ce\u0001\u0000\u0000\u0000\u06b3\u06b4\u0003K\u001d"+
-    "\u0000\u06b4\u06b5\u0001\u0000\u0000\u0000\u06b5\u06b6\u0006\u00df\f\u0000"+
-    "\u06b6\u01d0\u0001\u0000\u0000\u0000\u06b7\u06b8\u0003s1\u0000\u06b8\u06b9"+
-    "\u0001\u0000\u0000\u0000\u06b9\u06ba\u0006\u00e0\u0013\u0000\u06ba\u06bb"+
-    "\u0006\u00e0\r\u0000\u06bb\u06bc\u0006\u00e0\u000b\u0000\u06bc\u01d2\u0001"+
-    "\u0000\u0000\u0000\u06bd\u06be\u0003q0\u0000\u06be\u06bf\u0001\u0000\u0000"+
-    "\u0000\u06bf\u06c0\u0006\u00e1\u0014\u0000\u06c0\u06c1\u0006\u00e1\r\u0000"+
-    "\u06c1\u06c2\u0006\u00e1\u000b\u0000\u06c2\u01d4\u0001\u0000\u0000\u0000"+
-    "\u06c3\u06c4\u0003u2\u0000\u06c4\u06c5\u0001\u0000\u0000\u0000\u06c5\u06c6"+
-    "\u0006\u00e2\u0015\u0000\u06c6\u06c7\u0006\u00e2\r\u0000\u06c7\u06c8\u0006"+
-    "\u00e2\u000b\u0000\u06c8\u01d6\u0001\u0000\u0000\u0000\u06c9\u06ca\u0003"+
-    "G\u001b\u0000\u06ca\u06cb\u0001\u0000\u0000\u0000\u06cb\u06cc\u0006\u00e3"+
-    "\f\u0000\u06cc\u01d8\u0001\u0000\u0000\u0000\u06cd\u06ce\u0003I\u001c"+
-    "\u0000\u06ce\u06cf\u0001\u0000\u0000\u0000\u06cf\u06d0\u0006\u00e4\f\u0000"+
-    "\u06d0\u01da\u0001\u0000\u0000\u0000\u06d1\u06d2\u0003K\u001d\u0000\u06d2"+
-    "\u06d3\u0001\u0000\u0000\u0000\u06d3\u06d4\u0006\u00e5\f\u0000\u06d4\u01dc"+
-    "\u0001\u0000\u0000\u0000\u06d5\u06d6\u0003\u00c9\\\u0000\u06d6\u06d7\u0001"+
-    "\u0000\u0000\u0000\u06d7\u06d8\u0006\u00e6\r\u0000\u06d8\u06d9\u0006\u00e6"+
-    "\u0000\u0000\u06d9\u06da\u0006\u00e6$\u0000\u06da\u01de\u0001\u0000\u0000"+
-    "\u0000\u06db\u06dc\u0003\u00c5Z\u0000\u06dc\u06dd\u0001\u0000\u0000\u0000"+
-    "\u06dd\u06de\u0006\u00e7\r\u0000\u06de\u06df\u0006\u00e7\u0000\u0000\u06df"+
-    "\u06e0\u0006\u00e7%\u0000\u06e0\u01e0\u0001\u0000\u0000\u0000\u06e1\u06e2"+
-    "\u0003o/\u0000\u06e2\u06e3\u0001\u0000\u0000\u0000\u06e3\u06e4\u0006\u00e8"+
-    "\r\u0000\u06e4\u06e5\u0006\u00e8\u0000\u0000\u06e5\u06e6\u0006\u00e8)"+
-    "\u0000\u06e6\u01e2\u0001\u0000\u0000\u0000\u06e7\u06e8\u0003M\u001e\u0000"+
-    "\u06e8\u06e9\u0001\u0000\u0000\u0000\u06e9\u06ea\u0006\u00e9\u0011\u0000"+
-    "\u06ea\u06eb\u0006\u00e9\r\u0000\u06eb\u01e4\u0001\u0000\u0000\u0000\u06ec"+
-    "\u06ed\u0003M\u001e\u0000\u06ed\u06ee\u0001\u0000\u0000\u0000\u06ee\u06ef"+
-    "\u0006\u00ea\u0011\u0000\u06ef\u06f0\u0006\u00ea\r\u0000\u06f0\u01e6\u0001"+
-    "\u0000\u0000\u0000\u06f1\u06f2\u0003\u008f?\u0000\u06f2\u06f3\u0001\u0000"+
-    "\u0000\u0000\u06f3\u06f4\u0006\u00eb \u0000\u06f4\u01e8\u0001\u0000\u0000"+
-    "\u0000\u06f5\u06f6\u0003\u0123\u0089\u0000\u06f6\u06f7\u0001\u0000\u0000"+
-    "\u0000\u06f7\u06f8\u0006\u00ec\'\u0000\u06f8\u01ea\u0001\u0000\u0000\u0000"+
-    "\u06f9\u06fa\u0003y4\u0000\u06fa\u06fb\u0001\u0000\u0000\u0000\u06fb\u06fc"+
-    "\u0006\u00ed\u0019\u0000\u06fc\u01ec\u0001\u0000\u0000\u0000\u06fd\u06fe"+
-    "\u0003u2\u0000\u06fe\u06ff\u0001\u0000\u0000\u0000\u06ff\u0700\u0006\u00ee"+
-    "\u0015\u0000\u0700\u01ee\u0001\u0000\u0000\u0000\u0701\u0702\u0003\u00c9"+
-    "\\\u0000\u0702\u0703\u0001\u0000\u0000\u0000\u0703\u0704\u0006\u00ef$"+
-    "\u0000\u0704\u01f0\u0001\u0000\u0000\u0000\u0705\u0706\u0003\u00c5Z\u0000"+
-    "\u0706\u0707\u0001\u0000\u0000\u0000\u0707\u0708\u0006\u00f0%\u0000\u0708"+
-    "\u01f2\u0001\u0000\u0000\u0000\u0709\u070a\u0003G\u001b\u0000\u070a\u070b"+
-    "\u0001\u0000\u0000\u0000\u070b\u070c\u0006\u00f1\f\u0000\u070c\u01f4\u0001"+
-    "\u0000\u0000\u0000\u070d\u070e\u0003I\u001c\u0000\u070e\u070f\u0001\u0000"+
-    "\u0000\u0000\u070f\u0710\u0006\u00f2\f\u0000\u0710\u01f6\u0001\u0000\u0000"+
-    "\u0000\u0711\u0712\u0003K\u001d\u0000\u0712\u0713\u0001\u0000\u0000\u0000"+
-    "\u0713\u0714\u0006\u00f3\f\u0000\u0714\u01f8\u0001\u0000\u0000\u0000G"+
+    "\u0000\u01f1\u0000\u01f3\u0000\u01f5\u0089\u01f7\u008a\u01f9\u008b\u0011"+
     "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e"+
-    "\u000f\u0010\u02eb\u02f5\u02f9\u02fc\u0305\u0307\u0312\u0325\u032a\u0333"+
-    "\u033a\u033f\u0341\u034c\u0354\u0357\u0359\u035e\u0363\u0369\u0370\u0375"+
-    "\u037b\u037e\u0386\u038a\u0419\u041e\u0425\u0427\u042c\u0431\u0438\u043a"+
-    "\u044a\u044f\u0454\u0456\u045c\u04ad\u04b2\u04e9\u04ed\u04f2\u04f7\u04fc"+
-    "\u04fe\u0502\u0504\u055f\u0563\u0568\u0605\u0607*\u0005\u0001\u0000\u0005"+
-    "\u0004\u0000\u0005\u0006\u0000\u0005\u0002\u0000\u0005\u0003\u0000\u0005"+
-    "\b\u0000\u0005\u0005\u0000\u0005\t\u0000\u0005\r\u0000\u0005\u0010\u0000"+
-    "\u0005\u000b\u0000\u0005\u000e\u0000\u0000\u0001\u0000\u0004\u0000\u0000"+
-    "\u0007\u0011\u0000\u0007N\u0000\u0005\u0000\u0000\u0007\u001f\u0000\u0007"+
-    "O\u0000\u0007(\u0000\u0007\'\u0000\u0007)\u0000\u0007%\u0000\u0007Y\u0000"+
-    "\u0007 \u0000\u0007+\u0000\u00078\u0000\u0007L\u0000\u0007K\u0000\u0007"+
-    "M\u0000\u0007]\u0000\u0005\n\u0000\u00076\u0000\u0005\u0007\u0000\u0007"+
-    "<\u0000\u0007e\u0000\u0007Q\u0000\u0007P\u0000\u0005\f\u0000\u0007a\u0000"+
-    "\u0005\u000f\u0000\u0007&\u0000";
+    "\u000f\u0010$\u0002\u0000CCcc\u0002\u0000OOoo\u0002\u0000MMmm\u0002\u0000"+
+    "PPpp\u0002\u0000LLll\u0002\u0000EEee\u0002\u0000TTtt\u0002\u0000IIii\u0002"+
+    "\u0000NNnn\u0002\u0000DDdd\u0002\u0000SSss\u0002\u0000RRrr\u0002\u0000"+
+    "HHhh\u0002\u0000VVvv\u0002\u0000AAaa\u0002\u0000XXxx\u0002\u0000FFff\u0002"+
+    "\u0000GGgg\u0002\u0000KKkk\u0002\u0000WWww\u0002\u0000UUuu\u0006\u0000"+
+    "\t\n\r\r  //[[]]\u0002\u0000\n\n\r\r\u0003\u0000\t\n\r\r  \u0001\u0000"+
+    "09\u0002\u0000AZaz\b\u0000\"\"NNRRTT\\\\nnrrtt\u0004\u0000\n\n\r\r\"\""+
+    "\\\\\u0002\u0000++--\u0001\u0000``\u0002\u0000BBbb\u0002\u0000YYyy\u000b"+
+    "\u0000\t\n\r\r  \"\",,//::==[[]]||\u0002\u0000**//\u000b\u0000\t\n\r\r"+
+    "  \"#,,//::<<>?\\\\||\u0002\u0000JJjj\u073e\u0000\u0011\u0001\u0000\u0000"+
+    "\u0000\u0000\u0013\u0001\u0000\u0000\u0000\u0000\u0015\u0001\u0000\u0000"+
+    "\u0000\u0000\u0017\u0001\u0000\u0000\u0000\u0000\u0019\u0001\u0000\u0000"+
+    "\u0000\u0000\u001b\u0001\u0000\u0000\u0000\u0000\u001d\u0001\u0000\u0000"+
+    "\u0000\u0000\u001f\u0001\u0000\u0000\u0000\u0000!\u0001\u0000\u0000\u0000"+
+    "\u0000#\u0001\u0000\u0000\u0000\u0000%\u0001\u0000\u0000\u0000\u0000\'"+
+    "\u0001\u0000\u0000\u0000\u0000)\u0001\u0000\u0000\u0000\u0000+\u0001\u0000"+
+    "\u0000\u0000\u0000-\u0001\u0000\u0000\u0000\u0000/\u0001\u0000\u0000\u0000"+
+    "\u00001\u0001\u0000\u0000\u0000\u00003\u0001\u0000\u0000\u0000\u00005"+
+    "\u0001\u0000\u0000\u0000\u00007\u0001\u0000\u0000\u0000\u00009\u0001\u0000"+
+    "\u0000\u0000\u0000;\u0001\u0000\u0000\u0000\u0000=\u0001\u0000\u0000\u0000"+
+    "\u0000?\u0001\u0000\u0000\u0000\u0000A\u0001\u0000\u0000\u0000\u0000C"+
+    "\u0001\u0000\u0000\u0000\u0000E\u0001\u0000\u0000\u0000\u0000G\u0001\u0000"+
+    "\u0000\u0000\u0000I\u0001\u0000\u0000\u0000\u0000K\u0001\u0000\u0000\u0000"+
+    "\u0000M\u0001\u0000\u0000\u0000\u0001O\u0001\u0000\u0000\u0000\u0001e"+
+    "\u0001\u0000\u0000\u0000\u0001g\u0001\u0000\u0000\u0000\u0001i\u0001\u0000"+
+    "\u0000\u0000\u0001k\u0001\u0000\u0000\u0000\u0001m\u0001\u0000\u0000\u0000"+
+    "\u0001o\u0001\u0000\u0000\u0000\u0001q\u0001\u0000\u0000\u0000\u0001s"+
+    "\u0001\u0000\u0000\u0000\u0001u\u0001\u0000\u0000\u0000\u0001w\u0001\u0000"+
+    "\u0000\u0000\u0001y\u0001\u0000\u0000\u0000\u0001{\u0001\u0000\u0000\u0000"+
+    "\u0001}\u0001\u0000\u0000\u0000\u0001\u007f\u0001\u0000\u0000\u0000\u0001"+
+    "\u0081\u0001\u0000\u0000\u0000\u0001\u0083\u0001\u0000\u0000\u0000\u0001"+
+    "\u0085\u0001\u0000\u0000\u0000\u0001\u0087\u0001\u0000\u0000\u0000\u0001"+
+    "\u0089\u0001\u0000\u0000\u0000\u0001\u008b\u0001\u0000\u0000\u0000\u0001"+
+    "\u008d\u0001\u0000\u0000\u0000\u0001\u008f\u0001\u0000\u0000\u0000\u0001"+
+    "\u0091\u0001\u0000\u0000\u0000\u0001\u0093\u0001\u0000\u0000\u0000\u0001"+
+    "\u0095\u0001\u0000\u0000\u0000\u0001\u0097\u0001\u0000\u0000\u0000\u0001"+
+    "\u0099\u0001\u0000\u0000\u0000\u0001\u009b\u0001\u0000\u0000\u0000\u0001"+
+    "\u009d\u0001\u0000\u0000\u0000\u0001\u009f\u0001\u0000\u0000\u0000\u0001"+
+    "\u00a1\u0001\u0000\u0000\u0000\u0001\u00a3\u0001\u0000\u0000\u0000\u0001"+
+    "\u00a5\u0001\u0000\u0000\u0000\u0001\u00a7\u0001\u0000\u0000\u0000\u0001"+
+    "\u00a9\u0001\u0000\u0000\u0000\u0001\u00ab\u0001\u0000\u0000\u0000\u0001"+
+    "\u00ad\u0001\u0000\u0000\u0000\u0001\u00af\u0001\u0000\u0000\u0000\u0001"+
+    "\u00b1\u0001\u0000\u0000\u0000\u0001\u00b3\u0001\u0000\u0000\u0000\u0001"+
+    "\u00b5\u0001\u0000\u0000\u0000\u0001\u00b7\u0001\u0000\u0000\u0000\u0001"+
+    "\u00b9\u0001\u0000\u0000\u0000\u0001\u00bb\u0001\u0000\u0000\u0000\u0001"+
+    "\u00bd\u0001\u0000\u0000\u0000\u0001\u00bf\u0001\u0000\u0000\u0000\u0001"+
+    "\u00c1\u0001\u0000\u0000\u0000\u0001\u00c3\u0001\u0000\u0000\u0000\u0001"+
+    "\u00c5\u0001\u0000\u0000\u0000\u0001\u00c7\u0001\u0000\u0000\u0000\u0001"+
+    "\u00cb\u0001\u0000\u0000\u0000\u0001\u00cd\u0001\u0000\u0000\u0000\u0001"+
+    "\u00cf\u0001\u0000\u0000\u0000\u0001\u00d1\u0001\u0000\u0000\u0000\u0002"+
+    "\u00d3\u0001\u0000\u0000\u0000\u0002\u00d5\u0001\u0000\u0000\u0000\u0002"+
+    "\u00d7\u0001\u0000\u0000\u0000\u0002\u00d9\u0001\u0000\u0000\u0000\u0002"+
+    "\u00db\u0001\u0000\u0000\u0000\u0003\u00dd\u0001\u0000\u0000\u0000\u0003"+
+    "\u00df\u0001\u0000\u0000\u0000\u0003\u00e1\u0001\u0000\u0000\u0000\u0003"+
+    "\u00e3\u0001\u0000\u0000\u0000\u0003\u00e5\u0001\u0000\u0000\u0000\u0003"+
+    "\u00e7\u0001\u0000\u0000\u0000\u0003\u00e9\u0001\u0000\u0000\u0000\u0003"+
+    "\u00eb\u0001\u0000\u0000\u0000\u0003\u00ef\u0001\u0000\u0000\u0000\u0003"+
+    "\u00f1\u0001\u0000\u0000\u0000\u0003\u00f3\u0001\u0000\u0000\u0000\u0003"+
+    "\u00f5\u0001\u0000\u0000\u0000\u0003\u00f7\u0001\u0000\u0000\u0000\u0003"+
+    "\u00f9\u0001\u0000\u0000\u0000\u0004\u00fb\u0001\u0000\u0000\u0000\u0004"+
+    "\u00fd\u0001\u0000\u0000\u0000\u0004\u00ff\u0001\u0000\u0000\u0000\u0004"+
+    "\u0101\u0001\u0000\u0000\u0000\u0004\u0103\u0001\u0000\u0000\u0000\u0004"+
+    "\u0105\u0001\u0000\u0000\u0000\u0004\u0107\u0001\u0000\u0000\u0000\u0004"+
+    "\u010d\u0001\u0000\u0000\u0000\u0004\u010f\u0001\u0000\u0000\u0000\u0004"+
+    "\u0111\u0001\u0000\u0000\u0000\u0004\u0113\u0001\u0000\u0000\u0000\u0005"+
+    "\u0115\u0001\u0000\u0000\u0000\u0005\u0117\u0001\u0000\u0000\u0000\u0005"+
+    "\u0119\u0001\u0000\u0000\u0000\u0005\u011b\u0001\u0000\u0000\u0000\u0005"+
+    "\u011d\u0001\u0000\u0000\u0000\u0005\u011f\u0001\u0000\u0000\u0000\u0005"+
+    "\u0121\u0001\u0000\u0000\u0000\u0005\u0123\u0001\u0000\u0000\u0000\u0005"+
+    "\u0125\u0001\u0000\u0000\u0000\u0005\u0127\u0001\u0000\u0000\u0000\u0005"+
+    "\u0129\u0001\u0000\u0000\u0000\u0005\u012b\u0001\u0000\u0000\u0000\u0005"+
+    "\u012d\u0001\u0000\u0000\u0000\u0006\u012f\u0001\u0000\u0000\u0000\u0006"+
+    "\u0131\u0001\u0000\u0000\u0000\u0006\u0133\u0001\u0000\u0000\u0000\u0006"+
+    "\u0135\u0001\u0000\u0000\u0000\u0006\u0139\u0001\u0000\u0000\u0000\u0006"+
+    "\u013b\u0001\u0000\u0000\u0000\u0006\u013d\u0001\u0000\u0000\u0000\u0006"+
+    "\u013f\u0001\u0000\u0000\u0000\u0006\u0141\u0001\u0000\u0000\u0000\u0007"+
+    "\u0143\u0001\u0000\u0000\u0000\u0007\u0145\u0001\u0000\u0000\u0000\u0007"+
+    "\u0147\u0001\u0000\u0000\u0000\u0007\u0149\u0001\u0000\u0000\u0000\u0007"+
+    "\u014b\u0001\u0000\u0000\u0000\u0007\u014d\u0001\u0000\u0000\u0000\u0007"+
+    "\u014f\u0001\u0000\u0000\u0000\u0007\u0151\u0001\u0000\u0000\u0000\u0007"+
+    "\u0153\u0001\u0000\u0000\u0000\u0007\u0155\u0001\u0000\u0000\u0000\u0007"+
+    "\u0157\u0001\u0000\u0000\u0000\u0007\u0159\u0001\u0000\u0000\u0000\u0007"+
+    "\u015b\u0001\u0000\u0000\u0000\u0007\u015d\u0001\u0000\u0000\u0000\b\u015f"+
+    "\u0001\u0000\u0000\u0000\b\u0161\u0001\u0000\u0000\u0000\b\u0163\u0001"+
+    "\u0000\u0000\u0000\b\u0165\u0001\u0000\u0000\u0000\b\u0167\u0001\u0000"+
+    "\u0000\u0000\b\u0169\u0001\u0000\u0000\u0000\b\u016b\u0001\u0000\u0000"+
+    "\u0000\b\u016d\u0001\u0000\u0000\u0000\b\u016f\u0001\u0000\u0000\u0000"+
+    "\b\u0171\u0001\u0000\u0000\u0000\b\u0173\u0001\u0000\u0000\u0000\t\u0175"+
+    "\u0001\u0000\u0000\u0000\t\u0177\u0001\u0000\u0000\u0000\t\u0179\u0001"+
+    "\u0000\u0000\u0000\t\u017b\u0001\u0000\u0000\u0000\t\u017d\u0001\u0000"+
+    "\u0000\u0000\n\u017f\u0001\u0000\u0000\u0000\n\u0181\u0001\u0000\u0000"+
+    "\u0000\n\u0183\u0001\u0000\u0000\u0000\n\u0185\u0001\u0000\u0000\u0000"+
+    "\n\u0187\u0001\u0000\u0000\u0000\n\u0189\u0001\u0000\u0000\u0000\u000b"+
+    "\u018b\u0001\u0000\u0000\u0000\u000b\u018d\u0001\u0000\u0000\u0000\u000b"+
+    "\u018f\u0001\u0000\u0000\u0000\u000b\u0191\u0001\u0000\u0000\u0000\u000b"+
+    "\u0193\u0001\u0000\u0000\u0000\u000b\u0195\u0001\u0000\u0000\u0000\u000b"+
+    "\u0197\u0001\u0000\u0000\u0000\u000b\u0199\u0001\u0000\u0000\u0000\u000b"+
+    "\u019b\u0001\u0000\u0000\u0000\u000b\u019d\u0001\u0000\u0000\u0000\f\u019f"+
+    "\u0001\u0000\u0000\u0000\f\u01a1\u0001\u0000\u0000\u0000\f\u01a3\u0001"+
+    "\u0000\u0000\u0000\f\u01a5\u0001\u0000\u0000\u0000\f\u01a7\u0001\u0000"+
+    "\u0000\u0000\f\u01a9\u0001\u0000\u0000\u0000\f\u01ab\u0001\u0000\u0000"+
+    "\u0000\r\u01ad\u0001\u0000\u0000\u0000\r\u01af\u0001\u0000\u0000\u0000"+
+    "\r\u01b1\u0001\u0000\u0000\u0000\r\u01b3\u0001\u0000\u0000\u0000\r\u01b5"+
+    "\u0001\u0000\u0000\u0000\r\u01b7\u0001\u0000\u0000\u0000\r\u01b9\u0001"+
+    "\u0000\u0000\u0000\r\u01bb\u0001\u0000\u0000\u0000\r\u01bd\u0001\u0000"+
+    "\u0000\u0000\r\u01bf\u0001\u0000\u0000\u0000\r\u01c1\u0001\u0000\u0000"+
+    "\u0000\r\u01c3\u0001\u0000\u0000\u0000\r\u01c5\u0001\u0000\u0000\u0000"+
+    "\u000e\u01c7\u0001\u0000\u0000\u0000\u000e\u01c9\u0001\u0000\u0000\u0000"+
+    "\u000e\u01cb\u0001\u0000\u0000\u0000\u000e\u01cd\u0001\u0000\u0000\u0000"+
+    "\u000e\u01cf\u0001\u0000\u0000\u0000\u000e\u01d1\u0001\u0000\u0000\u0000"+
+    "\u000f\u01d3\u0001\u0000\u0000\u0000\u000f\u01d5\u0001\u0000\u0000\u0000"+
+    "\u000f\u01d7\u0001\u0000\u0000\u0000\u000f\u01d9\u0001\u0000\u0000\u0000"+
+    "\u000f\u01db\u0001\u0000\u0000\u0000\u000f\u01dd\u0001\u0000\u0000\u0000"+
+    "\u000f\u01df\u0001\u0000\u0000\u0000\u000f\u01e1\u0001\u0000\u0000\u0000"+
+    "\u000f\u01e3\u0001\u0000\u0000\u0000\u000f\u01e5\u0001\u0000\u0000\u0000"+
+    "\u0010\u01e7\u0001\u0000\u0000\u0000\u0010\u01e9\u0001\u0000\u0000\u0000"+
+    "\u0010\u01eb\u0001\u0000\u0000\u0000\u0010\u01ed\u0001\u0000\u0000\u0000"+
+    "\u0010\u01ef\u0001\u0000\u0000\u0000\u0010\u01f1\u0001\u0000\u0000\u0000"+
+    "\u0010\u01f3\u0001\u0000\u0000\u0000\u0010\u01f5\u0001\u0000\u0000\u0000"+
+    "\u0010\u01f7\u0001\u0000\u0000\u0000\u0010\u01f9\u0001\u0000\u0000\u0000"+
+    "\u0011\u01fb\u0001\u0000\u0000\u0000\u0013\u0208\u0001\u0000\u0000\u0000"+
+    "\u0015\u0212\u0001\u0000\u0000\u0000\u0017\u0219\u0001\u0000\u0000\u0000"+
+    "\u0019\u0222\u0001\u0000\u0000\u0000\u001b\u0229\u0001\u0000\u0000\u0000"+
+    "\u001d\u0233\u0001\u0000\u0000\u0000\u001f\u023a\u0001\u0000\u0000\u0000"+
+    "!\u0241\u0001\u0000\u0000\u0000#\u0248\u0001\u0000\u0000\u0000%\u0250"+
+    "\u0001\u0000\u0000\u0000\'\u025c\u0001\u0000\u0000\u0000)\u0265\u0001"+
+    "\u0000\u0000\u0000+\u026b\u0001\u0000\u0000\u0000-\u0274\u0001\u0000\u0000"+
+    "\u0000/\u027b\u0001\u0000\u0000\u00001\u0282\u0001\u0000\u0000\u00003"+
+    "\u028a\u0001\u0000\u0000\u00005\u0292\u0001\u0000\u0000\u00007\u029b\u0001"+
+    "\u0000\u0000\u00009\u02aa\u0001\u0000\u0000\u0000;\u02b9\u0001\u0000\u0000"+
+    "\u0000=\u02c5\u0001\u0000\u0000\u0000?\u02d0\u0001\u0000\u0000\u0000A"+
+    "\u02da\u0001\u0000\u0000\u0000C\u02e2\u0001\u0000\u0000\u0000E\u02ea\u0001"+
+    "\u0000\u0000\u0000G\u02f4\u0001\u0000\u0000\u0000I\u02fa\u0001\u0000\u0000"+
+    "\u0000K\u030b\u0001\u0000\u0000\u0000M\u031b\u0001\u0000\u0000\u0000O"+
+    "\u0321\u0001\u0000\u0000\u0000Q\u0325\u0001\u0000\u0000\u0000S\u0327\u0001"+
+    "\u0000\u0000\u0000U\u0329\u0001\u0000\u0000\u0000W\u032c\u0001\u0000\u0000"+
+    "\u0000Y\u032e\u0001\u0000\u0000\u0000[\u0337\u0001\u0000\u0000\u0000]"+
+    "\u0339\u0001\u0000\u0000\u0000_\u033e\u0001\u0000\u0000\u0000a\u0340\u0001"+
+    "\u0000\u0000\u0000c\u0345\u0001\u0000\u0000\u0000e\u0364\u0001\u0000\u0000"+
+    "\u0000g\u0367\u0001\u0000\u0000\u0000i\u0395\u0001\u0000\u0000\u0000k"+
+    "\u0397\u0001\u0000\u0000\u0000m\u039b\u0001\u0000\u0000\u0000o\u039f\u0001"+
+    "\u0000\u0000\u0000q\u03a1\u0001\u0000\u0000\u0000s\u03a4\u0001\u0000\u0000"+
+    "\u0000u\u03a7\u0001\u0000\u0000\u0000w\u03a9\u0001\u0000\u0000\u0000y"+
+    "\u03ab\u0001\u0000\u0000\u0000{\u03b0\u0001\u0000\u0000\u0000}\u03b2\u0001"+
+    "\u0000\u0000\u0000\u007f\u03b8\u0001\u0000\u0000\u0000\u0081\u03be\u0001"+
+    "\u0000\u0000\u0000\u0083\u03c1\u0001\u0000\u0000\u0000\u0085\u03c4\u0001"+
+    "\u0000\u0000\u0000\u0087\u03c9\u0001\u0000\u0000\u0000\u0089\u03ce\u0001"+
+    "\u0000\u0000\u0000\u008b\u03d0\u0001\u0000\u0000\u0000\u008d\u03d4\u0001"+
+    "\u0000\u0000\u0000\u008f\u03d9\u0001\u0000\u0000\u0000\u0091\u03df\u0001"+
+    "\u0000\u0000\u0000\u0093\u03e2\u0001\u0000\u0000\u0000\u0095\u03e5\u0001"+
+    "\u0000\u0000\u0000\u0097\u03e7\u0001\u0000\u0000\u0000\u0099\u03ed\u0001"+
+    "\u0000\u0000\u0000\u009b\u03ef\u0001\u0000\u0000\u0000\u009d\u03f4\u0001"+
+    "\u0000\u0000\u0000\u009f\u03f9\u0001\u0000\u0000\u0000\u00a1\u03fc\u0001"+
+    "\u0000\u0000\u0000\u00a3\u03ff\u0001\u0000\u0000\u0000\u00a5\u0402\u0001"+
+    "\u0000\u0000\u0000\u00a7\u0404\u0001\u0000\u0000\u0000\u00a9\u0407\u0001"+
+    "\u0000\u0000\u0000\u00ab\u0409\u0001\u0000\u0000\u0000\u00ad\u040c\u0001"+
+    "\u0000\u0000\u0000\u00af\u040e\u0001\u0000\u0000\u0000\u00b1\u0410\u0001"+
+    "\u0000\u0000\u0000\u00b3\u0412\u0001\u0000\u0000\u0000\u00b5\u0414\u0001"+
+    "\u0000\u0000\u0000\u00b7\u0416\u0001\u0000\u0000\u0000\u00b9\u0418\u0001"+
+    "\u0000\u0000\u0000\u00bb\u041a\u0001\u0000\u0000\u0000\u00bd\u041d\u0001"+
+    "\u0000\u0000\u0000\u00bf\u0432\u0001\u0000\u0000\u0000\u00c1\u0445\u0001"+
+    "\u0000\u0000\u0000\u00c3\u0447\u0001\u0000\u0000\u0000\u00c5\u044c\u0001"+
+    "\u0000\u0000\u0000\u00c7\u0461\u0001\u0000\u0000\u0000\u00c9\u0463\u0001"+
+    "\u0000\u0000\u0000\u00cb\u046b\u0001\u0000\u0000\u0000\u00cd\u046d\u0001"+
+    "\u0000\u0000\u0000\u00cf\u0471\u0001\u0000\u0000\u0000\u00d1\u0475\u0001"+
+    "\u0000\u0000\u0000\u00d3\u0479\u0001\u0000\u0000\u0000\u00d5\u047e\u0001"+
+    "\u0000\u0000\u0000\u00d7\u0483\u0001\u0000\u0000\u0000\u00d9\u0487\u0001"+
+    "\u0000\u0000\u0000\u00db\u048b\u0001\u0000\u0000\u0000\u00dd\u048f\u0001"+
+    "\u0000\u0000\u0000\u00df\u0494\u0001\u0000\u0000\u0000\u00e1\u0498\u0001"+
+    "\u0000\u0000\u0000\u00e3\u049c\u0001\u0000\u0000\u0000\u00e5\u04a0\u0001"+
+    "\u0000\u0000\u0000\u00e7\u04a4\u0001\u0000\u0000\u0000\u00e9\u04a8\u0001"+
+    "\u0000\u0000\u0000\u00eb\u04ac\u0001\u0000\u0000\u0000\u00ed\u04b8\u0001"+
+    "\u0000\u0000\u0000\u00ef\u04bb\u0001\u0000\u0000\u0000\u00f1\u04bf\u0001"+
+    "\u0000\u0000\u0000\u00f3\u04c3\u0001\u0000\u0000\u0000\u00f5\u04c7\u0001"+
+    "\u0000\u0000\u0000\u00f7\u04cb\u0001\u0000\u0000\u0000\u00f9\u04cf\u0001"+
+    "\u0000\u0000\u0000\u00fb\u04d3\u0001\u0000\u0000\u0000\u00fd\u04d8\u0001"+
+    "\u0000\u0000\u0000\u00ff\u04dc\u0001\u0000\u0000\u0000\u0101\u04e0\u0001"+
+    "\u0000\u0000\u0000\u0103\u04e4\u0001\u0000\u0000\u0000\u0105\u04e8\u0001"+
+    "\u0000\u0000\u0000\u0107\u04ec\u0001\u0000\u0000\u0000\u0109\u04f4\u0001"+
+    "\u0000\u0000\u0000\u010b\u0509\u0001\u0000\u0000\u0000\u010d\u050d\u0001"+
+    "\u0000\u0000\u0000\u010f\u0511\u0001\u0000\u0000\u0000\u0111\u0515\u0001"+
+    "\u0000\u0000\u0000\u0113\u0519\u0001\u0000\u0000\u0000\u0115\u051d\u0001"+
+    "\u0000\u0000\u0000\u0117\u0522\u0001\u0000\u0000\u0000\u0119\u0526\u0001"+
+    "\u0000\u0000\u0000\u011b\u052a\u0001\u0000\u0000\u0000\u011d\u052e\u0001"+
+    "\u0000\u0000\u0000\u011f\u0532\u0001\u0000\u0000\u0000\u0121\u0536\u0001"+
+    "\u0000\u0000\u0000\u0123\u053a\u0001\u0000\u0000\u0000\u0125\u053e\u0001"+
+    "\u0000\u0000\u0000\u0127\u0541\u0001\u0000\u0000\u0000\u0129\u0545\u0001"+
+    "\u0000\u0000\u0000\u012b\u0549\u0001\u0000\u0000\u0000\u012d\u054d\u0001"+
+    "\u0000\u0000\u0000\u012f\u0551\u0001\u0000\u0000\u0000\u0131\u0556\u0001"+
+    "\u0000\u0000\u0000\u0133\u055b\u0001\u0000\u0000\u0000\u0135\u0560\u0001"+
+    "\u0000\u0000\u0000\u0137\u0565\u0001\u0000\u0000\u0000\u0139\u056e\u0001"+
+    "\u0000\u0000\u0000\u013b\u0575\u0001\u0000\u0000\u0000\u013d\u0579\u0001"+
+    "\u0000\u0000\u0000\u013f\u057d\u0001\u0000\u0000\u0000\u0141\u0581\u0001"+
+    "\u0000\u0000\u0000\u0143\u0585\u0001\u0000\u0000\u0000\u0145\u058b\u0001"+
+    "\u0000\u0000\u0000\u0147\u058f\u0001\u0000\u0000\u0000\u0149\u0593\u0001"+
+    "\u0000\u0000\u0000\u014b\u0597\u0001\u0000\u0000\u0000\u014d\u059b\u0001"+
+    "\u0000\u0000\u0000\u014f\u059f\u0001\u0000\u0000\u0000\u0151\u05a3\u0001"+
+    "\u0000\u0000\u0000\u0153\u05a7\u0001\u0000\u0000\u0000\u0155\u05ab\u0001"+
+    "\u0000\u0000\u0000\u0157\u05af\u0001\u0000\u0000\u0000\u0159\u05b3\u0001"+
+    "\u0000\u0000\u0000\u015b\u05b7\u0001\u0000\u0000\u0000\u015d\u05bb\u0001"+
+    "\u0000\u0000\u0000\u015f\u05bf\u0001\u0000\u0000\u0000\u0161\u05c4\u0001"+
+    "\u0000\u0000\u0000\u0163\u05c8\u0001\u0000\u0000\u0000\u0165\u05cc\u0001"+
+    "\u0000\u0000\u0000\u0167\u05d0\u0001\u0000\u0000\u0000\u0169\u05d4\u0001"+
+    "\u0000\u0000\u0000\u016b\u05d8\u0001\u0000\u0000\u0000\u016d\u05dc\u0001"+
+    "\u0000\u0000\u0000\u016f\u05e0\u0001\u0000\u0000\u0000\u0171\u05e4\u0001"+
+    "\u0000\u0000\u0000\u0173\u05e8\u0001\u0000\u0000\u0000\u0175\u05ec\u0001"+
+    "\u0000\u0000\u0000\u0177\u05f1\u0001\u0000\u0000\u0000\u0179\u05f6\u0001"+
+    "\u0000\u0000\u0000\u017b\u05fa\u0001\u0000\u0000\u0000\u017d\u05fe\u0001"+
+    "\u0000\u0000\u0000\u017f\u0602\u0001\u0000\u0000\u0000\u0181\u0607\u0001"+
+    "\u0000\u0000\u0000\u0183\u0610\u0001\u0000\u0000\u0000\u0185\u0614\u0001"+
+    "\u0000\u0000\u0000\u0187\u0618\u0001\u0000\u0000\u0000\u0189\u061c\u0001"+
+    "\u0000\u0000\u0000\u018b\u0620\u0001\u0000\u0000\u0000\u018d\u0625\u0001"+
+    "\u0000\u0000\u0000\u018f\u0629\u0001\u0000\u0000\u0000\u0191\u062d\u0001"+
+    "\u0000\u0000\u0000\u0193\u0631\u0001\u0000\u0000\u0000\u0195\u0636\u0001"+
+    "\u0000\u0000\u0000\u0197\u063a\u0001\u0000\u0000\u0000\u0199\u063e\u0001"+
+    "\u0000\u0000\u0000\u019b\u0642\u0001\u0000\u0000\u0000\u019d\u0646\u0001"+
+    "\u0000\u0000\u0000\u019f\u064a\u0001\u0000\u0000\u0000\u01a1\u0650\u0001"+
+    "\u0000\u0000\u0000\u01a3\u0654\u0001\u0000\u0000\u0000\u01a5\u0658\u0001"+
+    "\u0000\u0000\u0000\u01a7\u065c\u0001\u0000\u0000\u0000\u01a9\u0660\u0001"+
+    "\u0000\u0000\u0000\u01ab\u0664\u0001\u0000\u0000\u0000\u01ad\u0668\u0001"+
+    "\u0000\u0000\u0000\u01af\u066d\u0001\u0000\u0000\u0000\u01b1\u0672\u0001"+
+    "\u0000\u0000\u0000\u01b3\u0676\u0001\u0000\u0000\u0000\u01b5\u067c\u0001"+
+    "\u0000\u0000\u0000\u01b7\u0685\u0001\u0000\u0000\u0000\u01b9\u0689\u0001"+
+    "\u0000\u0000\u0000\u01bb\u068d\u0001\u0000\u0000\u0000\u01bd\u0691\u0001"+
+    "\u0000\u0000\u0000\u01bf\u0695\u0001\u0000\u0000\u0000\u01c1\u0699\u0001"+
+    "\u0000\u0000\u0000\u01c3\u069d\u0001\u0000\u0000\u0000\u01c5\u06a1\u0001"+
+    "\u0000\u0000\u0000\u01c7\u06a5\u0001\u0000\u0000\u0000\u01c9\u06aa\u0001"+
+    "\u0000\u0000\u0000\u01cb\u06b0\u0001\u0000\u0000\u0000\u01cd\u06b6\u0001"+
+    "\u0000\u0000\u0000\u01cf\u06ba\u0001\u0000\u0000\u0000\u01d1\u06be\u0001"+
+    "\u0000\u0000\u0000\u01d3\u06c2\u0001\u0000\u0000\u0000\u01d5\u06c8\u0001"+
+    "\u0000\u0000\u0000\u01d7\u06ce\u0001\u0000\u0000\u0000\u01d9\u06d4\u0001"+
+    "\u0000\u0000\u0000\u01db\u06d8\u0001\u0000\u0000\u0000\u01dd\u06dc\u0001"+
+    "\u0000\u0000\u0000\u01df\u06e0\u0001\u0000\u0000\u0000\u01e1\u06e6\u0001"+
+    "\u0000\u0000\u0000\u01e3\u06ec\u0001\u0000\u0000\u0000\u01e5\u06f2\u0001"+
+    "\u0000\u0000\u0000\u01e7\u06f7\u0001\u0000\u0000\u0000\u01e9\u06fc\u0001"+
+    "\u0000\u0000\u0000\u01eb\u0700\u0001\u0000\u0000\u0000\u01ed\u0704\u0001"+
+    "\u0000\u0000\u0000\u01ef\u0708\u0001\u0000\u0000\u0000\u01f1\u070c\u0001"+
+    "\u0000\u0000\u0000\u01f3\u0710\u0001\u0000\u0000\u0000\u01f5\u0714\u0001"+
+    "\u0000\u0000\u0000\u01f7\u0718\u0001\u0000\u0000\u0000\u01f9\u071c\u0001"+
+    "\u0000\u0000\u0000\u01fb\u01fc\u0007\u0000\u0000\u0000\u01fc\u01fd\u0007"+
+    "\u0001\u0000\u0000\u01fd\u01fe\u0007\u0002\u0000\u0000\u01fe\u01ff\u0007"+
+    "\u0003\u0000\u0000\u01ff\u0200\u0007\u0004\u0000\u0000\u0200\u0201\u0007"+
+    "\u0005\u0000\u0000\u0201\u0202\u0007\u0006\u0000\u0000\u0202\u0203\u0007"+
+    "\u0007\u0000\u0000\u0203\u0204\u0007\u0001\u0000\u0000\u0204\u0205\u0007"+
+    "\b\u0000\u0000\u0205\u0206\u0001\u0000\u0000\u0000\u0206\u0207\u0006\u0000"+
+    "\u0000\u0000\u0207\u0012\u0001\u0000\u0000\u0000\u0208\u0209\u0007\t\u0000"+
+    "\u0000\u0209\u020a\u0007\u0007\u0000\u0000\u020a\u020b\u0007\n\u0000\u0000"+
+    "\u020b\u020c\u0007\n\u0000\u0000\u020c\u020d\u0007\u0005\u0000\u0000\u020d"+
+    "\u020e\u0007\u0000\u0000\u0000\u020e\u020f\u0007\u0006\u0000\u0000\u020f"+
+    "\u0210\u0001\u0000\u0000\u0000\u0210\u0211\u0006\u0001\u0000\u0000\u0211"+
+    "\u0014\u0001\u0000\u0000\u0000\u0212\u0213\u0007\t\u0000\u0000\u0213\u0214"+
+    "\u0007\u000b\u0000\u0000\u0214\u0215\u0007\u0001\u0000\u0000\u0215\u0216"+
+    "\u0007\u0003\u0000\u0000\u0216\u0217\u0001\u0000\u0000\u0000\u0217\u0218"+
+    "\u0006\u0002\u0001\u0000\u0218\u0016\u0001\u0000\u0000\u0000\u0219\u021a"+
+    "\u0007\u0005\u0000\u0000\u021a\u021b\u0007\b\u0000\u0000\u021b\u021c\u0007"+
+    "\u000b\u0000\u0000\u021c\u021d\u0007\u0007\u0000\u0000\u021d\u021e\u0007"+
+    "\u0000\u0000\u0000\u021e\u021f\u0007\f\u0000\u0000\u021f\u0220\u0001\u0000"+
+    "\u0000\u0000\u0220\u0221\u0006\u0003\u0002\u0000\u0221\u0018\u0001\u0000"+
+    "\u0000\u0000\u0222\u0223\u0007\u0005\u0000\u0000\u0223\u0224\u0007\r\u0000"+
+    "\u0000\u0224\u0225\u0007\u000e\u0000\u0000\u0225\u0226\u0007\u0004\u0000"+
+    "\u0000\u0226\u0227\u0001\u0000\u0000\u0000\u0227\u0228\u0006\u0004\u0000"+
+    "\u0000\u0228\u001a\u0001\u0000\u0000\u0000\u0229\u022a\u0007\u0005\u0000"+
+    "\u0000\u022a\u022b\u0007\u000f\u0000\u0000\u022b\u022c\u0007\u0003\u0000"+
+    "\u0000\u022c\u022d\u0007\u0004\u0000\u0000\u022d\u022e\u0007\u000e\u0000"+
+    "\u0000\u022e\u022f\u0007\u0007\u0000\u0000\u022f\u0230\u0007\b\u0000\u0000"+
+    "\u0230\u0231\u0001\u0000\u0000\u0000\u0231\u0232\u0006\u0005\u0003\u0000"+
+    "\u0232\u001c\u0001\u0000\u0000\u0000\u0233\u0234\u0007\u0010\u0000\u0000"+
+    "\u0234\u0235\u0007\u000b\u0000\u0000\u0235\u0236\u0007\u0001\u0000\u0000"+
+    "\u0236\u0237\u0007\u0002\u0000\u0000\u0237\u0238\u0001\u0000\u0000\u0000"+
+    "\u0238\u0239\u0006\u0006\u0004\u0000\u0239\u001e\u0001\u0000\u0000\u0000"+
+    "\u023a\u023b\u0007\u0011\u0000\u0000\u023b\u023c\u0007\u000b\u0000\u0000"+
+    "\u023c\u023d\u0007\u0001\u0000\u0000\u023d\u023e\u0007\u0012\u0000\u0000"+
+    "\u023e\u023f\u0001\u0000\u0000\u0000\u023f\u0240\u0006\u0007\u0000\u0000"+
+    "\u0240 \u0001\u0000\u0000\u0000\u0241\u0242\u0007\u0012\u0000\u0000\u0242"+
+    "\u0243\u0007\u0005\u0000\u0000\u0243\u0244\u0007\u0005\u0000\u0000\u0244"+
+    "\u0245\u0007\u0003\u0000\u0000\u0245\u0246\u0001\u0000\u0000\u0000\u0246"+
+    "\u0247\u0006\b\u0001\u0000\u0247\"\u0001\u0000\u0000\u0000\u0248\u0249"+
+    "\u0007\u0004\u0000\u0000\u0249\u024a\u0007\u0007\u0000\u0000\u024a\u024b"+
+    "\u0007\u0002\u0000\u0000\u024b\u024c\u0007\u0007\u0000\u0000\u024c\u024d"+
+    "\u0007\u0006\u0000\u0000\u024d\u024e\u0001\u0000\u0000\u0000\u024e\u024f"+
+    "\u0006\t\u0000\u0000\u024f$\u0001\u0000\u0000\u0000\u0250\u0251\u0007"+
+    "\u0002\u0000\u0000\u0251\u0252\u0007\r\u0000\u0000\u0252\u0253\u0005_"+
+    "\u0000\u0000\u0253\u0254\u0007\u0005\u0000\u0000\u0254\u0255\u0007\u000f"+
+    "\u0000\u0000\u0255\u0256\u0007\u0003\u0000\u0000\u0256\u0257\u0007\u000e"+
+    "\u0000\u0000\u0257\u0258\u0007\b\u0000\u0000\u0258\u0259\u0007\t\u0000"+
+    "\u0000\u0259\u025a\u0001\u0000\u0000\u0000\u025a\u025b\u0006\n\u0005\u0000"+
+    "\u025b&\u0001\u0000\u0000\u0000\u025c\u025d\u0007\u000b\u0000\u0000\u025d"+
+    "\u025e\u0007\u0005\u0000\u0000\u025e\u025f\u0007\b\u0000\u0000\u025f\u0260"+
+    "\u0007\u000e\u0000\u0000\u0260\u0261\u0007\u0002\u0000\u0000\u0261\u0262"+
+    "\u0007\u0005\u0000\u0000\u0262\u0263\u0001\u0000\u0000\u0000\u0263\u0264"+
+    "\u0006\u000b\u0006\u0000\u0264(\u0001\u0000\u0000\u0000\u0265\u0266\u0007"+
+    "\u000b\u0000\u0000\u0266\u0267\u0007\u0001\u0000\u0000\u0267\u0268\u0007"+
+    "\u0013\u0000\u0000\u0268\u0269\u0001\u0000\u0000\u0000\u0269\u026a\u0006"+
+    "\f\u0000\u0000\u026a*\u0001\u0000\u0000\u0000\u026b\u026c\u0007\n\u0000"+
+    "\u0000\u026c\u026d\u0007\u000e\u0000\u0000\u026d\u026e\u0007\u0002\u0000"+
+    "\u0000\u026e\u026f\u0007\u0003\u0000\u0000\u026f\u0270\u0007\u0004\u0000"+
+    "\u0000\u0270\u0271\u0007\u0005\u0000\u0000\u0271\u0272\u0001\u0000\u0000"+
+    "\u0000\u0272\u0273\u0006\r\u0000\u0000\u0273,\u0001\u0000\u0000\u0000"+
+    "\u0274\u0275\u0007\n\u0000\u0000\u0275\u0276\u0007\f\u0000\u0000\u0276"+
+    "\u0277\u0007\u0001\u0000\u0000\u0277\u0278\u0007\u0013\u0000\u0000\u0278"+
+    "\u0279\u0001\u0000\u0000\u0000\u0279\u027a\u0006\u000e\u0007\u0000\u027a"+
+    ".\u0001\u0000\u0000\u0000\u027b\u027c\u0007\n\u0000\u0000\u027c\u027d"+
+    "\u0007\u0001\u0000\u0000\u027d\u027e\u0007\u000b\u0000\u0000\u027e\u027f"+
+    "\u0007\u0006\u0000\u0000\u027f\u0280\u0001\u0000\u0000\u0000\u0280\u0281"+
+    "\u0006\u000f\u0000\u0000\u02810\u0001\u0000\u0000\u0000\u0282\u0283\u0007"+
+    "\n\u0000\u0000\u0283\u0284\u0007\u0006\u0000\u0000\u0284\u0285\u0007\u000e"+
+    "\u0000\u0000\u0285\u0286\u0007\u0006\u0000\u0000\u0286\u0287\u0007\n\u0000"+
+    "\u0000\u0287\u0288\u0001\u0000\u0000\u0000\u0288\u0289\u0006\u0010\u0000"+
+    "\u0000\u02892\u0001\u0000\u0000\u0000\u028a\u028b\u0007\u0013\u0000\u0000"+
+    "\u028b\u028c\u0007\f\u0000\u0000\u028c\u028d\u0007\u0005\u0000\u0000\u028d"+
+    "\u028e\u0007\u000b\u0000\u0000\u028e\u028f\u0007\u0005\u0000\u0000\u028f"+
+    "\u0290\u0001\u0000\u0000\u0000\u0290\u0291\u0006\u0011\u0000\u0000\u0291"+
+    "4\u0001\u0000\u0000\u0000\u0292\u0293\u0007\u0004\u0000\u0000\u0293\u0294"+
+    "\u0007\u0001\u0000\u0000\u0294\u0295\u0007\u0001\u0000\u0000\u0295\u0296"+
+    "\u0007\u0012\u0000\u0000\u0296\u0297\u0007\u0014\u0000\u0000\u0297\u0298"+
+    "\u0007\u0003\u0000\u0000\u0298\u0299\u0001\u0000\u0000\u0000\u0299\u029a"+
+    "\u0006\u0012\b\u0000\u029a6\u0001\u0000\u0000\u0000\u029b\u029c\u0007"+
+    "\u0000\u0000\u0000\u029c\u029d\u0007\f\u0000\u0000\u029d\u029e\u0007\u000e"+
+    "\u0000\u0000\u029e\u029f\u0007\b\u0000\u0000\u029f\u02a0\u0007\u0011\u0000"+
+    "\u0000\u02a0\u02a1\u0007\u0005\u0000\u0000\u02a1\u02a2\u0005_\u0000\u0000"+
+    "\u02a2\u02a3\u0007\u0003\u0000\u0000\u02a3\u02a4\u0007\u0001\u0000\u0000"+
+    "\u02a4\u02a5\u0007\u0007\u0000\u0000\u02a5\u02a6\u0007\b\u0000\u0000\u02a6"+
+    "\u02a7\u0007\u0006\u0000\u0000\u02a7\u02a8\u0001\u0000\u0000\u0000\u02a8"+
+    "\u02a9\u0006\u0013\t\u0000\u02a98\u0001\u0000\u0000\u0000\u02aa\u02ab"+
+    "\u0004\u0014\u0000\u0000\u02ab\u02ac\u0007\u0007\u0000\u0000\u02ac\u02ad"+
+    "\u0007\b\u0000\u0000\u02ad\u02ae\u0007\u0004\u0000\u0000\u02ae\u02af\u0007"+
+    "\u0007\u0000\u0000\u02af\u02b0\u0007\b\u0000\u0000\u02b0\u02b1\u0007\u0005"+
+    "\u0000\u0000\u02b1\u02b2\u0007\n\u0000\u0000\u02b2\u02b3\u0007\u0006\u0000"+
+    "\u0000\u02b3\u02b4\u0007\u000e\u0000\u0000\u02b4\u02b5\u0007\u0006\u0000"+
+    "\u0000\u02b5\u02b6\u0007\n\u0000\u0000\u02b6\u02b7\u0001\u0000\u0000\u0000"+
+    "\u02b7\u02b8\u0006\u0014\u0000\u0000\u02b8:\u0001\u0000\u0000\u0000\u02b9"+
+    "\u02ba\u0004\u0015\u0001\u0000\u02ba\u02bb\u0007\u0004\u0000\u0000\u02bb"+
+    "\u02bc\u0007\u0001\u0000\u0000\u02bc\u02bd\u0007\u0001\u0000\u0000\u02bd"+
+    "\u02be\u0007\u0012\u0000\u0000\u02be\u02bf\u0007\u0014\u0000\u0000\u02bf"+
+    "\u02c0\u0007\u0003\u0000\u0000\u02c0\u02c1\u0005_\u0000\u0000\u02c1\u02c2"+
+    "\u0005\u8001\uf414\u0000\u0000\u02c2\u02c3\u0001\u0000\u0000\u0000\u02c3"+
+    "\u02c4\u0006\u0015\n\u0000\u02c4<\u0001\u0000\u0000\u0000\u02c5\u02c6"+
+    "\u0004\u0016\u0002\u0000\u02c6\u02c7\u0007\u0002\u0000\u0000\u02c7\u02c8"+
+    "\u0007\u0005\u0000\u0000\u02c8\u02c9\u0007\u0006\u0000\u0000\u02c9\u02ca"+
+    "\u0007\u000b\u0000\u0000\u02ca\u02cb\u0007\u0007\u0000\u0000\u02cb\u02cc"+
+    "\u0007\u0000\u0000\u0000\u02cc\u02cd\u0007\n\u0000\u0000\u02cd\u02ce\u0001"+
+    "\u0000\u0000\u0000\u02ce\u02cf\u0006\u0016\u000b\u0000\u02cf>\u0001\u0000"+
+    "\u0000\u0000\u02d0\u02d1\u0004\u0017\u0003\u0000\u02d1\u02d2\u0007\u000b"+
+    "\u0000\u0000\u02d2\u02d3\u0007\u0005\u0000\u0000\u02d3\u02d4\u0007\u000b"+
+    "\u0000\u0000\u02d4\u02d5\u0007\u000e\u0000\u0000\u02d5\u02d6\u0007\b\u0000"+
+    "\u0000\u02d6\u02d7\u0007\u0012\u0000\u0000\u02d7\u02d8\u0001\u0000\u0000"+
+    "\u0000\u02d8\u02d9\u0006\u0017\u0000\u0000\u02d9@\u0001\u0000\u0000\u0000"+
+    "\u02da\u02db\u0004\u0018\u0004\u0000\u02db\u02dc\u0007\u0010\u0000\u0000"+
+    "\u02dc\u02dd\u0007\u0014\u0000\u0000\u02dd\u02de\u0007\u0004\u0000\u0000"+
+    "\u02de\u02df\u0007\u0004\u0000\u0000\u02df\u02e0\u0001\u0000\u0000\u0000"+
+    "\u02e0\u02e1\u0006\u0018\b\u0000\u02e1B\u0001\u0000\u0000\u0000\u02e2"+
+    "\u02e3\u0004\u0019\u0005\u0000\u02e3\u02e4\u0007\u0004\u0000\u0000\u02e4"+
+    "\u02e5\u0007\u0005\u0000\u0000\u02e5\u02e6\u0007\u0010\u0000\u0000\u02e6"+
+    "\u02e7\u0007\u0006\u0000\u0000\u02e7\u02e8\u0001\u0000\u0000\u0000\u02e8"+
+    "\u02e9\u0006\u0019\b\u0000\u02e9D\u0001\u0000\u0000\u0000\u02ea\u02eb"+
+    "\u0004\u001a\u0006\u0000\u02eb\u02ec\u0007\u000b\u0000\u0000\u02ec\u02ed"+
+    "\u0007\u0007\u0000\u0000\u02ed\u02ee\u0007\u0011\u0000\u0000\u02ee\u02ef"+
+    "\u0007\f\u0000\u0000\u02ef\u02f0\u0007\u0006\u0000\u0000\u02f0\u02f1\u0001"+
+    "\u0000\u0000\u0000\u02f1\u02f2\u0006\u001a\b\u0000\u02f2F\u0001\u0000"+
+    "\u0000\u0000\u02f3\u02f5\b\u0015\u0000\u0000\u02f4\u02f3\u0001\u0000\u0000"+
+    "\u0000\u02f5\u02f6\u0001\u0000\u0000\u0000\u02f6\u02f4\u0001\u0000\u0000"+
+    "\u0000\u02f6\u02f7\u0001\u0000\u0000\u0000\u02f7\u02f8\u0001\u0000\u0000"+
+    "\u0000\u02f8\u02f9\u0006\u001b\u0000\u0000\u02f9H\u0001\u0000\u0000\u0000"+
+    "\u02fa\u02fb\u0005/\u0000\u0000\u02fb\u02fc\u0005/\u0000\u0000\u02fc\u0300"+
+    "\u0001\u0000\u0000\u0000\u02fd\u02ff\b\u0016\u0000\u0000\u02fe\u02fd\u0001"+
+    "\u0000\u0000\u0000\u02ff\u0302\u0001\u0000\u0000\u0000\u0300\u02fe\u0001"+
+    "\u0000\u0000\u0000\u0300\u0301\u0001\u0000\u0000\u0000\u0301\u0304\u0001"+
+    "\u0000\u0000\u0000\u0302\u0300\u0001\u0000\u0000\u0000\u0303\u0305\u0005"+
+    "\r\u0000\u0000\u0304\u0303\u0001\u0000\u0000\u0000\u0304\u0305\u0001\u0000"+
+    "\u0000\u0000\u0305\u0307\u0001\u0000\u0000\u0000\u0306\u0308\u0005\n\u0000"+
+    "\u0000\u0307\u0306\u0001\u0000\u0000\u0000\u0307\u0308\u0001\u0000\u0000"+
+    "\u0000\u0308\u0309\u0001\u0000\u0000\u0000\u0309\u030a\u0006\u001c\f\u0000"+
+    "\u030aJ\u0001\u0000\u0000\u0000\u030b\u030c\u0005/\u0000\u0000\u030c\u030d"+
+    "\u0005*\u0000\u0000\u030d\u0312\u0001\u0000\u0000\u0000\u030e\u0311\u0003"+
+    "K\u001d\u0000\u030f\u0311\t\u0000\u0000\u0000\u0310\u030e\u0001\u0000"+
+    "\u0000\u0000\u0310\u030f\u0001\u0000\u0000\u0000\u0311\u0314\u0001\u0000"+
+    "\u0000\u0000\u0312\u0313\u0001\u0000\u0000\u0000\u0312\u0310\u0001\u0000"+
+    "\u0000\u0000\u0313\u0315\u0001\u0000\u0000\u0000\u0314\u0312\u0001\u0000"+
+    "\u0000\u0000\u0315\u0316\u0005*\u0000\u0000\u0316\u0317\u0005/\u0000\u0000"+
+    "\u0317\u0318\u0001\u0000\u0000\u0000\u0318\u0319\u0006\u001d\f\u0000\u0319"+
+    "L\u0001\u0000\u0000\u0000\u031a\u031c\u0007\u0017\u0000\u0000\u031b\u031a"+
+    "\u0001\u0000\u0000\u0000\u031c\u031d\u0001\u0000\u0000\u0000\u031d\u031b"+
+    "\u0001\u0000\u0000\u0000\u031d\u031e\u0001\u0000\u0000\u0000\u031e\u031f"+
+    "\u0001\u0000\u0000\u0000\u031f\u0320\u0006\u001e\f\u0000\u0320N\u0001"+
+    "\u0000\u0000\u0000\u0321\u0322\u0005|\u0000\u0000\u0322\u0323\u0001\u0000"+
+    "\u0000\u0000\u0323\u0324\u0006\u001f\r\u0000\u0324P\u0001\u0000\u0000"+
+    "\u0000\u0325\u0326\u0007\u0018\u0000\u0000\u0326R\u0001\u0000\u0000\u0000"+
+    "\u0327\u0328\u0007\u0019\u0000\u0000\u0328T\u0001\u0000\u0000\u0000\u0329"+
+    "\u032a\u0005\\\u0000\u0000\u032a\u032b\u0007\u001a\u0000\u0000\u032bV"+
+    "\u0001\u0000\u0000\u0000\u032c\u032d\b\u001b\u0000\u0000\u032dX\u0001"+
+    "\u0000\u0000\u0000\u032e\u0330\u0007\u0005\u0000\u0000\u032f\u0331\u0007"+
+    "\u001c\u0000\u0000\u0330\u032f\u0001\u0000\u0000\u0000\u0330\u0331\u0001"+
+    "\u0000\u0000\u0000\u0331\u0333\u0001\u0000\u0000\u0000\u0332\u0334\u0003"+
+    "Q \u0000\u0333\u0332\u0001\u0000\u0000\u0000\u0334\u0335\u0001\u0000\u0000"+
+    "\u0000\u0335\u0333\u0001\u0000\u0000\u0000\u0335\u0336\u0001\u0000\u0000"+
+    "\u0000\u0336Z\u0001\u0000\u0000\u0000\u0337\u0338\u0005@\u0000\u0000\u0338"+
+    "\\\u0001\u0000\u0000\u0000\u0339\u033a\u0005`\u0000\u0000\u033a^\u0001"+
+    "\u0000\u0000\u0000\u033b\u033f\b\u001d\u0000\u0000\u033c\u033d\u0005`"+
+    "\u0000\u0000\u033d\u033f\u0005`\u0000\u0000\u033e\u033b\u0001\u0000\u0000"+
+    "\u0000\u033e\u033c\u0001\u0000\u0000\u0000\u033f`\u0001\u0000\u0000\u0000"+
+    "\u0340\u0341\u0005_\u0000\u0000\u0341b\u0001\u0000\u0000\u0000\u0342\u0346"+
+    "\u0003S!\u0000\u0343\u0346\u0003Q \u0000\u0344\u0346\u0003a(\u0000\u0345"+
+    "\u0342\u0001\u0000\u0000\u0000\u0345\u0343\u0001\u0000\u0000\u0000\u0345"+
+    "\u0344\u0001\u0000\u0000\u0000\u0346d\u0001\u0000\u0000\u0000\u0347\u034c"+
+    "\u0005\"\u0000\u0000\u0348\u034b\u0003U\"\u0000\u0349\u034b\u0003W#\u0000"+
+    "\u034a\u0348\u0001\u0000\u0000\u0000\u034a\u0349\u0001\u0000\u0000\u0000"+
+    "\u034b\u034e\u0001\u0000\u0000\u0000\u034c\u034a\u0001\u0000\u0000\u0000"+
+    "\u034c\u034d\u0001\u0000\u0000\u0000\u034d\u034f\u0001\u0000\u0000\u0000"+
+    "\u034e\u034c\u0001\u0000\u0000\u0000\u034f\u0365\u0005\"\u0000\u0000\u0350"+
+    "\u0351\u0005\"\u0000\u0000\u0351\u0352\u0005\"\u0000\u0000\u0352\u0353"+
+    "\u0005\"\u0000\u0000\u0353\u0357\u0001\u0000\u0000\u0000\u0354\u0356\b"+
+    "\u0016\u0000\u0000\u0355\u0354\u0001\u0000\u0000\u0000\u0356\u0359\u0001"+
+    "\u0000\u0000\u0000\u0357\u0358\u0001\u0000\u0000\u0000\u0357\u0355\u0001"+
+    "\u0000\u0000\u0000\u0358\u035a\u0001\u0000\u0000\u0000\u0359\u0357\u0001"+
+    "\u0000\u0000\u0000\u035a\u035b\u0005\"\u0000\u0000\u035b\u035c\u0005\""+
+    "\u0000\u0000\u035c\u035d\u0005\"\u0000\u0000\u035d\u035f\u0001\u0000\u0000"+
+    "\u0000\u035e\u0360\u0005\"\u0000\u0000\u035f\u035e\u0001\u0000\u0000\u0000"+
+    "\u035f\u0360\u0001\u0000\u0000\u0000\u0360\u0362\u0001\u0000\u0000\u0000"+
+    "\u0361\u0363\u0005\"\u0000\u0000\u0362\u0361\u0001\u0000\u0000\u0000\u0362"+
+    "\u0363\u0001\u0000\u0000\u0000\u0363\u0365\u0001\u0000\u0000\u0000\u0364"+
+    "\u0347\u0001\u0000\u0000\u0000\u0364\u0350\u0001\u0000\u0000\u0000\u0365"+
+    "f\u0001\u0000\u0000\u0000\u0366\u0368\u0003Q \u0000\u0367\u0366\u0001"+
+    "\u0000\u0000\u0000\u0368\u0369\u0001\u0000\u0000\u0000\u0369\u0367\u0001"+
+    "\u0000\u0000\u0000\u0369\u036a\u0001\u0000\u0000\u0000\u036ah\u0001\u0000"+
+    "\u0000\u0000\u036b\u036d\u0003Q \u0000\u036c\u036b\u0001\u0000\u0000\u0000"+
+    "\u036d\u036e\u0001\u0000\u0000\u0000\u036e\u036c\u0001\u0000\u0000\u0000"+
+    "\u036e\u036f\u0001\u0000\u0000\u0000\u036f\u0370\u0001\u0000\u0000\u0000"+
+    "\u0370\u0374\u0003{5\u0000\u0371\u0373\u0003Q \u0000\u0372\u0371\u0001"+
+    "\u0000\u0000\u0000\u0373\u0376\u0001\u0000\u0000\u0000\u0374\u0372\u0001"+
+    "\u0000\u0000\u0000\u0374\u0375\u0001\u0000\u0000\u0000\u0375\u0396\u0001"+
+    "\u0000\u0000\u0000\u0376\u0374\u0001\u0000\u0000\u0000\u0377\u0379\u0003"+
+    "{5\u0000\u0378\u037a\u0003Q \u0000\u0379\u0378\u0001\u0000\u0000\u0000"+
+    "\u037a\u037b\u0001\u0000\u0000\u0000\u037b\u0379\u0001\u0000\u0000\u0000"+
+    "\u037b\u037c\u0001\u0000\u0000\u0000\u037c\u0396\u0001\u0000\u0000\u0000"+
+    "\u037d\u037f\u0003Q \u0000\u037e\u037d\u0001\u0000\u0000\u0000\u037f\u0380"+
+    "\u0001\u0000\u0000\u0000\u0380\u037e\u0001\u0000\u0000\u0000\u0380\u0381"+
+    "\u0001\u0000\u0000\u0000\u0381\u0389\u0001\u0000\u0000\u0000\u0382\u0386"+
+    "\u0003{5\u0000\u0383\u0385\u0003Q \u0000\u0384\u0383\u0001\u0000\u0000"+
+    "\u0000\u0385\u0388\u0001\u0000\u0000\u0000\u0386\u0384\u0001\u0000\u0000"+
+    "\u0000\u0386\u0387\u0001\u0000\u0000\u0000\u0387\u038a\u0001\u0000\u0000"+
+    "\u0000\u0388\u0386\u0001\u0000\u0000\u0000\u0389\u0382\u0001\u0000\u0000"+
+    "\u0000\u0389\u038a\u0001\u0000\u0000\u0000\u038a\u038b\u0001\u0000\u0000"+
+    "\u0000\u038b\u038c\u0003Y$\u0000\u038c\u0396\u0001\u0000\u0000\u0000\u038d"+
+    "\u038f\u0003{5\u0000\u038e\u0390\u0003Q \u0000\u038f\u038e\u0001\u0000"+
+    "\u0000\u0000\u0390\u0391\u0001\u0000\u0000\u0000\u0391\u038f\u0001\u0000"+
+    "\u0000\u0000\u0391\u0392\u0001\u0000\u0000\u0000\u0392\u0393\u0001\u0000"+
+    "\u0000\u0000\u0393\u0394\u0003Y$\u0000\u0394\u0396\u0001\u0000\u0000\u0000"+
+    "\u0395\u036c\u0001\u0000\u0000\u0000\u0395\u0377\u0001\u0000\u0000\u0000"+
+    "\u0395\u037e\u0001\u0000\u0000\u0000\u0395\u038d\u0001\u0000\u0000\u0000"+
+    "\u0396j\u0001\u0000\u0000\u0000\u0397\u0398\u0007\u000e\u0000\u0000\u0398"+
+    "\u0399\u0007\b\u0000\u0000\u0399\u039a\u0007\t\u0000\u0000\u039al\u0001"+
+    "\u0000\u0000\u0000\u039b\u039c\u0007\u000e\u0000\u0000\u039c\u039d\u0007"+
+    "\n\u0000\u0000\u039d\u039e\u0007\u0000\u0000\u0000\u039en\u0001\u0000"+
+    "\u0000\u0000\u039f\u03a0\u0005=\u0000\u0000\u03a0p\u0001\u0000\u0000\u0000"+
+    "\u03a1\u03a2\u0007\u001e\u0000\u0000\u03a2\u03a3\u0007\u001f\u0000\u0000"+
+    "\u03a3r\u0001\u0000\u0000\u0000\u03a4\u03a5\u0005:\u0000\u0000\u03a5\u03a6"+
+    "\u0005:\u0000\u0000\u03a6t\u0001\u0000\u0000\u0000\u03a7\u03a8\u0005:"+
+    "\u0000\u0000\u03a8v\u0001\u0000\u0000\u0000\u03a9\u03aa\u0005,\u0000\u0000"+
+    "\u03aax\u0001\u0000\u0000\u0000\u03ab\u03ac\u0007\t\u0000\u0000\u03ac"+
+    "\u03ad\u0007\u0005\u0000\u0000\u03ad\u03ae\u0007\n\u0000\u0000\u03ae\u03af"+
+    "\u0007\u0000\u0000\u0000\u03afz\u0001\u0000\u0000\u0000\u03b0\u03b1\u0005"+
+    ".\u0000\u0000\u03b1|\u0001\u0000\u0000\u0000\u03b2\u03b3\u0007\u0010\u0000"+
+    "\u0000\u03b3\u03b4\u0007\u000e\u0000\u0000\u03b4\u03b5\u0007\u0004\u0000"+
+    "\u0000\u03b5\u03b6\u0007\n\u0000\u0000\u03b6\u03b7\u0007\u0005\u0000\u0000"+
+    "\u03b7~\u0001\u0000\u0000\u0000\u03b8\u03b9\u0007\u0010\u0000\u0000\u03b9"+
+    "\u03ba\u0007\u0007\u0000\u0000\u03ba\u03bb\u0007\u000b\u0000\u0000\u03bb"+
+    "\u03bc\u0007\n\u0000\u0000\u03bc\u03bd\u0007\u0006\u0000\u0000\u03bd\u0080"+
+    "\u0001\u0000\u0000\u0000\u03be\u03bf\u0007\u0007\u0000\u0000\u03bf\u03c0"+
+    "\u0007\b\u0000\u0000\u03c0\u0082\u0001\u0000\u0000\u0000\u03c1\u03c2\u0007"+
+    "\u0007\u0000\u0000\u03c2\u03c3\u0007\n\u0000\u0000\u03c3\u0084\u0001\u0000"+
+    "\u0000\u0000\u03c4\u03c5\u0007\u0004\u0000\u0000\u03c5\u03c6\u0007\u000e"+
+    "\u0000\u0000\u03c6\u03c7\u0007\n\u0000\u0000\u03c7\u03c8\u0007\u0006\u0000"+
+    "\u0000\u03c8\u0086\u0001\u0000\u0000\u0000\u03c9\u03ca\u0007\u0004\u0000"+
+    "\u0000\u03ca\u03cb\u0007\u0007\u0000\u0000\u03cb\u03cc\u0007\u0012\u0000"+
+    "\u0000\u03cc\u03cd\u0007\u0005\u0000\u0000\u03cd\u0088\u0001\u0000\u0000"+
+    "\u0000\u03ce\u03cf\u0005(\u0000\u0000\u03cf\u008a\u0001\u0000\u0000\u0000"+
+    "\u03d0\u03d1\u0007\b\u0000\u0000\u03d1\u03d2\u0007\u0001\u0000\u0000\u03d2"+
+    "\u03d3\u0007\u0006\u0000\u0000\u03d3\u008c\u0001\u0000\u0000\u0000\u03d4"+
+    "\u03d5\u0007\b\u0000\u0000\u03d5\u03d6\u0007\u0014\u0000\u0000\u03d6\u03d7"+
+    "\u0007\u0004\u0000\u0000\u03d7\u03d8\u0007\u0004\u0000\u0000\u03d8\u008e"+
+    "\u0001\u0000\u0000\u0000\u03d9\u03da\u0007\b\u0000\u0000\u03da\u03db\u0007"+
+    "\u0014\u0000\u0000\u03db\u03dc\u0007\u0004\u0000\u0000\u03dc\u03dd\u0007"+
+    "\u0004\u0000\u0000\u03dd\u03de\u0007\n\u0000\u0000\u03de\u0090\u0001\u0000"+
+    "\u0000\u0000\u03df\u03e0\u0007\u0001\u0000\u0000\u03e0\u03e1\u0007\b\u0000"+
+    "\u0000\u03e1\u0092\u0001\u0000\u0000\u0000\u03e2\u03e3\u0007\u0001\u0000"+
+    "\u0000\u03e3\u03e4\u0007\u000b\u0000\u0000\u03e4\u0094\u0001\u0000\u0000"+
+    "\u0000\u03e5\u03e6\u0005?\u0000\u0000\u03e6\u0096\u0001\u0000\u0000\u0000"+
+    "\u03e7\u03e8\u0007\u000b\u0000\u0000\u03e8\u03e9\u0007\u0004\u0000\u0000"+
+    "\u03e9\u03ea\u0007\u0007\u0000\u0000\u03ea\u03eb\u0007\u0012\u0000\u0000"+
+    "\u03eb\u03ec\u0007\u0005\u0000\u0000\u03ec\u0098\u0001\u0000\u0000\u0000"+
+    "\u03ed\u03ee\u0005)\u0000\u0000\u03ee\u009a\u0001\u0000\u0000\u0000\u03ef"+
+    "\u03f0\u0007\u0006\u0000\u0000\u03f0\u03f1\u0007\u000b\u0000\u0000\u03f1"+
+    "\u03f2\u0007\u0014\u0000\u0000\u03f2\u03f3\u0007\u0005\u0000\u0000\u03f3"+
+    "\u009c\u0001\u0000\u0000\u0000\u03f4\u03f5\u0007\u0013\u0000\u0000\u03f5"+
+    "\u03f6\u0007\u0007\u0000\u0000\u03f6\u03f7\u0007\u0006\u0000\u0000\u03f7"+
+    "\u03f8\u0007\f\u0000\u0000\u03f8\u009e\u0001\u0000\u0000\u0000\u03f9\u03fa"+
+    "\u0005=\u0000\u0000\u03fa\u03fb\u0005=\u0000\u0000\u03fb\u00a0\u0001\u0000"+
+    "\u0000\u0000\u03fc\u03fd\u0005=\u0000\u0000\u03fd\u03fe\u0005~\u0000\u0000"+
+    "\u03fe\u00a2\u0001\u0000\u0000\u0000\u03ff\u0400\u0005!\u0000\u0000\u0400"+
+    "\u0401\u0005=\u0000\u0000\u0401\u00a4\u0001\u0000\u0000\u0000\u0402\u0403"+
+    "\u0005<\u0000\u0000\u0403\u00a6\u0001\u0000\u0000\u0000\u0404\u0405\u0005"+
+    "<\u0000\u0000\u0405\u0406\u0005=\u0000\u0000\u0406\u00a8\u0001\u0000\u0000"+
+    "\u0000\u0407\u0408\u0005>\u0000\u0000\u0408\u00aa\u0001\u0000\u0000\u0000"+
+    "\u0409\u040a\u0005>\u0000\u0000\u040a\u040b\u0005=\u0000\u0000\u040b\u00ac"+
+    "\u0001\u0000\u0000\u0000\u040c\u040d\u0005+\u0000\u0000\u040d\u00ae\u0001"+
+    "\u0000\u0000\u0000\u040e\u040f\u0005-\u0000\u0000\u040f\u00b0\u0001\u0000"+
+    "\u0000\u0000\u0410\u0411\u0005*\u0000\u0000\u0411\u00b2\u0001\u0000\u0000"+
+    "\u0000\u0412\u0413\u0005/\u0000\u0000\u0413\u00b4\u0001\u0000\u0000\u0000"+
+    "\u0414\u0415\u0005%\u0000\u0000\u0415\u00b6\u0001\u0000\u0000\u0000\u0416"+
+    "\u0417\u0005{\u0000\u0000\u0417\u00b8\u0001\u0000\u0000\u0000\u0418\u0419"+
+    "\u0005}\u0000\u0000\u0419\u00ba\u0001\u0000\u0000\u0000\u041a\u041b\u0005"+
+    "?\u0000\u0000\u041b\u041c\u0005?\u0000\u0000\u041c\u00bc\u0001\u0000\u0000"+
+    "\u0000\u041d\u041e\u00033\u0011\u0000\u041e\u041f\u0001\u0000\u0000\u0000"+
+    "\u041f\u0420\u0006V\u000e\u0000\u0420\u00be\u0001\u0000\u0000\u0000\u0421"+
+    "\u0424\u0003\u0095B\u0000\u0422\u0425\u0003S!\u0000\u0423\u0425\u0003"+
+    "a(\u0000\u0424\u0422\u0001\u0000\u0000\u0000\u0424\u0423\u0001\u0000\u0000"+
+    "\u0000\u0425\u0429\u0001\u0000\u0000\u0000\u0426\u0428\u0003c)\u0000\u0427"+
+    "\u0426\u0001\u0000\u0000\u0000\u0428\u042b\u0001\u0000\u0000\u0000\u0429"+
+    "\u0427\u0001\u0000\u0000\u0000\u0429\u042a\u0001\u0000\u0000\u0000\u042a"+
+    "\u0433\u0001\u0000\u0000\u0000\u042b\u0429\u0001\u0000\u0000\u0000\u042c"+
+    "\u042e\u0003\u0095B\u0000\u042d\u042f\u0003Q \u0000\u042e\u042d\u0001"+
+    "\u0000\u0000\u0000\u042f\u0430\u0001\u0000\u0000\u0000\u0430\u042e\u0001"+
+    "\u0000\u0000\u0000\u0430\u0431\u0001\u0000\u0000\u0000\u0431\u0433\u0001"+
+    "\u0000\u0000\u0000\u0432\u0421\u0001\u0000\u0000\u0000\u0432\u042c\u0001"+
+    "\u0000\u0000\u0000\u0433\u00c0\u0001\u0000\u0000\u0000\u0434\u0437\u0003"+
+    "\u00bbU\u0000\u0435\u0438\u0003S!\u0000\u0436\u0438\u0003a(\u0000\u0437"+
+    "\u0435\u0001\u0000\u0000\u0000\u0437\u0436\u0001\u0000\u0000\u0000\u0438"+
+    "\u043c\u0001\u0000\u0000\u0000\u0439\u043b\u0003c)\u0000\u043a\u0439\u0001"+
+    "\u0000\u0000\u0000\u043b\u043e\u0001\u0000\u0000\u0000\u043c\u043a\u0001"+
+    "\u0000\u0000\u0000\u043c\u043d\u0001\u0000\u0000\u0000\u043d\u0446\u0001"+
+    "\u0000\u0000\u0000\u043e\u043c\u0001\u0000\u0000\u0000\u043f\u0441\u0003"+
+    "\u00bbU\u0000\u0440\u0442\u0003Q \u0000\u0441\u0440\u0001\u0000\u0000"+
+    "\u0000\u0442\u0443\u0001\u0000\u0000\u0000\u0443\u0441\u0001\u0000\u0000"+
+    "\u0000\u0443\u0444\u0001\u0000\u0000\u0000\u0444\u0446\u0001\u0000\u0000"+
+    "\u0000\u0445\u0434\u0001\u0000\u0000\u0000\u0445\u043f\u0001\u0000\u0000"+
+    "\u0000\u0446\u00c2\u0001\u0000\u0000\u0000\u0447\u0448\u0005[\u0000\u0000"+
+    "\u0448\u0449\u0001\u0000\u0000\u0000\u0449\u044a\u0006Y\u0000\u0000\u044a"+
+    "\u044b\u0006Y\u0000\u0000\u044b\u00c4\u0001\u0000\u0000\u0000\u044c\u044d"+
+    "\u0005]\u0000\u0000\u044d\u044e\u0001\u0000\u0000\u0000\u044e\u044f\u0006"+
+    "Z\r\u0000\u044f\u0450\u0006Z\r\u0000\u0450\u00c6\u0001\u0000\u0000\u0000"+
+    "\u0451\u0455\u0003S!\u0000\u0452\u0454\u0003c)\u0000\u0453\u0452\u0001"+
+    "\u0000\u0000\u0000\u0454\u0457\u0001\u0000\u0000\u0000\u0455\u0453\u0001"+
+    "\u0000\u0000\u0000\u0455\u0456\u0001\u0000\u0000\u0000\u0456\u0462\u0001"+
+    "\u0000\u0000\u0000\u0457\u0455\u0001\u0000\u0000\u0000\u0458\u045b\u0003"+
+    "a(\u0000\u0459\u045b\u0003[%\u0000\u045a\u0458\u0001\u0000\u0000\u0000"+
+    "\u045a\u0459\u0001\u0000\u0000\u0000\u045b\u045d\u0001\u0000\u0000\u0000"+
+    "\u045c\u045e\u0003c)\u0000\u045d\u045c\u0001\u0000\u0000\u0000\u045e\u045f"+
+    "\u0001\u0000\u0000\u0000\u045f\u045d\u0001\u0000\u0000\u0000\u045f\u0460"+
+    "\u0001\u0000\u0000\u0000\u0460\u0462\u0001\u0000\u0000\u0000\u0461\u0451"+
+    "\u0001\u0000\u0000\u0000\u0461\u045a\u0001\u0000\u0000\u0000\u0462\u00c8"+
+    "\u0001\u0000\u0000\u0000\u0463\u0465\u0003]&\u0000\u0464\u0466\u0003_"+
+    "\'\u0000\u0465\u0464\u0001\u0000\u0000\u0000\u0466\u0467\u0001\u0000\u0000"+
+    "\u0000\u0467\u0465\u0001\u0000\u0000\u0000\u0467\u0468\u0001\u0000\u0000"+
+    "\u0000\u0468\u0469\u0001\u0000\u0000\u0000\u0469\u046a\u0003]&\u0000\u046a"+
+    "\u00ca\u0001\u0000\u0000\u0000\u046b\u046c\u0003\u00c9\\\u0000\u046c\u00cc"+
+    "\u0001\u0000\u0000\u0000\u046d\u046e\u0003I\u001c\u0000\u046e\u046f\u0001"+
+    "\u0000\u0000\u0000\u046f\u0470\u0006^\f\u0000\u0470\u00ce\u0001\u0000"+
+    "\u0000\u0000\u0471\u0472\u0003K\u001d\u0000\u0472\u0473\u0001\u0000\u0000"+
+    "\u0000\u0473\u0474\u0006_\f\u0000\u0474\u00d0\u0001\u0000\u0000\u0000"+
+    "\u0475\u0476\u0003M\u001e\u0000\u0476\u0477\u0001\u0000\u0000\u0000\u0477"+
+    "\u0478\u0006`\f\u0000\u0478\u00d2\u0001\u0000\u0000\u0000\u0479\u047a"+
+    "\u0003\u00c3Y\u0000\u047a\u047b\u0001\u0000\u0000\u0000\u047b\u047c\u0006"+
+    "a\u000f\u0000\u047c\u047d\u0006a\u0010\u0000\u047d\u00d4\u0001\u0000\u0000"+
+    "\u0000\u047e\u047f\u0003O\u001f\u0000\u047f\u0480\u0001\u0000\u0000\u0000"+
+    "\u0480\u0481\u0006b\u0011\u0000\u0481\u0482\u0006b\r\u0000\u0482\u00d6"+
+    "\u0001\u0000\u0000\u0000\u0483\u0484\u0003M\u001e\u0000\u0484\u0485\u0001"+
+    "\u0000\u0000\u0000\u0485\u0486\u0006c\f\u0000\u0486\u00d8\u0001\u0000"+
+    "\u0000\u0000\u0487\u0488\u0003I\u001c\u0000\u0488\u0489\u0001\u0000\u0000"+
+    "\u0000\u0489\u048a\u0006d\f\u0000\u048a\u00da\u0001\u0000\u0000\u0000"+
+    "\u048b\u048c\u0003K\u001d\u0000\u048c\u048d\u0001\u0000\u0000\u0000\u048d"+
+    "\u048e\u0006e\f\u0000\u048e\u00dc\u0001\u0000\u0000\u0000\u048f\u0490"+
+    "\u0003O\u001f\u0000\u0490\u0491\u0001\u0000\u0000\u0000\u0491\u0492\u0006"+
+    "f\u0011\u0000\u0492\u0493\u0006f\r\u0000\u0493\u00de\u0001\u0000\u0000"+
+    "\u0000\u0494\u0495\u0003\u00c3Y\u0000\u0495\u0496\u0001\u0000\u0000\u0000"+
+    "\u0496\u0497\u0006g\u000f\u0000\u0497\u00e0\u0001\u0000\u0000\u0000\u0498"+
+    "\u0499\u0003\u00c5Z\u0000\u0499\u049a\u0001\u0000\u0000\u0000\u049a\u049b"+
+    "\u0006h\u0012\u0000\u049b\u00e2\u0001\u0000\u0000\u0000\u049c\u049d\u0003"+
+    "u2\u0000\u049d\u049e\u0001\u0000\u0000\u0000\u049e\u049f\u0006i\u0013"+
+    "\u0000\u049f\u00e4\u0001\u0000\u0000\u0000\u04a0\u04a1\u0003s1\u0000\u04a1"+
+    "\u04a2\u0001\u0000\u0000\u0000\u04a2\u04a3\u0006j\u0014\u0000\u04a3\u00e6"+
+    "\u0001\u0000\u0000\u0000\u04a4\u04a5\u0003w3\u0000\u04a5\u04a6\u0001\u0000"+
+    "\u0000\u0000\u04a6\u04a7\u0006k\u0015\u0000\u04a7\u00e8\u0001\u0000\u0000"+
+    "\u0000\u04a8\u04a9\u0003o/\u0000\u04a9\u04aa\u0001\u0000\u0000\u0000\u04aa"+
+    "\u04ab\u0006l\u0016\u0000\u04ab\u00ea\u0001\u0000\u0000\u0000\u04ac\u04ad"+
+    "\u0007\u0002\u0000\u0000\u04ad\u04ae\u0007\u0005\u0000\u0000\u04ae\u04af"+
+    "\u0007\u0006\u0000\u0000\u04af\u04b0\u0007\u000e\u0000\u0000\u04b0\u04b1"+
+    "\u0007\t\u0000\u0000\u04b1\u04b2\u0007\u000e\u0000\u0000\u04b2\u04b3\u0007"+
+    "\u0006\u0000\u0000\u04b3\u04b4\u0007\u000e\u0000\u0000\u04b4\u00ec\u0001"+
+    "\u0000\u0000\u0000\u04b5\u04b9\b \u0000\u0000\u04b6\u04b7\u0005/\u0000"+
+    "\u0000\u04b7\u04b9\b!\u0000\u0000\u04b8\u04b5\u0001\u0000\u0000\u0000"+
+    "\u04b8\u04b6\u0001\u0000\u0000\u0000\u04b9\u00ee\u0001\u0000\u0000\u0000"+
+    "\u04ba\u04bc\u0003\u00edn\u0000\u04bb\u04ba\u0001\u0000\u0000\u0000\u04bc"+
+    "\u04bd\u0001\u0000\u0000\u0000\u04bd\u04bb\u0001\u0000\u0000\u0000\u04bd"+
+    "\u04be\u0001\u0000\u0000\u0000\u04be\u00f0\u0001\u0000\u0000\u0000\u04bf"+
+    "\u04c0\u0003\u00efo\u0000\u04c0\u04c1\u0001\u0000\u0000\u0000\u04c1\u04c2"+
+    "\u0006p\u0017\u0000\u04c2\u00f2\u0001\u0000\u0000\u0000\u04c3\u04c4\u0003"+
+    "e*\u0000\u04c4\u04c5\u0001\u0000\u0000\u0000\u04c5\u04c6\u0006q\u0018"+
+    "\u0000\u04c6\u00f4\u0001\u0000\u0000\u0000\u04c7\u04c8\u0003I\u001c\u0000"+
+    "\u04c8\u04c9\u0001\u0000\u0000\u0000\u04c9\u04ca\u0006r\f\u0000\u04ca"+
+    "\u00f6\u0001\u0000\u0000\u0000\u04cb\u04cc\u0003K\u001d\u0000\u04cc\u04cd"+
+    "\u0001\u0000\u0000\u0000\u04cd\u04ce\u0006s\f\u0000\u04ce\u00f8\u0001"+
+    "\u0000\u0000\u0000\u04cf\u04d0\u0003M\u001e\u0000\u04d0\u04d1\u0001\u0000"+
+    "\u0000\u0000\u04d1\u04d2\u0006t\f\u0000\u04d2\u00fa\u0001\u0000\u0000"+
+    "\u0000\u04d3\u04d4\u0003O\u001f\u0000\u04d4\u04d5\u0001\u0000\u0000\u0000"+
+    "\u04d5\u04d6\u0006u\u0011\u0000\u04d6\u04d7\u0006u\r\u0000\u04d7\u00fc"+
+    "\u0001\u0000\u0000\u0000\u04d8\u04d9\u0003{5\u0000\u04d9\u04da\u0001\u0000"+
+    "\u0000\u0000\u04da\u04db\u0006v\u0019\u0000\u04db\u00fe\u0001\u0000\u0000"+
+    "\u0000\u04dc\u04dd\u0003w3\u0000\u04dd\u04de\u0001\u0000\u0000\u0000\u04de"+
+    "\u04df\u0006w\u0015\u0000\u04df\u0100\u0001\u0000\u0000\u0000\u04e0\u04e1"+
+    "\u0003\u0095B\u0000\u04e1\u04e2\u0001\u0000\u0000\u0000\u04e2\u04e3\u0006"+
+    "x\u001a\u0000\u04e3\u0102\u0001\u0000\u0000\u0000\u04e4\u04e5\u0003\u00bf"+
+    "W\u0000\u04e5\u04e6\u0001\u0000\u0000\u0000\u04e6\u04e7\u0006y\u001b\u0000"+
+    "\u04e7\u0104\u0001\u0000\u0000\u0000\u04e8\u04e9\u0003\u00bbU\u0000\u04e9"+
+    "\u04ea\u0001\u0000\u0000\u0000\u04ea\u04eb\u0006z\u001c\u0000\u04eb\u0106"+
+    "\u0001\u0000\u0000\u0000\u04ec\u04ed\u0003\u00c1X\u0000\u04ed\u04ee\u0001"+
+    "\u0000\u0000\u0000\u04ee\u04ef\u0006{\u001d\u0000\u04ef\u0108\u0001\u0000"+
+    "\u0000\u0000\u04f0\u04f5\u0003S!\u0000\u04f1\u04f5\u0003Q \u0000\u04f2"+
+    "\u04f5\u0003a(\u0000\u04f3\u04f5\u0003\u00b1P\u0000\u04f4\u04f0\u0001"+
+    "\u0000\u0000\u0000\u04f4\u04f1\u0001\u0000\u0000\u0000\u04f4\u04f2\u0001"+
+    "\u0000\u0000\u0000\u04f4\u04f3\u0001\u0000\u0000\u0000\u04f5\u010a\u0001"+
+    "\u0000\u0000\u0000\u04f6\u04f9\u0003S!\u0000\u04f7\u04f9\u0003\u00b1P"+
+    "\u0000\u04f8\u04f6\u0001\u0000\u0000\u0000\u04f8\u04f7\u0001\u0000\u0000"+
+    "\u0000\u04f9\u04fd\u0001\u0000\u0000\u0000\u04fa\u04fc\u0003\u0109|\u0000"+
+    "\u04fb\u04fa\u0001\u0000\u0000\u0000\u04fc\u04ff\u0001\u0000\u0000\u0000"+
+    "\u04fd\u04fb\u0001\u0000\u0000\u0000\u04fd\u04fe\u0001\u0000\u0000\u0000"+
+    "\u04fe\u050a\u0001\u0000\u0000\u0000\u04ff\u04fd\u0001\u0000\u0000\u0000"+
+    "\u0500\u0503\u0003a(\u0000\u0501\u0503\u0003[%\u0000\u0502\u0500\u0001"+
+    "\u0000\u0000\u0000\u0502\u0501\u0001\u0000\u0000\u0000\u0503\u0505\u0001"+
+    "\u0000\u0000\u0000\u0504\u0506\u0003\u0109|\u0000\u0505\u0504\u0001\u0000"+
+    "\u0000\u0000\u0506\u0507\u0001\u0000\u0000\u0000\u0507\u0505\u0001\u0000"+
+    "\u0000\u0000\u0507\u0508\u0001\u0000\u0000\u0000\u0508\u050a\u0001\u0000"+
+    "\u0000\u0000\u0509\u04f8\u0001\u0000\u0000\u0000\u0509\u0502\u0001\u0000"+
+    "\u0000\u0000\u050a\u010c\u0001\u0000\u0000\u0000\u050b\u050e\u0003\u010b"+
+    "}\u0000\u050c\u050e\u0003\u00c9\\\u0000\u050d\u050b\u0001\u0000\u0000"+
+    "\u0000\u050d\u050c\u0001\u0000\u0000\u0000\u050e\u050f\u0001\u0000\u0000"+
+    "\u0000\u050f\u050d\u0001\u0000\u0000\u0000\u050f\u0510\u0001\u0000\u0000"+
+    "\u0000\u0510\u010e\u0001\u0000\u0000\u0000\u0511\u0512\u0003I\u001c\u0000"+
+    "\u0512\u0513\u0001\u0000\u0000\u0000\u0513\u0514\u0006\u007f\f\u0000\u0514"+
+    "\u0110\u0001\u0000\u0000\u0000\u0515\u0516\u0003K\u001d\u0000\u0516\u0517"+
+    "\u0001\u0000\u0000\u0000\u0517\u0518\u0006\u0080\f\u0000\u0518\u0112\u0001"+
+    "\u0000\u0000\u0000\u0519\u051a\u0003M\u001e\u0000\u051a\u051b\u0001\u0000"+
+    "\u0000\u0000\u051b\u051c\u0006\u0081\f\u0000\u051c\u0114\u0001\u0000\u0000"+
+    "\u0000\u051d\u051e\u0003O\u001f\u0000\u051e\u051f\u0001\u0000\u0000\u0000"+
+    "\u051f\u0520\u0006\u0082\u0011\u0000\u0520\u0521\u0006\u0082\r\u0000\u0521"+
+    "\u0116\u0001\u0000\u0000\u0000\u0522\u0523\u0003o/\u0000\u0523\u0524\u0001"+
+    "\u0000\u0000\u0000\u0524\u0525\u0006\u0083\u0016\u0000\u0525\u0118\u0001"+
+    "\u0000\u0000\u0000\u0526\u0527\u0003w3\u0000\u0527\u0528\u0001\u0000\u0000"+
+    "\u0000\u0528\u0529\u0006\u0084\u0015\u0000\u0529\u011a\u0001\u0000\u0000"+
+    "\u0000\u052a\u052b\u0003{5\u0000\u052b\u052c\u0001\u0000\u0000\u0000\u052c"+
+    "\u052d\u0006\u0085\u0019\u0000\u052d\u011c\u0001\u0000\u0000\u0000\u052e"+
+    "\u052f\u0003\u0095B\u0000\u052f\u0530\u0001\u0000\u0000\u0000\u0530\u0531"+
+    "\u0006\u0086\u001a\u0000\u0531\u011e\u0001\u0000\u0000\u0000\u0532\u0533"+
+    "\u0003\u00bfW\u0000\u0533\u0534\u0001\u0000\u0000\u0000\u0534\u0535\u0006"+
+    "\u0087\u001b\u0000\u0535\u0120\u0001\u0000\u0000\u0000\u0536\u0537\u0003"+
+    "\u00bbU\u0000\u0537\u0538\u0001\u0000\u0000\u0000\u0538\u0539\u0006\u0088"+
+    "\u001c\u0000\u0539\u0122\u0001\u0000\u0000\u0000\u053a\u053b\u0003\u00c1"+
+    "X\u0000\u053b\u053c\u0001\u0000\u0000\u0000\u053c\u053d\u0006\u0089\u001d"+
+    "\u0000\u053d\u0124\u0001\u0000\u0000\u0000\u053e\u053f\u0007\u000e\u0000"+
+    "\u0000\u053f\u0540\u0007\n\u0000\u0000\u0540\u0126\u0001\u0000\u0000\u0000"+
+    "\u0541\u0542\u0003\u010d~\u0000\u0542\u0543\u0001\u0000\u0000\u0000\u0543"+
+    "\u0544\u0006\u008b\u001e\u0000\u0544\u0128\u0001\u0000\u0000\u0000\u0545"+
+    "\u0546\u0003I\u001c\u0000\u0546\u0547\u0001\u0000\u0000\u0000\u0547\u0548"+
+    "\u0006\u008c\f\u0000\u0548\u012a\u0001\u0000\u0000\u0000\u0549\u054a\u0003"+
+    "K\u001d\u0000\u054a\u054b\u0001\u0000\u0000\u0000\u054b\u054c\u0006\u008d"+
+    "\f\u0000\u054c\u012c\u0001\u0000\u0000\u0000\u054d\u054e\u0003M\u001e"+
+    "\u0000\u054e\u054f\u0001\u0000\u0000\u0000\u054f\u0550\u0006\u008e\f\u0000"+
+    "\u0550\u012e\u0001\u0000\u0000\u0000\u0551\u0552\u0003O\u001f\u0000\u0552"+
+    "\u0553\u0001\u0000\u0000\u0000\u0553\u0554\u0006\u008f\u0011\u0000\u0554"+
+    "\u0555\u0006\u008f\r\u0000\u0555\u0130\u0001\u0000\u0000\u0000\u0556\u0557"+
+    "\u0003\u00c3Y\u0000\u0557\u0558\u0001\u0000\u0000\u0000\u0558\u0559\u0006"+
+    "\u0090\u000f\u0000\u0559\u055a\u0006\u0090\u001f\u0000\u055a\u0132\u0001"+
+    "\u0000\u0000\u0000\u055b\u055c\u0003\u0091@\u0000\u055c\u055d\u0001\u0000"+
+    "\u0000\u0000\u055d\u055e\u0006\u0091 \u0000\u055e\u055f\u0006\u0091!\u0000"+
+    "\u055f\u0134\u0001\u0000\u0000\u0000\u0560\u0561\u0003\u009dF\u0000\u0561"+
+    "\u0562\u0001\u0000\u0000\u0000\u0562\u0563\u0006\u0092\"\u0000\u0563\u0564"+
+    "\u0006\u0092!\u0000\u0564\u0136\u0001\u0000\u0000\u0000\u0565\u0566\b"+
+    "\"\u0000\u0000\u0566\u0138\u0001\u0000\u0000\u0000\u0567\u0569\u0003\u0137"+
+    "\u0093\u0000\u0568\u0567\u0001\u0000\u0000\u0000\u0569\u056a\u0001\u0000"+
+    "\u0000\u0000\u056a\u0568\u0001\u0000\u0000\u0000\u056a\u056b\u0001\u0000"+
+    "\u0000\u0000\u056b\u056c\u0001\u0000\u0000\u0000\u056c\u056d\u0003u2\u0000"+
+    "\u056d\u056f\u0001\u0000\u0000\u0000\u056e\u0568\u0001\u0000\u0000\u0000"+
+    "\u056e\u056f\u0001\u0000\u0000\u0000\u056f\u0571\u0001\u0000\u0000\u0000"+
+    "\u0570\u0572\u0003\u0137\u0093\u0000\u0571\u0570\u0001\u0000\u0000\u0000"+
+    "\u0572\u0573\u0001\u0000\u0000\u0000\u0573\u0571\u0001\u0000\u0000\u0000"+
+    "\u0573\u0574\u0001\u0000\u0000\u0000\u0574\u013a\u0001\u0000\u0000\u0000"+
+    "\u0575\u0576\u0003\u0139\u0094\u0000\u0576\u0577\u0001\u0000\u0000\u0000"+
+    "\u0577\u0578\u0006\u0095#\u0000\u0578\u013c\u0001\u0000\u0000\u0000\u0579"+
+    "\u057a\u0003I\u001c\u0000\u057a\u057b\u0001\u0000\u0000\u0000\u057b\u057c"+
+    "\u0006\u0096\f\u0000\u057c\u013e\u0001\u0000\u0000\u0000\u057d\u057e\u0003"+
+    "K\u001d\u0000\u057e\u057f\u0001\u0000\u0000\u0000\u057f\u0580\u0006\u0097"+
+    "\f\u0000\u0580\u0140\u0001\u0000\u0000\u0000\u0581\u0582\u0003M\u001e"+
+    "\u0000\u0582\u0583\u0001\u0000\u0000\u0000\u0583\u0584\u0006\u0098\f\u0000"+
+    "\u0584\u0142\u0001\u0000\u0000\u0000\u0585\u0586\u0003O\u001f\u0000\u0586"+
+    "\u0587\u0001\u0000\u0000\u0000\u0587\u0588\u0006\u0099\u0011\u0000\u0588"+
+    "\u0589\u0006\u0099\r\u0000\u0589\u058a\u0006\u0099\r\u0000\u058a\u0144"+
+    "\u0001\u0000\u0000\u0000\u058b\u058c\u0003o/\u0000\u058c\u058d\u0001\u0000"+
+    "\u0000\u0000\u058d\u058e\u0006\u009a\u0016\u0000\u058e\u0146\u0001\u0000"+
+    "\u0000\u0000\u058f\u0590\u0003w3\u0000\u0590\u0591\u0001\u0000\u0000\u0000"+
+    "\u0591\u0592\u0006\u009b\u0015\u0000\u0592\u0148\u0001\u0000\u0000\u0000"+
+    "\u0593\u0594\u0003{5\u0000\u0594\u0595\u0001\u0000\u0000\u0000\u0595\u0596"+
+    "\u0006\u009c\u0019\u0000\u0596\u014a\u0001\u0000\u0000\u0000\u0597\u0598"+
+    "\u0003\u009dF\u0000\u0598\u0599\u0001\u0000\u0000\u0000\u0599\u059a\u0006"+
+    "\u009d\"\u0000\u059a\u014c\u0001\u0000\u0000\u0000\u059b\u059c\u0003\u010d"+
+    "~\u0000\u059c\u059d\u0001\u0000\u0000\u0000\u059d\u059e\u0006\u009e\u001e"+
+    "\u0000\u059e\u014e\u0001\u0000\u0000\u0000\u059f\u05a0\u0003\u00cb]\u0000"+
+    "\u05a0\u05a1\u0001\u0000\u0000\u0000\u05a1\u05a2\u0006\u009f$\u0000\u05a2"+
+    "\u0150\u0001\u0000\u0000\u0000\u05a3\u05a4\u0003\u0095B\u0000\u05a4\u05a5"+
+    "\u0001\u0000\u0000\u0000\u05a5\u05a6\u0006\u00a0\u001a\u0000\u05a6\u0152"+
+    "\u0001\u0000\u0000\u0000\u05a7\u05a8\u0003\u00bfW\u0000\u05a8\u05a9\u0001"+
+    "\u0000\u0000\u0000\u05a9\u05aa\u0006\u00a1\u001b\u0000\u05aa\u0154\u0001"+
+    "\u0000\u0000\u0000\u05ab\u05ac\u0003\u00bbU\u0000\u05ac\u05ad\u0001\u0000"+
+    "\u0000\u0000\u05ad\u05ae\u0006\u00a2\u001c\u0000\u05ae\u0156\u0001\u0000"+
+    "\u0000\u0000\u05af\u05b0\u0003\u00c1X\u0000\u05b0\u05b1\u0001\u0000\u0000"+
+    "\u0000\u05b1\u05b2\u0006\u00a3\u001d\u0000\u05b2\u0158\u0001\u0000\u0000"+
+    "\u0000\u05b3\u05b4\u0003I\u001c\u0000\u05b4\u05b5\u0001\u0000\u0000\u0000"+
+    "\u05b5\u05b6\u0006\u00a4\f\u0000\u05b6\u015a\u0001\u0000\u0000\u0000\u05b7"+
+    "\u05b8\u0003K\u001d\u0000\u05b8\u05b9\u0001\u0000\u0000\u0000\u05b9\u05ba"+
+    "\u0006\u00a5\f\u0000\u05ba\u015c\u0001\u0000\u0000\u0000\u05bb\u05bc\u0003"+
+    "M\u001e\u0000\u05bc\u05bd\u0001\u0000\u0000\u0000\u05bd\u05be\u0006\u00a6"+
+    "\f\u0000\u05be\u015e\u0001\u0000\u0000\u0000\u05bf\u05c0\u0003O\u001f"+
+    "\u0000\u05c0\u05c1\u0001\u0000\u0000\u0000\u05c1\u05c2\u0006\u00a7\u0011"+
+    "\u0000\u05c2\u05c3\u0006\u00a7\r\u0000\u05c3\u0160\u0001\u0000\u0000\u0000"+
+    "\u05c4\u05c5\u0003{5\u0000\u05c5\u05c6\u0001\u0000\u0000\u0000\u05c6\u05c7"+
+    "\u0006\u00a8\u0019\u0000\u05c7\u0162\u0001\u0000\u0000\u0000\u05c8\u05c9"+
+    "\u0003\u0095B\u0000\u05c9\u05ca\u0001\u0000\u0000\u0000\u05ca\u05cb\u0006"+
+    "\u00a9\u001a\u0000\u05cb\u0164\u0001\u0000\u0000\u0000\u05cc\u05cd\u0003"+
+    "\u00bfW\u0000\u05cd\u05ce\u0001\u0000\u0000\u0000\u05ce\u05cf\u0006\u00aa"+
+    "\u001b\u0000\u05cf\u0166\u0001\u0000\u0000\u0000\u05d0\u05d1\u0003\u00bb"+
+    "U\u0000\u05d1\u05d2\u0001\u0000\u0000\u0000\u05d2\u05d3\u0006\u00ab\u001c"+
+    "\u0000\u05d3\u0168\u0001\u0000\u0000\u0000\u05d4\u05d5\u0003\u00c1X\u0000"+
+    "\u05d5\u05d6\u0001\u0000\u0000\u0000\u05d6\u05d7\u0006\u00ac\u001d\u0000"+
+    "\u05d7\u016a\u0001\u0000\u0000\u0000\u05d8\u05d9\u0003\u00cb]\u0000\u05d9"+
+    "\u05da\u0001\u0000\u0000\u0000\u05da\u05db\u0006\u00ad$\u0000\u05db\u016c"+
+    "\u0001\u0000\u0000\u0000\u05dc\u05dd\u0003\u00c7[\u0000\u05dd\u05de\u0001"+
+    "\u0000\u0000\u0000\u05de\u05df\u0006\u00ae%\u0000\u05df\u016e\u0001\u0000"+
+    "\u0000\u0000\u05e0\u05e1\u0003I\u001c\u0000\u05e1\u05e2\u0001\u0000\u0000"+
+    "\u0000\u05e2\u05e3\u0006\u00af\f\u0000\u05e3\u0170\u0001\u0000\u0000\u0000"+
+    "\u05e4\u05e5\u0003K\u001d\u0000\u05e5\u05e6\u0001\u0000\u0000\u0000\u05e6"+
+    "\u05e7\u0006\u00b0\f\u0000\u05e7\u0172\u0001\u0000\u0000\u0000\u05e8\u05e9"+
+    "\u0003M\u001e\u0000\u05e9\u05ea\u0001\u0000\u0000\u0000\u05ea\u05eb\u0006"+
+    "\u00b1\f\u0000\u05eb\u0174\u0001\u0000\u0000\u0000\u05ec\u05ed\u0003O"+
+    "\u001f\u0000\u05ed\u05ee\u0001\u0000\u0000\u0000\u05ee\u05ef\u0006\u00b2"+
+    "\u0011\u0000\u05ef\u05f0\u0006\u00b2\r\u0000\u05f0\u0176\u0001\u0000\u0000"+
+    "\u0000\u05f1\u05f2\u0007\u0007\u0000\u0000\u05f2\u05f3\u0007\b\u0000\u0000"+
+    "\u05f3\u05f4\u0007\u0010\u0000\u0000\u05f4\u05f5\u0007\u0001\u0000\u0000"+
+    "\u05f5\u0178\u0001\u0000\u0000\u0000\u05f6\u05f7\u0003I\u001c\u0000\u05f7"+
+    "\u05f8\u0001\u0000\u0000\u0000\u05f8\u05f9\u0006\u00b4\f\u0000\u05f9\u017a"+
+    "\u0001\u0000\u0000\u0000\u05fa\u05fb\u0003K\u001d\u0000\u05fb\u05fc\u0001"+
+    "\u0000\u0000\u0000\u05fc\u05fd\u0006\u00b5\f\u0000\u05fd\u017c\u0001\u0000"+
+    "\u0000\u0000\u05fe\u05ff\u0003M\u001e\u0000\u05ff\u0600\u0001\u0000\u0000"+
+    "\u0000\u0600\u0601\u0006\u00b6\f\u0000\u0601\u017e\u0001\u0000\u0000\u0000"+
+    "\u0602\u0603\u0003\u00c5Z\u0000\u0603\u0604\u0001\u0000\u0000\u0000\u0604"+
+    "\u0605\u0006\u00b7\u0012\u0000\u0605\u0606\u0006\u00b7\r\u0000\u0606\u0180"+
+    "\u0001\u0000\u0000\u0000\u0607\u0608\u0003u2\u0000\u0608\u0609\u0001\u0000"+
+    "\u0000\u0000\u0609\u060a\u0006\u00b8\u0013\u0000\u060a\u0182\u0001\u0000"+
+    "\u0000\u0000\u060b\u0611\u0003[%\u0000\u060c\u0611\u0003Q \u0000\u060d"+
+    "\u0611\u0003{5\u0000\u060e\u0611\u0003S!\u0000\u060f\u0611\u0003a(\u0000"+
+    "\u0610\u060b\u0001\u0000\u0000\u0000\u0610\u060c\u0001\u0000\u0000\u0000"+
+    "\u0610\u060d\u0001\u0000\u0000\u0000\u0610\u060e\u0001\u0000\u0000\u0000"+
+    "\u0610\u060f\u0001\u0000\u0000\u0000\u0611\u0612\u0001\u0000\u0000\u0000"+
+    "\u0612\u0610\u0001\u0000\u0000\u0000\u0612\u0613\u0001\u0000\u0000\u0000"+
+    "\u0613\u0184\u0001\u0000\u0000\u0000\u0614\u0615\u0003I\u001c\u0000\u0615"+
+    "\u0616\u0001\u0000\u0000\u0000\u0616\u0617\u0006\u00ba\f\u0000\u0617\u0186"+
+    "\u0001\u0000\u0000\u0000\u0618\u0619\u0003K\u001d\u0000\u0619\u061a\u0001"+
+    "\u0000\u0000\u0000\u061a\u061b\u0006\u00bb\f\u0000\u061b\u0188\u0001\u0000"+
+    "\u0000\u0000\u061c\u061d\u0003M\u001e\u0000\u061d\u061e\u0001\u0000\u0000"+
+    "\u0000\u061e\u061f\u0006\u00bc\f\u0000\u061f\u018a\u0001\u0000\u0000\u0000"+
+    "\u0620\u0621\u0003O\u001f\u0000\u0621\u0622\u0001\u0000\u0000\u0000\u0622"+
+    "\u0623\u0006\u00bd\u0011\u0000\u0623\u0624\u0006\u00bd\r\u0000\u0624\u018c"+
+    "\u0001\u0000\u0000\u0000\u0625\u0626\u0003u2\u0000\u0626\u0627\u0001\u0000"+
+    "\u0000\u0000\u0627\u0628\u0006\u00be\u0013\u0000\u0628\u018e\u0001\u0000"+
+    "\u0000\u0000\u0629\u062a\u0003w3\u0000\u062a\u062b\u0001\u0000\u0000\u0000"+
+    "\u062b\u062c\u0006\u00bf\u0015\u0000\u062c\u0190\u0001\u0000\u0000\u0000"+
+    "\u062d\u062e\u0003{5\u0000\u062e\u062f\u0001\u0000\u0000\u0000\u062f\u0630"+
+    "\u0006\u00c0\u0019\u0000\u0630\u0192\u0001\u0000\u0000\u0000\u0631\u0632"+
+    "\u0003\u0091@\u0000\u0632\u0633\u0001\u0000\u0000\u0000\u0633\u0634\u0006"+
+    "\u00c1 \u0000\u0634\u0635\u0006\u00c1&\u0000\u0635\u0194\u0001\u0000\u0000"+
+    "\u0000\u0636\u0637\u0003\u00efo\u0000\u0637\u0638\u0001\u0000\u0000\u0000"+
+    "\u0638\u0639\u0006\u00c2\u0017\u0000\u0639\u0196\u0001\u0000\u0000\u0000"+
+    "\u063a\u063b\u0003e*\u0000\u063b\u063c\u0001\u0000\u0000\u0000\u063c\u063d"+
+    "\u0006\u00c3\u0018\u0000\u063d\u0198\u0001\u0000\u0000\u0000\u063e\u063f"+
+    "\u0003I\u001c\u0000\u063f\u0640\u0001\u0000\u0000\u0000\u0640\u0641\u0006"+
+    "\u00c4\f\u0000\u0641\u019a\u0001\u0000\u0000\u0000\u0642\u0643\u0003K"+
+    "\u001d\u0000\u0643\u0644\u0001\u0000\u0000\u0000\u0644\u0645\u0006\u00c5"+
+    "\f\u0000\u0645\u019c\u0001\u0000\u0000\u0000\u0646\u0647\u0003M\u001e"+
+    "\u0000\u0647\u0648\u0001\u0000\u0000\u0000\u0648\u0649\u0006\u00c6\f\u0000"+
+    "\u0649\u019e\u0001\u0000\u0000\u0000\u064a\u064b\u0003O\u001f\u0000\u064b"+
+    "\u064c\u0001\u0000\u0000\u0000\u064c\u064d\u0006\u00c7\u0011\u0000\u064d"+
+    "\u064e\u0006\u00c7\r\u0000\u064e\u064f\u0006\u00c7\r\u0000\u064f\u01a0"+
+    "\u0001\u0000\u0000\u0000\u0650\u0651\u0003w3\u0000\u0651\u0652\u0001\u0000"+
+    "\u0000\u0000\u0652\u0653\u0006\u00c8\u0015\u0000\u0653\u01a2\u0001\u0000"+
+    "\u0000\u0000\u0654\u0655\u0003{5\u0000\u0655\u0656\u0001\u0000\u0000\u0000"+
+    "\u0656\u0657\u0006\u00c9\u0019\u0000\u0657\u01a4\u0001\u0000\u0000\u0000"+
+    "\u0658\u0659\u0003\u010d~\u0000\u0659\u065a\u0001\u0000\u0000\u0000\u065a"+
+    "\u065b\u0006\u00ca\u001e\u0000\u065b\u01a6\u0001\u0000\u0000\u0000\u065c"+
+    "\u065d\u0003I\u001c\u0000\u065d\u065e\u0001\u0000\u0000\u0000\u065e\u065f"+
+    "\u0006\u00cb\f\u0000\u065f\u01a8\u0001\u0000\u0000\u0000\u0660\u0661\u0003"+
+    "K\u001d\u0000\u0661\u0662\u0001\u0000\u0000\u0000\u0662\u0663\u0006\u00cc"+
+    "\f\u0000\u0663\u01aa\u0001\u0000\u0000\u0000\u0664\u0665\u0003M\u001e"+
+    "\u0000\u0665\u0666\u0001\u0000\u0000\u0000\u0666\u0667\u0006\u00cd\f\u0000"+
+    "\u0667\u01ac\u0001\u0000\u0000\u0000\u0668\u0669\u0003O\u001f\u0000\u0669"+
+    "\u066a\u0001\u0000\u0000\u0000\u066a\u066b\u0006\u00ce\u0011\u0000\u066b"+
+    "\u066c\u0006\u00ce\r\u0000\u066c\u01ae\u0001\u0000\u0000\u0000\u066d\u066e"+
+    "\u0007#\u0000\u0000\u066e\u066f\u0007\u0001\u0000\u0000\u066f\u0670\u0007"+
+    "\u0007\u0000\u0000\u0670\u0671\u0007\b\u0000\u0000\u0671\u01b0\u0001\u0000"+
+    "\u0000\u0000\u0672\u0673\u0003\u0125\u008a\u0000\u0673\u0674\u0001\u0000"+
+    "\u0000\u0000\u0674\u0675\u0006\u00d0\'\u0000\u0675\u01b2\u0001\u0000\u0000"+
+    "\u0000\u0676\u0677\u0003\u0091@\u0000\u0677\u0678\u0001\u0000\u0000\u0000"+
+    "\u0678\u0679\u0006\u00d1 \u0000\u0679\u067a\u0006\u00d1\r\u0000\u067a"+
+    "\u067b\u0006\u00d1\u0000\u0000\u067b\u01b4\u0001\u0000\u0000\u0000\u067c"+
+    "\u067d\u0007\u0014\u0000\u0000\u067d\u067e\u0007\n\u0000\u0000\u067e\u067f"+
+    "\u0007\u0007\u0000\u0000\u067f\u0680\u0007\b\u0000\u0000\u0680\u0681\u0007"+
+    "\u0011\u0000\u0000\u0681\u0682\u0001\u0000\u0000\u0000\u0682\u0683\u0006"+
+    "\u00d2\r\u0000\u0683\u0684\u0006\u00d2\u0000\u0000\u0684\u01b6\u0001\u0000"+
+    "\u0000\u0000\u0685\u0686\u0003\u00efo\u0000\u0686\u0687\u0001\u0000\u0000"+
+    "\u0000\u0687\u0688\u0006\u00d3\u0017\u0000\u0688\u01b8\u0001\u0000\u0000"+
+    "\u0000\u0689\u068a\u0003e*\u0000\u068a\u068b\u0001\u0000\u0000\u0000\u068b"+
+    "\u068c\u0006\u00d4\u0018\u0000\u068c\u01ba\u0001\u0000\u0000\u0000\u068d"+
+    "\u068e\u0003u2\u0000\u068e\u068f\u0001\u0000\u0000\u0000\u068f\u0690\u0006"+
+    "\u00d5\u0013\u0000\u0690\u01bc\u0001\u0000\u0000\u0000\u0691\u0692\u0003"+
+    "\u00c7[\u0000\u0692\u0693\u0001\u0000\u0000\u0000\u0693\u0694\u0006\u00d6"+
+    "%\u0000\u0694\u01be\u0001\u0000\u0000\u0000\u0695\u0696\u0003\u00cb]\u0000"+
+    "\u0696\u0697\u0001\u0000\u0000\u0000\u0697\u0698\u0006\u00d7$\u0000\u0698"+
+    "\u01c0\u0001\u0000\u0000\u0000\u0699\u069a\u0003I\u001c\u0000\u069a\u069b"+
+    "\u0001\u0000\u0000\u0000\u069b\u069c\u0006\u00d8\f\u0000\u069c\u01c2\u0001"+
+    "\u0000\u0000\u0000\u069d\u069e\u0003K\u001d\u0000\u069e\u069f\u0001\u0000"+
+    "\u0000\u0000\u069f\u06a0\u0006\u00d9\f\u0000\u06a0\u01c4\u0001\u0000\u0000"+
+    "\u0000\u06a1\u06a2\u0003M\u001e\u0000\u06a2\u06a3\u0001\u0000\u0000\u0000"+
+    "\u06a3\u06a4\u0006\u00da\f\u0000\u06a4\u01c6\u0001\u0000\u0000\u0000\u06a5"+
+    "\u06a6\u0003O\u001f\u0000\u06a6\u06a7\u0001\u0000\u0000\u0000\u06a7\u06a8"+
+    "\u0006\u00db\u0011\u0000\u06a8\u06a9\u0006\u00db\r\u0000\u06a9\u01c8\u0001"+
+    "\u0000\u0000\u0000\u06aa\u06ab\u0003\u00efo\u0000\u06ab\u06ac\u0001\u0000"+
+    "\u0000\u0000\u06ac\u06ad\u0006\u00dc\u0017\u0000\u06ad\u06ae\u0006\u00dc"+
+    "\r\u0000\u06ae\u06af\u0006\u00dc(\u0000\u06af\u01ca\u0001\u0000\u0000"+
+    "\u0000\u06b0\u06b1\u0003e*\u0000\u06b1\u06b2\u0001\u0000\u0000\u0000\u06b2"+
+    "\u06b3\u0006\u00dd\u0018\u0000\u06b3\u06b4\u0006\u00dd\r\u0000\u06b4\u06b5"+
+    "\u0006\u00dd(\u0000\u06b5\u01cc\u0001\u0000\u0000\u0000\u06b6\u06b7\u0003"+
+    "I\u001c\u0000\u06b7\u06b8\u0001\u0000\u0000\u0000\u06b8\u06b9\u0006\u00de"+
+    "\f\u0000\u06b9\u01ce\u0001\u0000\u0000\u0000\u06ba\u06bb\u0003K\u001d"+
+    "\u0000\u06bb\u06bc\u0001\u0000\u0000\u0000\u06bc\u06bd\u0006\u00df\f\u0000"+
+    "\u06bd\u01d0\u0001\u0000\u0000\u0000\u06be\u06bf\u0003M\u001e\u0000\u06bf"+
+    "\u06c0\u0001\u0000\u0000\u0000\u06c0\u06c1\u0006\u00e0\f\u0000\u06c1\u01d2"+
+    "\u0001\u0000\u0000\u0000\u06c2\u06c3\u0003u2\u0000\u06c3\u06c4\u0001\u0000"+
+    "\u0000\u0000\u06c4\u06c5\u0006\u00e1\u0013\u0000\u06c5\u06c6\u0006\u00e1"+
+    "\r\u0000\u06c6\u06c7\u0006\u00e1\u000b\u0000\u06c7\u01d4\u0001\u0000\u0000"+
+    "\u0000\u06c8\u06c9\u0003s1\u0000\u06c9\u06ca\u0001\u0000\u0000\u0000\u06ca"+
+    "\u06cb\u0006\u00e2\u0014\u0000\u06cb\u06cc\u0006\u00e2\r\u0000\u06cc\u06cd"+
+    "\u0006\u00e2\u000b\u0000\u06cd\u01d6\u0001\u0000\u0000\u0000\u06ce\u06cf"+
+    "\u0003w3\u0000\u06cf\u06d0\u0001\u0000\u0000\u0000\u06d0\u06d1\u0006\u00e3"+
+    "\u0015\u0000\u06d1\u06d2\u0006\u00e3\r\u0000\u06d2\u06d3\u0006\u00e3\u000b"+
+    "\u0000\u06d3\u01d8\u0001\u0000\u0000\u0000\u06d4\u06d5\u0003I\u001c\u0000"+
+    "\u06d5\u06d6\u0001\u0000\u0000\u0000\u06d6\u06d7\u0006\u00e4\f\u0000\u06d7"+
+    "\u01da\u0001\u0000\u0000\u0000\u06d8\u06d9\u0003K\u001d\u0000\u06d9\u06da"+
+    "\u0001\u0000\u0000\u0000\u06da\u06db\u0006\u00e5\f\u0000\u06db\u01dc\u0001"+
+    "\u0000\u0000\u0000\u06dc\u06dd\u0003M\u001e\u0000\u06dd\u06de\u0001\u0000"+
+    "\u0000\u0000\u06de\u06df\u0006\u00e6\f\u0000\u06df\u01de\u0001\u0000\u0000"+
+    "\u0000\u06e0\u06e1\u0003\u00cb]\u0000\u06e1\u06e2\u0001\u0000\u0000\u0000"+
+    "\u06e2\u06e3\u0006\u00e7\r\u0000\u06e3\u06e4\u0006\u00e7\u0000\u0000\u06e4"+
+    "\u06e5\u0006\u00e7$\u0000\u06e5\u01e0\u0001\u0000\u0000\u0000\u06e6\u06e7"+
+    "\u0003\u00c7[\u0000\u06e7\u06e8\u0001\u0000\u0000\u0000\u06e8\u06e9\u0006"+
+    "\u00e8\r\u0000\u06e9\u06ea\u0006\u00e8\u0000\u0000\u06ea\u06eb\u0006\u00e8"+
+    "%\u0000\u06eb\u01e2\u0001\u0000\u0000\u0000\u06ec\u06ed\u0003q0\u0000"+
+    "\u06ed\u06ee\u0001\u0000\u0000\u0000\u06ee\u06ef\u0006\u00e9\r\u0000\u06ef"+
+    "\u06f0\u0006\u00e9\u0000\u0000\u06f0\u06f1\u0006\u00e9)\u0000\u06f1\u01e4"+
+    "\u0001\u0000\u0000\u0000\u06f2\u06f3\u0003O\u001f\u0000\u06f3\u06f4\u0001"+
+    "\u0000\u0000\u0000\u06f4\u06f5\u0006\u00ea\u0011\u0000\u06f5\u06f6\u0006"+
+    "\u00ea\r\u0000\u06f6\u01e6\u0001\u0000\u0000\u0000\u06f7\u06f8\u0003O"+
+    "\u001f\u0000\u06f8\u06f9\u0001\u0000\u0000\u0000\u06f9\u06fa\u0006\u00eb"+
+    "\u0011\u0000\u06fa\u06fb\u0006\u00eb\r\u0000\u06fb\u01e8\u0001\u0000\u0000"+
+    "\u0000\u06fc\u06fd\u0003\u0091@\u0000\u06fd\u06fe\u0001\u0000\u0000\u0000"+
+    "\u06fe\u06ff\u0006\u00ec \u0000\u06ff\u01ea\u0001\u0000\u0000\u0000\u0700"+
+    "\u0701\u0003\u0125\u008a\u0000\u0701\u0702\u0001\u0000\u0000\u0000\u0702"+
+    "\u0703\u0006\u00ed\'\u0000\u0703\u01ec\u0001\u0000\u0000\u0000\u0704\u0705"+
+    "\u0003{5\u0000\u0705\u0706\u0001\u0000\u0000\u0000\u0706\u0707\u0006\u00ee"+
+    "\u0019\u0000\u0707\u01ee\u0001\u0000\u0000\u0000\u0708\u0709\u0003w3\u0000"+
+    "\u0709\u070a\u0001\u0000\u0000\u0000\u070a\u070b\u0006\u00ef\u0015\u0000"+
+    "\u070b\u01f0\u0001\u0000\u0000\u0000\u070c\u070d\u0003\u00cb]\u0000\u070d"+
+    "\u070e\u0001\u0000\u0000\u0000\u070e\u070f\u0006\u00f0$\u0000\u070f\u01f2"+
+    "\u0001\u0000\u0000\u0000\u0710\u0711\u0003\u00c7[\u0000\u0711\u0712\u0001"+
+    "\u0000\u0000\u0000\u0712\u0713\u0006\u00f1%\u0000\u0713\u01f4\u0001\u0000"+
+    "\u0000\u0000\u0714\u0715\u0003I\u001c\u0000\u0715\u0716\u0001\u0000\u0000"+
+    "\u0000\u0716\u0717\u0006\u00f2\f\u0000\u0717\u01f6\u0001\u0000\u0000\u0000"+
+    "\u0718\u0719\u0003K\u001d\u0000\u0719\u071a\u0001\u0000\u0000\u0000\u071a"+
+    "\u071b\u0006\u00f3\f\u0000\u071b\u01f8\u0001\u0000\u0000\u0000\u071c\u071d"+
+    "\u0003M\u001e\u0000\u071d\u071e\u0001\u0000\u0000\u0000\u071e\u071f\u0006"+
+    "\u00f4\f\u0000\u071f\u01fa\u0001\u0000\u0000\u0000G\u0000\u0001\u0002"+
+    "\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u02f6"+
+    "\u0300\u0304\u0307\u0310\u0312\u031d\u0330\u0335\u033e\u0345\u034a\u034c"+
+    "\u0357\u035f\u0362\u0364\u0369\u036e\u0374\u037b\u0380\u0386\u0389\u0391"+
+    "\u0395\u0424\u0429\u0430\u0432\u0437\u043c\u0443\u0445\u0455\u045a\u045f"+
+    "\u0461\u0467\u04b8\u04bd\u04f4\u04f8\u04fd\u0502\u0507\u0509\u050d\u050f"+
+    "\u056a\u056e\u0573\u0610\u0612*\u0005\u0001\u0000\u0005\u0004\u0000\u0005"+
+    "\u0006\u0000\u0005\u0002\u0000\u0005\u0003\u0000\u0005\b\u0000\u0005\u0005"+
+    "\u0000\u0005\t\u0000\u0005\r\u0000\u0005\u0010\u0000\u0005\u000b\u0000"+
+    "\u0005\u000e\u0000\u0000\u0001\u0000\u0004\u0000\u0000\u0007\u0012\u0000"+
+    "\u0007O\u0000\u0005\u0000\u0000\u0007 \u0000\u0007P\u0000\u0007)\u0000"+
+    "\u0007(\u0000\u0007*\u0000\u0007&\u0000\u0007Z\u0000\u0007!\u0000\u0007"+
+    ",\u0000\u00079\u0000\u0007M\u0000\u0007L\u0000\u0007N\u0000\u0007^\u0000"+
+    "\u0005\n\u0000\u00077\u0000\u0005\u0007\u0000\u0007=\u0000\u0007f\u0000"+
+    "\u0007R\u0000\u0007Q\u0000\u0005\f\u0000\u0007b\u0000\u0005\u000f\u0000"+
+    "\u0007\'\u0000";
   public static final ATN _ATN =
     new ATNDeserializer().deserialize(_serializedATN.toCharArray());
   static {

Diff do ficheiro suprimidas por serem muito extensas
+ 3 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp


Diff do ficheiro suprimidas por serem muito extensas
+ 211 - 199
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java


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

@@ -1160,6 +1160,18 @@ public class EsqlBaseParserBaseListener implements EsqlBaseParserListener {
    * <p>The default implementation does nothing.</p>
    */
   @Override public void exitChangePointCommand(EsqlBaseParser.ChangePointCommandContext ctx) { }
+  /**
+   * {@inheritDoc}
+   *
+   * <p>The default implementation does nothing.</p>
+   */
+  @Override public void enterSampleCommand(EsqlBaseParser.SampleCommandContext ctx) { }
+  /**
+   * {@inheritDoc}
+   *
+   * <p>The default implementation does nothing.</p>
+   */
+  @Override public void exitSampleCommand(EsqlBaseParser.SampleCommandContext ctx) { }
   /**
    * {@inheritDoc}
    *

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

@@ -685,6 +685,13 @@ public class EsqlBaseParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
    * {@link #visitChildren} on {@code ctx}.</p>
    */
   @Override public T visitChangePointCommand(EsqlBaseParser.ChangePointCommandContext ctx) { return visitChildren(ctx); }
+  /**
+   * {@inheritDoc}
+   *
+   * <p>The default implementation returns the result of calling
+   * {@link #visitChildren} on {@code ctx}.</p>
+   */
+  @Override public T visitSampleCommand(EsqlBaseParser.SampleCommandContext ctx) { return visitChildren(ctx); }
   /**
    * {@inheritDoc}
    *

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

@@ -1041,6 +1041,16 @@ public interface EsqlBaseParserListener extends ParseTreeListener {
    * @param ctx the parse tree
    */
   void exitChangePointCommand(EsqlBaseParser.ChangePointCommandContext ctx);
+  /**
+   * Enter a parse tree produced by {@link EsqlBaseParser#sampleCommand}.
+   * @param ctx the parse tree
+   */
+  void enterSampleCommand(EsqlBaseParser.SampleCommandContext ctx);
+  /**
+   * Exit a parse tree produced by {@link EsqlBaseParser#sampleCommand}.
+   * @param ctx the parse tree
+   */
+  void exitSampleCommand(EsqlBaseParser.SampleCommandContext ctx);
   /**
    * Enter a parse tree produced by {@link EsqlBaseParser#lookupCommand}.
    * @param ctx the parse tree

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

@@ -626,6 +626,12 @@ public interface EsqlBaseParserVisitor<T> extends ParseTreeVisitor<T> {
    * @return the visitor result
    */
   T visitChangePointCommand(EsqlBaseParser.ChangePointCommandContext ctx);
+  /**
+   * Visit a parse tree produced by {@link EsqlBaseParser#sampleCommand}.
+   * @param ctx the parse tree
+   * @return the visitor result
+   */
+  T visitSampleCommand(EsqlBaseParser.SampleCommandContext ctx);
   /**
    * Visit a parse tree produced by {@link EsqlBaseParser#lookupCommand}.
    * @param ctx the parse tree

+ 14 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/LogicalPlanBuilder.java

@@ -62,6 +62,7 @@ import org.elasticsearch.xpack.esql.plan.logical.MvExpand;
 import org.elasticsearch.xpack.esql.plan.logical.OrderBy;
 import org.elasticsearch.xpack.esql.plan.logical.Rename;
 import org.elasticsearch.xpack.esql.plan.logical.Row;
+import org.elasticsearch.xpack.esql.plan.logical.Sample;
 import org.elasticsearch.xpack.esql.plan.logical.UnresolvedRelation;
 import org.elasticsearch.xpack.esql.plan.logical.inference.Completion;
 import org.elasticsearch.xpack.esql.plan.logical.inference.Rerank;
@@ -797,4 +798,17 @@ public class LogicalPlanBuilder extends ExpressionBuilder {
             expression.getClass()
         );
     }
+
+    public PlanFactory visitSampleCommand(EsqlBaseParser.SampleCommandContext ctx) {
+        Source source = source(ctx);
+        Object val = expression(ctx.probability).fold(FoldContext.small() /* TODO remove me */);
+        if (val instanceof Double probability && probability > 0.0 && probability < 1.0) {
+            return input -> new Sample(source, new Literal(source, probability, DataType.DOUBLE), input);
+        } else {
+            throw new ParsingException(
+                source(ctx),
+                "invalid value for SAMPLE probability [" + BytesRefs.toString(val) + "], expecting a number between 0 and 1, exclusive"
+            );
+        }
+    }
 }

+ 4 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/PlanWritables.java

@@ -21,6 +21,7 @@ import org.elasticsearch.xpack.esql.plan.logical.Lookup;
 import org.elasticsearch.xpack.esql.plan.logical.MvExpand;
 import org.elasticsearch.xpack.esql.plan.logical.OrderBy;
 import org.elasticsearch.xpack.esql.plan.logical.Project;
+import org.elasticsearch.xpack.esql.plan.logical.Sample;
 import org.elasticsearch.xpack.esql.plan.logical.TopN;
 import org.elasticsearch.xpack.esql.plan.logical.inference.Completion;
 import org.elasticsearch.xpack.esql.plan.logical.inference.Rerank;
@@ -46,6 +47,7 @@ import org.elasticsearch.xpack.esql.plan.physical.LimitExec;
 import org.elasticsearch.xpack.esql.plan.physical.LocalSourceExec;
 import org.elasticsearch.xpack.esql.plan.physical.MvExpandExec;
 import org.elasticsearch.xpack.esql.plan.physical.ProjectExec;
+import org.elasticsearch.xpack.esql.plan.physical.SampleExec;
 import org.elasticsearch.xpack.esql.plan.physical.ShowExec;
 import org.elasticsearch.xpack.esql.plan.physical.SubqueryExec;
 import org.elasticsearch.xpack.esql.plan.physical.TopNExec;
@@ -85,6 +87,7 @@ public class PlanWritables {
             OrderBy.ENTRY,
             Project.ENTRY,
             Rerank.ENTRY,
+            Sample.ENTRY,
             TopN.ENTRY
         );
     }
@@ -111,6 +114,7 @@ public class PlanWritables {
             MvExpandExec.ENTRY,
             ProjectExec.ENTRY,
             RerankExec.ENTRY,
+            SampleExec.ENTRY,
             ShowExec.ENTRY,
             SubqueryExec.ENTRY,
             TopNExec.ENTRY

+ 88 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/logical/Sample.java

@@ -0,0 +1,88 @@
+/*
+ * 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.plan.logical;
+
+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.capabilities.TelemetryAware;
+import org.elasticsearch.xpack.esql.core.expression.Expression;
+import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput;
+
+import java.io.IOException;
+import java.util.Objects;
+
+public class Sample extends UnaryPlan implements TelemetryAware {
+    public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(LogicalPlan.class, "Sample", Sample::new);
+
+    private final Expression probability;
+
+    public Sample(Source source, Expression probability, LogicalPlan child) {
+        super(source, child);
+        this.probability = probability;
+    }
+
+    private Sample(StreamInput in) throws IOException {
+        this(
+            Source.readFrom((PlanStreamInput) in),
+            in.readNamedWriteable(Expression.class), // probability
+            in.readNamedWriteable(LogicalPlan.class) // child
+        );
+    }
+
+    @Override
+    public void writeTo(StreamOutput out) throws IOException {
+        source().writeTo(out);
+        out.writeNamedWriteable(probability);
+        out.writeNamedWriteable(child());
+    }
+
+    @Override
+    public String getWriteableName() {
+        return ENTRY.name;
+    }
+
+    @Override
+    protected NodeInfo<Sample> info() {
+        return NodeInfo.create(this, Sample::new, probability, child());
+    }
+
+    @Override
+    public Sample replaceChild(LogicalPlan newChild) {
+        return new Sample(source(), probability, newChild);
+    }
+
+    public Expression probability() {
+        return probability;
+    }
+
+    @Override
+    public boolean expressionsResolved() {
+        return probability.resolved();
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(probability, child());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+
+        var other = (Sample) obj;
+
+        return Objects.equals(probability, other.probability) && Objects.equals(child(), other.child());
+    }
+}

+ 6 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/physical/EsQueryExec.java

@@ -308,6 +308,12 @@ public class EsQueryExec extends LeafExec implements EstimatesRowSize {
             : new EsQueryExec(source(), indexPattern, indexMode, indexNameWithModes, attrs, query, limit, sorts, estimatedRowSize);
     }
 
+    public EsQueryExec withQuery(QueryBuilder query) {
+        return Objects.equals(this.query, query)
+            ? this
+            : new EsQueryExec(source(), indexPattern, indexMode, indexNameWithModes, attrs, query, limit, sorts, estimatedRowSize);
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(indexPattern, indexMode, indexNameWithModes, attrs, query, limit, sorts);

+ 90 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/physical/SampleExec.java

@@ -0,0 +1,90 @@
+/*
+ * 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.plan.physical;
+
+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.tree.NodeInfo;
+import org.elasticsearch.xpack.esql.core.tree.Source;
+import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput;
+
+import java.io.IOException;
+import java.util.Objects;
+
+public class SampleExec extends UnaryExec {
+    public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(
+        PhysicalPlan.class,
+        "SampleExec",
+        SampleExec::new
+    );
+
+    private final Expression probability;
+
+    public SampleExec(Source source, PhysicalPlan child, Expression probability) {
+        super(source, child);
+        this.probability = probability;
+    }
+
+    public SampleExec(StreamInput in) throws IOException {
+        this(
+            Source.readFrom((PlanStreamInput) in),
+            in.readNamedWriteable(PhysicalPlan.class), // child
+            in.readNamedWriteable(Expression.class) // probability
+        );
+    }
+
+    @Override
+    public void writeTo(StreamOutput out) throws IOException {
+        source().writeTo(out);
+        out.writeNamedWriteable(child());
+        out.writeNamedWriteable(probability);
+    }
+
+    @Override
+    public UnaryExec replaceChild(PhysicalPlan newChild) {
+        return new SampleExec(source(), newChild, probability);
+    }
+
+    @Override
+    protected NodeInfo<? extends PhysicalPlan> info() {
+        return NodeInfo.create(this, SampleExec::new, child(), probability);
+    }
+
+    /**
+     * Returns the name of the writeable object
+     */
+    @Override
+    public String getWriteableName() {
+        return ENTRY.name;
+    }
+
+    public Expression probability() {
+        return probability;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(child(), probability);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+
+        var other = (SampleExec) obj;
+
+        return Objects.equals(child(), other.child()) && Objects.equals(probability, other.probability);
+    }
+}

+ 11 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlanner.java

@@ -35,6 +35,7 @@ import org.elasticsearch.compute.operator.Operator;
 import org.elasticsearch.compute.operator.Operator.OperatorFactory;
 import org.elasticsearch.compute.operator.OutputOperator.OutputOperatorFactory;
 import org.elasticsearch.compute.operator.RowInTableLookupOperator;
+import org.elasticsearch.compute.operator.SampleOperator;
 import org.elasticsearch.compute.operator.ScoreOperator;
 import org.elasticsearch.compute.operator.ShowOperator;
 import org.elasticsearch.compute.operator.SinkOperator;
@@ -63,6 +64,7 @@ import org.elasticsearch.xpack.esql.core.expression.Expression;
 import org.elasticsearch.xpack.esql.core.expression.Expressions;
 import org.elasticsearch.xpack.esql.core.expression.FieldAttribute;
 import org.elasticsearch.xpack.esql.core.expression.FoldContext;
+import org.elasticsearch.xpack.esql.core.expression.Foldables;
 import org.elasticsearch.xpack.esql.core.expression.Literal;
 import org.elasticsearch.xpack.esql.core.expression.MetadataAttribute;
 import org.elasticsearch.xpack.esql.core.expression.NameId;
@@ -103,6 +105,7 @@ import org.elasticsearch.xpack.esql.plan.physical.MvExpandExec;
 import org.elasticsearch.xpack.esql.plan.physical.OutputExec;
 import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan;
 import org.elasticsearch.xpack.esql.plan.physical.ProjectExec;
+import org.elasticsearch.xpack.esql.plan.physical.SampleExec;
 import org.elasticsearch.xpack.esql.plan.physical.ShowExec;
 import org.elasticsearch.xpack.esql.plan.physical.TopNExec;
 import org.elasticsearch.xpack.esql.plan.physical.inference.CompletionExec;
@@ -247,6 +250,8 @@ public class LocalExecutionPlanner {
             return planChangePoint(changePoint, context);
         } else if (node instanceof CompletionExec completion) {
             return planCompletion(completion, context);
+        } else if (node instanceof SampleExec Sample) {
+            return planSample(Sample, context);
         }
         // source nodes
         else if (node instanceof EsQueryExec esQuery) {
@@ -814,6 +819,12 @@ public class LocalExecutionPlanner {
         );
     }
 
+    private PhysicalOperation planSample(SampleExec rsx, LocalExecutionPlannerContext context) {
+        PhysicalOperation source = plan(rsx.child(), context);
+        var probability = (double) Foldables.valueOf(context.foldCtx(), rsx.probability());
+        return source.with(new SampleOperator.Factory(probability), source.layout);
+    }
+
     /**
      * Immutable physical operation.
      */

+ 6 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/mapper/LocalMapper.java

@@ -17,6 +17,7 @@ import org.elasticsearch.xpack.esql.plan.logical.EsRelation;
 import org.elasticsearch.xpack.esql.plan.logical.LeafPlan;
 import org.elasticsearch.xpack.esql.plan.logical.Limit;
 import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan;
+import org.elasticsearch.xpack.esql.plan.logical.Sample;
 import org.elasticsearch.xpack.esql.plan.logical.TopN;
 import org.elasticsearch.xpack.esql.plan.logical.UnaryPlan;
 import org.elasticsearch.xpack.esql.plan.logical.join.Join;
@@ -28,6 +29,7 @@ import org.elasticsearch.xpack.esql.plan.physical.LimitExec;
 import org.elasticsearch.xpack.esql.plan.physical.LocalSourceExec;
 import org.elasticsearch.xpack.esql.plan.physical.LookupJoinExec;
 import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan;
+import org.elasticsearch.xpack.esql.plan.physical.SampleExec;
 import org.elasticsearch.xpack.esql.plan.physical.TopNExec;
 
 import java.util.List;
@@ -83,6 +85,10 @@ public class LocalMapper {
             return new TopNExec(topN.source(), mappedChild, topN.order(), topN.limit(), null);
         }
 
+        if (unary instanceof Sample sample) {
+            return new SampleExec(sample.source(), mappedChild, sample.probability());
+        }
+
         //
         // Pipeline operators
         //

+ 8 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/mapper/Mapper.java

@@ -20,6 +20,7 @@ import org.elasticsearch.xpack.esql.plan.logical.LeafPlan;
 import org.elasticsearch.xpack.esql.plan.logical.Limit;
 import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan;
 import org.elasticsearch.xpack.esql.plan.logical.OrderBy;
+import org.elasticsearch.xpack.esql.plan.logical.Sample;
 import org.elasticsearch.xpack.esql.plan.logical.TopN;
 import org.elasticsearch.xpack.esql.plan.logical.UnaryPlan;
 import org.elasticsearch.xpack.esql.plan.logical.inference.Rerank;
@@ -34,6 +35,7 @@ import org.elasticsearch.xpack.esql.plan.physical.LimitExec;
 import org.elasticsearch.xpack.esql.plan.physical.LocalSourceExec;
 import org.elasticsearch.xpack.esql.plan.physical.LookupJoinExec;
 import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan;
+import org.elasticsearch.xpack.esql.plan.physical.SampleExec;
 import org.elasticsearch.xpack.esql.plan.physical.TopNExec;
 import org.elasticsearch.xpack.esql.plan.physical.UnaryExec;
 import org.elasticsearch.xpack.esql.plan.physical.inference.RerankExec;
@@ -179,6 +181,12 @@ public class Mapper {
             );
         }
 
+        // TODO: share code with local LocalMapper?
+        if (unary instanceof Sample sample) {
+            mappedChild = addExchangeForFragment(sample, mappedChild);
+            return new SampleExec(sample.source(), mappedChild, sample.probability());
+        }
+
         //
         // Pipeline operators
         //

+ 11 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/mapper/MapperUtils.java

@@ -12,6 +12,7 @@ import org.elasticsearch.compute.aggregation.AggregatorMode;
 import org.elasticsearch.xpack.esql.EsqlIllegalArgumentException;
 import org.elasticsearch.xpack.esql.core.expression.Attribute;
 import org.elasticsearch.xpack.esql.core.expression.FoldContext;
+import org.elasticsearch.xpack.esql.core.expression.MetadataAttribute;
 import org.elasticsearch.xpack.esql.plan.logical.Aggregate;
 import org.elasticsearch.xpack.esql.plan.logical.ChangePoint;
 import org.elasticsearch.xpack.esql.plan.logical.Dissect;
@@ -49,7 +50,7 @@ import java.util.List;
 /**
  * Class for sharing code across Mappers.
  */
-class MapperUtils {
+public class MapperUtils {
     private MapperUtils() {}
 
     static PhysicalPlan mapLeaf(LeafPlan p) {
@@ -156,4 +157,13 @@ class MapperUtils {
     static PhysicalPlan unsupported(LogicalPlan p) {
         throw new EsqlIllegalArgumentException("unsupported logical plan node [" + p.nodeName() + "]");
     }
+
+    public static boolean hasScoreAttribute(List<? extends Attribute> attributes) {
+        for (Attribute attr : attributes) {
+            if (MetadataAttribute.isScoreAttribute(attr)) {
+                return true;
+            }
+        }
+        return false;
+    }
 }

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

@@ -27,6 +27,7 @@ import org.elasticsearch.xpack.esql.plan.logical.OrderBy;
 import org.elasticsearch.xpack.esql.plan.logical.Project;
 import org.elasticsearch.xpack.esql.plan.logical.Rename;
 import org.elasticsearch.xpack.esql.plan.logical.Row;
+import org.elasticsearch.xpack.esql.plan.logical.Sample;
 import org.elasticsearch.xpack.esql.plan.logical.UnresolvedRelation;
 import org.elasticsearch.xpack.esql.plan.logical.inference.Completion;
 import org.elasticsearch.xpack.esql.plan.logical.inference.Rerank;
@@ -60,7 +61,8 @@ public enum FeatureMetric {
     CHANGE_POINT(ChangePoint.class::isInstance),
     INLINESTATS(InlineStats.class::isInstance),
     COMPLETION(Completion.class::isInstance),
-    RERANK(Rerank.class::isInstance);
+    RERANK(Rerank.class::isInstance),
+    SAMPLE(Sample.class::isInstance);
 
     /**
      * List here plans we want to exclude from telemetry

+ 11 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java

@@ -30,6 +30,8 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
 
 import static org.elasticsearch.xpack.core.enrich.EnrichPolicy.GEO_MATCH_TYPE;
 import static org.elasticsearch.xpack.core.enrich.EnrichPolicy.MATCH_TYPE;
@@ -239,4 +241,13 @@ public final class AnalyzerTestUtils {
         );
         return IndexResolution.valid(index);
     }
+
+    public static <E> E randomValueOtherThanTest(Predicate<E> exclude, Supplier<E> supplier) {
+        while (true) {
+            E value = supplier.get();
+            if (exclude.test(value) == false) {
+                return value;
+            }
+        }
+    }
 }

+ 19 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/ParsingTests.java

@@ -158,6 +158,25 @@ public class ParsingTests extends ESTestCase {
         assertEquals("1:13: Invalid value for LIMIT [-1], expecting a non negative integer", error("row a = 1 | limit -1"));
     }
 
+    public void testInvalidSample() {
+        assertEquals(
+            "1:13: invalid value for SAMPLE probability [foo], expecting a number between 0 and 1, exclusive",
+            error("row a = 1 | sample \"foo\"")
+        );
+        assertEquals(
+            "1:13: invalid value for SAMPLE probability [-1.0], expecting a number between 0 and 1, exclusive",
+            error("row a = 1 | sample -1.0")
+        );
+        assertEquals(
+            "1:13: invalid value for SAMPLE probability [0], expecting a number between 0 and 1, exclusive",
+            error("row a = 1 | sample 0")
+        );
+        assertEquals(
+            "1:13: invalid value for SAMPLE probability [1], expecting a number between 0 and 1, exclusive",
+            error("row a = 1 | sample 1")
+        );
+    }
+
     private String error(String query) {
         ParsingException e = expectThrows(ParsingException.class, () -> defaultAnalyzer.analyze(parser.createStatement(query)));
         String message = e.getMessage();

+ 147 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java

@@ -102,6 +102,7 @@ import org.elasticsearch.xpack.esql.optimizer.rules.logical.SplitInWithFoldableV
 import org.elasticsearch.xpack.esql.parser.ParsingException;
 import org.elasticsearch.xpack.esql.plan.GeneratingPlan;
 import org.elasticsearch.xpack.esql.plan.logical.Aggregate;
+import org.elasticsearch.xpack.esql.plan.logical.ChangePoint;
 import org.elasticsearch.xpack.esql.plan.logical.Dissect;
 import org.elasticsearch.xpack.esql.plan.logical.Enrich;
 import org.elasticsearch.xpack.esql.plan.logical.EsRelation;
@@ -114,6 +115,7 @@ import org.elasticsearch.xpack.esql.plan.logical.MvExpand;
 import org.elasticsearch.xpack.esql.plan.logical.OrderBy;
 import org.elasticsearch.xpack.esql.plan.logical.Project;
 import org.elasticsearch.xpack.esql.plan.logical.Row;
+import org.elasticsearch.xpack.esql.plan.logical.Sample;
 import org.elasticsearch.xpack.esql.plan.logical.TopN;
 import org.elasticsearch.xpack.esql.plan.logical.UnaryPlan;
 import org.elasticsearch.xpack.esql.plan.logical.inference.Completion;
@@ -7568,4 +7570,149 @@ public class LogicalPlanOptimizerTests extends AbstractLogicalPlanOptimizerTests
         var mvExpand2 = as(mvExpand.child(), MvExpand.class);
         as(mvExpand2.child(), Row.class);
     }
+
+    /**
+     * Eval[[1[INTEGER] AS irrelevant1, 2[INTEGER] AS irrelevant2]]
+     *    \_Limit[1000[INTEGER],false]
+     *      \_Sample[0.015[DOUBLE],15[INTEGER]]
+     *        \_EsRelation[test][_meta_field{f}#12, emp_no{f}#6, first_name{f}#7, ge..]
+     */
+    public void testSampleMerged() {
+        assumeTrue("sample must be enabled", EsqlCapabilities.Cap.SAMPLE_V3.isEnabled());
+
+        var query = """
+            FROM TEST
+            | SAMPLE .3
+            | EVAL irrelevant1 = 1
+            | SAMPLE .5
+            | EVAL irrelevant2 = 2
+            | SAMPLE .1
+            """;
+        var optimized = optimizedPlan(query);
+
+        var eval = as(optimized, Eval.class);
+        var limit = as(eval.child(), Limit.class);
+        var sample = as(limit.child(), Sample.class);
+        var source = as(sample.child(), EsRelation.class);
+
+        assertThat(sample.probability().fold(FoldContext.small()), equalTo(0.015));
+    }
+
+    public void testSamplePushDown() {
+        assumeTrue("sample must be enabled", EsqlCapabilities.Cap.SAMPLE_V3.isEnabled());
+
+        for (var command : List.of(
+            "ENRICH languages_idx on first_name",
+            "EVAL x = 1",
+            // "INSIST emp_no", // TODO
+            "KEEP emp_no",
+            "DROP emp_no",
+            "RENAME emp_no AS x",
+            "GROK first_name \"%{WORD:bar}\"",
+            "DISSECT first_name \"%{z}\""
+        )) {
+            var query = "FROM TEST | " + command + " | SAMPLE .5";
+            var optimized = optimizedPlan(query);
+
+            var unary = as(optimized, UnaryPlan.class);
+            var limit = as(unary.child(), Limit.class);
+            var sample = as(limit.child(), Sample.class);
+            var source = as(sample.child(), EsRelation.class);
+
+            assertThat(sample.probability().fold(FoldContext.small()), equalTo(0.5));
+        }
+    }
+
+    public void testSamplePushDown_sort() {
+        assumeTrue("sample must be enabled", EsqlCapabilities.Cap.SAMPLE_V3.isEnabled());
+
+        var query = "FROM TEST | WHERE emp_no > 0 | SAMPLE 0.5 | LIMIT 100";
+        var optimized = optimizedPlan(query);
+
+        var limit = as(optimized, Limit.class);
+        var filter = as(limit.child(), Filter.class);
+        var sample = as(filter.child(), Sample.class);
+        var source = as(sample.child(), EsRelation.class);
+
+        assertThat(sample.probability().fold(FoldContext.small()), equalTo(0.5));
+    }
+
+    public void testSamplePushDown_where() {
+        assumeTrue("sample must be enabled", EsqlCapabilities.Cap.SAMPLE_V3.isEnabled());
+
+        var query = "FROM TEST | SORT emp_no | SAMPLE 0.5 | LIMIT 100";
+        var optimized = optimizedPlan(query);
+
+        var topN = as(optimized, TopN.class);
+        var sample = as(topN.child(), Sample.class);
+        var source = as(sample.child(), EsRelation.class);
+
+        assertThat(sample.probability().fold(FoldContext.small()), equalTo(0.5));
+    }
+
+    public void testSampleNoPushDown() {
+        assumeTrue("sample must be enabled", EsqlCapabilities.Cap.SAMPLE_V3.isEnabled());
+
+        for (var command : List.of("LIMIT 100", "MV_EXPAND languages", "STATS COUNT()")) {
+            var query = "FROM TEST | " + command + " | SAMPLE .5";
+            var optimized = optimizedPlan(query);
+
+            var limit = as(optimized, Limit.class);
+            var sample = as(limit.child(), Sample.class);
+            var unary = as(sample.child(), UnaryPlan.class);
+            var source = as(unary.child(), EsRelation.class);
+        }
+    }
+
+    /**
+     *    Limit[1000[INTEGER],false]
+     *    \_Sample[0.5[DOUBLE],null]
+     *      \_Join[LEFT,[language_code{r}#4],[language_code{r}#4],[language_code{f}#17]]
+     *        |_Eval[[emp_no{f}#6 AS language_code]]
+     *        | \_EsRelation[test][_meta_field{f}#12, emp_no{f}#6, first_name{f}#7, ge..]
+     *        \_EsRelation[languages_lookup][LOOKUP][language_code{f}#17, language_name{f}#18]
+     */
+    public void testSampleNoPushDownLookupJoin() {
+        assumeTrue("sample must be enabled", EsqlCapabilities.Cap.SAMPLE_V3.isEnabled());
+
+        var query = """
+            FROM TEST
+            | EVAL language_code = emp_no
+            | LOOKUP JOIN languages_lookup ON language_code
+            | SAMPLE .5
+            """;
+        var optimized = optimizedPlan(query);
+
+        var limit = as(optimized, Limit.class);
+        var sample = as(limit.child(), Sample.class);
+        var join = as(sample.child(), Join.class);
+        var eval = as(join.left(), Eval.class);
+        var source = as(eval.child(), EsRelation.class);
+    }
+
+    /**
+     *    Limit[1000[INTEGER],false]
+     *    \_Sample[0.5[DOUBLE],null]
+     *      \_Limit[1000[INTEGER],false]
+     *        \_ChangePoint[emp_no{f}#6,hire_date{f}#13,type{r}#4,pvalue{r}#5]
+     *          \_TopN[[Order[hire_date{f}#13,ASC,ANY]],1001[INTEGER]]
+     *            \_EsRelation[test][_meta_field{f}#12, emp_no{f}#6, first_name{f}#7, ge..]
+     */
+    public void testSampleNoPushDownChangePoint() {
+        assumeTrue("sample must be enabled", EsqlCapabilities.Cap.SAMPLE_V3.isEnabled());
+
+        var query = """
+            FROM TEST
+            | CHANGE_POINT emp_no ON hire_date
+            | SAMPLE .5
+            """;
+        var optimized = optimizedPlan(query);
+
+        var limit = as(optimized, Limit.class);
+        var sample = as(limit.child(), Sample.class);
+        limit = as(sample.child(), Limit.class);
+        var changePoint = as(limit.child(), ChangePoint.class);
+        var topN = as(changePoint.child(), TopN.class);
+        var source = as(topN.child(), EsRelation.class);
+    }
 }

+ 39 - 4
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java

@@ -35,6 +35,7 @@ import org.elasticsearch.index.query.RegexpQueryBuilder;
 import org.elasticsearch.index.query.TermQueryBuilder;
 import org.elasticsearch.index.query.TermsQueryBuilder;
 import org.elasticsearch.index.query.WildcardQueryBuilder;
+import org.elasticsearch.search.aggregations.bucket.sampler.random.RandomSamplingQueryBuilder;
 import org.elasticsearch.search.sort.FieldSortBuilder;
 import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
 import org.elasticsearch.test.ESTestCase;
@@ -187,6 +188,7 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE;
 import static org.elasticsearch.xpack.esql.core.util.TestUtils.stripThrough;
 import static org.elasticsearch.xpack.esql.parser.ExpressionBuilder.MAX_EXPRESSION_DEPTH;
 import static org.elasticsearch.xpack.esql.parser.LogicalPlanBuilder.MAX_QUERY_DEPTH;
+import static org.elasticsearch.xpack.esql.planner.mapper.MapperUtils.hasScoreAttribute;
 import static org.hamcrest.Matchers.closeTo;
 import static org.hamcrest.Matchers.contains;
 import static org.hamcrest.Matchers.containsInAnyOrder;
@@ -7904,7 +7906,7 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
         EsRelation esRelation = as(filter.child(), EsRelation.class);
         assertTrue(esRelation.optimized());
         assertTrue(esRelation.resolved());
-        assertTrue(esRelation.output().stream().anyMatch(a -> a.name().equals(MetadataAttribute.SCORE) && a instanceof MetadataAttribute));
+        assertTrue(hasScoreAttribute(esRelation.output()));
     }
 
     public void testScoreTopN() {
@@ -7927,7 +7929,7 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
         Order scoreOrer = order.get(0);
         assertEquals(Order.OrderDirection.DESC, scoreOrer.direction());
         Expression child = scoreOrer.child();
-        assertTrue(child instanceof MetadataAttribute ma && ma.name().equals(MetadataAttribute.SCORE));
+        assertTrue(MetadataAttribute.isScoreAttribute(child));
         Filter filter = as(topN.child(), Filter.class);
 
         Match match = as(filter.condition(), Match.class);
@@ -7937,7 +7939,7 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
         EsRelation esRelation = as(filter.child(), EsRelation.class);
         assertTrue(esRelation.optimized());
         assertTrue(esRelation.resolved());
-        assertTrue(esRelation.output().stream().anyMatch(a -> a.name().equals(MetadataAttribute.SCORE) && a instanceof MetadataAttribute));
+        assertTrue(hasScoreAttribute(esRelation.output()));
     }
 
     public void testReductionPlanForTopN() {
@@ -8021,6 +8023,39 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
         );
     }
 
+    /*
+     *    LimitExec[1000[INTEGER]]
+     *    \_ExchangeExec[[_meta_field{f}#8, emp_no{f}#2, first_name{f}#3, gender{f}#4, hire_date{f}#9, job{f}#10, job.raw{f}#11, langua
+     *              ges{f}#5, last_name{f}#6, long_noidx{f}#12, salary{f}#7],false]
+     *      \_ProjectExec[[_meta_field{f}#8, emp_no{f}#2, first_name{f}#3, gender{f}#4, hire_date{f}#9, job{f}#10, job.raw{f}#11, langua
+     *              ges{f}#5, last_name{f}#6, long_noidx{f}#12, salary{f}#7]]
+     *        \_FieldExtractExec[_meta_field{f}#8, emp_no{f}#2, first_name{f}#3, gen..]<[],[]>
+     *          \_EsQueryExec[test], indexMode[standard],
+     *                  query[{"bool":{"filter":[{"sampling":{"probability":0.1,"seed":234,"hash":0}}],"boost":1.0}}]
+     *                  [_doc{f}#24], limit[1000], sort[] estimatedRowSize[332]
+     */
+    public void testSamplePushDown() {
+        assumeTrue("sample must be enabled", EsqlCapabilities.Cap.SAMPLE_V3.isEnabled());
+
+        var plan = physicalPlan("""
+            FROM test
+            | SAMPLE +0.1
+            """);
+        var optimized = optimizedPlan(plan);
+
+        var limit = as(optimized, LimitExec.class);
+        var exchange = as(limit.child(), ExchangeExec.class);
+        var project = as(exchange.child(), ProjectExec.class);
+        var fieldExtract = as(project.child(), FieldExtractExec.class);
+        var esQuery = as(fieldExtract.child(), EsQueryExec.class);
+
+        var boolQuery = as(esQuery.query(), BoolQueryBuilder.class);
+        var filter = boolQuery.filter();
+        var randomSampling = as(filter.get(0), RandomSamplingQueryBuilder.class);
+        assertThat(randomSampling.probability(), equalTo(0.1));
+        assertThat(randomSampling.hash(), equalTo(0));
+    }
+
     @SuppressWarnings("SameParameterValue")
     private static void assertFilterCondition(
         Filter filter,
@@ -8204,7 +8239,7 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
         var logical = logicalOptimizer.optimize(dataSource.analyzer.analyze(parser.createStatement(query)));
         // System.out.println("Logical\n" + logical);
         var physical = mapper.map(logical);
-        // System.out.println(physical);
+        // System.out.println("Physical\n" + physical);
         if (assertSerialization) {
             assertSerialization(physical, config);
         }

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

@@ -106,6 +106,7 @@ import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.instanceOf;
 import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.startsWith;
 
 //@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE", reason = "debug")
 public class StatementParserTests extends AbstractStatementParserTests {
@@ -3542,6 +3543,21 @@ public class StatementParserTests extends AbstractStatementParserTests {
         expectError("FROM foo* | COMPLETION completion=prompt", "line 1:41: mismatched input '<EOF>' expecting {");
     }
 
+    public void testSample() {
+        assumeTrue("SAMPLE requires corresponding capability", EsqlCapabilities.Cap.SAMPLE_V3.isEnabled());
+        expectError("FROM test | SAMPLE .1 2", "line 1:23: extraneous input '2' expecting <EOF>");
+        expectError("FROM test | SAMPLE .1 \"2\"", "line 1:23: extraneous input '\"2\"' expecting <EOF>");
+        expectError(
+            "FROM test | SAMPLE 1",
+            "line 1:13: invalid value for SAMPLE probability [1], expecting a number between 0 and 1, exclusive"
+        );
+        expectThrows(
+            ParsingException.class,
+            startsWith("line 1:19: mismatched input '<EOF>' expecting {"),
+            () -> statement("FROM test | SAMPLE")
+        );
+    }
+
     static Alias alias(String name, Expression value) {
         return new Alias(EMPTY, name, value);
     }

+ 52 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plan/logical/SampleSerializationTests.java

@@ -0,0 +1,52 @@
+/*
+ * 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.plan.logical;
+
+import org.elasticsearch.xpack.esql.core.expression.Literal;
+import org.elasticsearch.xpack.esql.core.type.DataType;
+
+import java.io.IOException;
+
+public class SampleSerializationTests extends AbstractLogicalPlanSerializationTests<Sample> {
+    /**
+     * Creates a random test instance to use in the tests. This method will be
+     * called multiple times during test execution and should return a different
+     * random instance each time it is called.
+     */
+    @Override
+    protected Sample createTestInstance() {
+        return new Sample(randomSource(), randomProbability(), randomChild(0));
+    }
+
+    public static Literal randomProbability() {
+        return new Literal(randomSource(), randomDoubleBetween(0, 1, false), DataType.DOUBLE);
+    }
+
+    public static Literal randomSeed() {
+        return randomBoolean() ? new Literal(randomSource(), randomInt(), DataType.INTEGER) : null;
+    }
+
+    /**
+     * Returns an instance which is mutated slightly so it should not be equal
+     * to the given instance.
+     *
+     * @param instance
+     */
+    @Override
+    protected Sample mutateInstance(Sample instance) throws IOException {
+        var probability = instance.probability();
+        var child = instance.child();
+        int updateSelector = randomIntBetween(0, 1);
+        switch (updateSelector) {
+            case 0 -> probability = randomValueOtherThan(probability, SampleSerializationTests::randomProbability);
+            case 1 -> child = randomValueOtherThan(child, () -> randomChild(0));
+            default -> throw new IllegalArgumentException("Invalid selector: " + updateSelector);
+        }
+        return new Sample(instance.source(), probability, child);
+    }
+}

+ 45 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plan/physical/SampleExecSerializationTests.java

@@ -0,0 +1,45 @@
+/*
+ * 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.plan.physical;
+
+import org.elasticsearch.xpack.esql.plan.logical.SampleSerializationTests;
+
+import java.io.IOException;
+
+import static org.elasticsearch.xpack.esql.plan.logical.SampleSerializationTests.randomProbability;
+
+public class SampleExecSerializationTests extends AbstractPhysicalPlanSerializationTests<SampleExec> {
+    /**
+     * Creates a random test instance to use in the tests. This method will be
+     * called multiple times during test execution and should return a different
+     * random instance each time it is called.
+     */
+    @Override
+    protected SampleExec createTestInstance() {
+        return new SampleExec(randomSource(), randomChild(0), randomProbability());
+    }
+
+    /**
+     * Returns an instance which is mutated slightly so it should not be equal
+     * to the given instance.
+     *
+     * @param instance
+     */
+    @Override
+    protected SampleExec mutateInstance(SampleExec instance) throws IOException {
+        var probability = instance.probability();
+        var child = instance.child();
+        int updateSelector = randomIntBetween(0, 1);
+        switch (updateSelector) {
+            case 0 -> probability = randomValueOtherThan(probability, SampleSerializationTests::randomProbability);
+            case 1 -> child = randomValueOtherThan(child, () -> randomChild(0));
+            default -> throw new IllegalArgumentException("Invalid selector: " + updateSelector);
+        }
+        return new SampleExec(instance.source(), child, probability);
+    }
+}

+ 16 - 10
x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/10_basic.yml

@@ -359,20 +359,22 @@ setup:
   - match: {values.2: ["1",2.0,null,true,123,1674835275193]}
 
 ---
-"Test Unnamed Input Params Also For Limit":
+"Test Unnamed Input Params Also For Limit And Sample":
   - requires:
         test_runner_features: [ capabilities ]
         capabilities:
           - method: POST
             path: /_query
             parameters: [ ]
-            capabilities: [ parameter_for_limit ]
+            capabilities: [ parameter_for_limit, parameter_for_sample ]
         reason: "named or positional parameters"
   - do:
       esql.query:
         body:
-          query: 'from test | eval x = ?, y = ?, z = ?, t = ?, u = ?, v = ? | keep x, y, z, t, u, v | limit ?'
-          params: ["1", 2.0, null, true, 123, 1674835275193, 3]
+          # The "| sort time" is to work around https://github.com/elastic/elasticsearch/issues/120272
+          # TODO: remove it when the issue is fixed
+          query: 'from test | sort time | sample ? | eval x = ?, y = ?, z = ?, t = ?, u = ?, v = ? | keep x, y, z, t, u, v | limit ?'
+          params: [0.999999999999, "1", 2.0, null, true, 123, 1674835275193, 3]
 
   - length: {columns: 6}
   - match: {columns.0.name: "x"}
@@ -401,14 +403,16 @@ setup:
         - method: POST
           path: /_query
           parameters: [ ]
-          capabilities: [ parameter_for_limit ]
+          capabilities: [ parameter_for_limit, parameter_for_sample ]
       reason: "named or positional parameters"
 
   - do:
       esql.query:
         body:
-          query: 'from test | eval x = ?, y = ?, z = ?, t = ?, u = ?, v = ? | keep x, y, z, t, u, v | limit ?'
-          params: [{"n1" : "1"}, {"n2" : 2.0}, {"n3" : null}, {"n4" : true}, {"n5" : 123}, {"n6": 1674835275193}, {"l": 3}]
+          # The "| sort time" is to work around https://github.com/elastic/elasticsearch/issues/120272
+          # TODO: remove it when the issue is fixed
+          query: 'from test | sort time | sample ? | eval x = ?, y = ?, z = ?, t = ?, u = ?, v = ? | keep x, y, z, t, u, v | limit ?'
+          params: [{"s": 0.99999999999}, {"n1" : "1"}, {"n2" : 2.0}, {"n3" : null}, {"n4" : true}, {"n5" : 123}, {"n6": 1674835275193}, {"l": 3}]
 
   - length: {columns: 6}
   - match: {columns.0.name: "x"}
@@ -465,14 +469,16 @@ setup:
         - method: POST
           path: /_query
           parameters: [ ]
-          capabilities: [ parameter_for_limit ]
+          capabilities: [ parameter_for_limit, parameter_for_sample ]
       reason: "named or positional parameters for field names"
 
   - do:
       esql.query:
         body:
-          query: 'from test | stats x = count(?f1), y = sum(?f2) by ?f3 | sort ?f3 | keep ?f3, x, y  | limit ?l'
-          params: [{"f1" : {"identifier" : "time"}}, {"f2" : { "identifier" : "count" }}, {"f3" : { "identifier" : "color"}}, {"l": 3}]
+          # The "| sort time" is to work around https://github.com/elastic/elasticsearch/issues/120272
+          # TODO: remove it when the issue is fixed
+          query: 'from test | sort time | sample ?s | stats x = count(?f1), y = sum(?f2) by ?f3 | sort ?f3 | keep ?f3, x, y  | limit ?l'
+          params: [{"s": 0.99999999999}, {"f1" : {"identifier" : "time"}}, {"f2" : { "identifier" : "count" }}, {"f3" : { "identifier" : "color"}}, {"l": 3}]
 
   - length: {columns: 3}
   - match: {columns.0.name: "color"}

+ 5 - 2
x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml

@@ -37,7 +37,7 @@ setup:
   - do: {xpack.usage: {}}
   - match: { esql.available: true }
   - match: { esql.enabled: true }
-  - length: { esql.features: 21 }
+  - length: { esql.features: 22 }
   - set: {esql.features.dissect: dissect_counter}
   - set: {esql.features.drop: drop_counter}
   - set: {esql.features.eval: eval_counter}
@@ -59,6 +59,7 @@ setup:
   - set: {esql.features.inlinestats: inlinestats_counter}
   - set: {esql.features.rerank: rerank_counter}
   - set: {esql.features.completion: completion_counter}
+  - set: {esql.features.sample: sample_counter}
   - length: { esql.queries: 3 }
   - set: {esql.queries.rest.total: rest_total_counter}
   - set: {esql.queries.rest.failed: rest_failed_counter}
@@ -93,6 +94,7 @@ setup:
   - match: {esql.features.inlinestats: $inlinestats_counter}
   - match: {esql.features.rerank: $rerank_counter}
   - match: {esql.features.completion: $completion_counter}
+  - match: {esql.features.sample: $sample_counter}
   - gt: {esql.queries.rest.total: $rest_total_counter}
   - match: {esql.queries.rest.failed: $rest_failed_counter}
   - match: {esql.queries.kibana.total: $kibana_total_counter}
@@ -121,7 +123,7 @@ setup:
   - do: {xpack.usage: {}}
   - match: { esql.available: true }
   - match: { esql.enabled: true }
-  - length: { esql.features: 21 }
+  - length: { esql.features: 22 }
   - set: {esql.features.dissect: dissect_counter}
   - set: {esql.features.drop: drop_counter}
   - set: {esql.features.eval: eval_counter}
@@ -141,6 +143,7 @@ setup:
   - set: {esql.features.lookup: lookup_counter}
   - set: {esql.features.change_point: change_point_counter}
   - set: {esql.features.inlinestats: inlinestats_counter}
+  - set: {esql.features.sample: sample_counter}
   - length: { esql.queries: 3 }
   - set: {esql.queries.rest.total: rest_total_counter}
   - set: {esql.queries.rest.failed: rest_failed_counter}

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff