Merge pull request #19092 from rmuir/more_painless_docs

cutover some docs to painless
This commit is contained in:
Robert Muir 2016-06-28 13:40:25 -04:00 committed by GitHub
commit 6d52cec2a0
49 changed files with 1451 additions and 1149 deletions

View File

@ -8,20 +8,20 @@ and delete indexed scripts and templates.
[source,java]
--------------------------------------------------
PutIndexedScriptResponse = client.preparePutIndexedScript()
.setScriptLang("groovy")
.setScriptLang("painless")
.setId("script1")
.setSource("script", "_score * doc['my_numeric_field'].value")
.execute()
.actionGet();
GetIndexedScriptResponse = client.prepareGetIndexedScript()
.setScriptLang("groovy")
.setScriptLang("painless")
.setId("script1")
.execute()
.actionGet();
DeleteIndexedScriptResponse = client.prepareDeleteIndexedScript()
.setScriptLang("groovy")
.setScriptLang("painless")
.setId("script1")
.execute()
.actionGet();
@ -33,4 +33,4 @@ To store templates simply use "mustache" for the scriptLang.
The API allows one to set the language of the indexed script being
interacted with. If one is not provided the default scripting language
will be used.
will be used.

View File

@ -12,11 +12,11 @@ QueryBuilder qb = scriptQuery(
<1> inlined script
If you have stored on each data node a script named `mygroovyscript.groovy` with:
If you have stored on each data node a script named `myscript.painless` with:
[source,groovy]
[source,js]
--------------------------------------------------
doc['num1'].value > param1
doc['num1'].value > params.param1
--------------------------------------------------
You can use it then with:
@ -25,9 +25,9 @@ You can use it then with:
--------------------------------------------------
QueryBuilder qb = scriptQuery(
new Script(
"mygroovyscript", <1>
"myscript", <1>
ScriptType.FILE, <2>
"groovy", <3>
"painless", <3>
ImmutableMap.of("param1", 5)) <4>
);
--------------------------------------------------

View File

@ -115,8 +115,11 @@ Controlling diversity using a script:
{
"aggs" : {
"sample" : {
"diverisfied_sampler" : {
"script" : "doc['author'].value + '/' + doc['genre'].value"
"diversified_sampler" : {
"script" : {
"lang" : "painless",
"inline" : "doc['author'].value + '/' + doc['genre'].value"
}
}
}
}
@ -151,4 +154,4 @@ The de-duplication logic in the diversify settings applies only at a shard level
===== No specialized syntax for geo/date fields
Currently the syntax for defining the diversifying values is defined by a choice of `field` or `script` - there is no added syntactical sugar for expressing geo or date units such as "1w" (1 week).
This support may be added in a later release and users will currently have to create these sorts of values using a script.
This support may be added in a later release and users will currently have to create these sorts of values using a script.

View File

@ -134,7 +134,10 @@ It is also possible to customize the key for each range:
"aggs" : {
"price_ranges" : {
"range" : {
"script" : "doc['price'].value",
"script" : {
"lang": "painless",
"inline": "doc['price'].value"
},
"ranges" : [
{ "to" : 50 },
{ "from" : 50, "to" : 100 },
@ -146,7 +149,7 @@ It is also possible to customize the key for each range:
}
--------------------------------------------------
This will interpret the `script` parameter as an `inline` script with the default script language and no script parameters. To use a file script use the following syntax:
This will interpret the `script` parameter as an `inline` script with the `painless` script language and no script parameters. To use a file script use the following syntax:
[source,js]
--------------------------------------------------
@ -184,9 +187,12 @@ Lets say the product prices are in USD but we would like to get the price ranges
"price_ranges" : {
"range" : {
"field" : "price",
"script" : "_value * conversion_rate",
"params" : {
"conversion_rate" : 0.8
"script" : {
"lang": "painless",
"inline": "_value * params.conversion_rate",
"params" : {
"conversion_rate" : 0.8
}
},
"ranges" : [
{ "to" : 35 },

View File

@ -42,12 +42,19 @@ Computing the average grade based on a script:
...,
"aggs" : {
"avg_grade" : { "avg" : { "script" : "doc['grade'].value" } }
"avg_grade" : {
"avg" : {
"script" : {
"inline" : "doc['grade'].value",
"lang" : "painless"
}
}
}
}
}
--------------------------------------------------
This will interpret the `script` parameter as an `inline` script with the default script language and no script parameters. To use a file script use the following syntax:
This will interpret the `script` parameter as an `inline` script with the `painless` script language and no script parameters. To use a file script use the following syntax:
[source,js]
--------------------------------------------------
@ -86,7 +93,8 @@ It turned out that the exam was way above the level of the students and a grade
"avg" : {
"field" : "grade",
"script" : {
"inline": "_value * correction",
"lang": "painless",
"inline": "_value * params.correction",
"params" : {
"correction" : 1.2
}

View File

@ -104,14 +104,17 @@ however since hashes need to be computed on the fly.
"aggs" : {
"author_count" : {
"cardinality" : {
"script": "doc['author.first_name'].value + ' ' + doc['author.last_name'].value"
"script": {
"lang": "painless",
"inline": "doc['author.first_name'].value + ' ' + doc['author.last_name'].value"
}
}
}
}
}
--------------------------------------------------
This will interpret the `script` parameter as an `inline` script with the default script language and no script parameters. To use a file script use the following syntax:
This will interpret the `script` parameter as an `inline` script with the `painless` script language and no script parameters. To use a file script use the following syntax:
[source,js]
--------------------------------------------------

View File

@ -86,12 +86,19 @@ Computing the grades stats based on a script:
...,
"aggs" : {
"grades_stats" : { "extended_stats" : { "script" : "doc['grade'].value" } }
"grades_stats" : {
"extended_stats" : {
"script" : {
"inline" : "doc['grade'].value",
"lang" : "painless"
}
}
}
}
}
--------------------------------------------------
This will interpret the `script` parameter as an `inline` script with the default script language and no script parameters. To use a file script use the following syntax:
This will interpret the `script` parameter as an `inline` script with the `painless` script language and no script parameters. To use a file script use the following syntax:
[source,js]
--------------------------------------------------
@ -130,7 +137,8 @@ It turned out that the exam was way above the level of the students and a grade
"extended_stats" : {
"field" : "grade",
"script" : {
"inline": "_value * correction",
"lang" : "painless",
"inline": "_value * params.correction",
"params" : {
"correction" : 1.2
}

View File

@ -39,12 +39,19 @@ Computing the max price value across all document, this time using a script:
--------------------------------------------------
{
"aggs" : {
"max_price" : { "max" : { "script" : "doc['price'].value" } }
"max_price" : {
"max" : {
"script" : {
"inline" : "doc['price'].value",
"lang" : "painless"
}
}
}
}
}
--------------------------------------------------
This will interpret the `script` parameter as an `inline` script with the default script language and no script parameters. To use a file script use the following syntax:
This will interpret the `script` parameter as an `inline` script with the `painless` script language and no script parameters. To use a file script use the following syntax:
[source,js]
--------------------------------------------------
@ -78,7 +85,8 @@ Let's say that the prices of the documents in our index are in USD, but we would
"max" : {
"field" : "price",
"script" : {
"inline": "_value * conversion_rate",
"lang": "painless",
"inline": "_value * params.conversion_rate",
"params" : {
"conversion_rate" : 1.2
}

View File

@ -39,12 +39,19 @@ Computing the min price value across all document, this time using a script:
--------------------------------------------------
{
"aggs" : {
"min_price" : { "min" : { "script" : "doc['price'].value" } }
"min_price" : {
"min" : {
"script" : {
"inline" : "doc['price'].value",
"lang" : "painless"
}
}
}
}
}
--------------------------------------------------
This will interpret the `script` parameter as an `inline` script with the default script language and no script parameters. To use a file script use the following syntax:
This will interpret the `script` parameter as an `inline` script with the `painless` script language and no script parameters. To use a file script use the following syntax:
[source,js]
--------------------------------------------------
@ -78,7 +85,8 @@ Let's say that the prices of the documents in our index are in USD, but we would
"min" : {
"field" : "price",
"script" :
"inline": "_value * conversion_rate",
"lang" : "painless",
"inline": "_value * params.conversion_rate",
"params" : {
"conversion_rate" : 1.2
}

View File

@ -101,7 +101,8 @@ a script to convert them on-the-fly:
"load_time_outlier" : {
"percentiles" : {
"script" : {
"inline": "doc['load_time'].value / timeUnit", <1>
"lang": "painless",
"inline": "doc['load_time'].value / params.timeUnit", <1>
"params" : {
"timeUnit" : 1000 <2>
}
@ -115,7 +116,7 @@ a script to convert them on-the-fly:
script to generate values which percentiles are calculated on
<2> Scripting supports parameterized input just like any other script
This will interpret the `script` parameter as an `inline` script with the default script language and no script parameters. To use a file script use the following syntax:
This will interpret the `script` parameter as an `inline` script with the `painless` script language and no script parameters. To use a file script use the following syntax:
[source,js]
--------------------------------------------------

View File

@ -73,7 +73,8 @@ a script to convert them on-the-fly:
"percentile_ranks" : {
"values" : [3, 5],
"script" : {
"inline": "doc['load_time'].value / timeUnit", <1>
"lang": "painless",
"inline": "doc['load_time'].value / params.timeUnit", <1>
"params" : {
"timeUnit" : 1000 <2>
}
@ -87,7 +88,7 @@ a script to convert them on-the-fly:
script to generate values which percentile ranks are calculated on
<2> Scripting supports parameterized input just like any other script
This will interpret the `script` parameter as an `inline` script with the default script language and no script parameters. To use a file script use the following syntax:
This will interpret the `script` parameter as an `inline` script with the `painless` script language and no script parameters. To use a file script use the following syntax:
[source,js]
--------------------------------------------------

View File

@ -48,12 +48,19 @@ Computing the grades stats based on a script:
...,
"aggs" : {
"grades_stats" : { "stats" : { "script" : "doc['grade'].value" } }
"grades_stats" : {
"stats" : {
"script" : {
"lang": "painless",
"inline": "doc['grade'].value"
}
}
}
}
}
--------------------------------------------------
This will interpret the `script` parameter as an `inline` script with the default script language and no script parameters. To use a file script use the following syntax:
This will interpret the `script` parameter as an `inline` script with the `painless` script language and no script parameters. To use a file script use the following syntax:
[source,js]
--------------------------------------------------
@ -92,7 +99,8 @@ It turned out that the exam was way above the level of the students and a grade
"stats" : {
"field" : "grade",
"script" :
"inline": "_value * correction",
"lang": "painless",
"inline": "_value * params.correction",
"params" : {
"correction" : 1.2
}

View File

@ -49,12 +49,19 @@ Computing the intraday return based on a script:
...,
"aggs" : {
"intraday_return" : { "sum" : { "script" : "doc['change'].value" } }
"intraday_return" : {
"sum" : {
"script" : {
"lang": "painless",
"inline": "doc['change'].value"
}
}
}
}
}
--------------------------------------------------
This will interpret the `script` parameter as an `inline` script with the default script language and no script parameters. To use a file script use the following syntax:
This will interpret the `script` parameter as an `inline` script with the `painless` script language and no script parameters. To use a file script use the following syntax:
[source,js]
--------------------------------------------------
@ -92,7 +99,10 @@ Computing the sum of squares over all stock tick changes:
"daytime_return" : {
"sum" : {
"field" : "change",
"script" : "_value * _value"
"script" : {
"lang": "painless",
"inline": "_value * _value"
}
}
}
}

View File

@ -182,7 +182,10 @@ relevancy order of the most relevant document in a bucket.
},
"top_hit" : {
"max": {
"script": "_score"
"script": {
"lang": "painless",
"inline": "_score"
}
}
}
}

View File

@ -43,12 +43,19 @@ Counting the values generated by a script:
...,
"aggs" : {
"grades_count" : { "value_count" : { "script" : "doc['grade'].value" } }
"grades_count" : {
"value_count" : {
"script" : {
"inline" : "doc['grade'].value",
"lang" : "painless"
}
}
}
}
}
--------------------------------------------------
This will interpret the `script` parameter as an `inline` script with the default script language and no script parameters. To use a file script use the following syntax:
This will interpret the `script` parameter as an `inline` script with the `painless` script language and no script parameters. To use a file script use the following syntax:
[source,js]
--------------------------------------------------

View File

@ -168,7 +168,7 @@ the options. Curl example with update actions:
{ "update" : {"_id" : "1", "_type" : "type1", "_index" : "index1", "_retry_on_conflict" : 3} }
{ "doc" : {"field" : "value"} }
{ "update" : { "_id" : "0", "_type" : "type1", "_index" : "index1", "_retry_on_conflict" : 3} }
{ "script" : { "inline": "ctx._source.counter += param1", "lang" : "javascript", "params" : {"param1" : 1}}, "upsert" : {"counter" : 1}}
{ "script" : { "inline": "ctx._source.counter += params.param1", "lang" : "painless", "params" : {"param1" : 1}}, "upsert" : {"counter" : 1}}
{ "update" : {"_id" : "2", "_type" : "type1", "_index" : "index1", "_retry_on_conflict" : 3} }
{ "doc" : {"field" : "value"}, "doc_as_upsert" : true }
{ "update" : {"_id" : "3", "_type" : "type1", "_index" : "index1", "fields" : ["_source"]} }

View File

@ -238,7 +238,8 @@ POST _reindex
"version_type": "external"
},
"script": {
"inline": "if (ctx._source.foo == 'bar') {ctx._version++; ctx._source.remove('foo')}"
"inline": "if (ctx._source.foo == 'bar') {ctx._version++; ctx._source.remove('foo')}",
"lang": "painless"
}
}
--------------------------------------------------

View File

@ -104,7 +104,8 @@ will increment the `likes` field on all of kimchy's tweets:
POST twitter/_update_by_query
{
"script": {
"inline": "ctx._source.likes++"
"inline": "ctx._source.likes++",
"lang": "painless"
},
"query": {
"term": {

View File

@ -32,7 +32,8 @@ Now, we can execute a script that would increment the counter:
--------------------------------------------------
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
"script" : {
"inline": "ctx._source.counter += count",
"inline": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 4
}
@ -47,7 +48,8 @@ will still add it, since its a list):
--------------------------------------------------
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
"script" : {
"inline": "ctx._source.tags += tag",
"inline": "ctx._source.tags += params.tag",
"lang": "painless",
"params" : {
"tag" : "blue"
}
@ -85,7 +87,8 @@ the doc if the `tags` field contain `blue`, otherwise it does nothing
--------------------------------------------------
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
"script" : {
"inline": "ctx._source.tags.contains(tag) ? ctx.op = \"delete\" : ctx.op = \"none\"",
"inline": "ctx._source.tags.contains(params.tag) ? ctx.op = \"delete\" : ctx.op = \"none\"",
"lang": "painless",
"params" : {
"tag" : "blue"
}
@ -144,7 +147,8 @@ will be inserted as a new document. If the document does exist, then the
--------------------------------------------------
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
"script" : {
"inline": "ctx._source.counter += count",
"inline": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 4
}

View File

@ -31,7 +31,10 @@ GET my_index/_search
},
"script_fields": {
"Field names": {
"script": "doc['_field_names']" <2>
"script": {
"lang": "painless",
"inline": "doc['_field_names']" <2>
}
}
}
}
@ -40,4 +43,4 @@ GET my_index/_search
// CONSOLE
<1> Querying on the `_field_names` field (also see the <<query-dsl-exists-query,`exists`>> query)
<2> Accessing the `_field_names` field in scripts (inline scripts must be <<enable-dynamic-scripting,enabled>> for this example to work)
<2> Accessing the `_field_names` field in scripts

View File

@ -33,7 +33,10 @@ GET my_index/_search
},
"script_fields": {
"UID": {
"script": "doc['_id']" <2>
"script": {
"lang": "painless",
"inline": "doc['_id']" <2>
}
}
}
}
@ -41,5 +44,4 @@ GET my_index/_search
// CONSOLE
<1> Querying on the `_id` field (also see the <<query-dsl-ids-query,`ids` query>>)
<2> Accessing the `_id` field in scripts (inline scripts must be <<enable-dynamic-scripting,enabled>> for this example to work)
<2> Accessing the `_id` field in scripts

View File

@ -50,7 +50,10 @@ GET index_1,index_2/_search
],
"script_fields": {
"index_name": {
"script": "doc['_index']" <4>
"script": {
"lang": "painless",
"inline": "doc['_index']" <4>
}
}
}
}
@ -60,4 +63,4 @@ GET index_1,index_2/_search
<1> Querying on the `_index` field
<2> Aggregating on the `_index` field
<3> Sorting on the `_index` field
<4> Accessing the `_index` field in scripts (inline scripts must be <<enable-dynamic-scripting,enabled>> for this example to work)
<4> Accessing the `_index` field in scripts

View File

@ -81,7 +81,10 @@ GET my_index/_search
},
"script_fields": {
"parent": {
"script": "doc['_parent']" <3>
"script": {
"lang": "painless",
"inline": "doc['_parent']" <3>
}
}
}
}
@ -91,7 +94,7 @@ GET my_index/_search
<1> Querying on the `_parent` field (also see the <<query-dsl-has-parent-query,`has_parent` query>> and the <<query-dsl-has-child-query,`has_child` query>>)
<2> Aggregating on the `_parent` field (also see the <<search-aggregations-bucket-children-aggregation,`children`>> aggregation)
<3> Accessing the `_parent` field in scripts (inline scripts must be <<enable-dynamic-scripting,enabled>> for this example to work)
<3> Accessing the `_parent` field in scripts
==== Parent-child restrictions

View File

@ -42,7 +42,10 @@ GET my_index/_search
},
"script_fields": {
"Routing value": {
"script": "doc['_routing']" <2>
"script": {
"lang": "painless",
"inline": "doc['_routing']" <2>
}
}
}
}
@ -50,7 +53,7 @@ GET my_index/_search
// CONSOLE
<1> Querying on the `_routing` field (also see the <<query-dsl-ids-query,`ids` query>>)
<2> Accessing the `_routing` field in scripts (inline scripts must be <<enable-dynamic-scripting,enabled>> for this example to work)
<2> Accessing the `_routing` field in scripts
==== Searching with custom routing

View File

@ -45,7 +45,10 @@ GET my_index/type_*/_search
],
"script_fields": {
"type": {
"script": "doc['_type']" <4>
"script": {
"lang": "painless",
"inline": "doc['_type']" <4>
}
}
}
}
@ -56,5 +59,5 @@ GET my_index/type_*/_search
<1> Querying on the `_type` field
<2> Aggregating on the `_type` field
<3> Sorting on the `_type` field
<4> Accessing the `_type` field in scripts (inline scripts must be <<enable-dynamic-scripting,enabled>> for this example to work)
<4> Accessing the `_type` field in scripts

View File

@ -45,7 +45,10 @@ GET my_index/_search
],
"script_fields": {
"UID": {
"script": "doc['_uid']" <4>
"script": {
"lang": "painless",
"inline": "doc['_uid']" <4>
}
}
}
}
@ -55,5 +58,4 @@ GET my_index/_search
<1> Querying on the `_uid` field (also see the <<query-dsl-ids-query,`ids` query>>)
<2> Aggregating on the `_uid` field
<3> Sorting on the `_uid` field
<4> Accessing the `_uid` field in scripts (inline scripts must be <<enable-dynamic-scripting,enabled>> for this example to work)
<4> Accessing the `_uid` field in scripts

View File

@ -76,13 +76,15 @@ GET my_index/_search
},
"script_fields": {
"is_published": {
"script": "doc['is_published'].value" <1>
"script": {
"lang": "painless",
"inline": "doc['is_published'].value"
}
}
}
}
--------------------------------------------------
// CONSOLE
<1> Inline scripts must be <<enable-dynamic-scripting,enabled>> for this example to work.
[[boolean-params]]
==== Parameters for `boolean` fields

View File

@ -132,6 +132,15 @@ There are only a few minor differences and add-ons:
Java's https://docs.oracle.com/javase/tutorial/java/nutsandbolts/flow.html[control flow statements] are supported, with the exception
of the `switch` statement.
In addition to Java's `enhanced for` loop, the `for in` syntax from groovy can also be used:
[source,js]
---------------------------------------------------------
for (item : list) {
...
}
---------------------------------------------------------
[float]
[[painless-functions]]
=== Functions

View File

@ -124,7 +124,10 @@ simple sample:
[source,js]
--------------------------------------------------
"script_score" : {
"script" : "_score * doc['my_numeric_field'].value"
"script" : {
"lang": "painless",
"inline": "_score * doc['my_numeric_field'].value"
}
}
--------------------------------------------------
@ -140,12 +143,12 @@ script, and provide parameters to it:
--------------------------------------------------
"script_score": {
"script": {
"lang": "lang",
"lang": "painless",
"params": {
"param1": value1,
"param2": value2
},
"inline": "_score * doc['my_numeric_field'].value / pow(param1, param2)"
"inline": "_score * doc['my_numeric_field'].value / Math.pow(params.param1, params.param2)"
}
}
--------------------------------------------------

View File

@ -13,7 +13,10 @@ GET /_search
"bool" : {
"must" : {
"script" : {
"script" : "doc['num1'].value > 1"
"script" : {
"inline": "doc['num1'].value > 1",
"lang": "painless"
}
}
}
}
@ -38,7 +41,8 @@ GET /_search
"must" : {
"script" : {
"script" : {
"inline" : "doc['num1'].value > param1",
"inline" : "doc['num1'].value > params.param1",
"lang" : "painless",
"params" : {
"param1" : 5
}

View File

@ -118,7 +118,10 @@ curl -s -XPOST 'localhost:9200/_search' -d '{
"rescore_query" : {
"function_score" : {
"script_score": {
"script": "log10(doc['numeric'].value + 2)"
"script": {
"lang": "painless",
"inline": "Math.log10(doc['numeric'].value + 2)"
}
}
}
}

View File

@ -13,10 +13,14 @@ GET /_search
},
"script_fields" : {
"test1" : {
"script" : "doc['my_field_name'].value * 2"
"script" : {
"lang": "painless",
"inline": "doc['my_field_name'].value * 2"
}
},
"test2" : {
"script" : {
"lang": "painless",
"inline": "doc['my_field_name'].value * factor",
"params" : {
"factor" : 2.0

View File

@ -378,7 +378,8 @@ GET /_search
"_script" : {
"type" : "number",
"script" : {
"inline": "doc['field_name'].value * factor",
"lang": "painless",
"inline": "doc['field_name'].value * params.factor",
"params" : {
"factor" : 1.1
}

View File

@ -40,6 +40,7 @@ DOT: '.' -> mode(AFTER_DOT);
COMMA: ',';
SEMICOLON: ';';
IF: 'if';
IN: 'in';
ELSE: 'else';
WHILE: 'while';
DO: 'do';

View File

@ -10,75 +10,76 @@ DOT=9
COMMA=10
SEMICOLON=11
IF=12
ELSE=13
WHILE=14
DO=15
FOR=16
CONTINUE=17
BREAK=18
RETURN=19
NEW=20
TRY=21
CATCH=22
THROW=23
THIS=24
INSTANCEOF=25
BOOLNOT=26
BWNOT=27
MUL=28
DIV=29
REM=30
ADD=31
SUB=32
LSH=33
RSH=34
USH=35
LT=36
LTE=37
GT=38
GTE=39
EQ=40
EQR=41
NE=42
NER=43
BWAND=44
XOR=45
BWOR=46
BOOLAND=47
BOOLOR=48
COND=49
COLON=50
REF=51
ARROW=52
FIND=53
MATCH=54
INCR=55
DECR=56
ASSIGN=57
AADD=58
ASUB=59
AMUL=60
ADIV=61
AREM=62
AAND=63
AXOR=64
AOR=65
ALSH=66
ARSH=67
AUSH=68
OCTAL=69
HEX=70
INTEGER=71
DECIMAL=72
STRING=73
REGEX=74
TRUE=75
FALSE=76
NULL=77
TYPE=78
ID=79
DOTINTEGER=80
DOTID=81
IN=13
ELSE=14
WHILE=15
DO=16
FOR=17
CONTINUE=18
BREAK=19
RETURN=20
NEW=21
TRY=22
CATCH=23
THROW=24
THIS=25
INSTANCEOF=26
BOOLNOT=27
BWNOT=28
MUL=29
DIV=30
REM=31
ADD=32
SUB=33
LSH=34
RSH=35
USH=36
LT=37
LTE=38
GT=39
GTE=40
EQ=41
EQR=42
NE=43
NER=44
BWAND=45
XOR=46
BWOR=47
BOOLAND=48
BOOLOR=49
COND=50
COLON=51
REF=52
ARROW=53
FIND=54
MATCH=55
INCR=56
DECR=57
ASSIGN=58
AADD=59
ASUB=60
AMUL=61
ADIV=62
AREM=63
AAND=64
AXOR=65
AOR=66
ALSH=67
ARSH=68
AUSH=69
OCTAL=70
HEX=71
INTEGER=72
DECIMAL=73
STRING=74
REGEX=75
TRUE=76
FALSE=77
NULL=78
TYPE=79
ID=80
DOTINTEGER=81
DOTID=82
'{'=3
'}'=4
'['=5
@ -89,62 +90,63 @@ DOTID=81
','=10
';'=11
'if'=12
'else'=13
'while'=14
'do'=15
'for'=16
'continue'=17
'break'=18
'return'=19
'new'=20
'try'=21
'catch'=22
'throw'=23
'this'=24
'instanceof'=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
'::'=51
'->'=52
'=~'=53
'==~'=54
'++'=55
'--'=56
'='=57
'+='=58
'-='=59
'*='=60
'/='=61
'%='=62
'&='=63
'^='=64
'|='=65
'<<='=66
'>>='=67
'>>>='=68
'true'=75
'false'=76
'null'=77
'in'=13
'else'=14
'while'=15
'do'=16
'for'=17
'continue'=18
'break'=19
'return'=20
'new'=21
'try'=22
'catch'=23
'throw'=24
'this'=25
'instanceof'=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
':'=51
'::'=52
'->'=53
'=~'=54
'==~'=55
'++'=56
'--'=57
'='=58
'+='=59
'-='=60
'*='=61
'/='=62
'%='=63
'&='=64
'^='=65
'|='=66
'<<='=67
'>>='=68
'>>>='=69
'true'=76
'false'=77
'null'=78

View File

@ -42,6 +42,7 @@ statement
| DO block WHILE LP expression RP delimiter # do
| FOR LP initializer? SEMICOLON expression? SEMICOLON afterthought? RP ( trailer | empty ) # for
| FOR LP decltype ID COLON expression RP trailer # each
| FOR LP ID IN expression RP trailer # ineach
| declaration delimiter # decl
| CONTINUE delimiter # continue
| BREAK delimiter # break

View File

@ -10,75 +10,76 @@ DOT=9
COMMA=10
SEMICOLON=11
IF=12
ELSE=13
WHILE=14
DO=15
FOR=16
CONTINUE=17
BREAK=18
RETURN=19
NEW=20
TRY=21
CATCH=22
THROW=23
THIS=24
INSTANCEOF=25
BOOLNOT=26
BWNOT=27
MUL=28
DIV=29
REM=30
ADD=31
SUB=32
LSH=33
RSH=34
USH=35
LT=36
LTE=37
GT=38
GTE=39
EQ=40
EQR=41
NE=42
NER=43
BWAND=44
XOR=45
BWOR=46
BOOLAND=47
BOOLOR=48
COND=49
COLON=50
REF=51
ARROW=52
FIND=53
MATCH=54
INCR=55
DECR=56
ASSIGN=57
AADD=58
ASUB=59
AMUL=60
ADIV=61
AREM=62
AAND=63
AXOR=64
AOR=65
ALSH=66
ARSH=67
AUSH=68
OCTAL=69
HEX=70
INTEGER=71
DECIMAL=72
STRING=73
REGEX=74
TRUE=75
FALSE=76
NULL=77
TYPE=78
ID=79
DOTINTEGER=80
DOTID=81
IN=13
ELSE=14
WHILE=15
DO=16
FOR=17
CONTINUE=18
BREAK=19
RETURN=20
NEW=21
TRY=22
CATCH=23
THROW=24
THIS=25
INSTANCEOF=26
BOOLNOT=27
BWNOT=28
MUL=29
DIV=30
REM=31
ADD=32
SUB=33
LSH=34
RSH=35
USH=36
LT=37
LTE=38
GT=39
GTE=40
EQ=41
EQR=42
NE=43
NER=44
BWAND=45
XOR=46
BWOR=47
BOOLAND=48
BOOLOR=49
COND=50
COLON=51
REF=52
ARROW=53
FIND=54
MATCH=55
INCR=56
DECR=57
ASSIGN=58
AADD=59
ASUB=60
AMUL=61
ADIV=62
AREM=63
AAND=64
AXOR=65
AOR=66
ALSH=67
ARSH=68
AUSH=69
OCTAL=70
HEX=71
INTEGER=72
DECIMAL=73
STRING=74
REGEX=75
TRUE=76
FALSE=77
NULL=78
TYPE=79
ID=80
DOTINTEGER=81
DOTID=82
'{'=3
'}'=4
'['=5
@ -89,62 +90,63 @@ DOTID=81
','=10
';'=11
'if'=12
'else'=13
'while'=14
'do'=15
'for'=16
'continue'=17
'break'=18
'return'=19
'new'=20
'try'=21
'catch'=22
'throw'=23
'this'=24
'instanceof'=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
'::'=51
'->'=52
'=~'=53
'==~'=54
'++'=55
'--'=56
'='=57
'+='=58
'-='=59
'*='=60
'/='=61
'%='=62
'&='=63
'^='=64
'|='=65
'<<='=66
'>>='=67
'>>>='=68
'true'=75
'false'=76
'null'=77
'in'=13
'else'=14
'while'=15
'do'=16
'for'=17
'continue'=18
'break'=19
'return'=20
'new'=21
'try'=22
'catch'=23
'throw'=24
'this'=25
'instanceof'=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
':'=51
'::'=52
'->'=53
'=~'=54
'==~'=55
'++'=56
'--'=57
'='=58
'+='=59
'-='=60
'*='=61
'/='=62
'%='=63
'&='=64
'^='=65
'|='=66
'<<='=67
'>>='=68
'>>>='=69
'true'=76
'false'=77
'null'=78

View File

@ -74,7 +74,11 @@ public final class Locals {
Locals locals = new Locals(programScope, returnType);
for (int i = 0; i < parameters.size(); i++) {
Parameter parameter = parameters.get(i);
boolean isCapture = i < captureCount;
// TODO: allow non-captures to be r/w:
// boolean isCapture = i < captureCount;
// currently, this cannot be allowed, as we swap in real types,
// but that can prevent a store of a different type...
boolean isCapture = true;
locals.addVariable(parameter.location, parameter.type, parameter.name, isCapture);
}
// Loop counter to catch infinite loops. Internal use only.

View File

@ -0,0 +1,60 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.painless;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.util.CheckClassAdapter;
import org.objectweb.asm.util.CheckMethodAdapter;
import java.util.HashMap;
/**
* A CheckClassAdapter that does not use setAccessible to try to access private fields of Label!
* <p>
* This means jump insns are not checked, but we still get all the other checking.
*/
// TODO: we should really try to get this fixed in ASM!
public class SimpleChecksAdapter extends CheckClassAdapter {
public SimpleChecksAdapter(ClassVisitor cv) {
super(WriterConstants.ASM_VERSION, cv, false);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor in = cv.visitMethod(access, name, desc, signature, exceptions);
CheckMethodAdapter checker = new CheckMethodAdapter(WriterConstants.ASM_VERSION, in, new HashMap<Label, Integer>()) {
@Override
public void visitJumpInsn(int opcode, Label label) {
mv.visitJumpInsn(opcode, label);
}
@Override
public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
mv.visitTryCatchBlock(start, end, handler, type);
}
};
checker.version = WriterConstants.CLASS_VERSION;
return checker;
}
}

View File

@ -43,6 +43,8 @@ import java.util.regex.Pattern;
*/
public final class WriterConstants {
public final static int CLASS_VERSION = Opcodes.V1_8;
public final static int ASM_VERSION = Opcodes.ASM5;
public final static String BASE_CLASS_NAME = Executable.class.getName();
public final static Type BASE_CLASS_TYPE = Type.getType(Executable.class);

View File

@ -21,15 +21,16 @@ class PainlessLexer extends Lexer {
new PredictionContextCache();
public static final int
WS=1, COMMENT=2, LBRACK=3, RBRACK=4, LBRACE=5, RBRACE=6, LP=7, RP=8, DOT=9,
COMMA=10, SEMICOLON=11, IF=12, ELSE=13, WHILE=14, DO=15, FOR=16, CONTINUE=17,
BREAK=18, RETURN=19, NEW=20, TRY=21, CATCH=22, THROW=23, THIS=24, INSTANCEOF=25,
BOOLNOT=26, BWNOT=27, MUL=28, DIV=29, REM=30, ADD=31, SUB=32, LSH=33,
RSH=34, USH=35, LT=36, LTE=37, GT=38, GTE=39, EQ=40, EQR=41, NE=42, NER=43,
BWAND=44, XOR=45, BWOR=46, BOOLAND=47, BOOLOR=48, COND=49, COLON=50, REF=51,
ARROW=52, FIND=53, MATCH=54, INCR=55, DECR=56, ASSIGN=57, AADD=58, ASUB=59,
AMUL=60, ADIV=61, AREM=62, AAND=63, AXOR=64, AOR=65, ALSH=66, ARSH=67,
AUSH=68, OCTAL=69, HEX=70, INTEGER=71, DECIMAL=72, STRING=73, REGEX=74,
TRUE=75, FALSE=76, NULL=77, TYPE=78, ID=79, DOTINTEGER=80, DOTID=81;
COMMA=10, SEMICOLON=11, IF=12, IN=13, ELSE=14, WHILE=15, DO=16, FOR=17,
CONTINUE=18, BREAK=19, RETURN=20, NEW=21, TRY=22, CATCH=23, THROW=24,
THIS=25, INSTANCEOF=26, BOOLNOT=27, BWNOT=28, MUL=29, DIV=30, REM=31,
ADD=32, SUB=33, LSH=34, RSH=35, USH=36, LT=37, LTE=38, GT=39, GTE=40,
EQ=41, EQR=42, NE=43, NER=44, BWAND=45, XOR=46, BWOR=47, BOOLAND=48, BOOLOR=49,
COND=50, COLON=51, REF=52, ARROW=53, FIND=54, MATCH=55, INCR=56, DECR=57,
ASSIGN=58, AADD=59, ASUB=60, AMUL=61, ADIV=62, AREM=63, AAND=64, AXOR=65,
AOR=66, ALSH=67, ARSH=68, AUSH=69, OCTAL=70, HEX=71, INTEGER=72, DECIMAL=73,
STRING=74, REGEX=75, TRUE=76, FALSE=77, NULL=78, TYPE=79, ID=80, DOTINTEGER=81,
DOTID=82;
public static final int AFTER_DOT = 1;
public static String[] modeNames = {
"DEFAULT_MODE", "AFTER_DOT"
@ -37,7 +38,7 @@ class PainlessLexer extends Lexer {
public static final String[] ruleNames = {
"WS", "COMMENT", "LBRACK", "RBRACK", "LBRACE", "RBRACE", "LP", "RP", "DOT",
"COMMA", "SEMICOLON", "IF", "ELSE", "WHILE", "DO", "FOR", "CONTINUE",
"COMMA", "SEMICOLON", "IF", "IN", "ELSE", "WHILE", "DO", "FOR", "CONTINUE",
"BREAK", "RETURN", "NEW", "TRY", "CATCH", "THROW", "THIS", "INSTANCEOF",
"BOOLNOT", "BWNOT", "MUL", "DIV", "REM", "ADD", "SUB", "LSH", "RSH", "USH",
"LT", "LTE", "GT", "GTE", "EQ", "EQR", "NE", "NER", "BWAND", "XOR", "BWOR",
@ -50,25 +51,25 @@ class PainlessLexer extends Lexer {
private static final String[] _LITERAL_NAMES = {
null, null, null, "'{'", "'}'", "'['", "']'", "'('", "')'", "'.'", "','",
"';'", "'if'", "'else'", "'while'", "'do'", "'for'", "'continue'", "'break'",
"'return'", "'new'", "'try'", "'catch'", "'throw'", "'this'", "'instanceof'",
"'!'", "'~'", "'*'", "'/'", "'%'", "'+'", "'-'", "'<<'", "'>>'", "'>>>'",
"'<'", "'<='", "'>'", "'>='", "'=='", "'==='", "'!='", "'!=='", "'&'",
"'^'", "'|'", "'&&'", "'||'", "'?'", "':'", "'::'", "'->'", "'=~'", "'==~'",
"'++'", "'--'", "'='", "'+='", "'-='", "'*='", "'/='", "'%='", "'&='",
"'^='", "'|='", "'<<='", "'>>='", "'>>>='", null, null, null, null, null,
null, "'true'", "'false'", "'null'"
"';'", "'if'", "'in'", "'else'", "'while'", "'do'", "'for'", "'continue'",
"'break'", "'return'", "'new'", "'try'", "'catch'", "'throw'", "'this'",
"'instanceof'", "'!'", "'~'", "'*'", "'/'", "'%'", "'+'", "'-'", "'<<'",
"'>>'", "'>>>'", "'<'", "'<='", "'>'", "'>='", "'=='", "'==='", "'!='",
"'!=='", "'&'", "'^'", "'|'", "'&&'", "'||'", "'?'", "':'", "'::'", "'->'",
"'=~'", "'==~'", "'++'", "'--'", "'='", "'+='", "'-='", "'*='", "'/='",
"'%='", "'&='", "'^='", "'|='", "'<<='", "'>>='", "'>>>='", null, null,
null, null, null, null, "'true'", "'false'", "'null'"
};
private static final String[] _SYMBOLIC_NAMES = {
null, "WS", "COMMENT", "LBRACK", "RBRACK", "LBRACE", "RBRACE", "LP", "RP",
"DOT", "COMMA", "SEMICOLON", "IF", "ELSE", "WHILE", "DO", "FOR", "CONTINUE",
"BREAK", "RETURN", "NEW", "TRY", "CATCH", "THROW", "THIS", "INSTANCEOF",
"BOOLNOT", "BWNOT", "MUL", "DIV", "REM", "ADD", "SUB", "LSH", "RSH", "USH",
"LT", "LTE", "GT", "GTE", "EQ", "EQR", "NE", "NER", "BWAND", "XOR", "BWOR",
"BOOLAND", "BOOLOR", "COND", "COLON", "REF", "ARROW", "FIND", "MATCH",
"INCR", "DECR", "ASSIGN", "AADD", "ASUB", "AMUL", "ADIV", "AREM", "AAND",
"AXOR", "AOR", "ALSH", "ARSH", "AUSH", "OCTAL", "HEX", "INTEGER", "DECIMAL",
"STRING", "REGEX", "TRUE", "FALSE", "NULL", "TYPE", "ID", "DOTINTEGER",
"DOT", "COMMA", "SEMICOLON", "IF", "IN", "ELSE", "WHILE", "DO", "FOR",
"CONTINUE", "BREAK", "RETURN", "NEW", "TRY", "CATCH", "THROW", "THIS",
"INSTANCEOF", "BOOLNOT", "BWNOT", "MUL", "DIV", "REM", "ADD", "SUB", "LSH",
"RSH", "USH", "LT", "LTE", "GT", "GTE", "EQ", "EQR", "NE", "NER", "BWAND",
"XOR", "BWOR", "BOOLAND", "BOOLOR", "COND", "COLON", "REF", "ARROW", "FIND",
"MATCH", "INCR", "DECR", "ASSIGN", "AADD", "ASUB", "AMUL", "ADIV", "AREM",
"AAND", "AXOR", "AOR", "ALSH", "ARSH", "AUSH", "OCTAL", "HEX", "INTEGER",
"DECIMAL", "STRING", "REGEX", "TRUE", "FALSE", "NULL", "TYPE", "ID", "DOTINTEGER",
"DOTID"
};
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
@ -128,11 +129,11 @@ class PainlessLexer extends Lexer {
@Override
public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) {
switch (ruleIndex) {
case 28:
case 29:
return DIV_sempred((RuleContext)_localctx, predIndex);
case 73:
case 74:
return REGEX_sempred((RuleContext)_localctx, predIndex);
case 77:
case 78:
return TYPE_sempred((RuleContext)_localctx, predIndex);
}
return true;
@ -160,7 +161,7 @@ class PainlessLexer extends Lexer {
}
public static final String _serializedATN =
"\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2S\u0246\b\1\b\1\4"+
"\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2T\u024b\b\1\b\1\4"+
"\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n"+
"\4\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+
"\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31"+
@ -169,201 +170,202 @@ class PainlessLexer extends Lexer {
"+\4,\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64"+
"\t\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4;\t;\4<\t<\4=\t"+
"=\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4"+
"I\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\3\2\6\2\u00a8"+
"\n\2\r\2\16\2\u00a9\3\2\3\2\3\3\3\3\3\3\3\3\7\3\u00b2\n\3\f\3\16\3\u00b5"+
"\13\3\3\3\3\3\3\3\3\3\3\3\7\3\u00bc\n\3\f\3\16\3\u00bf\13\3\3\3\3\3\5"+
"\3\u00c3\n\3\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3"+
"\n\3\n\3\n\3\n\3\13\3\13\3\f\3\f\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16"+
"\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\22"+
"\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23"+
"\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\26\3\26\3\26"+
"\3\26\3\27\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3\30\3\30\3\31"+
"\3\31\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32"+
"\3\32\3\33\3\33\3\34\3\34\3\35\3\35\3\36\3\36\3\36\3\37\3\37\3 \3 \3!"+
"\3!\3\"\3\"\3\"\3#\3#\3#\3$\3$\3$\3$\3%\3%\3&\3&\3&\3\'\3\'\3(\3(\3(\3"+
")\3)\3)\3*\3*\3*\3*\3+\3+\3+\3,\3,\3,\3,\3-\3-\3.\3.\3/\3/\3\60\3\60\3"+
"\60\3\61\3\61\3\61\3\62\3\62\3\63\3\63\3\64\3\64\3\64\3\65\3\65\3\65\3"+
"\66\3\66\3\66\3\67\3\67\3\67\3\67\38\38\38\39\39\39\3:\3:\3;\3;\3;\3<"+
"\3<\3<\3=\3=\3=\3>\3>\3>\3?\3?\3?\3@\3@\3@\3A\3A\3A\3B\3B\3B\3C\3C\3C"+
"\3C\3D\3D\3D\3D\3E\3E\3E\3E\3E\3F\3F\6F\u01a7\nF\rF\16F\u01a8\3F\5F\u01ac"+
"\nF\3G\3G\3G\6G\u01b1\nG\rG\16G\u01b2\3G\5G\u01b6\nG\3H\3H\3H\7H\u01bb"+
"\nH\fH\16H\u01be\13H\5H\u01c0\nH\3H\5H\u01c3\nH\3I\3I\3I\7I\u01c8\nI\f"+
"I\16I\u01cb\13I\5I\u01cd\nI\3I\3I\6I\u01d1\nI\rI\16I\u01d2\5I\u01d5\n"+
"I\3I\3I\5I\u01d9\nI\3I\6I\u01dc\nI\rI\16I\u01dd\5I\u01e0\nI\3I\5I\u01e3"+
"\nI\3J\3J\3J\3J\3J\3J\7J\u01eb\nJ\fJ\16J\u01ee\13J\3J\3J\3J\3J\3J\3J\3"+
"J\7J\u01f7\nJ\fJ\16J\u01fa\13J\3J\5J\u01fd\nJ\3K\3K\3K\3K\6K\u0203\nK"+
"\rK\16K\u0204\3K\3K\7K\u0209\nK\fK\16K\u020c\13K\3K\3K\3L\3L\3L\3L\3L"+
"\3M\3M\3M\3M\3M\3M\3N\3N\3N\3N\3N\3O\3O\3O\3O\7O\u0224\nO\fO\16O\u0227"+
"\13O\3O\3O\3P\3P\7P\u022d\nP\fP\16P\u0230\13P\3Q\3Q\3Q\7Q\u0235\nQ\fQ"+
"\16Q\u0238\13Q\5Q\u023a\nQ\3Q\3Q\3R\3R\7R\u0240\nR\fR\16R\u0243\13R\3"+
"R\3R\6\u00b3\u00bd\u01ec\u01f8\2S\4\3\6\4\b\5\n\6\f\7\16\b\20\t\22\n\24"+
"\13\26\f\30\r\32\16\34\17\36\20 \21\"\22$\23&\24(\25*\26,\27.\30\60\31"+
"\62\32\64\33\66\348\35:\36<\37> @!B\"D#F$H%J&L\'N(P)R*T+V,X-Z.\\/^\60"+
"`\61b\62d\63f\64h\65j\66l\67n8p9r:t;v<x=z>|?~@\u0080A\u0082B\u0084C\u0086"+
"D\u0088E\u008aF\u008cG\u008eH\u0090I\u0092J\u0094K\u0096L\u0098M\u009a"+
"N\u009cO\u009eP\u00a0Q\u00a2R\u00a4S\4\2\3\24\5\2\13\f\17\17\"\"\4\2\f"+
"\f\17\17\3\2\629\4\2NNnn\4\2ZZzz\5\2\62;CHch\3\2\63;\3\2\62;\b\2FFHHN"+
"Nffhhnn\4\2GGgg\4\2--//\4\2HHhh\4\2$$^^\4\2\f\f\61\61\3\2\f\f\t\2WWee"+
"kknouuwwzz\5\2C\\aac|\6\2\62;C\\aac|\u0266\2\4\3\2\2\2\2\6\3\2\2\2\2\b"+
"\3\2\2\2\2\n\3\2\2\2\2\f\3\2\2\2\2\16\3\2\2\2\2\20\3\2\2\2\2\22\3\2\2"+
"\2\2\24\3\2\2\2\2\26\3\2\2\2\2\30\3\2\2\2\2\32\3\2\2\2\2\34\3\2\2\2\2"+
"\36\3\2\2\2\2 \3\2\2\2\2\"\3\2\2\2\2$\3\2\2\2\2&\3\2\2\2\2(\3\2\2\2\2"+
"*\3\2\2\2\2,\3\2\2\2\2.\3\2\2\2\2\60\3\2\2\2\2\62\3\2\2\2\2\64\3\2\2\2"+
"\2\66\3\2\2\2\28\3\2\2\2\2:\3\2\2\2\2<\3\2\2\2\2>\3\2\2\2\2@\3\2\2\2\2"+
"B\3\2\2\2\2D\3\2\2\2\2F\3\2\2\2\2H\3\2\2\2\2J\3\2\2\2\2L\3\2\2\2\2N\3"+
"\2\2\2\2P\3\2\2\2\2R\3\2\2\2\2T\3\2\2\2\2V\3\2\2\2\2X\3\2\2\2\2Z\3\2\2"+
"\2\2\\\3\2\2\2\2^\3\2\2\2\2`\3\2\2\2\2b\3\2\2\2\2d\3\2\2\2\2f\3\2\2\2"+
"\2h\3\2\2\2\2j\3\2\2\2\2l\3\2\2\2\2n\3\2\2\2\2p\3\2\2\2\2r\3\2\2\2\2t"+
"\3\2\2\2\2v\3\2\2\2\2x\3\2\2\2\2z\3\2\2\2\2|\3\2\2\2\2~\3\2\2\2\2\u0080"+
"\3\2\2\2\2\u0082\3\2\2\2\2\u0084\3\2\2\2\2\u0086\3\2\2\2\2\u0088\3\2\2"+
"\2\2\u008a\3\2\2\2\2\u008c\3\2\2\2\2\u008e\3\2\2\2\2\u0090\3\2\2\2\2\u0092"+
"\3\2\2\2\2\u0094\3\2\2\2\2\u0096\3\2\2\2\2\u0098\3\2\2\2\2\u009a\3\2\2"+
"\2\2\u009c\3\2\2\2\2\u009e\3\2\2\2\2\u00a0\3\2\2\2\3\u00a2\3\2\2\2\3\u00a4"+
"\3\2\2\2\4\u00a7\3\2\2\2\6\u00c2\3\2\2\2\b\u00c6\3\2\2\2\n\u00c8\3\2\2"+
"\2\f\u00ca\3\2\2\2\16\u00cc\3\2\2\2\20\u00ce\3\2\2\2\22\u00d0\3\2\2\2"+
"\24\u00d2\3\2\2\2\26\u00d6\3\2\2\2\30\u00d8\3\2\2\2\32\u00da\3\2\2\2\34"+
"\u00dd\3\2\2\2\36\u00e2\3\2\2\2 \u00e8\3\2\2\2\"\u00eb\3\2\2\2$\u00ef"+
"\3\2\2\2&\u00f8\3\2\2\2(\u00fe\3\2\2\2*\u0105\3\2\2\2,\u0109\3\2\2\2."+
"\u010d\3\2\2\2\60\u0113\3\2\2\2\62\u0119\3\2\2\2\64\u011e\3\2\2\2\66\u0129"+
"\3\2\2\28\u012b\3\2\2\2:\u012d\3\2\2\2<\u012f\3\2\2\2>\u0132\3\2\2\2@"+
"\u0134\3\2\2\2B\u0136\3\2\2\2D\u0138\3\2\2\2F\u013b\3\2\2\2H\u013e\3\2"+
"\2\2J\u0142\3\2\2\2L\u0144\3\2\2\2N\u0147\3\2\2\2P\u0149\3\2\2\2R\u014c"+
"\3\2\2\2T\u014f\3\2\2\2V\u0153\3\2\2\2X\u0156\3\2\2\2Z\u015a\3\2\2\2\\"+
"\u015c\3\2\2\2^\u015e\3\2\2\2`\u0160\3\2\2\2b\u0163\3\2\2\2d\u0166\3\2"+
"\2\2f\u0168\3\2\2\2h\u016a\3\2\2\2j\u016d\3\2\2\2l\u0170\3\2\2\2n\u0173"+
"\3\2\2\2p\u0177\3\2\2\2r\u017a\3\2\2\2t\u017d\3\2\2\2v\u017f\3\2\2\2x"+
"\u0182\3\2\2\2z\u0185\3\2\2\2|\u0188\3\2\2\2~\u018b\3\2\2\2\u0080\u018e"+
"\3\2\2\2\u0082\u0191\3\2\2\2\u0084\u0194\3\2\2\2\u0086\u0197\3\2\2\2\u0088"+
"\u019b\3\2\2\2\u008a\u019f\3\2\2\2\u008c\u01a4\3\2\2\2\u008e\u01ad\3\2"+
"\2\2\u0090\u01bf\3\2\2\2\u0092\u01cc\3\2\2\2\u0094\u01fc\3\2\2\2\u0096"+
"\u01fe\3\2\2\2\u0098\u020f\3\2\2\2\u009a\u0214\3\2\2\2\u009c\u021a\3\2"+
"\2\2\u009e\u021f\3\2\2\2\u00a0\u022a\3\2\2\2\u00a2\u0239\3\2\2\2\u00a4"+
"\u023d\3\2\2\2\u00a6\u00a8\t\2\2\2\u00a7\u00a6\3\2\2\2\u00a8\u00a9\3\2"+
"\2\2\u00a9\u00a7\3\2\2\2\u00a9\u00aa\3\2\2\2\u00aa\u00ab\3\2\2\2\u00ab"+
"\u00ac\b\2\2\2\u00ac\5\3\2\2\2\u00ad\u00ae\7\61\2\2\u00ae\u00af\7\61\2"+
"\2\u00af\u00b3\3\2\2\2\u00b0\u00b2\13\2\2\2\u00b1\u00b0\3\2\2\2\u00b2"+
"\u00b5\3\2\2\2\u00b3\u00b4\3\2\2\2\u00b3\u00b1\3\2\2\2\u00b4\u00b6\3\2"+
"\2\2\u00b5\u00b3\3\2\2\2\u00b6\u00c3\t\3\2\2\u00b7\u00b8\7\61\2\2\u00b8"+
"\u00b9\7,\2\2\u00b9\u00bd\3\2\2\2\u00ba\u00bc\13\2\2\2\u00bb\u00ba\3\2"+
"\2\2\u00bc\u00bf\3\2\2\2\u00bd\u00be\3\2\2\2\u00bd\u00bb\3\2\2\2\u00be"+
"\u00c0\3\2\2\2\u00bf\u00bd\3\2\2\2\u00c0\u00c1\7,\2\2\u00c1\u00c3\7\61"+
"\2\2\u00c2\u00ad\3\2\2\2\u00c2\u00b7\3\2\2\2\u00c3\u00c4\3\2\2\2\u00c4"+
"\u00c5\b\3\2\2\u00c5\7\3\2\2\2\u00c6\u00c7\7}\2\2\u00c7\t\3\2\2\2\u00c8"+
"\u00c9\7\177\2\2\u00c9\13\3\2\2\2\u00ca\u00cb\7]\2\2\u00cb\r\3\2\2\2\u00cc"+
"\u00cd\7_\2\2\u00cd\17\3\2\2\2\u00ce\u00cf\7*\2\2\u00cf\21\3\2\2\2\u00d0"+
"\u00d1\7+\2\2\u00d1\23\3\2\2\2\u00d2\u00d3\7\60\2\2\u00d3\u00d4\3\2\2"+
"\2\u00d4\u00d5\b\n\3\2\u00d5\25\3\2\2\2\u00d6\u00d7\7.\2\2\u00d7\27\3"+
"\2\2\2\u00d8\u00d9\7=\2\2\u00d9\31\3\2\2\2\u00da\u00db\7k\2\2\u00db\u00dc"+
"\7h\2\2\u00dc\33\3\2\2\2\u00dd\u00de\7g\2\2\u00de\u00df\7n\2\2\u00df\u00e0"+
"\7u\2\2\u00e0\u00e1\7g\2\2\u00e1\35\3\2\2\2\u00e2\u00e3\7y\2\2\u00e3\u00e4"+
"\7j\2\2\u00e4\u00e5\7k\2\2\u00e5\u00e6\7n\2\2\u00e6\u00e7\7g\2\2\u00e7"+
"\37\3\2\2\2\u00e8\u00e9\7f\2\2\u00e9\u00ea\7q\2\2\u00ea!\3\2\2\2\u00eb"+
"\u00ec\7h\2\2\u00ec\u00ed\7q\2\2\u00ed\u00ee\7t\2\2\u00ee#\3\2\2\2\u00ef"+
"\u00f0\7e\2\2\u00f0\u00f1\7q\2\2\u00f1\u00f2\7p\2\2\u00f2\u00f3\7v\2\2"+
"\u00f3\u00f4\7k\2\2\u00f4\u00f5\7p\2\2\u00f5\u00f6\7w\2\2\u00f6\u00f7"+
"\7g\2\2\u00f7%\3\2\2\2\u00f8\u00f9\7d\2\2\u00f9\u00fa\7t\2\2\u00fa\u00fb"+
"\7g\2\2\u00fb\u00fc\7c\2\2\u00fc\u00fd\7m\2\2\u00fd\'\3\2\2\2\u00fe\u00ff"+
"\7t\2\2\u00ff\u0100\7g\2\2\u0100\u0101\7v\2\2\u0101\u0102\7w\2\2\u0102"+
"\u0103\7t\2\2\u0103\u0104\7p\2\2\u0104)\3\2\2\2\u0105\u0106\7p\2\2\u0106"+
"\u0107\7g\2\2\u0107\u0108\7y\2\2\u0108+\3\2\2\2\u0109\u010a\7v\2\2\u010a"+
"\u010b\7t\2\2\u010b\u010c\7{\2\2\u010c-\3\2\2\2\u010d\u010e\7e\2\2\u010e"+
"\u010f\7c\2\2\u010f\u0110\7v\2\2\u0110\u0111\7e\2\2\u0111\u0112\7j\2\2"+
"\u0112/\3\2\2\2\u0113\u0114\7v\2\2\u0114\u0115\7j\2\2\u0115\u0116\7t\2"+
"\2\u0116\u0117\7q\2\2\u0117\u0118\7y\2\2\u0118\61\3\2\2\2\u0119\u011a"+
"\7v\2\2\u011a\u011b\7j\2\2\u011b\u011c\7k\2\2\u011c\u011d\7u\2\2\u011d"+
"\63\3\2\2\2\u011e\u011f\7k\2\2\u011f\u0120\7p\2\2\u0120\u0121\7u\2\2\u0121"+
"\u0122\7v\2\2\u0122\u0123\7c\2\2\u0123\u0124\7p\2\2\u0124\u0125\7e\2\2"+
"\u0125\u0126\7g\2\2\u0126\u0127\7q\2\2\u0127\u0128\7h\2\2\u0128\65\3\2"+
"\2\2\u0129\u012a\7#\2\2\u012a\67\3\2\2\2\u012b\u012c\7\u0080\2\2\u012c"+
"9\3\2\2\2\u012d\u012e\7,\2\2\u012e;\3\2\2\2\u012f\u0130\7\61\2\2\u0130"+
"\u0131\6\36\2\2\u0131=\3\2\2\2\u0132\u0133\7\'\2\2\u0133?\3\2\2\2\u0134"+
"\u0135\7-\2\2\u0135A\3\2\2\2\u0136\u0137\7/\2\2\u0137C\3\2\2\2\u0138\u0139"+
"\7>\2\2\u0139\u013a\7>\2\2\u013aE\3\2\2\2\u013b\u013c\7@\2\2\u013c\u013d"+
"\7@\2\2\u013dG\3\2\2\2\u013e\u013f\7@\2\2\u013f\u0140\7@\2\2\u0140\u0141"+
"\7@\2\2\u0141I\3\2\2\2\u0142\u0143\7>\2\2\u0143K\3\2\2\2\u0144\u0145\7"+
">\2\2\u0145\u0146\7?\2\2\u0146M\3\2\2\2\u0147\u0148\7@\2\2\u0148O\3\2"+
"\2\2\u0149\u014a\7@\2\2\u014a\u014b\7?\2\2\u014bQ\3\2\2\2\u014c\u014d"+
"\7?\2\2\u014d\u014e\7?\2\2\u014eS\3\2\2\2\u014f\u0150\7?\2\2\u0150\u0151"+
"\7?\2\2\u0151\u0152\7?\2\2\u0152U\3\2\2\2\u0153\u0154\7#\2\2\u0154\u0155"+
"\7?\2\2\u0155W\3\2\2\2\u0156\u0157\7#\2\2\u0157\u0158\7?\2\2\u0158\u0159"+
"\7?\2\2\u0159Y\3\2\2\2\u015a\u015b\7(\2\2\u015b[\3\2\2\2\u015c\u015d\7"+
"`\2\2\u015d]\3\2\2\2\u015e\u015f\7~\2\2\u015f_\3\2\2\2\u0160\u0161\7("+
"\2\2\u0161\u0162\7(\2\2\u0162a\3\2\2\2\u0163\u0164\7~\2\2\u0164\u0165"+
"\7~\2\2\u0165c\3\2\2\2\u0166\u0167\7A\2\2\u0167e\3\2\2\2\u0168\u0169\7"+
"<\2\2\u0169g\3\2\2\2\u016a\u016b\7<\2\2\u016b\u016c\7<\2\2\u016ci\3\2"+
"\2\2\u016d\u016e\7/\2\2\u016e\u016f\7@\2\2\u016fk\3\2\2\2\u0170\u0171"+
"\7?\2\2\u0171\u0172\7\u0080\2\2\u0172m\3\2\2\2\u0173\u0174\7?\2\2\u0174"+
"\u0175\7?\2\2\u0175\u0176\7\u0080\2\2\u0176o\3\2\2\2\u0177\u0178\7-\2"+
"\2\u0178\u0179\7-\2\2\u0179q\3\2\2\2\u017a\u017b\7/\2\2\u017b\u017c\7"+
"/\2\2\u017cs\3\2\2\2\u017d\u017e\7?\2\2\u017eu\3\2\2\2\u017f\u0180\7-"+
"\2\2\u0180\u0181\7?\2\2\u0181w\3\2\2\2\u0182\u0183\7/\2\2\u0183\u0184"+
"\7?\2\2\u0184y\3\2\2\2\u0185\u0186\7,\2\2\u0186\u0187\7?\2\2\u0187{\3"+
"\2\2\2\u0188\u0189\7\61\2\2\u0189\u018a\7?\2\2\u018a}\3\2\2\2\u018b\u018c"+
"\7\'\2\2\u018c\u018d\7?\2\2\u018d\177\3\2\2\2\u018e\u018f\7(\2\2\u018f"+
"\u0190\7?\2\2\u0190\u0081\3\2\2\2\u0191\u0192\7`\2\2\u0192\u0193\7?\2"+
"\2\u0193\u0083\3\2\2\2\u0194\u0195\7~\2\2\u0195\u0196\7?\2\2\u0196\u0085"+
"\3\2\2\2\u0197\u0198\7>\2\2\u0198\u0199\7>\2\2\u0199\u019a\7?\2\2\u019a"+
"\u0087\3\2\2\2\u019b\u019c\7@\2\2\u019c\u019d\7@\2\2\u019d\u019e\7?\2"+
"\2\u019e\u0089\3\2\2\2\u019f\u01a0\7@\2\2\u01a0\u01a1\7@\2\2\u01a1\u01a2"+
"\7@\2\2\u01a2\u01a3\7?\2\2\u01a3\u008b\3\2\2\2\u01a4\u01a6\7\62\2\2\u01a5"+
"\u01a7\t\4\2\2\u01a6\u01a5\3\2\2\2\u01a7\u01a8\3\2\2\2\u01a8\u01a6\3\2"+
"\2\2\u01a8\u01a9\3\2\2\2\u01a9\u01ab\3\2\2\2\u01aa\u01ac\t\5\2\2\u01ab"+
"\u01aa\3\2\2\2\u01ab\u01ac\3\2\2\2\u01ac\u008d\3\2\2\2\u01ad\u01ae\7\62"+
"\2\2\u01ae\u01b0\t\6\2\2\u01af\u01b1\t\7\2\2\u01b0\u01af\3\2\2\2\u01b1"+
"\u01b2\3\2\2\2\u01b2\u01b0\3\2\2\2\u01b2\u01b3\3\2\2\2\u01b3\u01b5\3\2"+
"\2\2\u01b4\u01b6\t\5\2\2\u01b5\u01b4\3\2\2\2\u01b5\u01b6\3\2\2\2\u01b6"+
"\u008f\3\2\2\2\u01b7\u01c0\7\62\2\2\u01b8\u01bc\t\b\2\2\u01b9\u01bb\t"+
"\t\2\2\u01ba\u01b9\3\2\2\2\u01bb\u01be\3\2\2\2\u01bc\u01ba\3\2\2\2\u01bc"+
"\u01bd\3\2\2\2\u01bd\u01c0\3\2\2\2\u01be\u01bc\3\2\2\2\u01bf\u01b7\3\2"+
"\2\2\u01bf\u01b8\3\2\2\2\u01c0\u01c2\3\2\2\2\u01c1\u01c3\t\n\2\2\u01c2"+
"\u01c1\3\2\2\2\u01c2\u01c3\3\2\2\2\u01c3\u0091\3\2\2\2\u01c4\u01cd\7\62"+
"\2\2\u01c5\u01c9\t\b\2\2\u01c6\u01c8\t\t\2\2\u01c7\u01c6\3\2\2\2\u01c8"+
"\u01cb\3\2\2\2\u01c9\u01c7\3\2\2\2\u01c9\u01ca\3\2\2\2\u01ca\u01cd\3\2"+
"\2\2\u01cb\u01c9\3\2\2\2\u01cc\u01c4\3\2\2\2\u01cc\u01c5\3\2\2\2\u01cd"+
"\u01d4\3\2\2\2\u01ce\u01d0\5\24\n\2\u01cf\u01d1\t\t\2\2\u01d0\u01cf\3"+
"\2\2\2\u01d1\u01d2\3\2\2\2\u01d2\u01d0\3\2\2\2\u01d2\u01d3\3\2\2\2\u01d3"+
"\u01d5\3\2\2\2\u01d4\u01ce\3\2\2\2\u01d4\u01d5\3\2\2\2\u01d5\u01df\3\2"+
"\2\2\u01d6\u01d8\t\13\2\2\u01d7\u01d9\t\f\2\2\u01d8\u01d7\3\2\2\2\u01d8"+
"\u01d9\3\2\2\2\u01d9\u01db\3\2\2\2\u01da\u01dc\t\t\2\2\u01db\u01da\3\2"+
"\2\2\u01dc\u01dd\3\2\2\2\u01dd\u01db\3\2\2\2\u01dd\u01de\3\2\2\2\u01de"+
"\u01e0\3\2\2\2\u01df\u01d6\3\2\2\2\u01df\u01e0\3\2\2\2\u01e0\u01e2\3\2"+
"\2\2\u01e1\u01e3\t\r\2\2\u01e2\u01e1\3\2\2\2\u01e2\u01e3\3\2\2\2\u01e3"+
"\u0093\3\2\2\2\u01e4\u01ec\7$\2\2\u01e5\u01e6\7^\2\2\u01e6\u01eb\7$\2"+
"\2\u01e7\u01e8\7^\2\2\u01e8\u01eb\7^\2\2\u01e9\u01eb\n\16\2\2\u01ea\u01e5"+
"\3\2\2\2\u01ea\u01e7\3\2\2\2\u01ea\u01e9\3\2\2\2\u01eb\u01ee\3\2\2\2\u01ec"+
"\u01ed\3\2\2\2\u01ec\u01ea\3\2\2\2\u01ed\u01ef\3\2\2\2\u01ee\u01ec\3\2"+
"\2\2\u01ef\u01fd\7$\2\2\u01f0\u01f8\7)\2\2\u01f1\u01f2\7^\2\2\u01f2\u01f7"+
"\7)\2\2\u01f3\u01f4\7^\2\2\u01f4\u01f7\7^\2\2\u01f5\u01f7\n\16\2\2\u01f6"+
"\u01f1\3\2\2\2\u01f6\u01f3\3\2\2\2\u01f6\u01f5\3\2\2\2\u01f7\u01fa\3\2"+
"\2\2\u01f8\u01f9\3\2\2\2\u01f8\u01f6\3\2\2\2\u01f9\u01fb\3\2\2\2\u01fa"+
"\u01f8\3\2\2\2\u01fb\u01fd\7)\2\2\u01fc\u01e4\3\2\2\2\u01fc\u01f0\3\2"+
"\2\2\u01fd\u0095\3\2\2\2\u01fe\u0202\7\61\2\2\u01ff\u0203\n\17\2\2\u0200"+
"\u0201\7^\2\2\u0201\u0203\n\20\2\2\u0202\u01ff\3\2\2\2\u0202\u0200\3\2"+
"\2\2\u0203\u0204\3\2\2\2\u0204\u0202\3\2\2\2\u0204\u0205\3\2\2\2\u0205"+
"\u0206\3\2\2\2\u0206\u020a\7\61\2\2\u0207\u0209\t\21\2\2\u0208\u0207\3"+
"\2\2\2\u0209\u020c\3\2\2\2\u020a\u0208\3\2\2\2\u020a\u020b\3\2\2\2\u020b"+
"\u020d\3\2\2\2\u020c\u020a\3\2\2\2\u020d\u020e\6K\3\2\u020e\u0097\3\2"+
"\2\2\u020f\u0210\7v\2\2\u0210\u0211\7t\2\2\u0211\u0212\7w\2\2\u0212\u0213"+
"\7g\2\2\u0213\u0099\3\2\2\2\u0214\u0215\7h\2\2\u0215\u0216\7c\2\2\u0216"+
"\u0217\7n\2\2\u0217\u0218\7u\2\2\u0218\u0219\7g\2\2\u0219\u009b\3\2\2"+
"\2\u021a\u021b\7p\2\2\u021b\u021c\7w\2\2\u021c\u021d\7n\2\2\u021d\u021e"+
"\7n\2\2\u021e\u009d\3\2\2\2\u021f\u0225\5\u00a0P\2\u0220\u0221\5\24\n"+
"\2\u0221\u0222\5\u00a0P\2\u0222\u0224\3\2\2\2\u0223\u0220\3\2\2\2\u0224"+
"\u0227\3\2\2\2\u0225\u0223\3\2\2\2\u0225\u0226\3\2\2\2\u0226\u0228\3\2"+
"\2\2\u0227\u0225\3\2\2\2\u0228\u0229\6O\4\2\u0229\u009f\3\2\2\2\u022a"+
"\u022e\t\22\2\2\u022b\u022d\t\23\2\2\u022c\u022b\3\2\2\2\u022d\u0230\3"+
"\2\2\2\u022e\u022c\3\2\2\2\u022e\u022f\3\2\2\2\u022f\u00a1\3\2\2\2\u0230"+
"\u022e\3\2\2\2\u0231\u023a\7\62\2\2\u0232\u0236\t\b\2\2\u0233\u0235\t"+
"\t\2\2\u0234\u0233\3\2\2\2\u0235\u0238\3\2\2\2\u0236\u0234\3\2\2\2\u0236"+
"\u0237\3\2\2\2\u0237\u023a\3\2\2\2\u0238\u0236\3\2\2\2\u0239\u0231\3\2"+
"\2\2\u0239\u0232\3\2\2\2\u023a\u023b\3\2\2\2\u023b\u023c\bQ\4\2\u023c"+
"\u00a3\3\2\2\2\u023d\u0241\t\22\2\2\u023e\u0240\t\23\2\2\u023f\u023e\3"+
"\2\2\2\u0240\u0243\3\2\2\2\u0241\u023f\3\2\2\2\u0241\u0242\3\2\2\2\u0242"+
"\u0244\3\2\2\2\u0243\u0241\3\2\2\2\u0244\u0245\bR\4\2\u0245\u00a5\3\2"+
"\2\2$\2\3\u00a9\u00b3\u00bd\u00c2\u01a8\u01ab\u01b2\u01b5\u01bc\u01bf"+
"\u01c2\u01c9\u01cc\u01d2\u01d4\u01d8\u01dd\u01df\u01e2\u01ea\u01ec\u01f6"+
"\u01f8\u01fc\u0202\u0204\u020a\u0225\u022e\u0236\u0239\u0241\5\b\2\2\4"+
"\3\2\4\2\2";
"I\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\3\2\6"+
"\2\u00aa\n\2\r\2\16\2\u00ab\3\2\3\2\3\3\3\3\3\3\3\3\7\3\u00b4\n\3\f\3"+
"\16\3\u00b7\13\3\3\3\3\3\3\3\3\3\3\3\7\3\u00be\n\3\f\3\16\3\u00c1\13\3"+
"\3\3\3\3\5\3\u00c5\n\3\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b"+
"\3\t\3\t\3\n\3\n\3\n\3\n\3\13\3\13\3\f\3\f\3\r\3\r\3\r\3\16\3\16\3\16"+
"\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21"+
"\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\24"+
"\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\26\3\26"+
"\3\26\3\26\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3\30\3\30\3\31\3\31"+
"\3\31\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\33\3\33\3\33\3\33\3\33"+
"\3\33\3\33\3\33\3\33\3\33\3\33\3\34\3\34\3\35\3\35\3\36\3\36\3\37\3\37"+
"\3\37\3 \3 \3!\3!\3\"\3\"\3#\3#\3#\3$\3$\3$\3%\3%\3%\3%\3&\3&\3\'\3\'"+
"\3\'\3(\3(\3)\3)\3)\3*\3*\3*\3+\3+\3+\3+\3,\3,\3,\3-\3-\3-\3-\3.\3.\3"+
"/\3/\3\60\3\60\3\61\3\61\3\61\3\62\3\62\3\62\3\63\3\63\3\64\3\64\3\65"+
"\3\65\3\65\3\66\3\66\3\66\3\67\3\67\3\67\38\38\38\38\39\39\39\3:\3:\3"+
":\3;\3;\3<\3<\3<\3=\3=\3=\3>\3>\3>\3?\3?\3?\3@\3@\3@\3A\3A\3A\3B\3B\3"+
"B\3C\3C\3C\3D\3D\3D\3D\3E\3E\3E\3E\3F\3F\3F\3F\3F\3G\3G\6G\u01ac\nG\r"+
"G\16G\u01ad\3G\5G\u01b1\nG\3H\3H\3H\6H\u01b6\nH\rH\16H\u01b7\3H\5H\u01bb"+
"\nH\3I\3I\3I\7I\u01c0\nI\fI\16I\u01c3\13I\5I\u01c5\nI\3I\5I\u01c8\nI\3"+
"J\3J\3J\7J\u01cd\nJ\fJ\16J\u01d0\13J\5J\u01d2\nJ\3J\3J\6J\u01d6\nJ\rJ"+
"\16J\u01d7\5J\u01da\nJ\3J\3J\5J\u01de\nJ\3J\6J\u01e1\nJ\rJ\16J\u01e2\5"+
"J\u01e5\nJ\3J\5J\u01e8\nJ\3K\3K\3K\3K\3K\3K\7K\u01f0\nK\fK\16K\u01f3\13"+
"K\3K\3K\3K\3K\3K\3K\3K\7K\u01fc\nK\fK\16K\u01ff\13K\3K\5K\u0202\nK\3L"+
"\3L\3L\3L\6L\u0208\nL\rL\16L\u0209\3L\3L\7L\u020e\nL\fL\16L\u0211\13L"+
"\3L\3L\3M\3M\3M\3M\3M\3N\3N\3N\3N\3N\3N\3O\3O\3O\3O\3O\3P\3P\3P\3P\7P"+
"\u0229\nP\fP\16P\u022c\13P\3P\3P\3Q\3Q\7Q\u0232\nQ\fQ\16Q\u0235\13Q\3"+
"R\3R\3R\7R\u023a\nR\fR\16R\u023d\13R\5R\u023f\nR\3R\3R\3S\3S\7S\u0245"+
"\nS\fS\16S\u0248\13S\3S\3S\6\u00b5\u00bf\u01f1\u01fd\2T\4\3\6\4\b\5\n"+
"\6\f\7\16\b\20\t\22\n\24\13\26\f\30\r\32\16\34\17\36\20 \21\"\22$\23&"+
"\24(\25*\26,\27.\30\60\31\62\32\64\33\66\348\35:\36<\37> @!B\"D#F$H%J"+
"&L\'N(P)R*T+V,X-Z.\\/^\60`\61b\62d\63f\64h\65j\66l\67n8p9r:t;v<x=z>|?"+
"~@\u0080A\u0082B\u0084C\u0086D\u0088E\u008aF\u008cG\u008eH\u0090I\u0092"+
"J\u0094K\u0096L\u0098M\u009aN\u009cO\u009eP\u00a0Q\u00a2R\u00a4S\u00a6"+
"T\4\2\3\24\5\2\13\f\17\17\"\"\4\2\f\f\17\17\3\2\629\4\2NNnn\4\2ZZzz\5"+
"\2\62;CHch\3\2\63;\3\2\62;\b\2FFHHNNffhhnn\4\2GGgg\4\2--//\4\2HHhh\4\2"+
"$$^^\4\2\f\f\61\61\3\2\f\f\t\2WWeekknouuwwzz\5\2C\\aac|\6\2\62;C\\aac"+
"|\u026b\2\4\3\2\2\2\2\6\3\2\2\2\2\b\3\2\2\2\2\n\3\2\2\2\2\f\3\2\2\2\2"+
"\16\3\2\2\2\2\20\3\2\2\2\2\22\3\2\2\2\2\24\3\2\2\2\2\26\3\2\2\2\2\30\3"+
"\2\2\2\2\32\3\2\2\2\2\34\3\2\2\2\2\36\3\2\2\2\2 \3\2\2\2\2\"\3\2\2\2\2"+
"$\3\2\2\2\2&\3\2\2\2\2(\3\2\2\2\2*\3\2\2\2\2,\3\2\2\2\2.\3\2\2\2\2\60"+
"\3\2\2\2\2\62\3\2\2\2\2\64\3\2\2\2\2\66\3\2\2\2\28\3\2\2\2\2:\3\2\2\2"+
"\2<\3\2\2\2\2>\3\2\2\2\2@\3\2\2\2\2B\3\2\2\2\2D\3\2\2\2\2F\3\2\2\2\2H"+
"\3\2\2\2\2J\3\2\2\2\2L\3\2\2\2\2N\3\2\2\2\2P\3\2\2\2\2R\3\2\2\2\2T\3\2"+
"\2\2\2V\3\2\2\2\2X\3\2\2\2\2Z\3\2\2\2\2\\\3\2\2\2\2^\3\2\2\2\2`\3\2\2"+
"\2\2b\3\2\2\2\2d\3\2\2\2\2f\3\2\2\2\2h\3\2\2\2\2j\3\2\2\2\2l\3\2\2\2\2"+
"n\3\2\2\2\2p\3\2\2\2\2r\3\2\2\2\2t\3\2\2\2\2v\3\2\2\2\2x\3\2\2\2\2z\3"+
"\2\2\2\2|\3\2\2\2\2~\3\2\2\2\2\u0080\3\2\2\2\2\u0082\3\2\2\2\2\u0084\3"+
"\2\2\2\2\u0086\3\2\2\2\2\u0088\3\2\2\2\2\u008a\3\2\2\2\2\u008c\3\2\2\2"+
"\2\u008e\3\2\2\2\2\u0090\3\2\2\2\2\u0092\3\2\2\2\2\u0094\3\2\2\2\2\u0096"+
"\3\2\2\2\2\u0098\3\2\2\2\2\u009a\3\2\2\2\2\u009c\3\2\2\2\2\u009e\3\2\2"+
"\2\2\u00a0\3\2\2\2\2\u00a2\3\2\2\2\3\u00a4\3\2\2\2\3\u00a6\3\2\2\2\4\u00a9"+
"\3\2\2\2\6\u00c4\3\2\2\2\b\u00c8\3\2\2\2\n\u00ca\3\2\2\2\f\u00cc\3\2\2"+
"\2\16\u00ce\3\2\2\2\20\u00d0\3\2\2\2\22\u00d2\3\2\2\2\24\u00d4\3\2\2\2"+
"\26\u00d8\3\2\2\2\30\u00da\3\2\2\2\32\u00dc\3\2\2\2\34\u00df\3\2\2\2\36"+
"\u00e2\3\2\2\2 \u00e7\3\2\2\2\"\u00ed\3\2\2\2$\u00f0\3\2\2\2&\u00f4\3"+
"\2\2\2(\u00fd\3\2\2\2*\u0103\3\2\2\2,\u010a\3\2\2\2.\u010e\3\2\2\2\60"+
"\u0112\3\2\2\2\62\u0118\3\2\2\2\64\u011e\3\2\2\2\66\u0123\3\2\2\28\u012e"+
"\3\2\2\2:\u0130\3\2\2\2<\u0132\3\2\2\2>\u0134\3\2\2\2@\u0137\3\2\2\2B"+
"\u0139\3\2\2\2D\u013b\3\2\2\2F\u013d\3\2\2\2H\u0140\3\2\2\2J\u0143\3\2"+
"\2\2L\u0147\3\2\2\2N\u0149\3\2\2\2P\u014c\3\2\2\2R\u014e\3\2\2\2T\u0151"+
"\3\2\2\2V\u0154\3\2\2\2X\u0158\3\2\2\2Z\u015b\3\2\2\2\\\u015f\3\2\2\2"+
"^\u0161\3\2\2\2`\u0163\3\2\2\2b\u0165\3\2\2\2d\u0168\3\2\2\2f\u016b\3"+
"\2\2\2h\u016d\3\2\2\2j\u016f\3\2\2\2l\u0172\3\2\2\2n\u0175\3\2\2\2p\u0178"+
"\3\2\2\2r\u017c\3\2\2\2t\u017f\3\2\2\2v\u0182\3\2\2\2x\u0184\3\2\2\2z"+
"\u0187\3\2\2\2|\u018a\3\2\2\2~\u018d\3\2\2\2\u0080\u0190\3\2\2\2\u0082"+
"\u0193\3\2\2\2\u0084\u0196\3\2\2\2\u0086\u0199\3\2\2\2\u0088\u019c\3\2"+
"\2\2\u008a\u01a0\3\2\2\2\u008c\u01a4\3\2\2\2\u008e\u01a9\3\2\2\2\u0090"+
"\u01b2\3\2\2\2\u0092\u01c4\3\2\2\2\u0094\u01d1\3\2\2\2\u0096\u0201\3\2"+
"\2\2\u0098\u0203\3\2\2\2\u009a\u0214\3\2\2\2\u009c\u0219\3\2\2\2\u009e"+
"\u021f\3\2\2\2\u00a0\u0224\3\2\2\2\u00a2\u022f\3\2\2\2\u00a4\u023e\3\2"+
"\2\2\u00a6\u0242\3\2\2\2\u00a8\u00aa\t\2\2\2\u00a9\u00a8\3\2\2\2\u00aa"+
"\u00ab\3\2\2\2\u00ab\u00a9\3\2\2\2\u00ab\u00ac\3\2\2\2\u00ac\u00ad\3\2"+
"\2\2\u00ad\u00ae\b\2\2\2\u00ae\5\3\2\2\2\u00af\u00b0\7\61\2\2\u00b0\u00b1"+
"\7\61\2\2\u00b1\u00b5\3\2\2\2\u00b2\u00b4\13\2\2\2\u00b3\u00b2\3\2\2\2"+
"\u00b4\u00b7\3\2\2\2\u00b5\u00b6\3\2\2\2\u00b5\u00b3\3\2\2\2\u00b6\u00b8"+
"\3\2\2\2\u00b7\u00b5\3\2\2\2\u00b8\u00c5\t\3\2\2\u00b9\u00ba\7\61\2\2"+
"\u00ba\u00bb\7,\2\2\u00bb\u00bf\3\2\2\2\u00bc\u00be\13\2\2\2\u00bd\u00bc"+
"\3\2\2\2\u00be\u00c1\3\2\2\2\u00bf\u00c0\3\2\2\2\u00bf\u00bd\3\2\2\2\u00c0"+
"\u00c2\3\2\2\2\u00c1\u00bf\3\2\2\2\u00c2\u00c3\7,\2\2\u00c3\u00c5\7\61"+
"\2\2\u00c4\u00af\3\2\2\2\u00c4\u00b9\3\2\2\2\u00c5\u00c6\3\2\2\2\u00c6"+
"\u00c7\b\3\2\2\u00c7\7\3\2\2\2\u00c8\u00c9\7}\2\2\u00c9\t\3\2\2\2\u00ca"+
"\u00cb\7\177\2\2\u00cb\13\3\2\2\2\u00cc\u00cd\7]\2\2\u00cd\r\3\2\2\2\u00ce"+
"\u00cf\7_\2\2\u00cf\17\3\2\2\2\u00d0\u00d1\7*\2\2\u00d1\21\3\2\2\2\u00d2"+
"\u00d3\7+\2\2\u00d3\23\3\2\2\2\u00d4\u00d5\7\60\2\2\u00d5\u00d6\3\2\2"+
"\2\u00d6\u00d7\b\n\3\2\u00d7\25\3\2\2\2\u00d8\u00d9\7.\2\2\u00d9\27\3"+
"\2\2\2\u00da\u00db\7=\2\2\u00db\31\3\2\2\2\u00dc\u00dd\7k\2\2\u00dd\u00de"+
"\7h\2\2\u00de\33\3\2\2\2\u00df\u00e0\7k\2\2\u00e0\u00e1\7p\2\2\u00e1\35"+
"\3\2\2\2\u00e2\u00e3\7g\2\2\u00e3\u00e4\7n\2\2\u00e4\u00e5\7u\2\2\u00e5"+
"\u00e6\7g\2\2\u00e6\37\3\2\2\2\u00e7\u00e8\7y\2\2\u00e8\u00e9\7j\2\2\u00e9"+
"\u00ea\7k\2\2\u00ea\u00eb\7n\2\2\u00eb\u00ec\7g\2\2\u00ec!\3\2\2\2\u00ed"+
"\u00ee\7f\2\2\u00ee\u00ef\7q\2\2\u00ef#\3\2\2\2\u00f0\u00f1\7h\2\2\u00f1"+
"\u00f2\7q\2\2\u00f2\u00f3\7t\2\2\u00f3%\3\2\2\2\u00f4\u00f5\7e\2\2\u00f5"+
"\u00f6\7q\2\2\u00f6\u00f7\7p\2\2\u00f7\u00f8\7v\2\2\u00f8\u00f9\7k\2\2"+
"\u00f9\u00fa\7p\2\2\u00fa\u00fb\7w\2\2\u00fb\u00fc\7g\2\2\u00fc\'\3\2"+
"\2\2\u00fd\u00fe\7d\2\2\u00fe\u00ff\7t\2\2\u00ff\u0100\7g\2\2\u0100\u0101"+
"\7c\2\2\u0101\u0102\7m\2\2\u0102)\3\2\2\2\u0103\u0104\7t\2\2\u0104\u0105"+
"\7g\2\2\u0105\u0106\7v\2\2\u0106\u0107\7w\2\2\u0107\u0108\7t\2\2\u0108"+
"\u0109\7p\2\2\u0109+\3\2\2\2\u010a\u010b\7p\2\2\u010b\u010c\7g\2\2\u010c"+
"\u010d\7y\2\2\u010d-\3\2\2\2\u010e\u010f\7v\2\2\u010f\u0110\7t\2\2\u0110"+
"\u0111\7{\2\2\u0111/\3\2\2\2\u0112\u0113\7e\2\2\u0113\u0114\7c\2\2\u0114"+
"\u0115\7v\2\2\u0115\u0116\7e\2\2\u0116\u0117\7j\2\2\u0117\61\3\2\2\2\u0118"+
"\u0119\7v\2\2\u0119\u011a\7j\2\2\u011a\u011b\7t\2\2\u011b\u011c\7q\2\2"+
"\u011c\u011d\7y\2\2\u011d\63\3\2\2\2\u011e\u011f\7v\2\2\u011f\u0120\7"+
"j\2\2\u0120\u0121\7k\2\2\u0121\u0122\7u\2\2\u0122\65\3\2\2\2\u0123\u0124"+
"\7k\2\2\u0124\u0125\7p\2\2\u0125\u0126\7u\2\2\u0126\u0127\7v\2\2\u0127"+
"\u0128\7c\2\2\u0128\u0129\7p\2\2\u0129\u012a\7e\2\2\u012a\u012b\7g\2\2"+
"\u012b\u012c\7q\2\2\u012c\u012d\7h\2\2\u012d\67\3\2\2\2\u012e\u012f\7"+
"#\2\2\u012f9\3\2\2\2\u0130\u0131\7\u0080\2\2\u0131;\3\2\2\2\u0132\u0133"+
"\7,\2\2\u0133=\3\2\2\2\u0134\u0135\7\61\2\2\u0135\u0136\6\37\2\2\u0136"+
"?\3\2\2\2\u0137\u0138\7\'\2\2\u0138A\3\2\2\2\u0139\u013a\7-\2\2\u013a"+
"C\3\2\2\2\u013b\u013c\7/\2\2\u013cE\3\2\2\2\u013d\u013e\7>\2\2\u013e\u013f"+
"\7>\2\2\u013fG\3\2\2\2\u0140\u0141\7@\2\2\u0141\u0142\7@\2\2\u0142I\3"+
"\2\2\2\u0143\u0144\7@\2\2\u0144\u0145\7@\2\2\u0145\u0146\7@\2\2\u0146"+
"K\3\2\2\2\u0147\u0148\7>\2\2\u0148M\3\2\2\2\u0149\u014a\7>\2\2\u014a\u014b"+
"\7?\2\2\u014bO\3\2\2\2\u014c\u014d\7@\2\2\u014dQ\3\2\2\2\u014e\u014f\7"+
"@\2\2\u014f\u0150\7?\2\2\u0150S\3\2\2\2\u0151\u0152\7?\2\2\u0152\u0153"+
"\7?\2\2\u0153U\3\2\2\2\u0154\u0155\7?\2\2\u0155\u0156\7?\2\2\u0156\u0157"+
"\7?\2\2\u0157W\3\2\2\2\u0158\u0159\7#\2\2\u0159\u015a\7?\2\2\u015aY\3"+
"\2\2\2\u015b\u015c\7#\2\2\u015c\u015d\7?\2\2\u015d\u015e\7?\2\2\u015e"+
"[\3\2\2\2\u015f\u0160\7(\2\2\u0160]\3\2\2\2\u0161\u0162\7`\2\2\u0162_"+
"\3\2\2\2\u0163\u0164\7~\2\2\u0164a\3\2\2\2\u0165\u0166\7(\2\2\u0166\u0167"+
"\7(\2\2\u0167c\3\2\2\2\u0168\u0169\7~\2\2\u0169\u016a\7~\2\2\u016ae\3"+
"\2\2\2\u016b\u016c\7A\2\2\u016cg\3\2\2\2\u016d\u016e\7<\2\2\u016ei\3\2"+
"\2\2\u016f\u0170\7<\2\2\u0170\u0171\7<\2\2\u0171k\3\2\2\2\u0172\u0173"+
"\7/\2\2\u0173\u0174\7@\2\2\u0174m\3\2\2\2\u0175\u0176\7?\2\2\u0176\u0177"+
"\7\u0080\2\2\u0177o\3\2\2\2\u0178\u0179\7?\2\2\u0179\u017a\7?\2\2\u017a"+
"\u017b\7\u0080\2\2\u017bq\3\2\2\2\u017c\u017d\7-\2\2\u017d\u017e\7-\2"+
"\2\u017es\3\2\2\2\u017f\u0180\7/\2\2\u0180\u0181\7/\2\2\u0181u\3\2\2\2"+
"\u0182\u0183\7?\2\2\u0183w\3\2\2\2\u0184\u0185\7-\2\2\u0185\u0186\7?\2"+
"\2\u0186y\3\2\2\2\u0187\u0188\7/\2\2\u0188\u0189\7?\2\2\u0189{\3\2\2\2"+
"\u018a\u018b\7,\2\2\u018b\u018c\7?\2\2\u018c}\3\2\2\2\u018d\u018e\7\61"+
"\2\2\u018e\u018f\7?\2\2\u018f\177\3\2\2\2\u0190\u0191\7\'\2\2\u0191\u0192"+
"\7?\2\2\u0192\u0081\3\2\2\2\u0193\u0194\7(\2\2\u0194\u0195\7?\2\2\u0195"+
"\u0083\3\2\2\2\u0196\u0197\7`\2\2\u0197\u0198\7?\2\2\u0198\u0085\3\2\2"+
"\2\u0199\u019a\7~\2\2\u019a\u019b\7?\2\2\u019b\u0087\3\2\2\2\u019c\u019d"+
"\7>\2\2\u019d\u019e\7>\2\2\u019e\u019f\7?\2\2\u019f\u0089\3\2\2\2\u01a0"+
"\u01a1\7@\2\2\u01a1\u01a2\7@\2\2\u01a2\u01a3\7?\2\2\u01a3\u008b\3\2\2"+
"\2\u01a4\u01a5\7@\2\2\u01a5\u01a6\7@\2\2\u01a6\u01a7\7@\2\2\u01a7\u01a8"+
"\7?\2\2\u01a8\u008d\3\2\2\2\u01a9\u01ab\7\62\2\2\u01aa\u01ac\t\4\2\2\u01ab"+
"\u01aa\3\2\2\2\u01ac\u01ad\3\2\2\2\u01ad\u01ab\3\2\2\2\u01ad\u01ae\3\2"+
"\2\2\u01ae\u01b0\3\2\2\2\u01af\u01b1\t\5\2\2\u01b0\u01af\3\2\2\2\u01b0"+
"\u01b1\3\2\2\2\u01b1\u008f\3\2\2\2\u01b2\u01b3\7\62\2\2\u01b3\u01b5\t"+
"\6\2\2\u01b4\u01b6\t\7\2\2\u01b5\u01b4\3\2\2\2\u01b6\u01b7\3\2\2\2\u01b7"+
"\u01b5\3\2\2\2\u01b7\u01b8\3\2\2\2\u01b8\u01ba\3\2\2\2\u01b9\u01bb\t\5"+
"\2\2\u01ba\u01b9\3\2\2\2\u01ba\u01bb\3\2\2\2\u01bb\u0091\3\2\2\2\u01bc"+
"\u01c5\7\62\2\2\u01bd\u01c1\t\b\2\2\u01be\u01c0\t\t\2\2\u01bf\u01be\3"+
"\2\2\2\u01c0\u01c3\3\2\2\2\u01c1\u01bf\3\2\2\2\u01c1\u01c2\3\2\2\2\u01c2"+
"\u01c5\3\2\2\2\u01c3\u01c1\3\2\2\2\u01c4\u01bc\3\2\2\2\u01c4\u01bd\3\2"+
"\2\2\u01c5\u01c7\3\2\2\2\u01c6\u01c8\t\n\2\2\u01c7\u01c6\3\2\2\2\u01c7"+
"\u01c8\3\2\2\2\u01c8\u0093\3\2\2\2\u01c9\u01d2\7\62\2\2\u01ca\u01ce\t"+
"\b\2\2\u01cb\u01cd\t\t\2\2\u01cc\u01cb\3\2\2\2\u01cd\u01d0\3\2\2\2\u01ce"+
"\u01cc\3\2\2\2\u01ce\u01cf\3\2\2\2\u01cf\u01d2\3\2\2\2\u01d0\u01ce\3\2"+
"\2\2\u01d1\u01c9\3\2\2\2\u01d1\u01ca\3\2\2\2\u01d2\u01d9\3\2\2\2\u01d3"+
"\u01d5\5\24\n\2\u01d4\u01d6\t\t\2\2\u01d5\u01d4\3\2\2\2\u01d6\u01d7\3"+
"\2\2\2\u01d7\u01d5\3\2\2\2\u01d7\u01d8\3\2\2\2\u01d8\u01da\3\2\2\2\u01d9"+
"\u01d3\3\2\2\2\u01d9\u01da\3\2\2\2\u01da\u01e4\3\2\2\2\u01db\u01dd\t\13"+
"\2\2\u01dc\u01de\t\f\2\2\u01dd\u01dc\3\2\2\2\u01dd\u01de\3\2\2\2\u01de"+
"\u01e0\3\2\2\2\u01df\u01e1\t\t\2\2\u01e0\u01df\3\2\2\2\u01e1\u01e2\3\2"+
"\2\2\u01e2\u01e0\3\2\2\2\u01e2\u01e3\3\2\2\2\u01e3\u01e5\3\2\2\2\u01e4"+
"\u01db\3\2\2\2\u01e4\u01e5\3\2\2\2\u01e5\u01e7\3\2\2\2\u01e6\u01e8\t\r"+
"\2\2\u01e7\u01e6\3\2\2\2\u01e7\u01e8\3\2\2\2\u01e8\u0095\3\2\2\2\u01e9"+
"\u01f1\7$\2\2\u01ea\u01eb\7^\2\2\u01eb\u01f0\7$\2\2\u01ec\u01ed\7^\2\2"+
"\u01ed\u01f0\7^\2\2\u01ee\u01f0\n\16\2\2\u01ef\u01ea\3\2\2\2\u01ef\u01ec"+
"\3\2\2\2\u01ef\u01ee\3\2\2\2\u01f0\u01f3\3\2\2\2\u01f1\u01f2\3\2\2\2\u01f1"+
"\u01ef\3\2\2\2\u01f2\u01f4\3\2\2\2\u01f3\u01f1\3\2\2\2\u01f4\u0202\7$"+
"\2\2\u01f5\u01fd\7)\2\2\u01f6\u01f7\7^\2\2\u01f7\u01fc\7)\2\2\u01f8\u01f9"+
"\7^\2\2\u01f9\u01fc\7^\2\2\u01fa\u01fc\n\16\2\2\u01fb\u01f6\3\2\2\2\u01fb"+
"\u01f8\3\2\2\2\u01fb\u01fa\3\2\2\2\u01fc\u01ff\3\2\2\2\u01fd\u01fe\3\2"+
"\2\2\u01fd\u01fb\3\2\2\2\u01fe\u0200\3\2\2\2\u01ff\u01fd\3\2\2\2\u0200"+
"\u0202\7)\2\2\u0201\u01e9\3\2\2\2\u0201\u01f5\3\2\2\2\u0202\u0097\3\2"+
"\2\2\u0203\u0207\7\61\2\2\u0204\u0208\n\17\2\2\u0205\u0206\7^\2\2\u0206"+
"\u0208\n\20\2\2\u0207\u0204\3\2\2\2\u0207\u0205\3\2\2\2\u0208\u0209\3"+
"\2\2\2\u0209\u0207\3\2\2\2\u0209\u020a\3\2\2\2\u020a\u020b\3\2\2\2\u020b"+
"\u020f\7\61\2\2\u020c\u020e\t\21\2\2\u020d\u020c\3\2\2\2\u020e\u0211\3"+
"\2\2\2\u020f\u020d\3\2\2\2\u020f\u0210\3\2\2\2\u0210\u0212\3\2\2\2\u0211"+
"\u020f\3\2\2\2\u0212\u0213\6L\3\2\u0213\u0099\3\2\2\2\u0214\u0215\7v\2"+
"\2\u0215\u0216\7t\2\2\u0216\u0217\7w\2\2\u0217\u0218\7g\2\2\u0218\u009b"+
"\3\2\2\2\u0219\u021a\7h\2\2\u021a\u021b\7c\2\2\u021b\u021c\7n\2\2\u021c"+
"\u021d\7u\2\2\u021d\u021e\7g\2\2\u021e\u009d\3\2\2\2\u021f\u0220\7p\2"+
"\2\u0220\u0221\7w\2\2\u0221\u0222\7n\2\2\u0222\u0223\7n\2\2\u0223\u009f"+
"\3\2\2\2\u0224\u022a\5\u00a2Q\2\u0225\u0226\5\24\n\2\u0226\u0227\5\u00a2"+
"Q\2\u0227\u0229\3\2\2\2\u0228\u0225\3\2\2\2\u0229\u022c\3\2\2\2\u022a"+
"\u0228\3\2\2\2\u022a\u022b\3\2\2\2\u022b\u022d\3\2\2\2\u022c\u022a\3\2"+
"\2\2\u022d\u022e\6P\4\2\u022e\u00a1\3\2\2\2\u022f\u0233\t\22\2\2\u0230"+
"\u0232\t\23\2\2\u0231\u0230\3\2\2\2\u0232\u0235\3\2\2\2\u0233\u0231\3"+
"\2\2\2\u0233\u0234\3\2\2\2\u0234\u00a3\3\2\2\2\u0235\u0233\3\2\2\2\u0236"+
"\u023f\7\62\2\2\u0237\u023b\t\b\2\2\u0238\u023a\t\t\2\2\u0239\u0238\3"+
"\2\2\2\u023a\u023d\3\2\2\2\u023b\u0239\3\2\2\2\u023b\u023c\3\2\2\2\u023c"+
"\u023f\3\2\2\2\u023d\u023b\3\2\2\2\u023e\u0236\3\2\2\2\u023e\u0237\3\2"+
"\2\2\u023f\u0240\3\2\2\2\u0240\u0241\bR\4\2\u0241\u00a5\3\2\2\2\u0242"+
"\u0246\t\22\2\2\u0243\u0245\t\23\2\2\u0244\u0243\3\2\2\2\u0245\u0248\3"+
"\2\2\2\u0246\u0244\3\2\2\2\u0246\u0247\3\2\2\2\u0247\u0249\3\2\2\2\u0248"+
"\u0246\3\2\2\2\u0249\u024a\bS\4\2\u024a\u00a7\3\2\2\2$\2\3\u00ab\u00b5"+
"\u00bf\u00c4\u01ad\u01b0\u01b7\u01ba\u01c1\u01c4\u01c7\u01ce\u01d1\u01d7"+
"\u01d9\u01dd\u01e2\u01e4\u01e7\u01ef\u01f1\u01fb\u01fd\u0201\u0207\u0209"+
"\u020f\u022a\u0233\u023b\u023e\u0246\5\b\2\2\4\3\2\4\2\2";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {

View File

@ -67,6 +67,13 @@ class PainlessParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> implement
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitEach(PainlessParser.EachContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitIneach(PainlessParser.IneachContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*

View File

@ -63,6 +63,13 @@ interface PainlessParserVisitor<T> extends ParseTreeVisitor<T> {
* @return the visitor result
*/
T visitEach(PainlessParser.EachContext ctx);
/**
* Visit a parse tree produced by the {@code ineach}
* labeled alternative in {@link PainlessParser#statement}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitIneach(PainlessParser.IneachContext ctx);
/**
* Visit a parse tree produced by the {@code decl}
* labeled alternative in {@link PainlessParser#statement}.

View File

@ -81,6 +81,7 @@ import org.elasticsearch.painless.antlr.PainlessParser.ForContext;
import org.elasticsearch.painless.antlr.PainlessParser.FuncrefContext;
import org.elasticsearch.painless.antlr.PainlessParser.FunctionContext;
import org.elasticsearch.painless.antlr.PainlessParser.IfContext;
import org.elasticsearch.painless.antlr.PainlessParser.IneachContext;
import org.elasticsearch.painless.antlr.PainlessParser.InitializerContext;
import org.elasticsearch.painless.antlr.PainlessParser.InstanceofContext;
import org.elasticsearch.painless.antlr.PainlessParser.LambdaContext;
@ -358,6 +359,17 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
return new SEach(location(ctx), type, name, expression, block);
}
@Override
public Object visitIneach(IneachContext ctx) {
reserved.peek().setMaxLoopCounter(settings.getMaxLoopCounter());
String name = ctx.ID().getText();
AExpression expression = (AExpression)visitExpression(ctx.expression());
SBlock block = (SBlock)visit(ctx.trailer());
return new SEach(location(ctx), "def", name, expression, block);
}
@Override
public Object visitDecl(DeclContext ctx) {

View File

@ -158,6 +158,7 @@ public class SFunction extends AStatement {
access |= Opcodes.ACC_SYNTHETIC;
}
final MethodWriter function = new MethodWriter(access, method.method, writer, globals.getStatements(), settings);
function.visitCode();
write(function, globals);
function.endMethod();
}

View File

@ -31,6 +31,7 @@ import org.elasticsearch.painless.node.SFunction.Reserved;
import org.elasticsearch.painless.WriterConstants;
import org.elasticsearch.painless.Location;
import org.elasticsearch.painless.MethodWriter;
import org.elasticsearch.painless.SimpleChecksAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
@ -146,7 +147,6 @@ public final class SSource extends AStatement {
// Create the ClassWriter.
int classFrames = ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS;
int classVersion = Opcodes.V1_8;
int classAccess = Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_FINAL;
String classBase = BASE_CLASS_TYPE.getInternalName();
String className = CLASS_TYPE.getInternalName();
@ -155,10 +155,15 @@ public final class SSource extends AStatement {
ClassWriter writer = new ClassWriter(classFrames);
ClassVisitor visitor = writer;
// if picky is enabled, turn on some checks. instead of VerifyError at the end, you get a helpful stacktrace.
if (settings.isPicky()) {
visitor = new SimpleChecksAdapter(visitor);
}
if (debugStream != null) {
visitor = new TraceClassVisitor(visitor, debugStream, null);
}
visitor.visit(classVersion, classAccess, className, null, classBase, classInterfaces);
visitor.visit(WriterConstants.CLASS_VERSION, classAccess, className, null, classBase, classInterfaces);
visitor.visitSource(Location.computeSourceName(name, source), null);
// Write the constructor:
@ -207,6 +212,7 @@ public final class SSource extends AStatement {
// Initialize the constants in a static initializer
final MethodWriter clinit = new MethodWriter(Opcodes.ACC_STATIC,
WriterConstants.CLINIT, visitor, globals.getStatements(), settings);
clinit.visitCode();
for (Constant constant : inits) {
constant.initializer.accept(clinit);
clinit.putStatic(CLASS_TYPE, constant.name, constant.type);

View File

@ -130,39 +130,65 @@ public class BasicStatementTests extends ScriptTestCase {
public void testIterableForEachStatement() {
assertEquals(6, exec("List l = new ArrayList(); l.add(1); l.add(2); l.add(3); int total = 0;" +
" for (int x : l) total += x; return total"));
assertEquals(6, exec("List l = new ArrayList(); l.add(1); l.add(2); l.add(3); int total = 0;" +
" for (x in l) total += x; return total"));
assertEquals("123", exec("List l = new ArrayList(); l.add('1'); l.add('2'); l.add('3'); String cat = '';" +
" for (String x : l) cat += x; return cat"));
assertEquals("123", exec("List l = new ArrayList(); l.add('1'); l.add('2'); l.add('3'); String cat = '';" +
" for (x in l) cat += x; return cat"));
assertEquals("1236", exec("Map m = new HashMap(); m.put('1', 1); m.put('2', 2); m.put('3', 3);" +
" String cat = ''; int total = 0;" +
" for (Map.Entry e : m.entrySet()) { cat += e.getKey(); total += e.getValue(); } return cat + total"));
assertEquals("1236", exec("Map m = new HashMap(); m.put('1', 1); m.put('2', 2); m.put('3', 3);" +
" String cat = ''; int total = 0;" +
" for (e in m.entrySet()) { cat += e.getKey(); total += e.getValue(); } return cat + total"));
}
public void testIterableForEachStatementDef() {
assertEquals(6, exec("def l = new ArrayList(); l.add(1); l.add(2); l.add(3); int total = 0;" +
" for (int x : l) total += x; return total"));
assertEquals(6, exec("def l = new ArrayList(); l.add(1); l.add(2); l.add(3); int total = 0;" +
" for (x in l) total += x; return total"));
assertEquals("123", exec("def l = new ArrayList(); l.add('1'); l.add('2'); l.add('3'); String cat = '';" +
" for (String x : l) cat += x; return cat"));
assertEquals("123", exec("def l = new ArrayList(); l.add('1'); l.add('2'); l.add('3'); String cat = '';" +
" for (x in l) cat += x; return cat"));
assertEquals("1236", exec("def m = new HashMap(); m.put('1', 1); m.put('2', 2); m.put('3', 3);" +
" String cat = ''; int total = 0;" +
" for (Map.Entry e : m.entrySet()) { cat += e.getKey(); total += e.getValue(); } return cat + total"));
assertEquals("1236", exec("def m = new HashMap(); m.put('1', 1); m.put('2', 2); m.put('3', 3);" +
" String cat = ''; int total = 0;" +
" for (e in m.entrySet()) { cat += e.getKey(); total += e.getValue(); } return cat + total"));
}
public void testArrayForEachStatement() {
assertEquals(6, exec("int[] a = new int[3]; a[0] = 1; a[1] = 2; a[2] = 3; int total = 0;" +
" for (int x : a) total += x; return total"));
assertEquals(6, exec("int[] a = new int[3]; a[0] = 1; a[1] = 2; a[2] = 3; int total = 0;" +
" for (x in a) total += x; return total"));
assertEquals("123", exec("String[] a = new String[3]; a[0] = '1'; a[1] = '2'; a[2] = '3'; def total = '';" +
" for (String x : a) total += x; return total"));
assertEquals("123", exec("String[] a = new String[3]; a[0] = '1'; a[1] = '2'; a[2] = '3'; def total = '';" +
" for (x in a) total += x; return total"));
assertEquals(6, exec("int[][] i = new int[3][1]; i[0][0] = 1; i[1][0] = 2; i[2][0] = 3; int total = 0;" +
" for (int[] j : i) total += j[0]; return total"));
assertEquals(6, exec("int[][] i = new int[3][1]; i[0][0] = 1; i[1][0] = 2; i[2][0] = 3; int total = 0;" +
" for (j in i) total += j[0]; return total"));
}
public void testArrayForEachStatementDef() {
assertEquals(6, exec("def a = new int[3]; a[0] = 1; a[1] = 2; a[2] = 3; int total = 0;" +
" for (int x : a) total += x; return total"));
assertEquals(6, exec("def a = new int[3]; a[0] = 1; a[1] = 2; a[2] = 3; int total = 0;" +
" for (x in a) total += x; return total"));
assertEquals("123", exec("def a = new String[3]; a[0] = '1'; a[1] = '2'; a[2] = '3'; def total = '';" +
" for (String x : a) total += x; return total"));
assertEquals("123", exec("def a = new String[3]; a[0] = '1'; a[1] = '2'; a[2] = '3'; def total = '';" +
" for (x in a) total += x; return total"));
assertEquals(6, exec("def i = new int[3][1]; i[0][0] = 1; i[1][0] = 2; i[2][0] = 3; int total = 0;" +
" for (int[] j : i) total += j[0]; return total"));
assertEquals(6, exec("def i = new int[3][1]; i[0][0] = 1; i[1][0] = 2; i[2][0] = 3; int total = 0;" +
" for (j in i) total += j[0]; return total"));
}
public void testDeclarationStatement() {

View File

@ -79,7 +79,7 @@ public class LambdaTests extends ScriptTestCase {
}
public void testMultipleStatements() {
assertEquals(2, exec("int applyOne(IntFunction arg) { arg.apply(1) } applyOne(x -> { x = x + 1; return x })"));
assertEquals(2, exec("int applyOne(IntFunction arg) { arg.apply(1) } applyOne(x -> { def y = x + 1; return y })"));
}
public void testUnneededCurlyStatements() {
@ -138,6 +138,7 @@ public class LambdaTests extends ScriptTestCase {
assertTrue(expected.getMessage().contains("is read-only"));
}
@AwaitsFix(bugUrl = "def type tracking")
public void testOnlyCapturesAreReadOnly() {
assertEquals(4, exec("List l = new ArrayList(); l.add(1); l.add(1); "
+ "return l.stream().mapToInt(x -> { x += 1; return x }).sum();"));