From 5ddf1ed2901983f36d5480cae213dfed5008c119 Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Wed, 25 Mar 2026 13:42:38 +0100 Subject: [PATCH 01/14] feat(#510): add VIRAL_ATTRIBUTE role to data model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add VIRAL_ATTRIBUTE = "Viral Attribute" to Role enum and Role_keys - Add get_viral_attributes() and get_viral_attributes_names() to Dataset - Fix _InternalApi.py: convert "ViralAttribute" → "Viral Attribute" (both loading paths) - Fix nullable default to include VIRAL_ATTRIBUTE - Add "ViralAttribute" to JSON schema for backward compatibility - Update existing test to expect VIRAL_ATTRIBUTE instead of ATTRIBUTE --- src/vtlengine/API/_InternalApi.py | 10 ++- .../API/data/schema/json_schema_2.1.json | 2 +- src/vtlengine/Model/__init__.py | 18 +++++- tests/API/test_api.py | 2 +- tests/ViralAttributes/__init__.py | 0 tests/ViralAttributes/test_viral_role.py | 62 +++++++++++++++++++ 6 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 tests/ViralAttributes/__init__.py create mode 100644 tests/ViralAttributes/test_viral_role.py diff --git a/src/vtlengine/API/_InternalApi.py b/src/vtlengine/API/_InternalApi.py index 8b179d196..2ee2749f4 100644 --- a/src/vtlengine/API/_InternalApi.py +++ b/src/vtlengine/API/_InternalApi.py @@ -119,14 +119,18 @@ def _load_dataset_from_structure( # Support both 'type' and 'data_type' for backward compatibility _, scalar_type = _extract_data_type(component) if component["role"] == "ViralAttribute": - component["role"] = "Attribute" + component["role"] = "Viral Attribute" check_key("role", Role_keys, component["role"]) if "nullable" not in component: if Role(component["role"]) == Role.IDENTIFIER: component["nullable"] = False - elif Role(component["role"]) in (Role.MEASURE, Role.ATTRIBUTE): + elif Role(component["role"]) in ( + Role.MEASURE, + Role.ATTRIBUTE, + Role.VIRAL_ATTRIBUTE, + ): component["nullable"] = True else: component["nullable"] = False @@ -142,6 +146,8 @@ def _load_dataset_from_structure( for component in dataset_json["DataStructure"]: # Support both 'type' and 'data_type' for backward compatibility _, scalar_type = _extract_data_type(component) + if component["role"] == "ViralAttribute": + component["role"] = "Viral Attribute" check_key("role", Role_keys, component["role"]) components[component["name"]] = VTL_Component( name=component["name"], diff --git a/src/vtlengine/API/data/schema/json_schema_2.1.json b/src/vtlengine/API/data/schema/json_schema_2.1.json index 8933cf189..779c273b3 100644 --- a/src/vtlengine/API/data/schema/json_schema_2.1.json +++ b/src/vtlengine/API/data/schema/json_schema_2.1.json @@ -48,7 +48,7 @@ "properties": { "role": { "type": "string", - "enum": [ "Identifier", "Measure", "Attribute", "Viral Attribute" ] + "enum": [ "Identifier", "Measure", "Attribute", "Viral Attribute", "ViralAttribute" ] }, "subset": { "$ref": "#/$defs/vtl-id" }, "nullable": { "type": "boolean" }, diff --git a/src/vtlengine/Model/__init__.py b/src/vtlengine/Model/__init__.py index 70664027d..780fa2bb7 100644 --- a/src/vtlengine/Model/__init__.py +++ b/src/vtlengine/Model/__init__.py @@ -85,17 +85,19 @@ def __eq__(self, other: Any) -> bool: "Identifier", "Attribute", "Measure", + "Viral Attribute", ] class Role(Enum): """ - Enum class for the role of a component (Identifier, Attribute, Measure) + Enum class for the role of a component (Identifier, Attribute, Measure, Viral Attribute) """ IDENTIFIER = "Identifier" ATTRIBUTE = "Attribute" MEASURE = "Measure" + VIRAL_ATTRIBUTE = "Viral Attribute" @dataclass @@ -374,6 +376,20 @@ def get_measures_names(self) -> List[str]: name for name, component in self.components.items() if component.role == Role.MEASURE ] + def get_viral_attributes(self) -> List[Component]: + return [ + component + for component in self.components.values() + if component.role == Role.VIRAL_ATTRIBUTE + ] + + def get_viral_attributes_names(self) -> List[str]: + return [ + name + for name, component in self.components.items() + if component.role == Role.VIRAL_ATTRIBUTE + ] + def get_components_names(self) -> List[str]: return list(self.components.keys()) diff --git a/tests/API/test_api.py b/tests/API/test_api.py index d27632614..c06413212 100644 --- a/tests/API/test_api.py +++ b/tests/API/test_api.py @@ -1515,7 +1515,7 @@ def test_load_data_structure_with_new_schema(data_structure): "At_1": Component( name="At_1", data_type=DataTypes.String, - role=Role.ATTRIBUTE, + role=Role.VIRAL_ATTRIBUTE, nullable=True, ), }, diff --git a/tests/ViralAttributes/__init__.py b/tests/ViralAttributes/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ViralAttributes/test_viral_role.py b/tests/ViralAttributes/test_viral_role.py new file mode 100644 index 000000000..693d23dfa --- /dev/null +++ b/tests/ViralAttributes/test_viral_role.py @@ -0,0 +1,62 @@ +import pandas as pd + +from vtlengine.DataTypes import Integer, Number, String +from vtlengine.Model import Component, Dataset, Role, Role_keys + + +class TestViralAttributeRole: + def test_viral_attribute_in_role_enum(self): + assert Role.VIRAL_ATTRIBUTE.value == "Viral Attribute" + + def test_viral_attribute_in_role_keys(self): + assert "Viral Attribute" in Role_keys + + def test_component_with_viral_attribute_role(self): + comp = Component( + name="At_1", + data_type=String, + role=Role.VIRAL_ATTRIBUTE, + nullable=True, + ) + assert comp.role == Role.VIRAL_ATTRIBUTE + + def test_dataset_get_viral_attributes(self): + ds = Dataset( + name="DS_1", + components={ + "Id_1": Component("Id_1", Integer, Role.IDENTIFIER, False), + "Me_1": Component("Me_1", Number, Role.MEASURE, True), + "At_1": Component("At_1", String, Role.VIRAL_ATTRIBUTE, True), + }, + data=pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]}), + ) + viral_attrs = ds.get_viral_attributes() + assert len(viral_attrs) == 1 + assert viral_attrs[0].name == "At_1" + + def test_dataset_get_viral_attributes_names(self): + ds = Dataset( + name="DS_1", + components={ + "Id_1": Component("Id_1", Integer, Role.IDENTIFIER, False), + "At_1": Component("At_1", String, Role.VIRAL_ATTRIBUTE, True), + }, + data=pd.DataFrame({"Id_1": [1], "At_1": ["A"]}), + ) + assert ds.get_viral_attributes_names() == ["At_1"] + + def test_get_attributes_excludes_viral(self): + """get_attributes() must NOT return VIRAL_ATTRIBUTE components.""" + ds = Dataset( + name="DS_1", + components={ + "Id_1": Component("Id_1", Integer, Role.IDENTIFIER, False), + "At_1": Component("At_1", String, Role.ATTRIBUTE, True), + "At_2": Component("At_2", String, Role.VIRAL_ATTRIBUTE, True), + }, + data=pd.DataFrame({"Id_1": [1], "At_1": ["A"], "At_2": ["B"]}), + ) + attrs = ds.get_attributes() + assert len(attrs) == 1 + assert attrs[0].name == "At_1" + assert "At_2" not in ds.get_attributes_names() From ada98479c40e38bc8ee944cdfc0416bd7cc75a77 Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Wed, 25 Mar 2026 13:46:54 +0100 Subject: [PATCH 02/14] feat(#510): implement visitViralAttribute and ViralAttribute role setter - Replace NotImplementedError in visitViralAttribute with return Role.VIRAL_ATTRIBUTE - Add ViralAttribute class to RoleSetter.py - Add VIRAL_ATTRIBUTE to ROLE_SETTER_MAPPING in Utils - Fix VIRAL_ATTRIBUTE token to match "viral attribute" (lowered Role.value) --- .../AST/ASTConstructorModules/Terminals.py | 6 +- src/vtlengine/AST/Grammar/tokens.py | 2 +- src/vtlengine/Operators/RoleSetter.py | 4 + src/vtlengine/Utils/__init__.py | 4 +- tests/ViralAttributes/test_viral_calc.py | 104 ++++++++++++++++++ 5 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 tests/ViralAttributes/test_viral_calc.py diff --git a/src/vtlengine/AST/ASTConstructorModules/Terminals.py b/src/vtlengine/AST/ASTConstructorModules/Terminals.py index 0f0f3d24e..01770cd0e 100644 --- a/src/vtlengine/AST/ASTConstructorModules/Terminals.py +++ b/src/vtlengine/AST/ASTConstructorModules/Terminals.py @@ -263,11 +263,7 @@ def visitViralAttribute(self, ctx: Parser.ViralAttributeContext): """ viralAttribute: VIRAL ATTRIBUTE; """ - # ctx_list = list(ctx.getChildren()) - # c = ctx_list[0] - # token = c.getSymbol() - - raise NotImplementedError + return Role.VIRAL_ATTRIBUTE def visitLists(self, ctx: Parser.ListsContext): """ diff --git a/src/vtlengine/AST/Grammar/tokens.py b/src/vtlengine/AST/Grammar/tokens.py index 94a7979ae..c7a2e8a3b 100644 --- a/src/vtlengine/AST/Grammar/tokens.py +++ b/src/vtlengine/AST/Grammar/tokens.py @@ -133,7 +133,7 @@ IDENTIFIER = "identifier" MEASURE = "measure" ATTRIBUTE = "attribute" -VIRAL_ATTRIBUTE = "viral" +VIRAL_ATTRIBUTE = "viral attribute" # Other Operators. TO = "to" AS = "as" diff --git a/src/vtlengine/Operators/RoleSetter.py b/src/vtlengine/Operators/RoleSetter.py index a3c8e8569..a5602d79a 100644 --- a/src/vtlengine/Operators/RoleSetter.py +++ b/src/vtlengine/Operators/RoleSetter.py @@ -71,3 +71,7 @@ class Attribute(RoleSetter): class Measure(RoleSetter): role = Role.MEASURE + + +class ViralAttribute(RoleSetter): + role = Role.VIRAL_ATTRIBUTE diff --git a/src/vtlengine/Utils/__init__.py b/src/vtlengine/Utils/__init__.py index eb2fe1afb..18ab2b6ae 100644 --- a/src/vtlengine/Utils/__init__.py +++ b/src/vtlengine/Utils/__init__.py @@ -94,6 +94,7 @@ UNPIVOT, VAR_POP, VAR_SAMP, + VIRAL_ATTRIBUTE, XOR, YEAR, YEARTODAY, @@ -206,7 +207,7 @@ UnMinus, UnPlus, ) -from vtlengine.Operators.RoleSetter import Attribute, Identifier, Measure +from vtlengine.Operators.RoleSetter import Attribute, Identifier, Measure, ViralAttribute from vtlengine.Operators.Set import Intersection, Setdiff, Symdiff, Union from vtlengine.Operators.String import ( Concatenate, @@ -326,6 +327,7 @@ IDENTIFIER: Identifier, ATTRIBUTE: Attribute, MEASURE: Measure, + VIRAL_ATTRIBUTE: ViralAttribute, } REGULAR_AGGREGATION_MAPPING = { diff --git a/tests/ViralAttributes/test_viral_calc.py b/tests/ViralAttributes/test_viral_calc.py new file mode 100644 index 000000000..bb6714d2f --- /dev/null +++ b/tests/ViralAttributes/test_viral_calc.py @@ -0,0 +1,104 @@ +import pandas as pd + +from vtlengine import run +from vtlengine.Model import Role + + +class TestViralAttributeCalc: + def test_calc_viral_attribute(self): + """Test that 'viral attribute' role setter works in calc clause.""" + script = """ + DS_r <- DS_1 [calc viral attribute At_1 := "X"]; + """ + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + ], + } + ] + } + datapoints = {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0]})} + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE + assert list(ds_r.data["At_1"]) == ["X", "X"] + + def test_input_viral_attribute_loaded(self): + """Test that a viral attribute in input data structure is correctly loaded.""" + script = """ + DS_r <- DS_1; + """ + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + } + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE + assert list(ds_r.data["At_1"]) == ["A", "B"] + + def test_input_viral_attribute_legacy_format(self): + """Test that 'ViralAttribute' (legacy format) is correctly loaded.""" + script = """ + DS_r <- DS_1; + """ + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + { + "name": "At_1", + "type": "String", + "role": "ViralAttribute", + "nullable": True, + }, + ], + } + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE From fd587b38a2fb91627f4ae95671df2c1fb72aaa27 Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Wed, 25 Mar 2026 14:25:25 +0100 Subject: [PATCH 03/14] feat(#510): propagate viral attributes through binary operators - Update Binary.dataset_validation() to keep VIRAL_ATTRIBUTE components - Collect viral attributes from both operands (not just base_operand) - Extract _cleanup_attributes_after_merge() for viral attr suffix handling - Update dataset_scalar_validation/evaluation to keep viral attr columns --- src/vtlengine/Operators/__init__.py | 73 +++++-- tests/ViralAttributes/test_viral_binary.py | 220 +++++++++++++++++++++ 2 files changed, 276 insertions(+), 17 deletions(-) create mode 100644 tests/ViralAttributes/test_viral_binary.py diff --git a/src/vtlengine/Operators/__init__.py b/src/vtlengine/Operators/__init__.py index 5d35bf2d8..921f7b74e 100644 --- a/src/vtlengine/Operators/__init__.py +++ b/src/vtlengine/Operators/__init__.py @@ -323,11 +323,16 @@ def dataset_validation(cls, left_operand: Dataset, right_operand: Dataset) -> Da # Deleting extra identifiers that we do not need anymore base_operand = right_operand if use_right_components else left_operand + other_operand = left_operand if use_right_components else right_operand result_components = { component_name: copy(component) for component_name, component in base_operand.components.items() - if component.role in [Role.IDENTIFIER, Role.MEASURE] + if component.role in [Role.IDENTIFIER, Role.MEASURE, Role.VIRAL_ATTRIBUTE] } + # Also include viral attributes from the other operand + for comp_name, comp in other_operand.components.items(): + if comp.role == Role.VIRAL_ATTRIBUTE and comp_name not in result_components: + result_components[comp_name] = copy(comp) for comp in [x for x in result_components.values() if x.role == Role.MEASURE]: if comp.name in left_operand.components and comp.name in right_operand.components: @@ -348,7 +353,7 @@ def dataset_scalar_validation(cls, dataset: Dataset, scalar: Scalar) -> Dataset: result_components = { comp_name: copy(comp) for comp_name, comp in dataset.components.items() - if comp.role in [Role.IDENTIFIER, Role.MEASURE] + if comp.role in [Role.IDENTIFIER, Role.MEASURE, Role.VIRAL_ATTRIBUTE] } result_dataset = Dataset(name=dataset_name, components=result_components, data=None) cls.apply_return_type_dataset(result_dataset, dataset, scalar) @@ -413,7 +418,7 @@ def dataset_set_validation(cls, dataset: Dataset, scalar_set: ScalarSet) -> Data result_components = { comp_name: copy(comp) for comp_name, comp in dataset.components.items() - if comp.role in [Role.IDENTIFIER, Role.MEASURE] + if comp.role in [Role.IDENTIFIER, Role.MEASURE, Role.VIRAL_ATTRIBUTE] } result_dataset = Dataset(name=dataset_name, components=result_components, data=None) @@ -515,6 +520,42 @@ def apply_return_type_dataset( else: measure.data_type = result_data_type + @staticmethod + def _cleanup_attributes_after_merge( + result_data: pd.DataFrame, + left_operand: Dataset, + right_operand: Dataset, + ) -> pd.DataFrame: + """Remove non-viral attributes and resolve viral attribute merge suffixes.""" + # Delete non-viral attributes from the result data + attributes = list( + set(left_operand.get_attributes_names()).union(right_operand.get_attributes_names()) + ) + for att in attributes: + if att in result_data.columns: + result_data = result_data.drop(att, axis=1) + if att + "_x" in result_data.columns: + result_data = result_data.drop(att + "_x", axis=1) + if att + "_y" in result_data.columns: + result_data = result_data.drop(att + "_y", axis=1) + + # Handle viral attribute merge suffixes + left_viral = set(left_operand.get_viral_attributes_names()) + right_viral = set(right_operand.get_viral_attributes_names()) + all_viral = left_viral | right_viral + for va in all_viral: + has_x = va + "_x" in result_data.columns + has_y = va + "_y" in result_data.columns + if has_x and has_y: + # Both operands have this viral attr; keep left value + result_data[va] = result_data[va + "_x"] + result_data = result_data.drop([va + "_x", va + "_y"], axis=1) + elif has_x: + result_data = result_data.rename(columns={va + "_x": va}) + elif has_y: + result_data = result_data.rename(columns={va + "_y": va}) + return result_data + @classmethod def dataset_evaluation(cls, left_operand: Dataset, right_operand: Dataset) -> Dataset: result_dataset = cls.dataset_validation(left_operand, right_operand) @@ -611,17 +652,7 @@ def _cast_y(v: Any, ft: Any = y_type) -> Any: result_data[measure.name] = result_data[measure.name].astype(target) # type: ignore[call-overload] result_data = result_data.drop([measure.name + "_x", measure.name + "_y"], axis=1) - # Delete attributes from the result data - attributes = list( - set(left_operand.get_attributes_names()).union(right_operand.get_attributes_names()) - ) - for att in attributes: - if att in result_data.columns: - result_data = result_data.drop(att, axis=1) - if att + "_x" in result_data.columns: - result_data = result_data.drop(att + "_x", axis=1) - if att + "_y" in result_data.columns: - result_data = result_data.drop(att + "_y", axis=1) + result_data = cls._cleanup_attributes_after_merge(result_data, left_operand, right_operand) result_dataset.data = result_data cls.modify_measure_column(result_dataset) @@ -666,7 +697,11 @@ def dataset_scalar_evaluation( ].astype(target) result_dataset.data = result_data - cols_to_keep = dataset.get_identifiers_names() + dataset.get_measures_names() + cols_to_keep = ( + dataset.get_identifiers_names() + + dataset.get_measures_names() + + dataset.get_viral_attributes_names() + ) result_dataset.data = result_dataset.data[cols_to_keep] cls.modify_measure_column(result_dataset) return result_dataset @@ -821,7 +856,7 @@ def dataset_validation(cls, operand: Dataset) -> Dataset: result_components = { comp_name: copy(comp) for comp_name, comp in operand.components.items() - if comp.role in [Role.IDENTIFIER, Role.MEASURE] + if comp.role in [Role.IDENTIFIER, Role.MEASURE, Role.VIRAL_ATTRIBUTE] } result_dataset = Dataset(name=dataset_name, components=result_components, data=None) @@ -930,7 +965,11 @@ def dataset_evaluation(cls, operand: Dataset) -> Dataset: if str(result_data[measure_name].dtype) != target: result_data[measure_name] = result_data[measure_name].astype(target) # type: ignore[call-overload] - cols_to_keep = operand.get_identifiers_names() + operand.get_measures_names() + cols_to_keep = ( + operand.get_identifiers_names() + + operand.get_measures_names() + + operand.get_viral_attributes_names() + ) result_data = result_data[cols_to_keep] result_dataset.data = result_data diff --git a/tests/ViralAttributes/test_viral_binary.py b/tests/ViralAttributes/test_viral_binary.py new file mode 100644 index 000000000..b56e0047f --- /dev/null +++ b/tests/ViralAttributes/test_viral_binary.py @@ -0,0 +1,220 @@ +import pandas as pd + +from vtlengine import run +from vtlengine.Model import Role + + +class TestViralAttributeBinaryOps: + def test_binary_propagation_single_viral_attribute(self): + """Viral attribute from one operand is kept in result with same values.""" + script = "DS_r <- DS_1 + DS_2;" + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Me_1", + "type": "Number", + "role": "Measure", + "nullable": True, + }, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + }, + { + "name": "DS_2", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Me_1", + "type": "Number", + "role": "Measure", + "nullable": True, + }, + ], + }, + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), + "DS_2": pd.DataFrame({"Id_1": [1, 2], "Me_1": [5.0, 15.0]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE + assert list(ds_r.data["At_1"]) == ["A", "B"] + + def test_binary_non_viral_attribute_still_dropped(self): + """Non-viral (regular) attributes are still dropped as before.""" + script = "DS_r <- DS_1 + DS_2;" + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Me_1", + "type": "Number", + "role": "Measure", + "nullable": True, + }, + { + "name": "At_1", + "type": "String", + "role": "Attribute", + "nullable": True, + }, + ], + }, + { + "name": "DS_2", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Me_1", + "type": "Number", + "role": "Measure", + "nullable": True, + }, + ], + }, + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), + "DS_2": pd.DataFrame({"Id_1": [1, 2], "Me_1": [5.0, 15.0]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" not in ds_r.components + + def test_binary_dataset_scalar_keeps_viral_attr(self): + """DS_r <- DS_1 + 5 where DS_1 has a viral attribute.""" + script = "DS_r <- DS_1 + 5;" + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Me_1", + "type": "Number", + "role": "Measure", + "nullable": True, + }, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + }, + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE + assert list(ds_r.data["At_1"]) == ["A", "B"] + + def test_binary_both_operands_viral_keeps_left(self): + """When both operands have the same viral attr, keep left value.""" + script = "DS_r <- DS_1 + DS_2;" + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Me_1", + "type": "Number", + "role": "Measure", + "nullable": True, + }, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + }, + { + "name": "DS_2", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Me_1", + "type": "Number", + "role": "Measure", + "nullable": True, + }, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + }, + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), + "DS_2": pd.DataFrame({"Id_1": [1, 2], "Me_1": [5.0, 15.0], "At_1": ["X", "Y"]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + # Left operand values kept when no propagation rule + assert list(ds_r.data["At_1"]) == ["A", "B"] From 50cadbc4ba61a2db884b2b6c5b30442abb41dfce Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Wed, 25 Mar 2026 14:25:32 +0100 Subject: [PATCH 04/14] feat(#510): propagate viral attributes through unary operators - Update Unary.dataset_validation() to keep VIRAL_ATTRIBUTE components - Update Unary.dataset_evaluation() to include viral attr in cols_to_keep - Add parametrized tests for numeric, string, boolean, and comparison ops --- tests/ViralAttributes/test_viral_unary.py | 189 ++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 tests/ViralAttributes/test_viral_unary.py diff --git a/tests/ViralAttributes/test_viral_unary.py b/tests/ViralAttributes/test_viral_unary.py new file mode 100644 index 000000000..6e239c1ec --- /dev/null +++ b/tests/ViralAttributes/test_viral_unary.py @@ -0,0 +1,189 @@ +import pandas as pd +import pytest + +from vtlengine import run +from vtlengine.Model import Role + +NUMERIC_UNARY_OPS = [ + ("abs", "Number", [10.0, -20.0]), + ("ceil", "Number", [1.1, 2.9]), + ("floor", "Number", [1.1, 2.9]), + ("ln", "Number", [1.0, 2.718]), + ("exp", "Number", [0.0, 1.0]), + ("sqrt", "Number", [4.0, 9.0]), +] + +STRING_UNARY_OPS = [ + ("upper", "String", ["abc", "def"]), + ("lower", "String", ["ABC", "DEF"]), + ("trim", "String", [" abc ", " def "]), + ("ltrim", "String", [" abc", " def"]), + ("rtrim", "String", ["abc ", "def "]), + ("length", "String", ["abc", "defgh"]), +] + + +class TestViralAttributeUnaryOps: + @pytest.mark.parametrize( + "op,me_type,me_values", + NUMERIC_UNARY_OPS, + ids=[x[0] for x in NUMERIC_UNARY_OPS], + ) + def test_numeric_unary_preserves_viral_attr( + self, op: str, me_type: str, me_values: list + ) -> None: + script = f"DS_r <- {op}(DS_1);" + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Me_1", + "type": me_type, + "role": "Measure", + "nullable": True, + }, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + } + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": me_values, "At_1": ["A", "B"]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE + assert list(ds_r.data["At_1"]) == ["A", "B"] + + @pytest.mark.parametrize( + "op,me_type,me_values", + STRING_UNARY_OPS, + ids=[x[0] for x in STRING_UNARY_OPS], + ) + def test_string_unary_preserves_viral_attr( + self, op: str, me_type: str, me_values: list + ) -> None: + script = f"DS_r <- {op}(DS_1);" + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Me_1", + "type": me_type, + "role": "Measure", + "nullable": True, + }, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + } + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": me_values, "At_1": ["A", "B"]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE + assert list(ds_r.data["At_1"]) == ["A", "B"] + + def test_not_preserves_viral_attr(self) -> None: + script = "DS_r <- not DS_1;" + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Me_1", + "type": "Boolean", + "role": "Measure", + "nullable": True, + }, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + } + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [True, False], "At_1": ["A", "B"]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE + + def test_isnull_preserves_viral_attr(self) -> None: + script = "DS_r <- isnull(DS_1);" + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Me_1", + "type": "Number", + "role": "Measure", + "nullable": True, + }, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + } + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, None], "At_1": ["A", "B"]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE From 8df105efbbe8749d35977cee7836262bd2cf0723 Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Wed, 25 Mar 2026 14:25:41 +0100 Subject: [PATCH 05/14] feat(#510): propagate viral attributes through remaining operators - Update Between, Time_Aggregation, Check, Membership to keep VIRAL_ATTRIBUTE - Update Set operators (Intersection, Symdiff) to include viral attr columns - Update Interpreter HAVING clause to preserve VIRAL_ATTRIBUTE - Verified Aggregation, Nvl, Check_Hierarchy already correct (no changes needed) --- src/vtlengine/Interpreter/__init__.py | 3 +- src/vtlengine/Operators/Comparison.py | 2 +- src/vtlengine/Operators/General.py | 4 +- src/vtlengine/Operators/Set.py | 12 +- src/vtlengine/Operators/Time.py | 2 +- src/vtlengine/Operators/Validation.py | 2 +- .../test_viral_remaining_ops.py | 158 ++++++++++++++++++ 7 files changed, 176 insertions(+), 7 deletions(-) create mode 100644 tests/ViralAttributes/test_viral_remaining_ops.py diff --git a/src/vtlengine/Interpreter/__init__.py b/src/vtlengine/Interpreter/__init__.py index 1492a5fea..664cb5139 100644 --- a/src/vtlengine/Interpreter/__init__.py +++ b/src/vtlengine/Interpreter/__init__.py @@ -1263,7 +1263,8 @@ def visit_ParamOp(self, node: AST.ParamOp) -> None: # noqa: C901 self.aggregation_dataset.components = { comp_name: deepcopy(comp) for comp_name, comp in self.aggregation_dataset.components.items() - if comp_name in self.aggregation_grouping or comp.role == Role.MEASURE + if comp_name in self.aggregation_grouping + or comp.role in [Role.MEASURE, Role.VIRAL_ATTRIBUTE] } self.aggregation_dataset.data = ( diff --git a/src/vtlengine/Operators/Comparison.py b/src/vtlengine/Operators/Comparison.py index 78e8aa686..de2e2e1da 100644 --- a/src/vtlengine/Operators/Comparison.py +++ b/src/vtlengine/Operators/Comparison.py @@ -367,7 +367,7 @@ def validate( result_components = { comp_name: copy(comp) for comp_name, comp in operand.components.items() - if comp.role == Role.IDENTIFIER or comp.role == Role.MEASURE + if comp.role in [Role.IDENTIFIER, Role.MEASURE, Role.VIRAL_ATTRIBUTE] } result = Dataset(name=operand.name, components=result_components, data=None) elif isinstance(operand, DataComponent): diff --git a/src/vtlengine/Operators/General.py b/src/vtlengine/Operators/General.py index b660f7ac5..33f7656b8 100644 --- a/src/vtlengine/Operators/General.py +++ b/src/vtlengine/Operators/General.py @@ -48,7 +48,9 @@ def validate(cls, left_operand: Any, right_operand: Any) -> Dataset: result_components = { name: comp for name, comp in left_operand.components.items() - if comp.role == Role.IDENTIFIER or comp.name == right_operand + if comp.role == Role.IDENTIFIER + or comp.name == right_operand + or comp.role == Role.VIRAL_ATTRIBUTE } result_dataset = Dataset(name=dataset_name, components=result_components, data=None) return result_dataset diff --git a/src/vtlengine/Operators/Set.py b/src/vtlengine/Operators/Set.py index d9826ad88..0208489af 100644 --- a/src/vtlengine/Operators/Set.py +++ b/src/vtlengine/Operators/Set.py @@ -85,7 +85,11 @@ def evaluate(cls, operands: List[Dataset]) -> Dataset: data, how="inner", on=result.get_identifiers_names() ) - not_identifiers = result.get_measures_names() + result.get_attributes_names() + not_identifiers = ( + result.get_measures_names() + + result.get_attributes_names() + + result.get_viral_attributes_names() + ) for col in not_identifiers: result.data[col] = result.data[col + "_x"] @@ -121,7 +125,11 @@ def evaluate(cls, operands: List[Dataset]) -> Dataset: merge_col = merge_col.where(~y_null, "left_only") result.data["_merge"] = merge_col - not_identifiers = result.get_measures_names() + result.get_attributes_names() + not_identifiers = ( + result.get_measures_names() + + result.get_attributes_names() + + result.get_viral_attributes_names() + ) left_mask = result.data["_merge"] == "left_only" right_mask = result.data["_merge"] == "right_only" for col in not_identifiers: diff --git a/src/vtlengine/Operators/Time.py b/src/vtlengine/Operators/Time.py index b8ed60dd6..0268ec0c1 100644 --- a/src/vtlengine/Operators/Time.py +++ b/src/vtlengine/Operators/Time.py @@ -691,7 +691,7 @@ def dataset_validation( result_components = { comp.name: comp for comp in operand.components.values() - if comp.role in [Role.IDENTIFIER, Role.MEASURE] + if comp.role in [Role.IDENTIFIER, Role.MEASURE, Role.VIRAL_ATTRIBUTE] } return Dataset(name=operand.name, components=result_components, data=None) diff --git a/src/vtlengine/Operators/Validation.py b/src/vtlengine/Operators/Validation.py index 7c89d6273..140632594 100644 --- a/src/vtlengine/Operators/Validation.py +++ b/src/vtlengine/Operators/Validation.py @@ -66,7 +66,7 @@ def validate( result_components = { comp.name: comp for comp in validation_element.components.values() - if comp.role in [Role.IDENTIFIER, Role.MEASURE] + if comp.role in [Role.IDENTIFIER, Role.MEASURE, Role.VIRAL_ATTRIBUTE] } if imbalance_measure is None: result_components["imbalance"] = Component( diff --git a/tests/ViralAttributes/test_viral_remaining_ops.py b/tests/ViralAttributes/test_viral_remaining_ops.py new file mode 100644 index 000000000..1674b882d --- /dev/null +++ b/tests/ViralAttributes/test_viral_remaining_ops.py @@ -0,0 +1,158 @@ +import pandas as pd + +from vtlengine import run +from vtlengine.Model import Role + + +class TestViralAttributeAggregation: + def test_aggregation_keeps_viral_attribute(self): + script = "DS_r <- sum(DS_1 group by Id_1);" + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Id_2", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Me_1", + "type": "Number", + "role": "Measure", + "nullable": True, + }, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + } + ] + } + datapoints = { + "DS_1": pd.DataFrame( + { + "Id_1": [1, 1, 2], + "Id_2": [1, 2, 1], + "Me_1": [10.0, 20.0, 30.0], + "At_1": ["A", "A", "B"], + } + ), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE + + +class TestViralAttributeBetween: + def test_between_keeps_viral_attribute(self): + script = "DS_r <- between(DS_1, 5, 25);" + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Me_1", + "type": "Number", + "role": "Measure", + "nullable": True, + }, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + } + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 30.0], "At_1": ["A", "B"]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE + + +class TestViralAttributeSetOps: + def test_intersect_preserves_viral_attribute(self): + script = "DS_r <- intersect(DS_1, DS_2);" + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Me_1", + "type": "Number", + "role": "Measure", + "nullable": True, + }, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + }, + { + "name": "DS_2", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Me_1", + "type": "Number", + "role": "Measure", + "nullable": True, + }, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + }, + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), + "DS_2": pd.DataFrame({"Id_1": [1, 3], "Me_1": [10.0, 30.0], "At_1": ["A", "C"]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE From 81c1eade60b3f08e07ef6a224b0ed571ea410f63 Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Wed, 25 Mar 2026 16:25:20 +0100 Subject: [PATCH 06/14] feat(#510): add define viral propagation grammar rules and AST nodes - Add PROPAGATION token to VtlTokens.g4 - Add defViralPropagation, vpSignature, vpBody, vpClause grammar rules - Regenerate parser/lexer with ANTLR 4.9.3 - Define EnumeratedVpClause, AggregateVpClause, ViralPropagationDef AST nodes - Implement visitor methods in ASTConstructor - Update DAG to accept ViralPropagationDef as top-level statement - Add visit_ViralPropagationDef stub in Interpreter --- src/vtlengine/AST/ASTConstructor.py | 101 + src/vtlengine/AST/DAG/__init__.py | 7 +- src/vtlengine/AST/Grammar/Vtl.g4 | 20 + src/vtlengine/AST/Grammar/VtlTokens.g4 | 1 + src/vtlengine/AST/Grammar/lexer.py | 2322 ++++---- src/vtlengine/AST/Grammar/parser.py | 5948 ++++++++++--------- src/vtlengine/AST/Grammar/tokens.py | 1 + src/vtlengine/AST/VtlVisitor.py | 28 + src/vtlengine/AST/__init__.py | 38 + src/vtlengine/Interpreter/__init__.py | 8 +- tests/ViralAttributes/test_viral_parsing.py | 157 + 11 files changed, 4723 insertions(+), 3908 deletions(-) create mode 100644 tests/ViralAttributes/test_viral_parsing.py diff --git a/src/vtlengine/AST/ASTConstructor.py b/src/vtlengine/AST/ASTConstructor.py index 994661b16..31bdd45c3 100644 --- a/src/vtlengine/AST/ASTConstructor.py +++ b/src/vtlengine/AST/ASTConstructor.py @@ -7,14 +7,18 @@ Node Creator. """ +from typing import List, Optional + from antlr4.tree.Tree import TerminalNodeImpl from vtlengine.AST import ( + AggregateVpClause, Argument, Assignment, DefIdentifier, DPRule, DPRuleset, + EnumeratedVpClause, HRBinOp, HRule, HRuleset, @@ -22,6 +26,7 @@ Operator, PersistentAssignment, Start, + ViralPropagationDef, ) from vtlengine.AST.ASTConstructorModules import extract_token_info from vtlengine.AST.ASTConstructorModules.Expr import Expr @@ -150,6 +155,102 @@ def visitDefineExpression(self, ctx: Parser.DefineExpressionContext): elif isinstance(ctx, Parser.DefHierarchicalContext): return self.visitDefHierarchical(ctx) + elif isinstance(ctx, Parser.DefViralPropagationContext): + return self.visitDefViralPropagation(ctx) + + def visitDefViralPropagation(self, ctx: Parser.DefViralPropagationContext): + """ + DEFINE VIRAL PROPAGATION varID LPAREN vpSignature RPAREN IS + vpBody END VIRAL PROPAGATION # defViralPropagation + """ + ctx_list = list(ctx.getChildren()) + + propagation_name = Terminals().visitVarID(ctx_list[3]).value + signature_type, target = self.visitVpSignature(ctx_list[5]) + enumerated_clauses, aggregate_clause, default_value = self.visitVpBody(ctx_list[8]) + + token_info = extract_token_info(ctx) + + return ViralPropagationDef( + name=propagation_name, + signature_type=signature_type, + target=target, + enumerated_clauses=enumerated_clauses, + aggregate_clause=aggregate_clause, + default_value=default_value, + **token_info, + ) + + def visitVpSignature(self, ctx: Parser.VpSignatureContext): + """vpSignature: VALUE_DOMAIN varID | VARIABLE varID ;""" + ctx_list = list(ctx.getChildren()) + signature_type = ctx_list[0].getSymbol().text + target = Terminals().visitVarID(ctx_list[1]).value + return signature_type, target + + def visitVpBody(self, ctx: Parser.VpBodyContext): + """vpBody: vpClause (EOL vpClause)* ;""" + ctx_list = list(ctx.getChildren()) + enumerated_clauses: List[EnumeratedVpClause] = [] + aggregate_clause: Optional[AggregateVpClause] = None + default_value: Optional[str] = None + + for child in ctx_list: + if isinstance(child, Parser.EnumeratedVpClauseContext): + enumerated_clauses.append(self.visitEnumeratedVpClause(child)) + elif isinstance(child, Parser.AggregationVpClauseContext): + aggregate_clause = self.visitAggregationVpClause(child) + elif isinstance(child, Parser.DefaultVpClauseContext): + default_value = self.visitDefaultVpClause(child) + + return enumerated_clauses, aggregate_clause, default_value + + def visitEnumeratedVpClause(self, ctx: Parser.EnumeratedVpClauseContext): + """enumeratedVpClause: (IDENTIFIER COLON)? WHEN vpCondition THEN constant ;""" + ctx_list = list(ctx.getChildren()) + rule_name: Optional[str] = None + values: List[str] = [] + result: str = "" + + i = 0 + # Optional rule name: IDENTIFIER COLON + if ctx_list[i].getSymbol().type == Parser.IDENTIFIER: + rule_name = ctx_list[i].getSymbol().text + i += 2 # skip IDENTIFIER and COLON + + i += 1 # skip WHEN + # vpCondition + values = self.visitVpCondition(ctx_list[i]) + i += 1 + + i += 1 # skip THEN + # constant (result) + result = Terminals().visitConstant(ctx_list[i]).value + + token_info = extract_token_info(ctx) + return EnumeratedVpClause(name=rule_name, values=values, result=result, **token_info) + + def visitAggregationVpClause(self, ctx: Parser.AggregationVpClauseContext): + """aggregationVpClause: AGGREGATE (MIN | MAX | SUM | AVG) ;""" + ctx_list = list(ctx.getChildren()) + function = ctx_list[1].getSymbol().text + token_info = extract_token_info(ctx) + return AggregateVpClause(function=function, **token_info) + + def visitDefaultVpClause(self, ctx: Parser.DefaultVpClauseContext): + """defaultVpClause: ELSE constant ;""" + ctx_list = list(ctx.getChildren()) + return Terminals().visitConstant(ctx_list[1]).value + + def visitVpCondition(self, ctx: Parser.VpConditionContext): + """vpCondition: constant (AND constant)? ;""" + ctx_list = list(ctx.getChildren()) + values = [] + for child in ctx_list: + if isinstance(child, Parser.ConstantContext): + values.append(Terminals().visitConstant(child).value) + return values + def visitDefOperator(self, ctx: Parser.DefOperatorContext): """ DEFINE OPERATOR operatorID LPAREN (parameterItem (COMMA parameterItem)*)? RPAREN diff --git a/src/vtlengine/AST/DAG/__init__.py b/src/vtlengine/AST/DAG/__init__.py index 29d7cb819..8c19d7825 100644 --- a/src/vtlengine/AST/DAG/__init__.py +++ b/src/vtlengine/AST/DAG/__init__.py @@ -35,6 +35,7 @@ Start, UDOCall, VarID, + ViralPropagationDef, ) from vtlengine.AST.ASTTemplate import ASTTemplate from vtlengine.AST.DAG._models import DatasetSchedule, StatementDeps @@ -132,7 +133,9 @@ def create_dag(cls, ast: Start) -> "DAGAnalyzer": dag.sort_ast(ast) else: ml_statements: list = [ - ml for ml in ast.children if not isinstance(ml, (HRuleset, DPRuleset, Operator)) + ml + for ml in ast.children + if not isinstance(ml, (HRuleset, DPRuleset, Operator, ViralPropagationDef)) ] dag.check_overwriting(ml_statements) return dag @@ -207,7 +210,7 @@ def sort_ast(self, ast: AST) -> None: ml_statements: list = [ node for node in statements_nodes - if not isinstance(node, (HRuleset, DPRuleset, Operator)) + if not isinstance(node, (HRuleset, DPRuleset, Operator, ViralPropagationDef)) ] intermediate = self.sort_elements(ml_statements) diff --git a/src/vtlengine/AST/Grammar/Vtl.g4 b/src/vtlengine/AST/Grammar/Vtl.g4 index 2ddd93029..9177e151e 100644 --- a/src/vtlengine/AST/Grammar/Vtl.g4 +++ b/src/vtlengine/AST/Grammar/Vtl.g4 @@ -139,6 +139,26 @@ defOperators: DEFINE OPERATOR operatorID LPAREN (parameterItem (COMMA parameterItem)*)? RPAREN (RETURNS outputParameterType)? IS (expr) END OPERATOR # defOperator | DEFINE DATAPOINT RULESET rulesetID LPAREN rulesetSignature RPAREN IS ruleClauseDatapoint END DATAPOINT RULESET # defDatapointRuleset | DEFINE HIERARCHICAL RULESET rulesetID LPAREN hierRuleSignature RPAREN IS ruleClauseHierarchical END HIERARCHICAL RULESET # defHierarchical + | DEFINE VIRAL PROPAGATION varID LPAREN vpSignature RPAREN IS vpBody END VIRAL PROPAGATION # defViralPropagation +; + +vpSignature: + VALUE_DOMAIN varID + | VARIABLE varID +; + +vpBody: + vpClause (EOL vpClause)* +; + +vpClause: + (IDENTIFIER COLON)? WHEN vpCondition THEN constant # enumeratedVpClause + | AGGREGATE (MIN | MAX | SUM | AVG) # aggregationVpClause + | ELSE constant # defaultVpClause +; + +vpCondition: + constant (AND constant)? ; /* --------------------------------------------END DEFINE FUNCTIONS------------------------------------------------- */ diff --git a/src/vtlengine/AST/Grammar/VtlTokens.g4 b/src/vtlengine/AST/Grammar/VtlTokens.g4 index 062aefd24..a6776c287 100644 --- a/src/vtlengine/AST/Grammar/VtlTokens.g4 +++ b/src/vtlengine/AST/Grammar/VtlTokens.g4 @@ -115,6 +115,7 @@ lexer grammar VtlTokens; EXP : 'exp'; ROLE : 'componentRole'; VIRAL : 'viral'; + PROPAGATION : 'propagation'; CHARSET_MATCH : 'match_characters'; TYPE : 'type'; NVL : 'nvl'; diff --git a/src/vtlengine/AST/Grammar/lexer.py b/src/vtlengine/AST/Grammar/lexer.py index fa3d00b98..233a74ec6 100644 --- a/src/vtlengine/AST/Grammar/lexer.py +++ b/src/vtlengine/AST/Grammar/lexer.py @@ -1,23 +1,19 @@ # Generated from Vtl.g4 by ANTLR 4.9.3 -import sys +from antlr4 import * +from antlr4 import Lexer as ANTLRLexer from io import StringIO -from typing import TextIO +import sys -from antlr4 import ( - DFA, - ATNDeserializer, - LexerATNSimulator, - PredictionContextCache, -) -from antlr4 import ( - Lexer as ANTLRLexer, -) +if sys.version_info[1] > 5: + from typing import TextIO +else: + from typing.io import TextIO def serializedATN(): with StringIO() as buf: - buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\u00fb") - buf.write("\u0953\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\u00fc") + buf.write("\u0961\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") buf.write("\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") buf.write("\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23") buf.write("\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30") @@ -69,1051 +65,1057 @@ def serializedATN(): buf.write("\t\u00f0\4\u00f1\t\u00f1\4\u00f2\t\u00f2\4\u00f3\t\u00f3") buf.write("\4\u00f4\t\u00f4\4\u00f5\t\u00f5\4\u00f6\t\u00f6\4\u00f7") buf.write("\t\u00f7\4\u00f8\t\u00f8\4\u00f9\t\u00f9\4\u00fa\t\u00fa") - buf.write("\4\u00fb\t\u00fb\4\u00fc\t\u00fc\3\2\3\2\3\3\3\3\3\4\3") - buf.write("\4\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\13") - buf.write("\3\13\3\13\3\f\3\f\3\f\3\r\3\r\3\r\3\16\3\16\3\17\3\17") - buf.write("\3\20\3\20\3\21\3\21\3\22\3\22\3\23\3\23\3\23\3\24\3\24") - buf.write("\3\25\3\25\3\25\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\30") - buf.write("\3\30\3\30\3\31\3\31\3\31\3\31\3\31\3\32\3\32\3\32\3\32") - buf.write("\3\32\3\33\3\33\3\33\3\33\3\33\3\34\3\34\3\34\3\34\3\34") - buf.write("\3\34\3\35\3\35\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36") - buf.write("\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\37\3\37\3\37") - buf.write("\3\37\3\37\3\37\3\37\3\37\3\37\3 \3 \3 \3 \3 \3 \3 \3") - buf.write(' \3!\3!\3!\3!\3!\3!\3!\3!\3"\3"\3"\3"\3"\3"\3"') - buf.write('\3"\3"\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3$\3$\3$\3$') - buf.write("\3$\3$\3$\3$\3$\3$\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3&\3") - buf.write("&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3'\3'\3'\3'\3'\3'\3") - buf.write("'\3'\3'\3'\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3)\3)") - buf.write("\3)\3*\3*\3*\3*\3*\3+\3+\3+\3+\3+\3,\3,\3,\3,\3,\3-\3") - buf.write("-\3-\3-\3-\3-\3-\3-\3-\3.\3.\3.\3.\3.\3.\3.\3/\3/\3/\3") - buf.write("\60\3\60\3\60\3\60\3\61\3\61\3\61\3\62\3\62\3\62\3\62") - buf.write("\3\63\3\63\3\63\3\63\3\64\3\64\3\64\3\64\3\64\3\64\3\64") - buf.write("\3\64\3\65\3\65\3\65\3\66\3\66\3\66\3\66\3\66\3\66\3\66") - buf.write("\3\67\3\67\3\67\3\67\3\67\38\38\38\38\38\38\38\39\39\3") - buf.write("9\3:\3:\3:\3:\3:\3:\3;\3;\3;\3;\3;\3<\3<\3<\3<\3<\3<\3") - buf.write("<\3<\3=\3=\3=\3=\3=\3=\3=\3=\3=\3=\3>\3>\3>\3>\3>\3>\3") - buf.write(">\3?\3?\3?\3?\3?\3@\3@\3@\3@\3@\3@\3@\3@\3A\3A\3A\3A\3") - buf.write("A\3A\3A\3A\3A\3B\3B\3B\3B\3B\3B\3B\3C\3C\3C\3C\3C\3C\3") - buf.write("D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3E\3E\3E\3F\3F\3F\3F\3F\3") - buf.write("F\3F\3G\3G\3G\3G\3G\3G\3G\3G\3G\3G\3H\3H\3H\3H\3H\3H\3") - buf.write("H\3H\3H\3H\3I\3I\3I\3I\3J\3J\3J\3J\3J\3K\3K\3K\3K\3K\3") - buf.write("K\3K\3K\3K\3K\3K\3L\3L\3L\3L\3L\3L\3M\3M\3M\3N\3N\3N\3") - buf.write("N\3N\3O\3O\3O\3O\3P\3P\3P\3P\3P\3Q\3Q\3Q\3Q\3R\3R\3R\3") - buf.write("R\3S\3S\3S\3S\3S\3S\3T\3T\3T\3T\3T\3U\3U\3U\3U\3U\3U\3") - buf.write("U\3U\3V\3V\3V\3V\3W\3W\3W\3W\3X\3X\3X\3Y\3Y\3Y\3Y\3Z\3") - buf.write("Z\3Z\3Z\3Z\3Z\3[\3[\3[\3[\3[\3[\3\\\3\\\3\\\3\\\3\\\3") - buf.write("\\\3]\3]\3]\3]\3^\3^\3^\3^\3^\3^\3^\3_\3_\3_\3`\3`\3`") - buf.write("\3`\3`\3a\3a\3a\3a\3a\3a\3b\3b\3b\3b\3b\3b\3c\3c\3c\3") - buf.write("c\3c\3c\3c\3d\3d\3d\3d\3e\3e\3e\3e\3f\3f\3f\3f\3f\3f\3") - buf.write("f\3g\3g\3g\3g\3g\3g\3h\3h\3h\3h\3h\3h\3h\3h\3h\3h\3h\3") - buf.write("i\3i\3i\3i\3i\3i\3i\3i\3j\3j\3j\3j\3j\3j\3j\3j\3j\3j\3") - buf.write("k\3k\3k\3k\3k\3k\3k\3l\3l\3l\3l\3l\3l\3m\3m\3m\3m\3n\3") - buf.write("n\3n\3n\3n\3n\3n\3n\3n\3n\3n\3n\3n\3n\3o\3o\3o\3o\3o\3") - buf.write("o\3p\3p\3p\3p\3p\3p\3p\3p\3p\3p\3p\3p\3p\3p\3p\3p\3p\3") - buf.write("q\3q\3q\3q\3q\3r\3r\3r\3r\3s\3s\3s\3s\3s\3s\3s\3s\3s\3") - buf.write("s\3t\3t\3u\3u\3u\3u\3u\3u\3u\3u\3v\3v\3v\3v\3v\3v\3v\3") - buf.write("v\3v\3v\3v\3v\3w\3w\3w\3w\3w\3w\3w\3w\3w\3x\3x\3x\3x\3") - buf.write("x\3y\3y\3y\3y\3y\3y\3y\3y\3y\3y\3z\3z\3z\3z\3z\3z\3z\3") - buf.write("z\3{\3{\3{\3{\3{\3{\3{\3{\3{\3|\3|\3|\3|\3|\3|\3|\3}\3") - buf.write("}\3}\3~\3~\3~\3~\3~\3~\3~\3~\3~\3~\3\177\3\177\3\177\3") - buf.write("\177\3\177\3\177\3\177\3\177\3\177\3\177\3\177\3\177\3") - buf.write("\177\3\u0080\3\u0080\3\u0080\3\u0080\3\u0080\3\u0080\3") - buf.write("\u0080\3\u0080\3\u0081\3\u0081\3\u0081\3\u0081\3\u0081") - buf.write("\3\u0082\3\u0082\3\u0082\3\u0082\3\u0083\3\u0083\3\u0083") - buf.write("\3\u0083\3\u0083\3\u0083\3\u0083\3\u0083\3\u0083\3\u0083") + buf.write("\4\u00fb\t\u00fb\4\u00fc\t\u00fc\4\u00fd\t\u00fd\3\2\3") + buf.write("\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t") + buf.write("\3\t\3\n\3\n\3\13\3\13\3\13\3\f\3\f\3\f\3\r\3\r\3\r\3") + buf.write("\16\3\16\3\17\3\17\3\20\3\20\3\21\3\21\3\22\3\22\3\23") + buf.write("\3\23\3\23\3\24\3\24\3\25\3\25\3\25\3\26\3\26\3\27\3\27") + buf.write("\3\27\3\27\3\27\3\30\3\30\3\30\3\31\3\31\3\31\3\31\3\31") + buf.write("\3\32\3\32\3\32\3\32\3\32\3\33\3\33\3\33\3\33\3\33\3\34") + buf.write("\3\34\3\34\3\34\3\34\3\34\3\35\3\35\3\35\3\35\3\35\3\36") + buf.write("\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36") + buf.write("\3\36\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3 ") + buf.write('\3 \3 \3 \3 \3 \3 \3 \3!\3!\3!\3!\3!\3!\3!\3!\3"\3"') + buf.write('\3"\3"\3"\3"\3"\3"\3"\3#\3#\3#\3#\3#\3#\3#\3#\3') + buf.write("#\3#\3#\3$\3$\3$\3$\3$\3$\3$\3$\3$\3$\3%\3%\3%\3%\3%\3") + buf.write("%\3%\3%\3%\3%\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3'\3'") + buf.write("\3'\3'\3'\3'\3'\3'\3'\3'\3(\3(\3(\3(\3(\3(\3(") + buf.write("\3(\3(\3(\3(\3)\3)\3)\3*\3*\3*\3*\3*\3+\3+\3+\3+\3+\3") + buf.write(",\3,\3,\3,\3,\3-\3-\3-\3-\3-\3-\3-\3-\3-\3.\3.\3.\3.\3") + buf.write(".\3.\3.\3/\3/\3/\3\60\3\60\3\60\3\60\3\61\3\61\3\61\3") + buf.write("\62\3\62\3\62\3\62\3\63\3\63\3\63\3\63\3\64\3\64\3\64") + buf.write("\3\64\3\64\3\64\3\64\3\64\3\65\3\65\3\65\3\66\3\66\3\66") + buf.write("\3\66\3\66\3\66\3\66\3\67\3\67\3\67\3\67\3\67\38\38\3") + buf.write("8\38\38\38\38\39\39\39\3:\3:\3:\3:\3:\3:\3;\3;\3;\3;\3") + buf.write(";\3<\3<\3<\3<\3<\3<\3<\3<\3=\3=\3=\3=\3=\3=\3=\3=\3=\3") + buf.write("=\3>\3>\3>\3>\3>\3>\3>\3?\3?\3?\3?\3?\3@\3@\3@\3@\3@\3") + buf.write("@\3@\3@\3A\3A\3A\3A\3A\3A\3A\3A\3A\3B\3B\3B\3B\3B\3B\3") + buf.write("B\3C\3C\3C\3C\3C\3C\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3E\3") + buf.write("E\3E\3F\3F\3F\3F\3F\3F\3F\3G\3G\3G\3G\3G\3G\3G\3G\3G\3") + buf.write("G\3H\3H\3H\3H\3H\3H\3H\3H\3H\3H\3I\3I\3I\3I\3J\3J\3J\3") + buf.write("J\3J\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3L\3L\3L\3L\3L\3") + buf.write("L\3M\3M\3M\3N\3N\3N\3N\3N\3O\3O\3O\3O\3P\3P\3P\3P\3P\3") + buf.write("Q\3Q\3Q\3Q\3R\3R\3R\3R\3S\3S\3S\3S\3S\3S\3T\3T\3T\3T\3") + buf.write("T\3U\3U\3U\3U\3U\3U\3U\3U\3V\3V\3V\3V\3W\3W\3W\3W\3X\3") + buf.write("X\3X\3Y\3Y\3Y\3Y\3Z\3Z\3Z\3Z\3Z\3Z\3[\3[\3[\3[\3[\3[\3") + buf.write("\\\3\\\3\\\3\\\3\\\3\\\3]\3]\3]\3]\3^\3^\3^\3^\3^\3^\3") + buf.write("^\3_\3_\3_\3`\3`\3`\3`\3`\3a\3a\3a\3a\3a\3a\3b\3b\3b\3") + buf.write("b\3b\3b\3c\3c\3c\3c\3c\3c\3c\3d\3d\3d\3d\3e\3e\3e\3e\3") + buf.write("f\3f\3f\3f\3f\3f\3f\3g\3g\3g\3g\3g\3g\3h\3h\3h\3h\3h\3") + buf.write("h\3h\3h\3h\3h\3h\3i\3i\3i\3i\3i\3i\3i\3i\3j\3j\3j\3j\3") + buf.write("j\3j\3j\3j\3j\3j\3k\3k\3k\3k\3k\3k\3k\3l\3l\3l\3l\3l\3") + buf.write("l\3m\3m\3m\3m\3n\3n\3n\3n\3n\3n\3n\3n\3n\3n\3n\3n\3n\3") + buf.write("n\3o\3o\3o\3o\3o\3o\3p\3p\3p\3p\3p\3p\3p\3p\3p\3p\3p\3") + buf.write("p\3q\3q\3q\3q\3q\3q\3q\3q\3q\3q\3q\3q\3q\3q\3q\3q\3q\3") + buf.write("r\3r\3r\3r\3r\3s\3s\3s\3s\3t\3t\3t\3t\3t\3t\3t\3t\3t\3") + buf.write("t\3u\3u\3v\3v\3v\3v\3v\3v\3v\3v\3w\3w\3w\3w\3w\3w\3w\3") + buf.write("w\3w\3w\3w\3w\3x\3x\3x\3x\3x\3x\3x\3x\3x\3y\3y\3y\3y\3") + buf.write("y\3z\3z\3z\3z\3z\3z\3z\3z\3z\3z\3{\3{\3{\3{\3{\3{\3{\3") + buf.write("{\3|\3|\3|\3|\3|\3|\3|\3|\3|\3}\3}\3}\3}\3}\3}\3}\3~\3") + buf.write("~\3~\3\177\3\177\3\177\3\177\3\177\3\177\3\177\3\177\3") + buf.write("\177\3\177\3\u0080\3\u0080\3\u0080\3\u0080\3\u0080\3\u0080") + buf.write("\3\u0080\3\u0080\3\u0080\3\u0080\3\u0080\3\u0080\3\u0080") + buf.write("\3\u0081\3\u0081\3\u0081\3\u0081\3\u0081\3\u0081\3\u0081") + buf.write("\3\u0081\3\u0082\3\u0082\3\u0082\3\u0082\3\u0082\3\u0083") buf.write("\3\u0083\3\u0083\3\u0083\3\u0084\3\u0084\3\u0084\3\u0084") + buf.write("\3\u0084\3\u0084\3\u0084\3\u0084\3\u0084\3\u0084\3\u0084") buf.write("\3\u0084\3\u0084\3\u0085\3\u0085\3\u0085\3\u0085\3\u0085") buf.write("\3\u0085\3\u0086\3\u0086\3\u0086\3\u0086\3\u0086\3\u0086") - buf.write("\3\u0087\3\u0087\3\u0087\3\u0087\3\u0087\3\u0087\3\u0087") - buf.write("\3\u0087\3\u0088\3\u0088\3\u0088\3\u0088\3\u0088\3\u0089") + buf.write("\3\u0087\3\u0087\3\u0087\3\u0087\3\u0087\3\u0087\3\u0088") + buf.write("\3\u0088\3\u0088\3\u0088\3\u0088\3\u0088\3\u0088\3\u0088") buf.write("\3\u0089\3\u0089\3\u0089\3\u0089\3\u0089\3\u008a\3\u008a") - buf.write("\3\u008a\3\u008a\3\u008a\3\u008b\3\u008b\3\u008b\3\u008b") - buf.write("\3\u008c\3\u008c\3\u008c\3\u008c\3\u008c\3\u008c\3\u008c") - buf.write("\3\u008c\3\u008d\3\u008d\3\u008d\3\u008d\3\u008d\3\u008d") - buf.write("\3\u008d\3\u008d\3\u008d\3\u008d\3\u008d\3\u008e\3\u008e") + buf.write("\3\u008a\3\u008a\3\u008a\3\u008a\3\u008b\3\u008b\3\u008b") + buf.write("\3\u008b\3\u008b\3\u008c\3\u008c\3\u008c\3\u008c\3\u008d") + buf.write("\3\u008d\3\u008d\3\u008d\3\u008d\3\u008d\3\u008d\3\u008d") buf.write("\3\u008e\3\u008e\3\u008e\3\u008e\3\u008e\3\u008e\3\u008e") - buf.write("\3\u008e\3\u008e\3\u008e\3\u008f\3\u008f\3\u008f\3\u008f") - buf.write("\3\u008f\3\u008f\3\u008f\3\u008f\3\u0090\3\u0090\3\u0090") - buf.write("\3\u0090\3\u0090\3\u0090\3\u0090\3\u0090\3\u0090\3\u0091") + buf.write("\3\u008e\3\u008e\3\u008e\3\u008e\3\u008f\3\u008f\3\u008f") + buf.write("\3\u008f\3\u008f\3\u008f\3\u008f\3\u008f\3\u008f\3\u008f") + buf.write("\3\u008f\3\u008f\3\u0090\3\u0090\3\u0090\3\u0090\3\u0090") + buf.write("\3\u0090\3\u0090\3\u0090\3\u0091\3\u0091\3\u0091\3\u0091") buf.write("\3\u0091\3\u0091\3\u0091\3\u0091\3\u0091\3\u0092\3\u0092") - buf.write("\3\u0092\3\u0092\3\u0092\3\u0092\3\u0092\3\u0093\3\u0093") - buf.write("\3\u0093\3\u0093\3\u0093\3\u0093\3\u0093\3\u0094\3\u0094") - buf.write("\3\u0094\3\u0094\3\u0094\3\u0094\3\u0094\3\u0094\3\u0094") - buf.write("\3\u0094\3\u0094\3\u0094\3\u0095\3\u0095\3\u0095\3\u0095") + buf.write("\3\u0092\3\u0092\3\u0092\3\u0092\3\u0093\3\u0093\3\u0093") + buf.write("\3\u0093\3\u0093\3\u0093\3\u0093\3\u0094\3\u0094\3\u0094") + buf.write("\3\u0094\3\u0094\3\u0094\3\u0094\3\u0095\3\u0095\3\u0095") buf.write("\3\u0095\3\u0095\3\u0095\3\u0095\3\u0095\3\u0095\3\u0095") - buf.write("\3\u0096\3\u0096\3\u0096\3\u0096\3\u0097\3\u0097\3\u0097") - buf.write("\3\u0097\3\u0097\3\u0098\3\u0098\3\u0098\3\u0098\3\u0098") - buf.write("\3\u0098\3\u0098\3\u0098\3\u0098\3\u0098\3\u0098\3\u0098") - buf.write("\3\u0098\3\u0098\3\u0098\3\u0098\3\u0099\3\u0099\3\u0099") - buf.write("\3\u0099\3\u0099\3\u009a\3\u009a\3\u009a\3\u009a\3\u009a") - buf.write("\3\u009a\3\u009a\3\u009a\3\u009a\3\u009a\3\u009b\3\u009b") - buf.write("\3\u009b\3\u009b\3\u009b\3\u009b\3\u009b\3\u009b\3\u009b") - buf.write("\3\u009b\3\u009c\3\u009c\3\u009c\3\u009c\3\u009c\3\u009c") - buf.write("\3\u009c\3\u009c\3\u009c\3\u009c\3\u009d\3\u009d\3\u009d") + buf.write("\3\u0095\3\u0095\3\u0096\3\u0096\3\u0096\3\u0096\3\u0096") + buf.write("\3\u0096\3\u0096\3\u0096\3\u0096\3\u0096\3\u0096\3\u0097") + buf.write("\3\u0097\3\u0097\3\u0097\3\u0098\3\u0098\3\u0098\3\u0098") + buf.write("\3\u0098\3\u0099\3\u0099\3\u0099\3\u0099\3\u0099\3\u0099") + buf.write("\3\u0099\3\u0099\3\u0099\3\u0099\3\u0099\3\u0099\3\u0099") + buf.write("\3\u0099\3\u0099\3\u0099\3\u009a\3\u009a\3\u009a\3\u009a") + buf.write("\3\u009a\3\u009b\3\u009b\3\u009b\3\u009b\3\u009b\3\u009b") + buf.write("\3\u009b\3\u009b\3\u009b\3\u009b\3\u009c\3\u009c\3\u009c") + buf.write("\3\u009c\3\u009c\3\u009c\3\u009c\3\u009c\3\u009c\3\u009c") buf.write("\3\u009d\3\u009d\3\u009d\3\u009d\3\u009d\3\u009d\3\u009d") - buf.write("\3\u009e\3\u009e\3\u009e\3\u009e\3\u009e\3\u009f\3\u009f") + buf.write("\3\u009d\3\u009d\3\u009d\3\u009e\3\u009e\3\u009e\3\u009e") + buf.write("\3\u009e\3\u009e\3\u009e\3\u009e\3\u009e\3\u009e\3\u009f") buf.write("\3\u009f\3\u009f\3\u009f\3\u009f\3\u00a0\3\u00a0\3\u00a0") - buf.write("\3\u00a0\3\u00a0\3\u00a0\3\u00a0\3\u00a0\3\u00a1\3\u00a1") + buf.write("\3\u00a0\3\u00a0\3\u00a0\3\u00a1\3\u00a1\3\u00a1\3\u00a1") buf.write("\3\u00a1\3\u00a1\3\u00a1\3\u00a1\3\u00a2\3\u00a2\3\u00a2") - buf.write("\3\u00a2\3\u00a2\3\u00a2\3\u00a2\3\u00a2\3\u00a2\3\u00a2") - buf.write("\3\u00a2\3\u00a2\3\u00a2\3\u00a2\3\u00a2\3\u00a2\3\u00a2") + buf.write("\3\u00a2\3\u00a2\3\u00a2\3\u00a3\3\u00a3\3\u00a3\3\u00a3") buf.write("\3\u00a3\3\u00a3\3\u00a3\3\u00a3\3\u00a3\3\u00a3\3\u00a3") - buf.write("\3\u00a3\3\u00a3\3\u00a3\3\u00a3\3\u00a3\3\u00a3\3\u00a3") - buf.write("\3\u00a4\3\u00a4\3\u00a4\3\u00a4\3\u00a4\3\u00a4\3\u00a4") + buf.write("\3\u00a3\3\u00a3\3\u00a3\3\u00a3\3\u00a3\3\u00a3\3\u00a4") buf.write("\3\u00a4\3\u00a4\3\u00a4\3\u00a4\3\u00a4\3\u00a4\3\u00a4") + buf.write("\3\u00a4\3\u00a4\3\u00a4\3\u00a4\3\u00a4\3\u00a4\3\u00a5") buf.write("\3\u00a5\3\u00a5\3\u00a5\3\u00a5\3\u00a5\3\u00a5\3\u00a5") - buf.write("\3\u00a5\3\u00a5\3\u00a5\3\u00a6\3\u00a6\3\u00a6\3\u00a6") - buf.write("\3\u00a6\3\u00a6\3\u00a6\3\u00a6\3\u00a6\3\u00a7\3\u00a7") - buf.write("\3\u00a7\3\u00a7\3\u00a7\3\u00a7\3\u00a7\3\u00a7\3\u00a7") - buf.write("\3\u00a7\3\u00a7\3\u00a7\3\u00a8\3\u00a8\3\u00a8\3\u00a8") - buf.write("\3\u00a8\3\u00a8\3\u00a8\3\u00a8\3\u00a8\3\u00a8\3\u00a9") - buf.write("\3\u00a9\3\u00a9\3\u00a9\3\u00a9\3\u00a9\3\u00a9\3\u00a9") - buf.write("\3\u00aa\3\u00aa\3\u00aa\3\u00aa\3\u00aa\3\u00ab\3\u00ab") - buf.write("\3\u00ab\3\u00ab\3\u00ab\3\u00ab\3\u00ab\3\u00ab\3\u00ab") - buf.write("\3\u00ab\3\u00ab\3\u00ab\3\u00ac\3\u00ac\3\u00ac\3\u00ac") - buf.write("\3\u00ac\3\u00ac\3\u00ac\3\u00ad\3\u00ad\3\u00ad\3\u00ad") - buf.write("\3\u00ad\3\u00ad\3\u00ad\3\u00ae\3\u00ae\3\u00ae\3\u00ae") - buf.write("\3\u00ae\3\u00af\3\u00af\3\u00af\3\u00af\3\u00af\3\u00af") - buf.write("\3\u00af\3\u00af\3\u00b0\3\u00b0\3\u00b0\3\u00b0\3\u00b0") - buf.write("\3\u00b0\3\u00b1\3\u00b1\3\u00b1\3\u00b1\3\u00b1\3\u00b2") - buf.write("\3\u00b2\3\u00b2\3\u00b2\3\u00b2\3\u00b2\3\u00b2\3\u00b3") - buf.write("\3\u00b3\3\u00b3\3\u00b3\3\u00b3\3\u00b3\3\u00b3\3\u00b3") - buf.write("\3\u00b3\3\u00b4\3\u00b4\3\u00b4\3\u00b4\3\u00b4\3\u00b5") - buf.write("\3\u00b5\3\u00b5\3\u00b6\3\u00b6\3\u00b6\3\u00b7\3\u00b7") - buf.write("\3\u00b7\3\u00b7\3\u00b7\3\u00b7\3\u00b7\3\u00b7\3\u00b7") - buf.write("\3\u00b7\3\u00b8\3\u00b8\3\u00b8\3\u00b8\3\u00b8\3\u00b8") - buf.write("\3\u00b8\3\u00b9\3\u00b9\3\u00b9\3\u00ba\3\u00ba\3\u00ba") - buf.write("\3\u00ba\3\u00ba\3\u00bb\3\u00bb\3\u00bb\3\u00bb\3\u00bb") - buf.write("\3\u00bc\3\u00bc\3\u00bc\3\u00bc\3\u00bc\3\u00bc\3\u00bc") - buf.write("\3\u00bc\3\u00bc\3\u00bc\3\u00bc\3\u00bd\3\u00bd\3\u00bd") - buf.write("\3\u00bd\3\u00bd\3\u00bd\3\u00bd\3\u00be\3\u00be\3\u00be") + buf.write("\3\u00a5\3\u00a5\3\u00a5\3\u00a5\3\u00a5\3\u00a5\3\u00a6") + buf.write("\3\u00a6\3\u00a6\3\u00a6\3\u00a6\3\u00a6\3\u00a6\3\u00a6") + buf.write("\3\u00a6\3\u00a6\3\u00a7\3\u00a7\3\u00a7\3\u00a7\3\u00a7") + buf.write("\3\u00a7\3\u00a7\3\u00a7\3\u00a7\3\u00a8\3\u00a8\3\u00a8") + buf.write("\3\u00a8\3\u00a8\3\u00a8\3\u00a8\3\u00a8\3\u00a8\3\u00a8") + buf.write("\3\u00a8\3\u00a8\3\u00a9\3\u00a9\3\u00a9\3\u00a9\3\u00a9") + buf.write("\3\u00a9\3\u00a9\3\u00a9\3\u00a9\3\u00a9\3\u00aa\3\u00aa") + buf.write("\3\u00aa\3\u00aa\3\u00aa\3\u00aa\3\u00aa\3\u00aa\3\u00ab") + buf.write("\3\u00ab\3\u00ab\3\u00ab\3\u00ab\3\u00ac\3\u00ac\3\u00ac") + buf.write("\3\u00ac\3\u00ac\3\u00ac\3\u00ac\3\u00ac\3\u00ac\3\u00ac") + buf.write("\3\u00ac\3\u00ac\3\u00ad\3\u00ad\3\u00ad\3\u00ad\3\u00ad") + buf.write("\3\u00ad\3\u00ad\3\u00ae\3\u00ae\3\u00ae\3\u00ae\3\u00ae") + buf.write("\3\u00ae\3\u00ae\3\u00af\3\u00af\3\u00af\3\u00af\3\u00af") + buf.write("\3\u00b0\3\u00b0\3\u00b0\3\u00b0\3\u00b0\3\u00b0\3\u00b0") + buf.write("\3\u00b0\3\u00b1\3\u00b1\3\u00b1\3\u00b1\3\u00b1\3\u00b1") + buf.write("\3\u00b2\3\u00b2\3\u00b2\3\u00b2\3\u00b2\3\u00b3\3\u00b3") + buf.write("\3\u00b3\3\u00b3\3\u00b3\3\u00b3\3\u00b3\3\u00b4\3\u00b4") + buf.write("\3\u00b4\3\u00b4\3\u00b4\3\u00b4\3\u00b4\3\u00b4\3\u00b4") + buf.write("\3\u00b5\3\u00b5\3\u00b5\3\u00b5\3\u00b5\3\u00b6\3\u00b6") + buf.write("\3\u00b6\3\u00b7\3\u00b7\3\u00b7\3\u00b8\3\u00b8\3\u00b8") + buf.write("\3\u00b8\3\u00b8\3\u00b8\3\u00b8\3\u00b8\3\u00b8\3\u00b8") + buf.write("\3\u00b9\3\u00b9\3\u00b9\3\u00b9\3\u00b9\3\u00b9\3\u00b9") + buf.write("\3\u00ba\3\u00ba\3\u00ba\3\u00bb\3\u00bb\3\u00bb\3\u00bb") + buf.write("\3\u00bb\3\u00bc\3\u00bc\3\u00bc\3\u00bc\3\u00bc\3\u00bd") + buf.write("\3\u00bd\3\u00bd\3\u00bd\3\u00bd\3\u00bd\3\u00bd\3\u00bd") + buf.write("\3\u00bd\3\u00bd\3\u00bd\3\u00be\3\u00be\3\u00be\3\u00be") buf.write("\3\u00be\3\u00be\3\u00be\3\u00bf\3\u00bf\3\u00bf\3\u00bf") buf.write("\3\u00bf\3\u00bf\3\u00c0\3\u00c0\3\u00c0\3\u00c0\3\u00c0") - buf.write("\3\u00c0\3\u00c0\3\u00c0\3\u00c1\3\u00c1\3\u00c1\3\u00c1") - buf.write("\3\u00c1\3\u00c1\3\u00c1\3\u00c2\3\u00c2\3\u00c2\3\u00c2") - buf.write("\3\u00c2\3\u00c2\3\u00c2\3\u00c2\3\u00c2\3\u00c2\3\u00c2") - buf.write("\3\u00c3\3\u00c3\3\u00c3\3\u00c3\3\u00c3\3\u00c3\3\u00c3") - buf.write("\3\u00c3\3\u00c3\3\u00c3\3\u00c4\3\u00c4\3\u00c4\3\u00c4") + buf.write("\3\u00c0\3\u00c1\3\u00c1\3\u00c1\3\u00c1\3\u00c1\3\u00c1") + buf.write("\3\u00c1\3\u00c1\3\u00c2\3\u00c2\3\u00c2\3\u00c2\3\u00c2") + buf.write("\3\u00c2\3\u00c2\3\u00c3\3\u00c3\3\u00c3\3\u00c3\3\u00c3") + buf.write("\3\u00c3\3\u00c3\3\u00c3\3\u00c3\3\u00c3\3\u00c3\3\u00c4") buf.write("\3\u00c4\3\u00c4\3\u00c4\3\u00c4\3\u00c4\3\u00c4\3\u00c4") - buf.write("\3\u00c5\3\u00c5\3\u00c5\3\u00c5\3\u00c5\3\u00c5\3\u00c5") - buf.write("\3\u00c5\3\u00c5\3\u00c5\3\u00c6\3\u00c6\3\u00c6\3\u00c6") - buf.write("\3\u00c6\3\u00c6\3\u00c6\3\u00c6\3\u00c6\3\u00c6\3\u00c7") - buf.write("\3\u00c7\3\u00c7\3\u00c7\3\u00c7\3\u00c7\3\u00c7\3\u00c7") - buf.write("\3\u00c8\3\u00c8\3\u00c8\3\u00c8\3\u00c8\3\u00c8\3\u00c8") - buf.write("\3\u00c9\3\u00c9\3\u00c9\3\u00c9\3\u00c9\3\u00c9\3\u00c9") - buf.write("\3\u00c9\3\u00c9\3\u00ca\3\u00ca\3\u00ca\3\u00ca\3\u00ca") - buf.write("\3\u00ca\3\u00ca\3\u00ca\3\u00cb\3\u00cb\3\u00cb\3\u00cb") + buf.write("\3\u00c4\3\u00c4\3\u00c5\3\u00c5\3\u00c5\3\u00c5\3\u00c5") + buf.write("\3\u00c5\3\u00c5\3\u00c5\3\u00c5\3\u00c5\3\u00c5\3\u00c6") + buf.write("\3\u00c6\3\u00c6\3\u00c6\3\u00c6\3\u00c6\3\u00c6\3\u00c6") + buf.write("\3\u00c6\3\u00c6\3\u00c7\3\u00c7\3\u00c7\3\u00c7\3\u00c7") + buf.write("\3\u00c7\3\u00c7\3\u00c7\3\u00c7\3\u00c7\3\u00c8\3\u00c8") + buf.write("\3\u00c8\3\u00c8\3\u00c8\3\u00c8\3\u00c8\3\u00c8\3\u00c9") + buf.write("\3\u00c9\3\u00c9\3\u00c9\3\u00c9\3\u00c9\3\u00c9\3\u00ca") + buf.write("\3\u00ca\3\u00ca\3\u00ca\3\u00ca\3\u00ca\3\u00ca\3\u00ca") + buf.write("\3\u00ca\3\u00cb\3\u00cb\3\u00cb\3\u00cb\3\u00cb\3\u00cb") buf.write("\3\u00cb\3\u00cb\3\u00cc\3\u00cc\3\u00cc\3\u00cc\3\u00cc") - buf.write("\3\u00cc\3\u00cc\3\u00cc\3\u00cc\3\u00cc\3\u00cc\3\u00cc") - buf.write("\3\u00cd\3\u00cd\3\u00cd\3\u00cd\3\u00cd\3\u00cd\3\u00cd") - buf.write("\3\u00cd\3\u00ce\3\u00ce\3\u00ce\3\u00ce\3\u00cf\3\u00cf") + buf.write("\3\u00cc\3\u00cd\3\u00cd\3\u00cd\3\u00cd\3\u00cd\3\u00cd") + buf.write("\3\u00cd\3\u00cd\3\u00cd\3\u00cd\3\u00cd\3\u00cd\3\u00ce") + buf.write("\3\u00ce\3\u00ce\3\u00ce\3\u00ce\3\u00ce\3\u00ce\3\u00ce") buf.write("\3\u00cf\3\u00cf\3\u00cf\3\u00cf\3\u00d0\3\u00d0\3\u00d0") - buf.write("\3\u00d0\3\u00d0\3\u00d0\3\u00d0\3\u00d0\3\u00d0\3\u00d0") - buf.write("\3\u00d0\3\u00d0\3\u00d1\3\u00d1\3\u00d1\3\u00d1\3\u00d1") + buf.write("\3\u00d0\3\u00d0\3\u00d0\3\u00d1\3\u00d1\3\u00d1\3\u00d1") buf.write("\3\u00d1\3\u00d1\3\u00d1\3\u00d1\3\u00d1\3\u00d1\3\u00d1") - buf.write("\3\u00d1\3\u00d1\3\u00d1\3\u00d1\3\u00d1\3\u00d2\3\u00d2") - buf.write("\3\u00d2\3\u00d2\3\u00d2\3\u00d2\3\u00d2\3\u00d3\3\u00d3") - buf.write("\3\u00d3\3\u00d3\3\u00d3\3\u00d3\3\u00d3\3\u00d3\3\u00d3") - buf.write("\3\u00d4\3\u00d4\3\u00d4\3\u00d4\3\u00d4\3\u00d4\3\u00d4") - buf.write("\3\u00d4\3\u00d4\3\u00d5\3\u00d5\3\u00d5\3\u00d5\3\u00d5") - buf.write("\3\u00d6\3\u00d6\3\u00d6\3\u00d6\3\u00d6\3\u00d6\3\u00d7") - buf.write("\3\u00d7\3\u00d7\3\u00d7\3\u00d7\3\u00d7\3\u00d7\3\u00d7") + buf.write("\3\u00d1\3\u00d2\3\u00d2\3\u00d2\3\u00d2\3\u00d2\3\u00d2") + buf.write("\3\u00d2\3\u00d2\3\u00d2\3\u00d2\3\u00d2\3\u00d2\3\u00d2") + buf.write("\3\u00d2\3\u00d2\3\u00d2\3\u00d2\3\u00d3\3\u00d3\3\u00d3") + buf.write("\3\u00d3\3\u00d3\3\u00d3\3\u00d3\3\u00d4\3\u00d4\3\u00d4") + buf.write("\3\u00d4\3\u00d4\3\u00d4\3\u00d4\3\u00d4\3\u00d4\3\u00d5") + buf.write("\3\u00d5\3\u00d5\3\u00d5\3\u00d5\3\u00d5\3\u00d5\3\u00d5") + buf.write("\3\u00d5\3\u00d6\3\u00d6\3\u00d6\3\u00d6\3\u00d6\3\u00d7") buf.write("\3\u00d7\3\u00d7\3\u00d7\3\u00d7\3\u00d7\3\u00d8\3\u00d8") buf.write("\3\u00d8\3\u00d8\3\u00d8\3\u00d8\3\u00d8\3\u00d8\3\u00d8") - buf.write("\3\u00d8\3\u00d9\3\u00d9\3\u00d9\3\u00d9\3\u00d9\3\u00d9") - buf.write("\3\u00da\3\u00da\3\u00da\3\u00da\3\u00da\3\u00da\3\u00da") - buf.write("\3\u00db\3\u00db\3\u00db\3\u00db\3\u00db\3\u00dc\3\u00dc") - buf.write("\3\u00dc\3\u00dc\3\u00dc\3\u00dc\3\u00dc\3\u00dc\3\u00dc") - buf.write("\3\u00dc\3\u00dc\3\u00dc\3\u00dc\3\u00dc\3\u00dd\3\u00dd") + buf.write("\3\u00d8\3\u00d8\3\u00d8\3\u00d8\3\u00d9\3\u00d9\3\u00d9") + buf.write("\3\u00d9\3\u00d9\3\u00d9\3\u00d9\3\u00d9\3\u00d9\3\u00d9") + buf.write("\3\u00da\3\u00da\3\u00da\3\u00da\3\u00da\3\u00da\3\u00db") + buf.write("\3\u00db\3\u00db\3\u00db\3\u00db\3\u00db\3\u00db\3\u00dc") + buf.write("\3\u00dc\3\u00dc\3\u00dc\3\u00dc\3\u00dd\3\u00dd\3\u00dd") buf.write("\3\u00dd\3\u00dd\3\u00dd\3\u00dd\3\u00dd\3\u00dd\3\u00dd") - buf.write("\3\u00dd\3\u00dd\3\u00dd\3\u00dd\3\u00dd\3\u00dd\3\u00dd") - buf.write("\3\u00dd\3\u00de\3\u00de\3\u00de\3\u00de\3\u00de\3\u00de") - buf.write("\3\u00de\3\u00de\3\u00df\3\u00df\3\u00df\3\u00df\3\u00df") + buf.write("\3\u00dd\3\u00dd\3\u00dd\3\u00dd\3\u00de\3\u00de\3\u00de") + buf.write("\3\u00de\3\u00de\3\u00de\3\u00de\3\u00de\3\u00de\3\u00de") + buf.write("\3\u00de\3\u00de\3\u00de\3\u00de\3\u00de\3\u00de\3\u00de") buf.write("\3\u00df\3\u00df\3\u00df\3\u00df\3\u00df\3\u00df\3\u00df") - buf.write("\3\u00df\3\u00df\3\u00df\3\u00df\3\u00e0\3\u00e0\3\u00e0") + buf.write("\3\u00df\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0") buf.write("\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0") - buf.write("\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e1") + buf.write("\3\u00e0\3\u00e0\3\u00e0\3\u00e1\3\u00e1\3\u00e1\3\u00e1") buf.write("\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e1") - buf.write("\3\u00e1\3\u00e2\3\u00e2\3\u00e2\3\u00e2\3\u00e2\3\u00e2") - buf.write("\3\u00e2\3\u00e2\3\u00e2\3\u00e3\3\u00e3\3\u00e3\3\u00e3") - buf.write("\3\u00e3\3\u00e3\3\u00e3\3\u00e3\3\u00e3\3\u00e4\3\u00e4") - buf.write("\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4") + buf.write("\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e2\3\u00e2") + buf.write("\3\u00e2\3\u00e2\3\u00e2\3\u00e2\3\u00e2\3\u00e2\3\u00e2") + buf.write("\3\u00e3\3\u00e3\3\u00e3\3\u00e3\3\u00e3\3\u00e3\3\u00e3") + buf.write("\3\u00e3\3\u00e3\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4") buf.write("\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e5\3\u00e5\3\u00e5") buf.write("\3\u00e5\3\u00e5\3\u00e5\3\u00e5\3\u00e5\3\u00e5\3\u00e5") buf.write("\3\u00e5\3\u00e5\3\u00e5\3\u00e6\3\u00e6\3\u00e6\3\u00e6") buf.write("\3\u00e6\3\u00e6\3\u00e6\3\u00e6\3\u00e6\3\u00e6\3\u00e6") - buf.write("\3\u00e6\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e7") - buf.write("\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e8") + buf.write("\3\u00e6\3\u00e6\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e7") + buf.write("\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e7") buf.write("\3\u00e8\3\u00e8\3\u00e8\3\u00e8\3\u00e8\3\u00e8\3\u00e8") - buf.write("\3\u00e8\3\u00e8\3\u00e8\3\u00e9\3\u00e9\3\u00e9\3\u00e9") + buf.write("\3\u00e8\3\u00e8\3\u00e8\3\u00e8\3\u00e8\3\u00e9\3\u00e9") buf.write("\3\u00e9\3\u00e9\3\u00e9\3\u00e9\3\u00e9\3\u00e9\3\u00e9") buf.write("\3\u00e9\3\u00e9\3\u00ea\3\u00ea\3\u00ea\3\u00ea\3\u00ea") - buf.write("\3\u00ea\3\u00ea\3\u00eb\3\u00eb\3\u00eb\3\u00eb\3\u00eb") - buf.write("\3\u00eb\3\u00eb\3\u00eb\3\u00eb\3\u00eb\3\u00ec\3\u00ec") - buf.write("\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec") - buf.write("\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec") - buf.write("\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec") - buf.write("\3\u00ec\3\u00ec\3\u00ec\3\u00ed\3\u00ed\3\u00ed\3\u00ed") + buf.write("\3\u00ea\3\u00ea\3\u00ea\3\u00ea\3\u00ea\3\u00ea\3\u00ea") + buf.write("\3\u00ea\3\u00eb\3\u00eb\3\u00eb\3\u00eb\3\u00eb\3\u00eb") + buf.write("\3\u00eb\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec") + buf.write("\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ed\3\u00ed\3\u00ed") buf.write("\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed") buf.write("\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed") - buf.write("\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ee\3\u00ee") - buf.write("\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee") + buf.write("\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed") + buf.write("\3\u00ed\3\u00ed\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee") buf.write("\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee") buf.write("\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee") - buf.write("\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ef") + buf.write("\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ef\3\u00ef\3\u00ef") buf.write("\3\u00ef\3\u00ef\3\u00ef\3\u00ef\3\u00ef\3\u00ef\3\u00ef") buf.write("\3\u00ef\3\u00ef\3\u00ef\3\u00ef\3\u00ef\3\u00ef\3\u00ef") buf.write("\3\u00ef\3\u00ef\3\u00ef\3\u00ef\3\u00ef\3\u00ef\3\u00ef") - buf.write("\3\u00ef\3\u00ef\3\u00ef\3\u00ef\3\u00f0\3\u00f0\3\u00f0") - buf.write("\3\u00f0\3\u00f1\3\u00f1\3\u00f1\3\u00f1\3\u00f1\3\u00f1") - buf.write("\3\u00f1\3\u00f1\3\u00f1\3\u00f2\3\u00f2\3\u00f3\3\u00f3") - buf.write("\3\u00f4\6\u00f4\u08ff\n\u00f4\r\u00f4\16\u00f4\u0900") - buf.write("\3\u00f5\3\u00f5\3\u00f5\3\u00f5\3\u00f6\3\u00f6\3\u00f6") - buf.write("\3\u00f6\3\u00f6\3\u00f6\3\u00f6\3\u00f6\3\u00f6\5\u00f6") - buf.write("\u0910\n\u00f6\3\u00f7\3\u00f7\7\u00f7\u0914\n\u00f7\f") - buf.write("\u00f7\16\u00f7\u0917\13\u00f7\3\u00f7\3\u00f7\3\u00f8") - buf.write("\3\u00f8\7\u00f8\u091d\n\u00f8\f\u00f8\16\u00f8\u0920") - buf.write("\13\u00f8\3\u00f8\3\u00f8\6\u00f8\u0924\n\u00f8\r\u00f8") - buf.write("\16\u00f8\u0925\3\u00f8\3\u00f8\7\u00f8\u092a\n\u00f8") - buf.write("\f\u00f8\16\u00f8\u092d\13\u00f8\3\u00f8\5\u00f8\u0930") - buf.write("\n\u00f8\3\u00f9\6\u00f9\u0933\n\u00f9\r\u00f9\16\u00f9") - buf.write("\u0934\3\u00f9\3\u00f9\3\u00fa\3\u00fa\3\u00fb\3\u00fb") - buf.write("\3\u00fb\3\u00fb\7\u00fb\u093f\n\u00fb\f\u00fb\16\u00fb") - buf.write("\u0942\13\u00fb\3\u00fb\3\u00fb\3\u00fb\3\u00fb\3\u00fb") - buf.write("\3\u00fc\3\u00fc\3\u00fc\3\u00fc\7\u00fc\u094d\n\u00fc") - buf.write("\f\u00fc\16\u00fc\u0950\13\u00fc\3\u00fc\3\u00fc\4\u092b") - buf.write("\u0940\2\u00fd\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13") - buf.write("\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24'\25)\26") - buf.write('+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A"C#') - buf.write("E$G%I&K'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66") - buf.write("k\67m8o9q:s;u{?}@\177A\u0081B\u0083C\u0085D\u0087") - buf.write("E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097") - buf.write("M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7") - buf.write("U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7") - buf.write("]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5d\u00c7") - buf.write("e\u00c9f\u00cbg\u00cdh\u00cfi\u00d1j\u00d3k\u00d5l\u00d7") - buf.write("m\u00d9n\u00dbo\u00ddp\u00dfq\u00e1r\u00e3s\u00e5t\u00e7") - buf.write("u\u00e9v\u00ebw\u00edx\u00efy\u00f1z\u00f3{\u00f5|\u00f7") - buf.write("}\u00f9~\u00fb\177\u00fd\u0080\u00ff\u0081\u0101\u0082") - buf.write("\u0103\u0083\u0105\u0084\u0107\u0085\u0109\u0086\u010b") - buf.write("\u0087\u010d\u0088\u010f\u0089\u0111\u008a\u0113\u008b") - buf.write("\u0115\u008c\u0117\u008d\u0119\u008e\u011b\u008f\u011d") - buf.write("\u0090\u011f\u0091\u0121\u0092\u0123\u0093\u0125\u0094") - buf.write("\u0127\u0095\u0129\u0096\u012b\u0097\u012d\u0098\u012f") - buf.write("\u0099\u0131\u009a\u0133\u009b\u0135\u009c\u0137\u009d") - buf.write("\u0139\u009e\u013b\u009f\u013d\u00a0\u013f\u00a1\u0141") - buf.write("\u00a2\u0143\u00a3\u0145\u00a4\u0147\u00a5\u0149\u00a6") - buf.write("\u014b\u00a7\u014d\u00a8\u014f\u00a9\u0151\u00aa\u0153") - buf.write("\u00ab\u0155\u00ac\u0157\u00ad\u0159\u00ae\u015b\u00af") - buf.write("\u015d\u00b0\u015f\u00b1\u0161\u00b2\u0163\u00b3\u0165") - buf.write("\u00b4\u0167\u00b5\u0169\u00b6\u016b\u00b7\u016d\u00b8") - buf.write("\u016f\u00b9\u0171\u00ba\u0173\u00bb\u0175\u00bc\u0177") - buf.write("\u00bd\u0179\u00be\u017b\u00bf\u017d\u00c0\u017f\u00c1") - buf.write("\u0181\u00c2\u0183\u00c3\u0185\u00c4\u0187\u00c5\u0189") - buf.write("\u00c6\u018b\u00c7\u018d\u00c8\u018f\u00c9\u0191\u00ca") - buf.write("\u0193\u00cb\u0195\u00cc\u0197\u00cd\u0199\u00ce\u019b") - buf.write("\u00cf\u019d\u00d0\u019f\u00d1\u01a1\u00d2\u01a3\u00d3") - buf.write("\u01a5\u00d4\u01a7\u00d5\u01a9\u00d6\u01ab\u00d7\u01ad") - buf.write("\u00d8\u01af\u00d9\u01b1\u00da\u01b3\u00db\u01b5\u00dc") - buf.write("\u01b7\u00dd\u01b9\u00de\u01bb\u00df\u01bd\u00e0\u01bf") - buf.write("\u00e1\u01c1\u00e2\u01c3\u00e3\u01c5\u00e4\u01c7\u00e5") - buf.write("\u01c9\u00e6\u01cb\u00e7\u01cd\u00e8\u01cf\u00e9\u01d1") - buf.write("\u00ea\u01d3\u00eb\u01d5\u00ec\u01d7\u00ed\u01d9\u00ee") - buf.write("\u01db\u00ef\u01dd\u00f0\u01df\u00f1\u01e1\u00f2\u01e3") - buf.write("\2\u01e5\2\u01e7\u00f3\u01e9\u00f4\u01eb\u00f5\u01ed\u00f6") - buf.write("\u01ef\u00f7\u01f1\u00f8\u01f3\u00f9\u01f5\u00fa\u01f7") - buf.write("\u00fb\3\2\7\4\2C\\c|\3\2$$\7\2\60\60\62;C\\aac|\5\2\13") - buf.write('\f\16\17""\4\2\f\f\17\17\2\u095b\2\3\3\2\2\2\2\5\3\2') - buf.write("\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2") - buf.write("\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2") - buf.write("\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37") - buf.write("\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2'\3\2\2\2") - buf.write("\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2") - buf.write("\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2") - buf.write("\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2") - buf.write("\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2") - buf.write("\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3") - buf.write("\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a") - buf.write("\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2") - buf.write("k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2") - buf.write("\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2") - buf.write("\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085") - buf.write("\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2") - buf.write("\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093") - buf.write("\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099\3\2\2") - buf.write("\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1") - buf.write("\3\2\2\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2") - buf.write("\2\2\u00a9\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2\2\2\u00af") - buf.write("\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2\2\2\u00b5\3\2\2") - buf.write("\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb\3\2\2\2\2\u00bd") - buf.write("\3\2\2\2\2\u00bf\3\2\2\2\2\u00c1\3\2\2\2\2\u00c3\3\2\2") - buf.write("\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb") - buf.write("\3\2\2\2\2\u00cd\3\2\2\2\2\u00cf\3\2\2\2\2\u00d1\3\2\2") - buf.write("\2\2\u00d3\3\2\2\2\2\u00d5\3\2\2\2\2\u00d7\3\2\2\2\2\u00d9") - buf.write("\3\2\2\2\2\u00db\3\2\2\2\2\u00dd\3\2\2\2\2\u00df\3\2\2") - buf.write("\2\2\u00e1\3\2\2\2\2\u00e3\3\2\2\2\2\u00e5\3\2\2\2\2\u00e7") - buf.write("\3\2\2\2\2\u00e9\3\2\2\2\2\u00eb\3\2\2\2\2\u00ed\3\2\2") - buf.write("\2\2\u00ef\3\2\2\2\2\u00f1\3\2\2\2\2\u00f3\3\2\2\2\2\u00f5") - buf.write("\3\2\2\2\2\u00f7\3\2\2\2\2\u00f9\3\2\2\2\2\u00fb\3\2\2") - buf.write("\2\2\u00fd\3\2\2\2\2\u00ff\3\2\2\2\2\u0101\3\2\2\2\2\u0103") - buf.write("\3\2\2\2\2\u0105\3\2\2\2\2\u0107\3\2\2\2\2\u0109\3\2\2") - buf.write("\2\2\u010b\3\2\2\2\2\u010d\3\2\2\2\2\u010f\3\2\2\2\2\u0111") - buf.write("\3\2\2\2\2\u0113\3\2\2\2\2\u0115\3\2\2\2\2\u0117\3\2\2") - buf.write("\2\2\u0119\3\2\2\2\2\u011b\3\2\2\2\2\u011d\3\2\2\2\2\u011f") - buf.write("\3\2\2\2\2\u0121\3\2\2\2\2\u0123\3\2\2\2\2\u0125\3\2\2") - buf.write("\2\2\u0127\3\2\2\2\2\u0129\3\2\2\2\2\u012b\3\2\2\2\2\u012d") - buf.write("\3\2\2\2\2\u012f\3\2\2\2\2\u0131\3\2\2\2\2\u0133\3\2\2") - buf.write("\2\2\u0135\3\2\2\2\2\u0137\3\2\2\2\2\u0139\3\2\2\2\2\u013b") - buf.write("\3\2\2\2\2\u013d\3\2\2\2\2\u013f\3\2\2\2\2\u0141\3\2\2") - buf.write("\2\2\u0143\3\2\2\2\2\u0145\3\2\2\2\2\u0147\3\2\2\2\2\u0149") - buf.write("\3\2\2\2\2\u014b\3\2\2\2\2\u014d\3\2\2\2\2\u014f\3\2\2") - buf.write("\2\2\u0151\3\2\2\2\2\u0153\3\2\2\2\2\u0155\3\2\2\2\2\u0157") - buf.write("\3\2\2\2\2\u0159\3\2\2\2\2\u015b\3\2\2\2\2\u015d\3\2\2") - buf.write("\2\2\u015f\3\2\2\2\2\u0161\3\2\2\2\2\u0163\3\2\2\2\2\u0165") - buf.write("\3\2\2\2\2\u0167\3\2\2\2\2\u0169\3\2\2\2\2\u016b\3\2\2") - buf.write("\2\2\u016d\3\2\2\2\2\u016f\3\2\2\2\2\u0171\3\2\2\2\2\u0173") - buf.write("\3\2\2\2\2\u0175\3\2\2\2\2\u0177\3\2\2\2\2\u0179\3\2\2") - buf.write("\2\2\u017b\3\2\2\2\2\u017d\3\2\2\2\2\u017f\3\2\2\2\2\u0181") - buf.write("\3\2\2\2\2\u0183\3\2\2\2\2\u0185\3\2\2\2\2\u0187\3\2\2") - buf.write("\2\2\u0189\3\2\2\2\2\u018b\3\2\2\2\2\u018d\3\2\2\2\2\u018f") - buf.write("\3\2\2\2\2\u0191\3\2\2\2\2\u0193\3\2\2\2\2\u0195\3\2\2") - buf.write("\2\2\u0197\3\2\2\2\2\u0199\3\2\2\2\2\u019b\3\2\2\2\2\u019d") - buf.write("\3\2\2\2\2\u019f\3\2\2\2\2\u01a1\3\2\2\2\2\u01a3\3\2\2") - buf.write("\2\2\u01a5\3\2\2\2\2\u01a7\3\2\2\2\2\u01a9\3\2\2\2\2\u01ab") - buf.write("\3\2\2\2\2\u01ad\3\2\2\2\2\u01af\3\2\2\2\2\u01b1\3\2\2") - buf.write("\2\2\u01b3\3\2\2\2\2\u01b5\3\2\2\2\2\u01b7\3\2\2\2\2\u01b9") - buf.write("\3\2\2\2\2\u01bb\3\2\2\2\2\u01bd\3\2\2\2\2\u01bf\3\2\2") - buf.write("\2\2\u01c1\3\2\2\2\2\u01c3\3\2\2\2\2\u01c5\3\2\2\2\2\u01c7") - buf.write("\3\2\2\2\2\u01c9\3\2\2\2\2\u01cb\3\2\2\2\2\u01cd\3\2\2") - buf.write("\2\2\u01cf\3\2\2\2\2\u01d1\3\2\2\2\2\u01d3\3\2\2\2\2\u01d5") - buf.write("\3\2\2\2\2\u01d7\3\2\2\2\2\u01d9\3\2\2\2\2\u01db\3\2\2") - buf.write("\2\2\u01dd\3\2\2\2\2\u01df\3\2\2\2\2\u01e1\3\2\2\2\2\u01e7") - buf.write("\3\2\2\2\2\u01e9\3\2\2\2\2\u01eb\3\2\2\2\2\u01ed\3\2\2") - buf.write("\2\2\u01ef\3\2\2\2\2\u01f1\3\2\2\2\2\u01f3\3\2\2\2\2\u01f5") - buf.write("\3\2\2\2\2\u01f7\3\2\2\2\3\u01f9\3\2\2\2\5\u01fb\3\2\2") - buf.write("\2\7\u01fd\3\2\2\2\t\u01ff\3\2\2\2\13\u0201\3\2\2\2\r") - buf.write("\u0203\3\2\2\2\17\u0205\3\2\2\2\21\u0207\3\2\2\2\23\u0209") - buf.write("\3\2\2\2\25\u020b\3\2\2\2\27\u020e\3\2\2\2\31\u0211\3") - buf.write("\2\2\2\33\u0214\3\2\2\2\35\u0216\3\2\2\2\37\u0218\3\2") - buf.write("\2\2!\u021a\3\2\2\2#\u021c\3\2\2\2%\u021e\3\2\2\2'\u0221") - buf.write("\3\2\2\2)\u0223\3\2\2\2+\u0226\3\2\2\2-\u0228\3\2\2\2") - buf.write("/\u022d\3\2\2\2\61\u0230\3\2\2\2\63\u0235\3\2\2\2\65\u023a") - buf.write("\3\2\2\2\67\u023f\3\2\2\29\u0245\3\2\2\2;\u024a\3\2\2") - buf.write("\2=\u0257\3\2\2\2?\u0260\3\2\2\2A\u0268\3\2\2\2C\u0270") - buf.write("\3\2\2\2E\u0279\3\2\2\2G\u0284\3\2\2\2I\u028e\3\2\2\2") - buf.write("K\u0298\3\2\2\2M\u02a3\3\2\2\2O\u02ad\3\2\2\2Q\u02b8\3") - buf.write("\2\2\2S\u02bb\3\2\2\2U\u02c0\3\2\2\2W\u02c5\3\2\2\2Y\u02ca") - buf.write("\3\2\2\2[\u02d3\3\2\2\2]\u02da\3\2\2\2_\u02dd\3\2\2\2") - buf.write("a\u02e1\3\2\2\2c\u02e4\3\2\2\2e\u02e8\3\2\2\2g\u02ec\3") - buf.write("\2\2\2i\u02f4\3\2\2\2k\u02f7\3\2\2\2m\u02fe\3\2\2\2o\u0303") - buf.write("\3\2\2\2q\u030a\3\2\2\2s\u030d\3\2\2\2u\u0313\3\2\2\2") - buf.write("w\u0318\3\2\2\2y\u0320\3\2\2\2{\u032a\3\2\2\2}\u0331\3") - buf.write("\2\2\2\177\u0336\3\2\2\2\u0081\u033e\3\2\2\2\u0083\u0347") - buf.write("\3\2\2\2\u0085\u034e\3\2\2\2\u0087\u0354\3\2\2\2\u0089") - buf.write("\u035e\3\2\2\2\u008b\u0361\3\2\2\2\u008d\u0368\3\2\2\2") - buf.write("\u008f\u0372\3\2\2\2\u0091\u037c\3\2\2\2\u0093\u0380\3") - buf.write("\2\2\2\u0095\u0385\3\2\2\2\u0097\u0390\3\2\2\2\u0099\u0396") - buf.write("\3\2\2\2\u009b\u0399\3\2\2\2\u009d\u039e\3\2\2\2\u009f") - buf.write("\u03a2\3\2\2\2\u00a1\u03a7\3\2\2\2\u00a3\u03ab\3\2\2\2") - buf.write("\u00a5\u03af\3\2\2\2\u00a7\u03b5\3\2\2\2\u00a9\u03ba\3") - buf.write("\2\2\2\u00ab\u03c2\3\2\2\2\u00ad\u03c6\3\2\2\2\u00af\u03ca") - buf.write("\3\2\2\2\u00b1\u03cd\3\2\2\2\u00b3\u03d1\3\2\2\2\u00b5") - buf.write("\u03d7\3\2\2\2\u00b7\u03dd\3\2\2\2\u00b9\u03e3\3\2\2\2") - buf.write("\u00bb\u03e7\3\2\2\2\u00bd\u03ee\3\2\2\2\u00bf\u03f1\3") - buf.write("\2\2\2\u00c1\u03f6\3\2\2\2\u00c3\u03fc\3\2\2\2\u00c5\u0402") - buf.write("\3\2\2\2\u00c7\u0409\3\2\2\2\u00c9\u040d\3\2\2\2\u00cb") - buf.write("\u0411\3\2\2\2\u00cd\u0418\3\2\2\2\u00cf\u041e\3\2\2\2") - buf.write("\u00d1\u0429\3\2\2\2\u00d3\u0431\3\2\2\2\u00d5\u043b\3") - buf.write("\2\2\2\u00d7\u0442\3\2\2\2\u00d9\u0448\3\2\2\2\u00db\u044c") - buf.write("\3\2\2\2\u00dd\u045a\3\2\2\2\u00df\u0460\3\2\2\2\u00e1") - buf.write("\u0471\3\2\2\2\u00e3\u0476\3\2\2\2\u00e5\u047a\3\2\2\2") - buf.write("\u00e7\u0484\3\2\2\2\u00e9\u0486\3\2\2\2\u00eb\u048e\3") - buf.write("\2\2\2\u00ed\u049a\3\2\2\2\u00ef\u04a3\3\2\2\2\u00f1\u04a8") - buf.write("\3\2\2\2\u00f3\u04b2\3\2\2\2\u00f5\u04ba\3\2\2\2\u00f7") - buf.write("\u04c3\3\2\2\2\u00f9\u04ca\3\2\2\2\u00fb\u04cd\3\2\2\2") - buf.write("\u00fd\u04d7\3\2\2\2\u00ff\u04e4\3\2\2\2\u0101\u04ec\3") - buf.write("\2\2\2\u0103\u04f1\3\2\2\2\u0105\u04f5\3\2\2\2\u0107\u0502") - buf.write("\3\2\2\2\u0109\u0508\3\2\2\2\u010b\u050e\3\2\2\2\u010d") - buf.write("\u0514\3\2\2\2\u010f\u051c\3\2\2\2\u0111\u0521\3\2\2\2") - buf.write("\u0113\u0527\3\2\2\2\u0115\u052c\3\2\2\2\u0117\u0530\3") - buf.write("\2\2\2\u0119\u0538\3\2\2\2\u011b\u0543\3\2\2\2\u011d\u054f") - buf.write("\3\2\2\2\u011f\u0557\3\2\2\2\u0121\u0560\3\2\2\2\u0123") - buf.write("\u0566\3\2\2\2\u0125\u056d\3\2\2\2\u0127\u0574\3\2\2\2") - buf.write("\u0129\u0580\3\2\2\2\u012b\u058b\3\2\2\2\u012d\u058f\3") - buf.write("\2\2\2\u012f\u0594\3\2\2\2\u0131\u05a4\3\2\2\2\u0133\u05a9") - buf.write("\3\2\2\2\u0135\u05b3\3\2\2\2\u0137\u05bd\3\2\2\2\u0139") - buf.write("\u05c7\3\2\2\2\u013b\u05d1\3\2\2\2\u013d\u05d6\3\2\2\2") - buf.write("\u013f\u05dc\3\2\2\2\u0141\u05e4\3\2\2\2\u0143\u05ea\3") - buf.write("\2\2\2\u0145\u05fb\3\2\2\2\u0147\u0609\3\2\2\2\u0149\u0617") - buf.write("\3\2\2\2\u014b\u0621\3\2\2\2\u014d\u062a\3\2\2\2\u014f") - buf.write("\u0636\3\2\2\2\u0151\u0640\3\2\2\2\u0153\u0648\3\2\2\2") - buf.write("\u0155\u064d\3\2\2\2\u0157\u0659\3\2\2\2\u0159\u0660\3") - buf.write("\2\2\2\u015b\u0667\3\2\2\2\u015d\u066c\3\2\2\2\u015f\u0674") - buf.write("\3\2\2\2\u0161\u067a\3\2\2\2\u0163\u067f\3\2\2\2\u0165") - buf.write("\u0686\3\2\2\2\u0167\u068f\3\2\2\2\u0169\u0694\3\2\2\2") - buf.write("\u016b\u0697\3\2\2\2\u016d\u069a\3\2\2\2\u016f\u06a4\3") - buf.write("\2\2\2\u0171\u06ab\3\2\2\2\u0173\u06ae\3\2\2\2\u0175\u06b3") - buf.write("\3\2\2\2\u0177\u06b8\3\2\2\2\u0179\u06c3\3\2\2\2\u017b") - buf.write("\u06ca\3\2\2\2\u017d\u06d0\3\2\2\2\u017f\u06d6\3\2\2\2") - buf.write("\u0181\u06de\3\2\2\2\u0183\u06e5\3\2\2\2\u0185\u06f0\3") - buf.write("\2\2\2\u0187\u06fa\3\2\2\2\u0189\u0705\3\2\2\2\u018b\u070f") - buf.write("\3\2\2\2\u018d\u0719\3\2\2\2\u018f\u0721\3\2\2\2\u0191") - buf.write("\u0728\3\2\2\2\u0193\u0731\3\2\2\2\u0195\u0739\3\2\2\2") - buf.write("\u0197\u073f\3\2\2\2\u0199\u074b\3\2\2\2\u019b\u0753\3") - buf.write("\2\2\2\u019d\u0757\3\2\2\2\u019f\u075d\3\2\2\2\u01a1\u0769") - buf.write("\3\2\2\2\u01a3\u077a\3\2\2\2\u01a5\u0781\3\2\2\2\u01a7") - buf.write("\u078a\3\2\2\2\u01a9\u0793\3\2\2\2\u01ab\u0798\3\2\2\2") - buf.write("\u01ad\u079e\3\2\2\2\u01af\u07ab\3\2\2\2\u01b1\u07b5\3") - buf.write("\2\2\2\u01b3\u07bb\3\2\2\2\u01b5\u07c2\3\2\2\2\u01b7\u07c7") - buf.write("\3\2\2\2\u01b9\u07d5\3\2\2\2\u01bb\u07e6\3\2\2\2\u01bd") - buf.write("\u07ee\3\2\2\2\u01bf\u07fe\3\2\2\2\u01c1\u080e\3\2\2\2") - buf.write("\u01c3\u0817\3\2\2\2\u01c5\u0820\3\2\2\2\u01c7\u0829\3") - buf.write("\2\2\2\u01c9\u0836\3\2\2\2\u01cb\u0843\3\2\2\2\u01cd\u084f") - buf.write("\3\2\2\2\u01cf\u085b\3\2\2\2\u01d1\u0866\3\2\2\2\u01d3") - buf.write("\u0873\3\2\2\2\u01d5\u087a\3\2\2\2\u01d7\u0884\3\2\2\2") - buf.write("\u01d9\u089e\3\2\2\2\u01db\u08b5\3\2\2\2\u01dd\u08d2\3") - buf.write("\2\2\2\u01df\u08ec\3\2\2\2\u01e1\u08f0\3\2\2\2\u01e3\u08f9") - buf.write("\3\2\2\2\u01e5\u08fb\3\2\2\2\u01e7\u08fe\3\2\2\2\u01e9") - buf.write("\u0902\3\2\2\2\u01eb\u090f\3\2\2\2\u01ed\u0911\3\2\2\2") - buf.write("\u01ef\u092f\3\2\2\2\u01f1\u0932\3\2\2\2\u01f3\u0938\3") - buf.write("\2\2\2\u01f5\u093a\3\2\2\2\u01f7\u0948\3\2\2\2\u01f9\u01fa") - buf.write("\7*\2\2\u01fa\4\3\2\2\2\u01fb\u01fc\7+\2\2\u01fc\6\3\2") - buf.write("\2\2\u01fd\u01fe\7]\2\2\u01fe\b\3\2\2\2\u01ff\u0200\7") - buf.write("_\2\2\u0200\n\3\2\2\2\u0201\u0202\7}\2\2\u0202\f\3\2\2") - buf.write("\2\u0203\u0204\7\177\2\2\u0204\16\3\2\2\2\u0205\u0206") - buf.write("\7?\2\2\u0206\20\3\2\2\2\u0207\u0208\7>\2\2\u0208\22\3") - buf.write("\2\2\2\u0209\u020a\7@\2\2\u020a\24\3\2\2\2\u020b\u020c") - buf.write("\7@\2\2\u020c\u020d\7?\2\2\u020d\26\3\2\2\2\u020e\u020f") - buf.write("\7>\2\2\u020f\u0210\7@\2\2\u0210\30\3\2\2\2\u0211\u0212") - buf.write("\7>\2\2\u0212\u0213\7?\2\2\u0213\32\3\2\2\2\u0214\u0215") - buf.write("\7-\2\2\u0215\34\3\2\2\2\u0216\u0217\7/\2\2\u0217\36\3") - buf.write("\2\2\2\u0218\u0219\7,\2\2\u0219 \3\2\2\2\u021a\u021b\7") - buf.write('\61\2\2\u021b"\3\2\2\2\u021c\u021d\7.\2\2\u021d$\3\2') - buf.write("\2\2\u021e\u021f\7/\2\2\u021f\u0220\7@\2\2\u0220&\3\2") - buf.write("\2\2\u0221\u0222\7<\2\2\u0222(\3\2\2\2\u0223\u0224\7<") - buf.write("\2\2\u0224\u0225\7?\2\2\u0225*\3\2\2\2\u0226\u0227\7%") - buf.write("\2\2\u0227,\3\2\2\2\u0228\u0229\7g\2\2\u0229\u022a\7x") - buf.write("\2\2\u022a\u022b\7c\2\2\u022b\u022c\7n\2\2\u022c.\3\2") - buf.write("\2\2\u022d\u022e\7k\2\2\u022e\u022f\7h\2\2\u022f\60\3") - buf.write("\2\2\2\u0230\u0231\7e\2\2\u0231\u0232\7c\2\2\u0232\u0233") - buf.write("\7u\2\2\u0233\u0234\7g\2\2\u0234\62\3\2\2\2\u0235\u0236") - buf.write("\7v\2\2\u0236\u0237\7j\2\2\u0237\u0238\7g\2\2\u0238\u0239") - buf.write("\7p\2\2\u0239\64\3\2\2\2\u023a\u023b\7g\2\2\u023b\u023c") - buf.write("\7n\2\2\u023c\u023d\7u\2\2\u023d\u023e\7g\2\2\u023e\66") - buf.write("\3\2\2\2\u023f\u0240\7w\2\2\u0240\u0241\7u\2\2\u0241\u0242") - buf.write("\7k\2\2\u0242\u0243\7p\2\2\u0243\u0244\7i\2\2\u02448\3") - buf.write("\2\2\2\u0245\u0246\7y\2\2\u0246\u0247\7k\2\2\u0247\u0248") - buf.write("\7v\2\2\u0248\u0249\7j\2\2\u0249:\3\2\2\2\u024a\u024b") - buf.write("\7e\2\2\u024b\u024c\7w\2\2\u024c\u024d\7t\2\2\u024d\u024e") - buf.write("\7t\2\2\u024e\u024f\7g\2\2\u024f\u0250\7p\2\2\u0250\u0251") - buf.write("\7v\2\2\u0251\u0252\7a\2\2\u0252\u0253\7f\2\2\u0253\u0254") - buf.write("\7c\2\2\u0254\u0255\7v\2\2\u0255\u0256\7g\2\2\u0256<\3") - buf.write("\2\2\2\u0257\u0258\7f\2\2\u0258\u0259\7c\2\2\u0259\u025a") - buf.write("\7v\2\2\u025a\u025b\7g\2\2\u025b\u025c\7f\2\2\u025c\u025d") - buf.write("\7k\2\2\u025d\u025e\7h\2\2\u025e\u025f\7h\2\2\u025f>\3") - buf.write("\2\2\2\u0260\u0261\7f\2\2\u0261\u0262\7c\2\2\u0262\u0263") - buf.write("\7v\2\2\u0263\u0264\7g\2\2\u0264\u0265\7c\2\2\u0265\u0266") - buf.write("\7f\2\2\u0266\u0267\7f\2\2\u0267@\3\2\2\2\u0268\u0269") - buf.write("\7i\2\2\u0269\u026a\7g\2\2\u026a\u026b\7v\2\2\u026b\u026c") - buf.write("\7{\2\2\u026c\u026d\7g\2\2\u026d\u026e\7c\2\2\u026e\u026f") - buf.write("\7t\2\2\u026fB\3\2\2\2\u0270\u0271\7i\2\2\u0271\u0272") - buf.write("\7g\2\2\u0272\u0273\7v\2\2\u0273\u0274\7o\2\2\u0274\u0275") - buf.write("\7q\2\2\u0275\u0276\7p\2\2\u0276\u0277\7v\2\2\u0277\u0278") - buf.write("\7j\2\2\u0278D\3\2\2\2\u0279\u027a\7f\2\2\u027a\u027b") - buf.write("\7c\2\2\u027b\u027c\7{\2\2\u027c\u027d\7q\2\2\u027d\u027e") - buf.write("\7h\2\2\u027e\u027f\7o\2\2\u027f\u0280\7q\2\2\u0280\u0281") - buf.write("\7p\2\2\u0281\u0282\7v\2\2\u0282\u0283\7j\2\2\u0283F\3") - buf.write("\2\2\2\u0284\u0285\7f\2\2\u0285\u0286\7c\2\2\u0286\u0287") - buf.write("\7{\2\2\u0287\u0288\7q\2\2\u0288\u0289\7h\2\2\u0289\u028a") - buf.write("\7{\2\2\u028a\u028b\7g\2\2\u028b\u028c\7c\2\2\u028c\u028d") - buf.write("\7t\2\2\u028dH\3\2\2\2\u028e\u028f\7f\2\2\u028f\u0290") - buf.write("\7c\2\2\u0290\u0291\7{\2\2\u0291\u0292\7v\2\2\u0292\u0293") - buf.write("\7q\2\2\u0293\u0294\7{\2\2\u0294\u0295\7g\2\2\u0295\u0296") - buf.write("\7c\2\2\u0296\u0297\7t\2\2\u0297J\3\2\2\2\u0298\u0299") - buf.write("\7f\2\2\u0299\u029a\7c\2\2\u029a\u029b\7{\2\2\u029b\u029c") - buf.write("\7v\2\2\u029c\u029d\7q\2\2\u029d\u029e\7o\2\2\u029e\u029f") - buf.write("\7q\2\2\u029f\u02a0\7p\2\2\u02a0\u02a1\7v\2\2\u02a1\u02a2") - buf.write("\7j\2\2\u02a2L\3\2\2\2\u02a3\u02a4\7{\2\2\u02a4\u02a5") - buf.write("\7g\2\2\u02a5\u02a6\7c\2\2\u02a6\u02a7\7t\2\2\u02a7\u02a8") - buf.write("\7v\2\2\u02a8\u02a9\7q\2\2\u02a9\u02aa\7f\2\2\u02aa\u02ab") - buf.write("\7c\2\2\u02ab\u02ac\7{\2\2\u02acN\3\2\2\2\u02ad\u02ae") - buf.write("\7o\2\2\u02ae\u02af\7q\2\2\u02af\u02b0\7p\2\2\u02b0\u02b1") - buf.write("\7v\2\2\u02b1\u02b2\7j\2\2\u02b2\u02b3\7v\2\2\u02b3\u02b4") - buf.write("\7q\2\2\u02b4\u02b5\7f\2\2\u02b5\u02b6\7c\2\2\u02b6\u02b7") - buf.write("\7{\2\2\u02b7P\3\2\2\2\u02b8\u02b9\7q\2\2\u02b9\u02ba") - buf.write("\7p\2\2\u02baR\3\2\2\2\u02bb\u02bc\7f\2\2\u02bc\u02bd") - buf.write("\7t\2\2\u02bd\u02be\7q\2\2\u02be\u02bf\7r\2\2\u02bfT\3") - buf.write("\2\2\2\u02c0\u02c1\7m\2\2\u02c1\u02c2\7g\2\2\u02c2\u02c3") - buf.write("\7g\2\2\u02c3\u02c4\7r\2\2\u02c4V\3\2\2\2\u02c5\u02c6") - buf.write("\7e\2\2\u02c6\u02c7\7c\2\2\u02c7\u02c8\7n\2\2\u02c8\u02c9") - buf.write("\7e\2\2\u02c9X\3\2\2\2\u02ca\u02cb\7c\2\2\u02cb\u02cc") - buf.write("\7v\2\2\u02cc\u02cd\7v\2\2\u02cd\u02ce\7t\2\2\u02ce\u02cf") - buf.write("\7e\2\2\u02cf\u02d0\7c\2\2\u02d0\u02d1\7n\2\2\u02d1\u02d2") - buf.write("\7e\2\2\u02d2Z\3\2\2\2\u02d3\u02d4\7t\2\2\u02d4\u02d5") - buf.write("\7g\2\2\u02d5\u02d6\7p\2\2\u02d6\u02d7\7c\2\2\u02d7\u02d8") - buf.write("\7o\2\2\u02d8\u02d9\7g\2\2\u02d9\\\3\2\2\2\u02da\u02db") - buf.write("\7c\2\2\u02db\u02dc\7u\2\2\u02dc^\3\2\2\2\u02dd\u02de") - buf.write("\7c\2\2\u02de\u02df\7p\2\2\u02df\u02e0\7f\2\2\u02e0`\3") - buf.write("\2\2\2\u02e1\u02e2\7q\2\2\u02e2\u02e3\7t\2\2\u02e3b\3") - buf.write("\2\2\2\u02e4\u02e5\7z\2\2\u02e5\u02e6\7q\2\2\u02e6\u02e7") - buf.write("\7t\2\2\u02e7d\3\2\2\2\u02e8\u02e9\7p\2\2\u02e9\u02ea") - buf.write("\7q\2\2\u02ea\u02eb\7v\2\2\u02ebf\3\2\2\2\u02ec\u02ed") - buf.write("\7d\2\2\u02ed\u02ee\7g\2\2\u02ee\u02ef\7v\2\2\u02ef\u02f0") - buf.write("\7y\2\2\u02f0\u02f1\7g\2\2\u02f1\u02f2\7g\2\2\u02f2\u02f3") - buf.write("\7p\2\2\u02f3h\3\2\2\2\u02f4\u02f5\7k\2\2\u02f5\u02f6") - buf.write("\7p\2\2\u02f6j\3\2\2\2\u02f7\u02f8\7p\2\2\u02f8\u02f9") - buf.write("\7q\2\2\u02f9\u02fa\7v\2\2\u02fa\u02fb\7a\2\2\u02fb\u02fc") - buf.write("\7k\2\2\u02fc\u02fd\7p\2\2\u02fdl\3\2\2\2\u02fe\u02ff") - buf.write("\7p\2\2\u02ff\u0300\7w\2\2\u0300\u0301\7n\2\2\u0301\u0302") - buf.write("\7n\2\2\u0302n\3\2\2\2\u0303\u0304\7k\2\2\u0304\u0305") - buf.write("\7u\2\2\u0305\u0306\7p\2\2\u0306\u0307\7w\2\2\u0307\u0308") - buf.write("\7n\2\2\u0308\u0309\7n\2\2\u0309p\3\2\2\2\u030a\u030b") - buf.write("\7g\2\2\u030b\u030c\7z\2\2\u030cr\3\2\2\2\u030d\u030e") - buf.write("\7w\2\2\u030e\u030f\7p\2\2\u030f\u0310\7k\2\2\u0310\u0311") - buf.write("\7q\2\2\u0311\u0312\7p\2\2\u0312t\3\2\2\2\u0313\u0314") - buf.write("\7f\2\2\u0314\u0315\7k\2\2\u0315\u0316\7h\2\2\u0316\u0317") - buf.write("\7h\2\2\u0317v\3\2\2\2\u0318\u0319\7u\2\2\u0319\u031a") - buf.write("\7{\2\2\u031a\u031b\7o\2\2\u031b\u031c\7f\2\2\u031c\u031d") - buf.write("\7k\2\2\u031d\u031e\7h\2\2\u031e\u031f\7h\2\2\u031fx\3") - buf.write("\2\2\2\u0320\u0321\7k\2\2\u0321\u0322\7p\2\2\u0322\u0323") - buf.write("\7v\2\2\u0323\u0324\7g\2\2\u0324\u0325\7t\2\2\u0325\u0326") - buf.write("\7u\2\2\u0326\u0327\7g\2\2\u0327\u0328\7e\2\2\u0328\u0329") - buf.write("\7v\2\2\u0329z\3\2\2\2\u032a\u032b\7t\2\2\u032b\u032c") - buf.write("\7c\2\2\u032c\u032d\7p\2\2\u032d\u032e\7f\2\2\u032e\u032f") - buf.write("\7q\2\2\u032f\u0330\7o\2\2\u0330|\3\2\2\2\u0331\u0332") - buf.write("\7m\2\2\u0332\u0333\7g\2\2\u0333\u0334\7{\2\2\u0334\u0335") - buf.write("\7u\2\2\u0335~\3\2\2\2\u0336\u0337\7k\2\2\u0337\u0338") - buf.write("\7p\2\2\u0338\u0339\7v\2\2\u0339\u033a\7{\2\2\u033a\u033b") - buf.write("\7g\2\2\u033b\u033c\7c\2\2\u033c\u033d\7t\2\2\u033d\u0080") - buf.write("\3\2\2\2\u033e\u033f\7k\2\2\u033f\u0340\7p\2\2\u0340\u0341") - buf.write("\7v\2\2\u0341\u0342\7o\2\2\u0342\u0343\7q\2\2\u0343\u0344") - buf.write("\7p\2\2\u0344\u0345\7v\2\2\u0345\u0346\7j\2\2\u0346\u0082") - buf.write("\3\2\2\2\u0347\u0348\7k\2\2\u0348\u0349\7p\2\2\u0349\u034a") - buf.write("\7v\2\2\u034a\u034b\7f\2\2\u034b\u034c\7c\2\2\u034c\u034d") - buf.write("\7{\2\2\u034d\u0084\3\2\2\2\u034e\u034f\7e\2\2\u034f\u0350") - buf.write("\7j\2\2\u0350\u0351\7g\2\2\u0351\u0352\7e\2\2\u0352\u0353") - buf.write("\7m\2\2\u0353\u0086\3\2\2\2\u0354\u0355\7g\2\2\u0355\u0356") - buf.write("\7z\2\2\u0356\u0357\7k\2\2\u0357\u0358\7u\2\2\u0358\u0359") - buf.write("\7v\2\2\u0359\u035a\7u\2\2\u035a\u035b\7a\2\2\u035b\u035c") - buf.write("\7k\2\2\u035c\u035d\7p\2\2\u035d\u0088\3\2\2\2\u035e\u035f") - buf.write("\7v\2\2\u035f\u0360\7q\2\2\u0360\u008a\3\2\2\2\u0361\u0362") - buf.write("\7t\2\2\u0362\u0363\7g\2\2\u0363\u0364\7v\2\2\u0364\u0365") - buf.write("\7w\2\2\u0365\u0366\7t\2\2\u0366\u0367\7p\2\2\u0367\u008c") - buf.write("\3\2\2\2\u0368\u0369\7k\2\2\u0369\u036a\7o\2\2\u036a\u036b") - buf.write("\7d\2\2\u036b\u036c\7c\2\2\u036c\u036d\7n\2\2\u036d\u036e") - buf.write("\7c\2\2\u036e\u036f\7p\2\2\u036f\u0370\7e\2\2\u0370\u0371") - buf.write("\7g\2\2\u0371\u008e\3\2\2\2\u0372\u0373\7g\2\2\u0373\u0374") - buf.write("\7t\2\2\u0374\u0375\7t\2\2\u0375\u0376\7q\2\2\u0376\u0377") - buf.write("\7t\2\2\u0377\u0378\7e\2\2\u0378\u0379\7q\2\2\u0379\u037a") - buf.write("\7f\2\2\u037a\u037b\7g\2\2\u037b\u0090\3\2\2\2\u037c\u037d") - buf.write("\7c\2\2\u037d\u037e\7n\2\2\u037e\u037f\7n\2\2\u037f\u0092") - buf.write("\3\2\2\2\u0380\u0381\7c\2\2\u0381\u0382\7i\2\2\u0382\u0383") - buf.write("\7i\2\2\u0383\u0384\7t\2\2\u0384\u0094\3\2\2\2\u0385\u0386") - buf.write("\7g\2\2\u0386\u0387\7t\2\2\u0387\u0388\7t\2\2\u0388\u0389") - buf.write("\7q\2\2\u0389\u038a\7t\2\2\u038a\u038b\7n\2\2\u038b\u038c") - buf.write("\7g\2\2\u038c\u038d\7x\2\2\u038d\u038e\7g\2\2\u038e\u038f") - buf.write("\7n\2\2\u038f\u0096\3\2\2\2\u0390\u0391\7q\2\2\u0391\u0392") - buf.write("\7t\2\2\u0392\u0393\7f\2\2\u0393\u0394\7g\2\2\u0394\u0395") - buf.write("\7t\2\2\u0395\u0098\3\2\2\2\u0396\u0397\7d\2\2\u0397\u0398") - buf.write("\7{\2\2\u0398\u009a\3\2\2\2\u0399\u039a\7t\2\2\u039a\u039b") - buf.write("\7c\2\2\u039b\u039c\7p\2\2\u039c\u039d\7m\2\2\u039d\u009c") - buf.write("\3\2\2\2\u039e\u039f\7c\2\2\u039f\u03a0\7u\2\2\u03a0\u03a1") - buf.write("\7e\2\2\u03a1\u009e\3\2\2\2\u03a2\u03a3\7f\2\2\u03a3\u03a4") - buf.write("\7g\2\2\u03a4\u03a5\7u\2\2\u03a5\u03a6\7e\2\2\u03a6\u00a0") - buf.write("\3\2\2\2\u03a7\u03a8\7o\2\2\u03a8\u03a9\7k\2\2\u03a9\u03aa") - buf.write("\7p\2\2\u03aa\u00a2\3\2\2\2\u03ab\u03ac\7o\2\2\u03ac\u03ad") - buf.write("\7c\2\2\u03ad\u03ae\7z\2\2\u03ae\u00a4\3\2\2\2\u03af\u03b0") - buf.write("\7h\2\2\u03b0\u03b1\7k\2\2\u03b1\u03b2\7t\2\2\u03b2\u03b3") - buf.write("\7u\2\2\u03b3\u03b4\7v\2\2\u03b4\u00a6\3\2\2\2\u03b5\u03b6") - buf.write("\7n\2\2\u03b6\u03b7\7c\2\2\u03b7\u03b8\7u\2\2\u03b8\u03b9") - buf.write("\7v\2\2\u03b9\u00a8\3\2\2\2\u03ba\u03bb\7k\2\2\u03bb\u03bc") - buf.write("\7p\2\2\u03bc\u03bd\7f\2\2\u03bd\u03be\7g\2\2\u03be\u03bf") - buf.write("\7z\2\2\u03bf\u03c0\7q\2\2\u03c0\u03c1\7h\2\2\u03c1\u00aa") - buf.write("\3\2\2\2\u03c2\u03c3\7c\2\2\u03c3\u03c4\7d\2\2\u03c4\u03c5") - buf.write("\7u\2\2\u03c5\u00ac\3\2\2\2\u03c6\u03c7\7m\2\2\u03c7\u03c8") - buf.write("\7g\2\2\u03c8\u03c9\7{\2\2\u03c9\u00ae\3\2\2\2\u03ca\u03cb") - buf.write("\7n\2\2\u03cb\u03cc\7p\2\2\u03cc\u00b0\3\2\2\2\u03cd\u03ce") - buf.write("\7n\2\2\u03ce\u03cf\7q\2\2\u03cf\u03d0\7i\2\2\u03d0\u00b2") - buf.write("\3\2\2\2\u03d1\u03d2\7v\2\2\u03d2\u03d3\7t\2\2\u03d3\u03d4") - buf.write("\7w\2\2\u03d4\u03d5\7p\2\2\u03d5\u03d6\7e\2\2\u03d6\u00b4") - buf.write("\3\2\2\2\u03d7\u03d8\7t\2\2\u03d8\u03d9\7q\2\2\u03d9\u03da") - buf.write("\7w\2\2\u03da\u03db\7p\2\2\u03db\u03dc\7f\2\2\u03dc\u00b6") - buf.write("\3\2\2\2\u03dd\u03de\7r\2\2\u03de\u03df\7q\2\2\u03df\u03e0") - buf.write("\7y\2\2\u03e0\u03e1\7g\2\2\u03e1\u03e2\7t\2\2\u03e2\u00b8") - buf.write("\3\2\2\2\u03e3\u03e4\7o\2\2\u03e4\u03e5\7q\2\2\u03e5\u03e6") - buf.write("\7f\2\2\u03e6\u00ba\3\2\2\2\u03e7\u03e8\7n\2\2\u03e8\u03e9") - buf.write("\7g\2\2\u03e9\u03ea\7p\2\2\u03ea\u03eb\7i\2\2\u03eb\u03ec") - buf.write("\7v\2\2\u03ec\u03ed\7j\2\2\u03ed\u00bc\3\2\2\2\u03ee\u03ef") - buf.write("\7~\2\2\u03ef\u03f0\7~\2\2\u03f0\u00be\3\2\2\2\u03f1\u03f2") - buf.write("\7v\2\2\u03f2\u03f3\7t\2\2\u03f3\u03f4\7k\2\2\u03f4\u03f5") - buf.write("\7o\2\2\u03f5\u00c0\3\2\2\2\u03f6\u03f7\7w\2\2\u03f7\u03f8") - buf.write("\7r\2\2\u03f8\u03f9\7r\2\2\u03f9\u03fa\7g\2\2\u03fa\u03fb") - buf.write("\7t\2\2\u03fb\u00c2\3\2\2\2\u03fc\u03fd\7n\2\2\u03fd\u03fe") - buf.write("\7q\2\2\u03fe\u03ff\7y\2\2\u03ff\u0400\7g\2\2\u0400\u0401") - buf.write("\7t\2\2\u0401\u00c4\3\2\2\2\u0402\u0403\7u\2\2\u0403\u0404") - buf.write("\7w\2\2\u0404\u0405\7d\2\2\u0405\u0406\7u\2\2\u0406\u0407") - buf.write("\7v\2\2\u0407\u0408\7t\2\2\u0408\u00c6\3\2\2\2\u0409\u040a") - buf.write("\7u\2\2\u040a\u040b\7w\2\2\u040b\u040c\7o\2\2\u040c\u00c8") - buf.write("\3\2\2\2\u040d\u040e\7c\2\2\u040e\u040f\7x\2\2\u040f\u0410") - buf.write("\7i\2\2\u0410\u00ca\3\2\2\2\u0411\u0412\7o\2\2\u0412\u0413") - buf.write("\7g\2\2\u0413\u0414\7f\2\2\u0414\u0415\7k\2\2\u0415\u0416") - buf.write("\7c\2\2\u0416\u0417\7p\2\2\u0417\u00cc\3\2\2\2\u0418\u0419") - buf.write("\7e\2\2\u0419\u041a\7q\2\2\u041a\u041b\7w\2\2\u041b\u041c") - buf.write("\7p\2\2\u041c\u041d\7v\2\2\u041d\u00ce\3\2\2\2\u041e\u041f") - buf.write("\7k\2\2\u041f\u0420\7f\2\2\u0420\u0421\7g\2\2\u0421\u0422") - buf.write("\7p\2\2\u0422\u0423\7v\2\2\u0423\u0424\7k\2\2\u0424\u0425") - buf.write("\7h\2\2\u0425\u0426\7k\2\2\u0426\u0427\7g\2\2\u0427\u0428") - buf.write("\7t\2\2\u0428\u00d0\3\2\2\2\u0429\u042a\7o\2\2\u042a\u042b") - buf.write("\7g\2\2\u042b\u042c\7c\2\2\u042c\u042d\7u\2\2\u042d\u042e") - buf.write("\7w\2\2\u042e\u042f\7t\2\2\u042f\u0430\7g\2\2\u0430\u00d2") - buf.write("\3\2\2\2\u0431\u0432\7c\2\2\u0432\u0433\7v\2\2\u0433\u0434") - buf.write("\7v\2\2\u0434\u0435\7t\2\2\u0435\u0436\7k\2\2\u0436\u0437") - buf.write("\7d\2\2\u0437\u0438\7w\2\2\u0438\u0439\7v\2\2\u0439\u043a") - buf.write("\7g\2\2\u043a\u00d4\3\2\2\2\u043b\u043c\7h\2\2\u043c\u043d") - buf.write("\7k\2\2\u043d\u043e\7n\2\2\u043e\u043f\7v\2\2\u043f\u0440") - buf.write("\7g\2\2\u0440\u0441\7t\2\2\u0441\u00d6\3\2\2\2\u0442\u0443") - buf.write("\7o\2\2\u0443\u0444\7g\2\2\u0444\u0445\7t\2\2\u0445\u0446") - buf.write("\7i\2\2\u0446\u0447\7g\2\2\u0447\u00d8\3\2\2\2\u0448\u0449") - buf.write("\7g\2\2\u0449\u044a\7z\2\2\u044a\u044b\7r\2\2\u044b\u00da") - buf.write("\3\2\2\2\u044c\u044d\7e\2\2\u044d\u044e\7q\2\2\u044e\u044f") - buf.write("\7o\2\2\u044f\u0450\7r\2\2\u0450\u0451\7q\2\2\u0451\u0452") - buf.write("\7p\2\2\u0452\u0453\7g\2\2\u0453\u0454\7p\2\2\u0454\u0455") - buf.write("\7v\2\2\u0455\u0456\7T\2\2\u0456\u0457\7q\2\2\u0457\u0458") - buf.write("\7n\2\2\u0458\u0459\7g\2\2\u0459\u00dc\3\2\2\2\u045a\u045b") - buf.write("\7x\2\2\u045b\u045c\7k\2\2\u045c\u045d\7t\2\2\u045d\u045e") - buf.write("\7c\2\2\u045e\u045f\7n\2\2\u045f\u00de\3\2\2\2\u0460\u0461") - buf.write("\7o\2\2\u0461\u0462\7c\2\2\u0462\u0463\7v\2\2\u0463\u0464") - buf.write("\7e\2\2\u0464\u0465\7j\2\2\u0465\u0466\7a\2\2\u0466\u0467") - buf.write("\7e\2\2\u0467\u0468\7j\2\2\u0468\u0469\7c\2\2\u0469\u046a") - buf.write("\7t\2\2\u046a\u046b\7c\2\2\u046b\u046c\7e\2\2\u046c\u046d") - buf.write("\7v\2\2\u046d\u046e\7g\2\2\u046e\u046f\7t\2\2\u046f\u0470") - buf.write("\7u\2\2\u0470\u00e0\3\2\2\2\u0471\u0472\7v\2\2\u0472\u0473") - buf.write("\7{\2\2\u0473\u0474\7r\2\2\u0474\u0475\7g\2\2\u0475\u00e2") - buf.write("\3\2\2\2\u0476\u0477\7p\2\2\u0477\u0478\7x\2\2\u0478\u0479") - buf.write("\7n\2\2\u0479\u00e4\3\2\2\2\u047a\u047b\7j\2\2\u047b\u047c") - buf.write("\7k\2\2\u047c\u047d\7g\2\2\u047d\u047e\7t\2\2\u047e\u047f") - buf.write("\7c\2\2\u047f\u0480\7t\2\2\u0480\u0481\7e\2\2\u0481\u0482") - buf.write("\7j\2\2\u0482\u0483\7{\2\2\u0483\u00e6\3\2\2\2\u0484\u0485") - buf.write("\7a\2\2\u0485\u00e8\3\2\2\2\u0486\u0487\7k\2\2\u0487\u0488") - buf.write("\7p\2\2\u0488\u0489\7x\2\2\u0489\u048a\7c\2\2\u048a\u048b") - buf.write("\7n\2\2\u048b\u048c\7k\2\2\u048c\u048d\7f\2\2\u048d\u00ea") - buf.write("\3\2\2\2\u048e\u048f\7x\2\2\u048f\u0490\7c\2\2\u0490\u0491") - buf.write("\7n\2\2\u0491\u0492\7w\2\2\u0492\u0493\7g\2\2\u0493\u0494") - buf.write("\7f\2\2\u0494\u0495\7q\2\2\u0495\u0496\7o\2\2\u0496\u0497") - buf.write("\7c\2\2\u0497\u0498\7k\2\2\u0498\u0499\7p\2\2\u0499\u00ec") - buf.write("\3\2\2\2\u049a\u049b\7x\2\2\u049b\u049c\7c\2\2\u049c\u049d") - buf.write("\7t\2\2\u049d\u049e\7k\2\2\u049e\u049f\7c\2\2\u049f\u04a0") - buf.write("\7d\2\2\u04a0\u04a1\7n\2\2\u04a1\u04a2\7g\2\2\u04a2\u00ee") - buf.write("\3\2\2\2\u04a3\u04a4\7f\2\2\u04a4\u04a5\7c\2\2\u04a5\u04a6") - buf.write("\7v\2\2\u04a6\u04a7\7c\2\2\u04a7\u00f0\3\2\2\2\u04a8\u04a9") - buf.write("\7u\2\2\u04a9\u04aa\7v\2\2\u04aa\u04ab\7t\2\2\u04ab\u04ac") - buf.write("\7w\2\2\u04ac\u04ad\7e\2\2\u04ad\u04ae\7v\2\2\u04ae\u04af") - buf.write("\7w\2\2\u04af\u04b0\7t\2\2\u04b0\u04b1\7g\2\2\u04b1\u00f2") - buf.write("\3\2\2\2\u04b2\u04b3\7f\2\2\u04b3\u04b4\7c\2\2\u04b4\u04b5") - buf.write("\7v\2\2\u04b5\u04b6\7c\2\2\u04b6\u04b7\7u\2\2\u04b7\u04b8") - buf.write("\7g\2\2\u04b8\u04b9\7v\2\2\u04b9\u00f4\3\2\2\2\u04ba\u04bb") - buf.write("\7q\2\2\u04bb\u04bc\7r\2\2\u04bc\u04bd\7g\2\2\u04bd\u04be") - buf.write("\7t\2\2\u04be\u04bf\7c\2\2\u04bf\u04c0\7v\2\2\u04c0\u04c1") - buf.write("\7q\2\2\u04c1\u04c2\7t\2\2\u04c2\u00f6\3\2\2\2\u04c3\u04c4") - buf.write("\7f\2\2\u04c4\u04c5\7g\2\2\u04c5\u04c6\7h\2\2\u04c6\u04c7") - buf.write("\7k\2\2\u04c7\u04c8\7p\2\2\u04c8\u04c9\7g\2\2\u04c9\u00f8") - buf.write("\3\2\2\2\u04ca\u04cb\7>\2\2\u04cb\u04cc\7/\2\2\u04cc\u00fa") - buf.write("\3\2\2\2\u04cd\u04ce\7f\2\2\u04ce\u04cf\7c\2\2\u04cf\u04d0") - buf.write("\7v\2\2\u04d0\u04d1\7c\2\2\u04d1\u04d2\7r\2\2\u04d2\u04d3") - buf.write("\7q\2\2\u04d3\u04d4\7k\2\2\u04d4\u04d5\7p\2\2\u04d5\u04d6") - buf.write("\7v\2\2\u04d6\u00fc\3\2\2\2\u04d7\u04d8\7j\2\2\u04d8\u04d9") - buf.write("\7k\2\2\u04d9\u04da\7g\2\2\u04da\u04db\7t\2\2\u04db\u04dc") - buf.write("\7c\2\2\u04dc\u04dd\7t\2\2\u04dd\u04de\7e\2\2\u04de\u04df") - buf.write("\7j\2\2\u04df\u04e0\7k\2\2\u04e0\u04e1\7e\2\2\u04e1\u04e2") - buf.write("\7c\2\2\u04e2\u04e3\7n\2\2\u04e3\u00fe\3\2\2\2\u04e4\u04e5") - buf.write("\7t\2\2\u04e5\u04e6\7w\2\2\u04e6\u04e7\7n\2\2\u04e7\u04e8") - buf.write("\7g\2\2\u04e8\u04e9\7u\2\2\u04e9\u04ea\7g\2\2\u04ea\u04eb") - buf.write("\7v\2\2\u04eb\u0100\3\2\2\2\u04ec\u04ed\7t\2\2\u04ed\u04ee") - buf.write("\7w\2\2\u04ee\u04ef\7n\2\2\u04ef\u04f0\7g\2\2\u04f0\u0102") - buf.write("\3\2\2\2\u04f1\u04f2\7g\2\2\u04f2\u04f3\7p\2\2\u04f3\u04f4") - buf.write("\7f\2\2\u04f4\u0104\3\2\2\2\u04f5\u04f6\7c\2\2\u04f6\u04f7") - buf.write("\7n\2\2\u04f7\u04f8\7v\2\2\u04f8\u04f9\7g\2\2\u04f9\u04fa") - buf.write("\7t\2\2\u04fa\u04fb\7F\2\2\u04fb\u04fc\7c\2\2\u04fc\u04fd") - buf.write("\7v\2\2\u04fd\u04fe\7c\2\2\u04fe\u04ff\7u\2\2\u04ff\u0500") - buf.write("\7g\2\2\u0500\u0501\7v\2\2\u0501\u0106\3\2\2\2\u0502\u0503") - buf.write("\7n\2\2\u0503\u0504\7v\2\2\u0504\u0505\7t\2\2\u0505\u0506") - buf.write("\7k\2\2\u0506\u0507\7o\2\2\u0507\u0108\3\2\2\2\u0508\u0509") - buf.write("\7t\2\2\u0509\u050a\7v\2\2\u050a\u050b\7t\2\2\u050b\u050c") - buf.write("\7k\2\2\u050c\u050d\7o\2\2\u050d\u010a\3\2\2\2\u050e\u050f") - buf.write("\7k\2\2\u050f\u0510\7p\2\2\u0510\u0511\7u\2\2\u0511\u0512") - buf.write("\7v\2\2\u0512\u0513\7t\2\2\u0513\u010c\3\2\2\2\u0514\u0515") - buf.write("\7t\2\2\u0515\u0516\7g\2\2\u0516\u0517\7r\2\2\u0517\u0518") - buf.write("\7n\2\2\u0518\u0519\7c\2\2\u0519\u051a\7e\2\2\u051a\u051b") - buf.write("\7g\2\2\u051b\u010e\3\2\2\2\u051c\u051d\7e\2\2\u051d\u051e") - buf.write("\7g\2\2\u051e\u051f\7k\2\2\u051f\u0520\7n\2\2\u0520\u0110") - buf.write("\3\2\2\2\u0521\u0522\7h\2\2\u0522\u0523\7n\2\2\u0523\u0524") - buf.write("\7q\2\2\u0524\u0525\7q\2\2\u0525\u0526\7t\2\2\u0526\u0112") - buf.write("\3\2\2\2\u0527\u0528\7u\2\2\u0528\u0529\7s\2\2\u0529\u052a") - buf.write("\7t\2\2\u052a\u052b\7v\2\2\u052b\u0114\3\2\2\2\u052c\u052d") - buf.write("\7c\2\2\u052d\u052e\7p\2\2\u052e\u052f\7{\2\2\u052f\u0116") - buf.write("\3\2\2\2\u0530\u0531\7u\2\2\u0531\u0532\7g\2\2\u0532\u0533") - buf.write("\7v\2\2\u0533\u0534\7f\2\2\u0534\u0535\7k\2\2\u0535\u0536") - buf.write("\7h\2\2\u0536\u0537\7h\2\2\u0537\u0118\3\2\2\2\u0538\u0539") - buf.write("\7u\2\2\u0539\u053a\7v\2\2\u053a\u053b\7f\2\2\u053b\u053c") - buf.write("\7f\2\2\u053c\u053d\7g\2\2\u053d\u053e\7x\2\2\u053e\u053f") - buf.write("\7a\2\2\u053f\u0540\7r\2\2\u0540\u0541\7q\2\2\u0541\u0542") - buf.write("\7r\2\2\u0542\u011a\3\2\2\2\u0543\u0544\7u\2\2\u0544\u0545") - buf.write("\7v\2\2\u0545\u0546\7f\2\2\u0546\u0547\7f\2\2\u0547\u0548") - buf.write("\7g\2\2\u0548\u0549\7x\2\2\u0549\u054a\7a\2\2\u054a\u054b") - buf.write("\7u\2\2\u054b\u054c\7c\2\2\u054c\u054d\7o\2\2\u054d\u054e") - buf.write("\7r\2\2\u054e\u011c\3\2\2\2\u054f\u0550\7x\2\2\u0550\u0551") - buf.write("\7c\2\2\u0551\u0552\7t\2\2\u0552\u0553\7a\2\2\u0553\u0554") - buf.write("\7r\2\2\u0554\u0555\7q\2\2\u0555\u0556\7r\2\2\u0556\u011e") - buf.write("\3\2\2\2\u0557\u0558\7x\2\2\u0558\u0559\7c\2\2\u0559\u055a") - buf.write("\7t\2\2\u055a\u055b\7a\2\2\u055b\u055c\7u\2\2\u055c\u055d") - buf.write("\7c\2\2\u055d\u055e\7o\2\2\u055e\u055f\7r\2\2\u055f\u0120") - buf.write("\3\2\2\2\u0560\u0561\7i\2\2\u0561\u0562\7t\2\2\u0562\u0563") - buf.write("\7q\2\2\u0563\u0564\7w\2\2\u0564\u0565\7r\2\2\u0565\u0122") - buf.write("\3\2\2\2\u0566\u0567\7g\2\2\u0567\u0568\7z\2\2\u0568\u0569") - buf.write("\7e\2\2\u0569\u056a\7g\2\2\u056a\u056b\7r\2\2\u056b\u056c") - buf.write("\7v\2\2\u056c\u0124\3\2\2\2\u056d\u056e\7j\2\2\u056e\u056f") - buf.write("\7c\2\2\u056f\u0570\7x\2\2\u0570\u0571\7k\2\2\u0571\u0572") - buf.write("\7p\2\2\u0572\u0573\7i\2\2\u0573\u0126\3\2\2\2\u0574\u0575") - buf.write("\7h\2\2\u0575\u0576\7k\2\2\u0576\u0577\7t\2\2\u0577\u0578") - buf.write("\7u\2\2\u0578\u0579\7v\2\2\u0579\u057a\7a\2\2\u057a\u057b") - buf.write("\7x\2\2\u057b\u057c\7c\2\2\u057c\u057d\7n\2\2\u057d\u057e") - buf.write("\7w\2\2\u057e\u057f\7g\2\2\u057f\u0128\3\2\2\2\u0580\u0581") - buf.write("\7n\2\2\u0581\u0582\7c\2\2\u0582\u0583\7u\2\2\u0583\u0584") - buf.write("\7v\2\2\u0584\u0585\7a\2\2\u0585\u0586\7x\2\2\u0586\u0587") - buf.write("\7c\2\2\u0587\u0588\7n\2\2\u0588\u0589\7w\2\2\u0589\u058a") - buf.write("\7g\2\2\u058a\u012a\3\2\2\2\u058b\u058c\7n\2\2\u058c\u058d") - buf.write("\7c\2\2\u058d\u058e\7i\2\2\u058e\u012c\3\2\2\2\u058f\u0590") - buf.write("\7n\2\2\u0590\u0591\7g\2\2\u0591\u0592\7c\2\2\u0592\u0593") - buf.write("\7f\2\2\u0593\u012e\3\2\2\2\u0594\u0595\7t\2\2\u0595\u0596") - buf.write("\7c\2\2\u0596\u0597\7v\2\2\u0597\u0598\7k\2\2\u0598\u0599") - buf.write("\7q\2\2\u0599\u059a\7a\2\2\u059a\u059b\7v\2\2\u059b\u059c") - buf.write("\7q\2\2\u059c\u059d\7a\2\2\u059d\u059e\7t\2\2\u059e\u059f") - buf.write("\7g\2\2\u059f\u05a0\7r\2\2\u05a0\u05a1\7q\2\2\u05a1\u05a2") - buf.write("\7t\2\2\u05a2\u05a3\7v\2\2\u05a3\u0130\3\2\2\2\u05a4\u05a5") - buf.write("\7q\2\2\u05a5\u05a6\7x\2\2\u05a6\u05a7\7g\2\2\u05a7\u05a8") - buf.write("\7t\2\2\u05a8\u0132\3\2\2\2\u05a9\u05aa\7r\2\2\u05aa\u05ab") - buf.write("\7t\2\2\u05ab\u05ac\7g\2\2\u05ac\u05ad\7e\2\2\u05ad\u05ae") - buf.write("\7g\2\2\u05ae\u05af\7f\2\2\u05af\u05b0\7k\2\2\u05b0\u05b1") - buf.write("\7p\2\2\u05b1\u05b2\7i\2\2\u05b2\u0134\3\2\2\2\u05b3\u05b4") - buf.write("\7h\2\2\u05b4\u05b5\7q\2\2\u05b5\u05b6\7n\2\2\u05b6\u05b7") - buf.write("\7n\2\2\u05b7\u05b8\7q\2\2\u05b8\u05b9\7y\2\2\u05b9\u05ba") - buf.write("\7k\2\2\u05ba\u05bb\7p\2\2\u05bb\u05bc\7i\2\2\u05bc\u0136") - buf.write("\3\2\2\2\u05bd\u05be\7w\2\2\u05be\u05bf\7p\2\2\u05bf\u05c0") - buf.write("\7d\2\2\u05c0\u05c1\7q\2\2\u05c1\u05c2\7w\2\2\u05c2\u05c3") - buf.write("\7p\2\2\u05c3\u05c4\7f\2\2\u05c4\u05c5\7g\2\2\u05c5\u05c6") - buf.write("\7f\2\2\u05c6\u0138\3\2\2\2\u05c7\u05c8\7r\2\2\u05c8\u05c9") - buf.write("\7c\2\2\u05c9\u05ca\7t\2\2\u05ca\u05cb\7v\2\2\u05cb\u05cc") - buf.write("\7k\2\2\u05cc\u05cd\7v\2\2\u05cd\u05ce\7k\2\2\u05ce\u05cf") - buf.write("\7q\2\2\u05cf\u05d0\7p\2\2\u05d0\u013a\3\2\2\2\u05d1\u05d2") - buf.write("\7t\2\2\u05d2\u05d3\7q\2\2\u05d3\u05d4\7y\2\2\u05d4\u05d5") - buf.write("\7u\2\2\u05d5\u013c\3\2\2\2\u05d6\u05d7\7t\2\2\u05d7\u05d8") - buf.write("\7c\2\2\u05d8\u05d9\7p\2\2\u05d9\u05da\7i\2\2\u05da\u05db") - buf.write("\7g\2\2\u05db\u013e\3\2\2\2\u05dc\u05dd\7e\2\2\u05dd\u05de") - buf.write("\7w\2\2\u05de\u05df\7t\2\2\u05df\u05e0\7t\2\2\u05e0\u05e1") - buf.write("\7g\2\2\u05e1\u05e2\7p\2\2\u05e2\u05e3\7v\2\2\u05e3\u0140") - buf.write("\3\2\2\2\u05e4\u05e5\7x\2\2\u05e5\u05e6\7c\2\2\u05e6\u05e7") - buf.write("\7n\2\2\u05e7\u05e8\7k\2\2\u05e8\u05e9\7f\2\2\u05e9\u0142") - buf.write("\3\2\2\2\u05ea\u05eb\7h\2\2\u05eb\u05ec\7k\2\2\u05ec\u05ed") - buf.write("\7n\2\2\u05ed\u05ee\7n\2\2\u05ee\u05ef\7a\2\2\u05ef\u05f0") - buf.write("\7v\2\2\u05f0\u05f1\7k\2\2\u05f1\u05f2\7o\2\2\u05f2\u05f3") - buf.write("\7g\2\2\u05f3\u05f4\7a\2\2\u05f4\u05f5\7u\2\2\u05f5\u05f6") - buf.write("\7g\2\2\u05f6\u05f7\7t\2\2\u05f7\u05f8\7k\2\2\u05f8\u05f9") - buf.write("\7g\2\2\u05f9\u05fa\7u\2\2\u05fa\u0144\3\2\2\2\u05fb\u05fc") - buf.write("\7h\2\2\u05fc\u05fd\7n\2\2\u05fd\u05fe\7q\2\2\u05fe\u05ff") - buf.write("\7y\2\2\u05ff\u0600\7a\2\2\u0600\u0601\7v\2\2\u0601\u0602") - buf.write("\7q\2\2\u0602\u0603\7a\2\2\u0603\u0604\7u\2\2\u0604\u0605") - buf.write("\7v\2\2\u0605\u0606\7q\2\2\u0606\u0607\7e\2\2\u0607\u0608") - buf.write("\7m\2\2\u0608\u0146\3\2\2\2\u0609\u060a\7u\2\2\u060a\u060b") - buf.write("\7v\2\2\u060b\u060c\7q\2\2\u060c\u060d\7e\2\2\u060d\u060e") - buf.write("\7m\2\2\u060e\u060f\7a\2\2\u060f\u0610\7v\2\2\u0610\u0611") - buf.write("\7q\2\2\u0611\u0612\7a\2\2\u0612\u0613\7h\2\2\u0613\u0614") - buf.write("\7n\2\2\u0614\u0615\7q\2\2\u0615\u0616\7y\2\2\u0616\u0148") - buf.write("\3\2\2\2\u0617\u0618\7v\2\2\u0618\u0619\7k\2\2\u0619\u061a") - buf.write("\7o\2\2\u061a\u061b\7g\2\2\u061b\u061c\7u\2\2\u061c\u061d") - buf.write("\7j\2\2\u061d\u061e\7k\2\2\u061e\u061f\7h\2\2\u061f\u0620") - buf.write("\7v\2\2\u0620\u014a\3\2\2\2\u0621\u0622\7o\2\2\u0622\u0623") - buf.write("\7g\2\2\u0623\u0624\7c\2\2\u0624\u0625\7u\2\2\u0625\u0626") - buf.write("\7w\2\2\u0626\u0627\7t\2\2\u0627\u0628\7g\2\2\u0628\u0629") - buf.write("\7u\2\2\u0629\u014c\3\2\2\2\u062a\u062b\7p\2\2\u062b\u062c") - buf.write("\7q\2\2\u062c\u062d\7a\2\2\u062d\u062e\7o\2\2\u062e\u062f") - buf.write("\7g\2\2\u062f\u0630\7c\2\2\u0630\u0631\7u\2\2\u0631\u0632") - buf.write("\7w\2\2\u0632\u0633\7t\2\2\u0633\u0634\7g\2\2\u0634\u0635") - buf.write("\7u\2\2\u0635\u014e\3\2\2\2\u0636\u0637\7e\2\2\u0637\u0638") - buf.write("\7q\2\2\u0638\u0639\7p\2\2\u0639\u063a\7f\2\2\u063a\u063b") - buf.write("\7k\2\2\u063b\u063c\7v\2\2\u063c\u063d\7k\2\2\u063d\u063e") - buf.write("\7q\2\2\u063e\u063f\7p\2\2\u063f\u0150\3\2\2\2\u0640\u0641") - buf.write("\7d\2\2\u0641\u0642\7q\2\2\u0642\u0643\7q\2\2\u0643\u0644") - buf.write("\7n\2\2\u0644\u0645\7g\2\2\u0645\u0646\7c\2\2\u0646\u0647") - buf.write("\7p\2\2\u0647\u0152\3\2\2\2\u0648\u0649\7f\2\2\u0649\u064a") - buf.write("\7c\2\2\u064a\u064b\7v\2\2\u064b\u064c\7g\2\2\u064c\u0154") - buf.write("\3\2\2\2\u064d\u064e\7v\2\2\u064e\u064f\7k\2\2\u064f\u0650") - buf.write("\7o\2\2\u0650\u0651\7g\2\2\u0651\u0652\7a\2\2\u0652\u0653") - buf.write("\7r\2\2\u0653\u0654\7g\2\2\u0654\u0655\7t\2\2\u0655\u0656") - buf.write("\7k\2\2\u0656\u0657\7q\2\2\u0657\u0658\7f\2\2\u0658\u0156") - buf.write("\3\2\2\2\u0659\u065a\7p\2\2\u065a\u065b\7w\2\2\u065b\u065c") - buf.write("\7o\2\2\u065c\u065d\7d\2\2\u065d\u065e\7g\2\2\u065e\u065f") - buf.write("\7t\2\2\u065f\u0158\3\2\2\2\u0660\u0661\7u\2\2\u0661\u0662") - buf.write("\7v\2\2\u0662\u0663\7t\2\2\u0663\u0664\7k\2\2\u0664\u0665") - buf.write("\7p\2\2\u0665\u0666\7i\2\2\u0666\u015a\3\2\2\2\u0667\u0668") - buf.write("\7v\2\2\u0668\u0669\7k\2\2\u0669\u066a\7o\2\2\u066a\u066b") - buf.write("\7g\2\2\u066b\u015c\3\2\2\2\u066c\u066d\7k\2\2\u066d\u066e") - buf.write("\7p\2\2\u066e\u066f\7v\2\2\u066f\u0670\7g\2\2\u0670\u0671") - buf.write("\7i\2\2\u0671\u0672\7g\2\2\u0672\u0673\7t\2\2\u0673\u015e") - buf.write("\3\2\2\2\u0674\u0675\7h\2\2\u0675\u0676\7n\2\2\u0676\u0677") - buf.write("\7q\2\2\u0677\u0678\7c\2\2\u0678\u0679\7v\2\2\u0679\u0160") - buf.write("\3\2\2\2\u067a\u067b\7n\2\2\u067b\u067c\7k\2\2\u067c\u067d") - buf.write("\7u\2\2\u067d\u067e\7v\2\2\u067e\u0162\3\2\2\2\u067f\u0680") - buf.write("\7t\2\2\u0680\u0681\7g\2\2\u0681\u0682\7e\2\2\u0682\u0683") - buf.write("\7q\2\2\u0683\u0684\7t\2\2\u0684\u0685\7f\2\2\u0685\u0164") - buf.write("\3\2\2\2\u0686\u0687\7t\2\2\u0687\u0688\7g\2\2\u0688\u0689") - buf.write("\7u\2\2\u0689\u068a\7v\2\2\u068a\u068b\7t\2\2\u068b\u068c") - buf.write("\7k\2\2\u068c\u068d\7e\2\2\u068d\u068e\7v\2\2\u068e\u0166") - buf.write("\3\2\2\2\u068f\u0690\7{\2\2\u0690\u0691\7{\2\2\u0691\u0692") - buf.write("\7{\2\2\u0692\u0693\7{\2\2\u0693\u0168\3\2\2\2\u0694\u0695") - buf.write("\7o\2\2\u0695\u0696\7o\2\2\u0696\u016a\3\2\2\2\u0697\u0698") - buf.write("\7f\2\2\u0698\u0699\7f\2\2\u0699\u016c\3\2\2\2\u069a\u069b") - buf.write("\7o\2\2\u069b\u069c\7c\2\2\u069c\u069d\7z\2\2\u069d\u069e") - buf.write("\7N\2\2\u069e\u069f\7g\2\2\u069f\u06a0\7p\2\2\u06a0\u06a1") - buf.write("\7i\2\2\u06a1\u06a2\7v\2\2\u06a2\u06a3\7j\2\2\u06a3\u016e") - buf.write("\3\2\2\2\u06a4\u06a5\7t\2\2\u06a5\u06a6\7g\2\2\u06a6\u06a7") - buf.write("\7i\2\2\u06a7\u06a8\7g\2\2\u06a8\u06a9\7z\2\2\u06a9\u06aa") - buf.write("\7r\2\2\u06aa\u0170\3\2\2\2\u06ab\u06ac\7k\2\2\u06ac\u06ad") - buf.write("\7u\2\2\u06ad\u0172\3\2\2\2\u06ae\u06af\7y\2\2\u06af\u06b0") - buf.write("\7j\2\2\u06b0\u06b1\7g\2\2\u06b1\u06b2\7p\2\2\u06b2\u0174") - buf.write("\3\2\2\2\u06b3\u06b4\7h\2\2\u06b4\u06b5\7t\2\2\u06b5\u06b6") - buf.write("\7q\2\2\u06b6\u06b7\7o\2\2\u06b7\u0176\3\2\2\2\u06b8\u06b9") - buf.write("\7c\2\2\u06b9\u06ba\7i\2\2\u06ba\u06bb\7i\2\2\u06bb\u06bc") - buf.write("\7t\2\2\u06bc\u06bd\7g\2\2\u06bd\u06be\7i\2\2\u06be\u06bf") - buf.write("\7c\2\2\u06bf\u06c0\7v\2\2\u06c0\u06c1\7g\2\2\u06c1\u06c2") - buf.write("\7u\2\2\u06c2\u0178\3\2\2\2\u06c3\u06c4\7r\2\2\u06c4\u06c5") - buf.write("\7q\2\2\u06c5\u06c6\7k\2\2\u06c6\u06c7\7p\2\2\u06c7\u06c8") - buf.write("\7v\2\2\u06c8\u06c9\7u\2\2\u06c9\u017a\3\2\2\2\u06ca\u06cb") - buf.write("\7r\2\2\u06cb\u06cc\7q\2\2\u06cc\u06cd\7k\2\2\u06cd\u06ce") - buf.write("\7p\2\2\u06ce\u06cf\7v\2\2\u06cf\u017c\3\2\2\2\u06d0\u06d1") - buf.write("\7v\2\2\u06d1\u06d2\7q\2\2\u06d2\u06d3\7v\2\2\u06d3\u06d4") - buf.write("\7c\2\2\u06d4\u06d5\7n\2\2\u06d5\u017e\3\2\2\2\u06d6\u06d7") - buf.write("\7r\2\2\u06d7\u06d8\7c\2\2\u06d8\u06d9\7t\2\2\u06d9\u06da") - buf.write("\7v\2\2\u06da\u06db\7k\2\2\u06db\u06dc\7c\2\2\u06dc\u06dd") - buf.write("\7n\2\2\u06dd\u0180\3\2\2\2\u06de\u06df\7c\2\2\u06df\u06e0") - buf.write("\7n\2\2\u06e0\u06e1\7y\2\2\u06e1\u06e2\7c\2\2\u06e2\u06e3") - buf.write("\7{\2\2\u06e3\u06e4\7u\2\2\u06e4\u0182\3\2\2\2\u06e5\u06e6") - buf.write("\7k\2\2\u06e6\u06e7\7p\2\2\u06e7\u06e8\7p\2\2\u06e8\u06e9") - buf.write("\7g\2\2\u06e9\u06ea\7t\2\2\u06ea\u06eb\7a\2\2\u06eb\u06ec") - buf.write("\7l\2\2\u06ec\u06ed\7q\2\2\u06ed\u06ee\7k\2\2\u06ee\u06ef") - buf.write("\7p\2\2\u06ef\u0184\3\2\2\2\u06f0\u06f1\7n\2\2\u06f1\u06f2") - buf.write("\7g\2\2\u06f2\u06f3\7h\2\2\u06f3\u06f4\7v\2\2\u06f4\u06f5") - buf.write("\7a\2\2\u06f5\u06f6\7l\2\2\u06f6\u06f7\7q\2\2\u06f7\u06f8") - buf.write("\7k\2\2\u06f8\u06f9\7p\2\2\u06f9\u0186\3\2\2\2\u06fa\u06fb") - buf.write("\7e\2\2\u06fb\u06fc\7t\2\2\u06fc\u06fd\7q\2\2\u06fd\u06fe") - buf.write("\7u\2\2\u06fe\u06ff\7u\2\2\u06ff\u0700\7a\2\2\u0700\u0701") - buf.write("\7l\2\2\u0701\u0702\7q\2\2\u0702\u0703\7k\2\2\u0703\u0704") - buf.write("\7p\2\2\u0704\u0188\3\2\2\2\u0705\u0706\7h\2\2\u0706\u0707") - buf.write("\7w\2\2\u0707\u0708\7n\2\2\u0708\u0709\7n\2\2\u0709\u070a") - buf.write("\7a\2\2\u070a\u070b\7l\2\2\u070b\u070c\7q\2\2\u070c\u070d") - buf.write("\7k\2\2\u070d\u070e\7p\2\2\u070e\u018a\3\2\2\2\u070f\u0710") - buf.write("\7o\2\2\u0710\u0711\7c\2\2\u0711\u0712\7r\2\2\u0712\u0713") - buf.write("\7u\2\2\u0713\u0714\7a\2\2\u0714\u0715\7h\2\2\u0715\u0716") - buf.write("\7t\2\2\u0716\u0717\7q\2\2\u0717\u0718\7o\2\2\u0718\u018c") - buf.write("\3\2\2\2\u0719\u071a\7o\2\2\u071a\u071b\7c\2\2\u071b\u071c") - buf.write("\7r\2\2\u071c\u071d\7u\2\2\u071d\u071e\7a\2\2\u071e\u071f") - buf.write("\7v\2\2\u071f\u0720\7q\2\2\u0720\u018e\3\2\2\2\u0721\u0722") - buf.write("\7o\2\2\u0722\u0723\7c\2\2\u0723\u0724\7r\2\2\u0724\u0725") - buf.write("\7a\2\2\u0725\u0726\7v\2\2\u0726\u0727\7q\2\2\u0727\u0190") - buf.write("\3\2\2\2\u0728\u0729\7o\2\2\u0729\u072a\7c\2\2\u072a\u072b") - buf.write("\7r\2\2\u072b\u072c\7a\2\2\u072c\u072d\7h\2\2\u072d\u072e") - buf.write("\7t\2\2\u072e\u072f\7q\2\2\u072f\u0730\7o\2\2\u0730\u0192") - buf.write("\3\2\2\2\u0731\u0732\7t\2\2\u0732\u0733\7g\2\2\u0733\u0734") - buf.write("\7v\2\2\u0734\u0735\7w\2\2\u0735\u0736\7t\2\2\u0736\u0737") - buf.write("\7p\2\2\u0737\u0738\7u\2\2\u0738\u0194\3\2\2\2\u0739\u073a") - buf.write("\7r\2\2\u073a\u073b\7k\2\2\u073b\u073c\7x\2\2\u073c\u073d") - buf.write("\7q\2\2\u073d\u073e\7v\2\2\u073e\u0196\3\2\2\2\u073f\u0740") - buf.write("\7e\2\2\u0740\u0741\7w\2\2\u0741\u0742\7u\2\2\u0742\u0743") - buf.write("\7v\2\2\u0743\u0744\7q\2\2\u0744\u0745\7o\2\2\u0745\u0746") - buf.write("\7R\2\2\u0746\u0747\7k\2\2\u0747\u0748\7x\2\2\u0748\u0749") - buf.write("\7q\2\2\u0749\u074a\7v\2\2\u074a\u0198\3\2\2\2\u074b\u074c") - buf.write("\7w\2\2\u074c\u074d\7p\2\2\u074d\u074e\7r\2\2\u074e\u074f") - buf.write("\7k\2\2\u074f\u0750\7x\2\2\u0750\u0751\7q\2\2\u0751\u0752") - buf.write("\7v\2\2\u0752\u019a\3\2\2\2\u0753\u0754\7u\2\2\u0754\u0755") - buf.write("\7w\2\2\u0755\u0756\7d\2\2\u0756\u019c\3\2\2\2\u0757\u0758") - buf.write("\7c\2\2\u0758\u0759\7r\2\2\u0759\u075a\7r\2\2\u075a\u075b") - buf.write("\7n\2\2\u075b\u075c\7{\2\2\u075c\u019e\3\2\2\2\u075d\u075e") - buf.write("\7e\2\2\u075e\u075f\7q\2\2\u075f\u0760\7p\2\2\u0760\u0761") - buf.write("\7f\2\2\u0761\u0762\7k\2\2\u0762\u0763\7v\2\2\u0763\u0764") - buf.write("\7k\2\2\u0764\u0765\7q\2\2\u0765\u0766\7p\2\2\u0766\u0767") - buf.write("\7g\2\2\u0767\u0768\7f\2\2\u0768\u01a0\3\2\2\2\u0769\u076a") - buf.write("\7r\2\2\u076a\u076b\7g\2\2\u076b\u076c\7t\2\2\u076c\u076d") - buf.write("\7k\2\2\u076d\u076e\7q\2\2\u076e\u076f\7f\2\2\u076f\u0770") - buf.write("\7a\2\2\u0770\u0771\7k\2\2\u0771\u0772\7p\2\2\u0772\u0773") - buf.write("\7f\2\2\u0773\u0774\7k\2\2\u0774\u0775\7e\2\2\u0775\u0776") - buf.write("\7c\2\2\u0776\u0777\7v\2\2\u0777\u0778\7q\2\2\u0778\u0779") - buf.write("\7t\2\2\u0779\u01a2\3\2\2\2\u077a\u077b\7u\2\2\u077b\u077c") - buf.write("\7k\2\2\u077c\u077d\7p\2\2\u077d\u077e\7i\2\2\u077e\u077f") - buf.write("\7n\2\2\u077f\u0780\7g\2\2\u0780\u01a4\3\2\2\2\u0781\u0782") - buf.write("\7f\2\2\u0782\u0783\7w\2\2\u0783\u0784\7t\2\2\u0784\u0785") - buf.write("\7c\2\2\u0785\u0786\7v\2\2\u0786\u0787\7k\2\2\u0787\u0788") - buf.write("\7q\2\2\u0788\u0789\7p\2\2\u0789\u01a6\3\2\2\2\u078a\u078b") - buf.write("\7v\2\2\u078b\u078c\7k\2\2\u078c\u078d\7o\2\2\u078d\u078e") - buf.write("\7g\2\2\u078e\u078f\7a\2\2\u078f\u0790\7c\2\2\u0790\u0791") - buf.write("\7i\2\2\u0791\u0792\7i\2\2\u0792\u01a8\3\2\2\2\u0793\u0794") - buf.write("\7w\2\2\u0794\u0795\7p\2\2\u0795\u0796\7k\2\2\u0796\u0797") - buf.write("\7v\2\2\u0797\u01aa\3\2\2\2\u0798\u0799\7X\2\2\u0799\u079a") - buf.write("\7c\2\2\u079a\u079b\7n\2\2\u079b\u079c\7w\2\2\u079c\u079d") - buf.write("\7g\2\2\u079d\u01ac\3\2\2\2\u079e\u079f\7x\2\2\u079f\u07a0") - buf.write("\7c\2\2\u07a0\u07a1\7n\2\2\u07a1\u07a2\7w\2\2\u07a2\u07a3") - buf.write("\7g\2\2\u07a3\u07a4\7f\2\2\u07a4\u07a5\7q\2\2\u07a5\u07a6") - buf.write("\7o\2\2\u07a6\u07a7\7c\2\2\u07a7\u07a8\7k\2\2\u07a8\u07a9") - buf.write("\7p\2\2\u07a9\u07aa\7u\2\2\u07aa\u01ae\3\2\2\2\u07ab\u07ac") - buf.write("\7x\2\2\u07ac\u07ad\7c\2\2\u07ad\u07ae\7t\2\2\u07ae\u07af") - buf.write("\7k\2\2\u07af\u07b0\7c\2\2\u07b0\u07b1\7d\2\2\u07b1\u07b2") - buf.write("\7n\2\2\u07b2\u07b3\7g\2\2\u07b3\u07b4\7u\2\2\u07b4\u01b0") - buf.write("\3\2\2\2\u07b5\u07b6\7k\2\2\u07b6\u07b7\7p\2\2\u07b7\u07b8") - buf.write("\7r\2\2\u07b8\u07b9\7w\2\2\u07b9\u07ba\7v\2\2\u07ba\u01b2") - buf.write("\3\2\2\2\u07bb\u07bc\7q\2\2\u07bc\u07bd\7w\2\2\u07bd\u07be") - buf.write("\7v\2\2\u07be\u07bf\7r\2\2\u07bf\u07c0\7w\2\2\u07c0\u07c1") - buf.write("\7v\2\2\u07c1\u01b4\3\2\2\2\u07c2\u07c3\7e\2\2\u07c3\u07c4") - buf.write("\7c\2\2\u07c4\u07c5\7u\2\2\u07c5\u07c6\7v\2\2\u07c6\u01b6") - buf.write("\3\2\2\2\u07c7\u07c8\7t\2\2\u07c8\u07c9\7w\2\2\u07c9\u07ca") - buf.write("\7n\2\2\u07ca\u07cb\7g\2\2\u07cb\u07cc\7a\2\2\u07cc\u07cd") - buf.write("\7r\2\2\u07cd\u07ce\7t\2\2\u07ce\u07cf\7k\2\2\u07cf\u07d0") - buf.write("\7q\2\2\u07d0\u07d1\7t\2\2\u07d1\u07d2\7k\2\2\u07d2\u07d3") - buf.write("\7v\2\2\u07d3\u07d4\7{\2\2\u07d4\u01b8\3\2\2\2\u07d5\u07d6") - buf.write("\7f\2\2\u07d6\u07d7\7c\2\2\u07d7\u07d8\7v\2\2\u07d8\u07d9") - buf.write("\7c\2\2\u07d9\u07da\7u\2\2\u07da\u07db\7g\2\2\u07db\u07dc") - buf.write("\7v\2\2\u07dc\u07dd\7a\2\2\u07dd\u07de\7r\2\2\u07de\u07df") - buf.write("\7t\2\2\u07df\u07e0\7k\2\2\u07e0\u07e1\7q\2\2\u07e1\u07e2") - buf.write("\7t\2\2\u07e2\u07e3\7k\2\2\u07e3\u07e4\7v\2\2\u07e4\u07e5") - buf.write("\7{\2\2\u07e5\u01ba\3\2\2\2\u07e6\u07e7\7f\2\2\u07e7\u07e8") - buf.write("\7g\2\2\u07e8\u07e9\7h\2\2\u07e9\u07ea\7c\2\2\u07ea\u07eb") - buf.write("\7w\2\2\u07eb\u07ec\7n\2\2\u07ec\u07ed\7v\2\2\u07ed\u01bc") - buf.write("\3\2\2\2\u07ee\u07ef\7e\2\2\u07ef\u07f0\7j\2\2\u07f0\u07f1") - buf.write("\7g\2\2\u07f1\u07f2\7e\2\2\u07f2\u07f3\7m\2\2\u07f3\u07f4") - buf.write("\7a\2\2\u07f4\u07f5\7f\2\2\u07f5\u07f6\7c\2\2\u07f6\u07f7") - buf.write("\7v\2\2\u07f7\u07f8\7c\2\2\u07f8\u07f9\7r\2\2\u07f9\u07fa") - buf.write("\7q\2\2\u07fa\u07fb\7k\2\2\u07fb\u07fc\7p\2\2\u07fc\u07fd") - buf.write("\7v\2\2\u07fd\u01be\3\2\2\2\u07fe\u07ff\7e\2\2\u07ff\u0800") - buf.write("\7j\2\2\u0800\u0801\7g\2\2\u0801\u0802\7e\2\2\u0802\u0803") - buf.write("\7m\2\2\u0803\u0804\7a\2\2\u0804\u0805\7j\2\2\u0805\u0806") - buf.write("\7k\2\2\u0806\u0807\7g\2\2\u0807\u0808\7t\2\2\u0808\u0809") - buf.write("\7c\2\2\u0809\u080a\7t\2\2\u080a\u080b\7e\2\2\u080b\u080c") - buf.write("\7j\2\2\u080c\u080d\7{\2\2\u080d\u01c0\3\2\2\2\u080e\u080f") - buf.write("\7e\2\2\u080f\u0810\7q\2\2\u0810\u0811\7o\2\2\u0811\u0812") - buf.write("\7r\2\2\u0812\u0813\7w\2\2\u0813\u0814\7v\2\2\u0814\u0815") - buf.write("\7g\2\2\u0815\u0816\7f\2\2\u0816\u01c2\3\2\2\2\u0817\u0818") - buf.write("\7p\2\2\u0818\u0819\7q\2\2\u0819\u081a\7p\2\2\u081a\u081b") - buf.write("\7a\2\2\u081b\u081c\7p\2\2\u081c\u081d\7w\2\2\u081d\u081e") - buf.write("\7n\2\2\u081e\u081f\7n\2\2\u081f\u01c4\3\2\2\2\u0820\u0821") - buf.write("\7p\2\2\u0821\u0822\7q\2\2\u0822\u0823\7p\2\2\u0823\u0824") - buf.write("\7a\2\2\u0824\u0825\7|\2\2\u0825\u0826\7g\2\2\u0826\u0827") - buf.write("\7t\2\2\u0827\u0828\7q\2\2\u0828\u01c6\3\2\2\2\u0829\u082a") - buf.write("\7r\2\2\u082a\u082b\7c\2\2\u082b\u082c\7t\2\2\u082c\u082d") - buf.write("\7v\2\2\u082d\u082e\7k\2\2\u082e\u082f\7c\2\2\u082f\u0830") - buf.write("\7n\2\2\u0830\u0831\7a\2\2\u0831\u0832\7p\2\2\u0832\u0833") - buf.write("\7w\2\2\u0833\u0834\7n\2\2\u0834\u0835\7n\2\2\u0835\u01c8") - buf.write("\3\2\2\2\u0836\u0837\7r\2\2\u0837\u0838\7c\2\2\u0838\u0839") - buf.write("\7t\2\2\u0839\u083a\7v\2\2\u083a\u083b\7k\2\2\u083b\u083c") - buf.write("\7c\2\2\u083c\u083d\7n\2\2\u083d\u083e\7a\2\2\u083e\u083f") - buf.write("\7|\2\2\u083f\u0840\7g\2\2\u0840\u0841\7t\2\2\u0841\u0842") - buf.write("\7q\2\2\u0842\u01ca\3\2\2\2\u0843\u0844\7c\2\2\u0844\u0845") - buf.write("\7n\2\2\u0845\u0846\7y\2\2\u0846\u0847\7c\2\2\u0847\u0848") - buf.write("\7{\2\2\u0848\u0849\7u\2\2\u0849\u084a\7a\2\2\u084a\u084b") - buf.write("\7p\2\2\u084b\u084c\7w\2\2\u084c\u084d\7n\2\2\u084d\u084e") - buf.write("\7n\2\2\u084e\u01cc\3\2\2\2\u084f\u0850\7c\2\2\u0850\u0851") - buf.write("\7n\2\2\u0851\u0852\7y\2\2\u0852\u0853\7c\2\2\u0853\u0854") - buf.write("\7{\2\2\u0854\u0855\7u\2\2\u0855\u0856\7a\2\2\u0856\u0857") - buf.write("\7|\2\2\u0857\u0858\7g\2\2\u0858\u0859\7t\2\2\u0859\u085a") - buf.write("\7q\2\2\u085a\u01ce\3\2\2\2\u085b\u085c\7e\2\2\u085c\u085d") - buf.write("\7q\2\2\u085d\u085e\7o\2\2\u085e\u085f\7r\2\2\u085f\u0860") - buf.write("\7q\2\2\u0860\u0861\7p\2\2\u0861\u0862\7g\2\2\u0862\u0863") - buf.write("\7p\2\2\u0863\u0864\7v\2\2\u0864\u0865\7u\2\2\u0865\u01d0") - buf.write("\3\2\2\2\u0866\u0867\7c\2\2\u0867\u0868\7n\2\2\u0868\u0869") - buf.write("\7n\2\2\u0869\u086a\7a\2\2\u086a\u086b\7o\2\2\u086b\u086c") - buf.write("\7g\2\2\u086c\u086d\7c\2\2\u086d\u086e\7u\2\2\u086e\u086f") - buf.write("\7w\2\2\u086f\u0870\7t\2\2\u0870\u0871\7g\2\2\u0871\u0872") - buf.write("\7u\2\2\u0872\u01d2\3\2\2\2\u0873\u0874\7u\2\2\u0874\u0875") - buf.write("\7e\2\2\u0875\u0876\7c\2\2\u0876\u0877\7n\2\2\u0877\u0878") - buf.write("\7c\2\2\u0878\u0879\7t\2\2\u0879\u01d4\3\2\2\2\u087a\u087b") - buf.write("\7e\2\2\u087b\u087c\7q\2\2\u087c\u087d\7o\2\2\u087d\u087e") - buf.write("\7r\2\2\u087e\u087f\7q\2\2\u087f\u0880\7p\2\2\u0880\u0881") - buf.write("\7g\2\2\u0881\u0882\7p\2\2\u0882\u0883\7v\2\2\u0883\u01d6") - buf.write("\3\2\2\2\u0884\u0885\7f\2\2\u0885\u0886\7c\2\2\u0886\u0887") - buf.write("\7v\2\2\u0887\u0888\7c\2\2\u0888\u0889\7r\2\2\u0889\u088a") - buf.write("\7q\2\2\u088a\u088b\7k\2\2\u088b\u088c\7p\2\2\u088c\u088d") - buf.write("\7v\2\2\u088d\u088e\7a\2\2\u088e\u088f\7q\2\2\u088f\u0890") - buf.write("\7p\2\2\u0890\u0891\7a\2\2\u0891\u0892\7x\2\2\u0892\u0893") - buf.write("\7c\2\2\u0893\u0894\7n\2\2\u0894\u0895\7w\2\2\u0895\u0896") - buf.write("\7g\2\2\u0896\u0897\7f\2\2\u0897\u0898\7q\2\2\u0898\u0899") - buf.write("\7o\2\2\u0899\u089a\7c\2\2\u089a\u089b\7k\2\2\u089b\u089c") - buf.write("\7p\2\2\u089c\u089d\7u\2\2\u089d\u01d8\3\2\2\2\u089e\u089f") - buf.write("\7f\2\2\u089f\u08a0\7c\2\2\u08a0\u08a1\7v\2\2\u08a1\u08a2") - buf.write("\7c\2\2\u08a2\u08a3\7r\2\2\u08a3\u08a4\7q\2\2\u08a4\u08a5") - buf.write("\7k\2\2\u08a5\u08a6\7p\2\2\u08a6\u08a7\7v\2\2\u08a7\u08a8") - buf.write("\7a\2\2\u08a8\u08a9\7q\2\2\u08a9\u08aa\7p\2\2\u08aa\u08ab") - buf.write("\7a\2\2\u08ab\u08ac\7x\2\2\u08ac\u08ad\7c\2\2\u08ad\u08ae") - buf.write("\7t\2\2\u08ae\u08af\7k\2\2\u08af\u08b0\7c\2\2\u08b0\u08b1") - buf.write("\7d\2\2\u08b1\u08b2\7n\2\2\u08b2\u08b3\7g\2\2\u08b3\u08b4") - buf.write("\7u\2\2\u08b4\u01da\3\2\2\2\u08b5\u08b6\7j\2\2\u08b6\u08b7") - buf.write("\7k\2\2\u08b7\u08b8\7g\2\2\u08b8\u08b9\7t\2\2\u08b9\u08ba") - buf.write("\7c\2\2\u08ba\u08bb\7t\2\2\u08bb\u08bc\7e\2\2\u08bc\u08bd") - buf.write("\7j\2\2\u08bd\u08be\7k\2\2\u08be\u08bf\7e\2\2\u08bf\u08c0") - buf.write("\7c\2\2\u08c0\u08c1\7n\2\2\u08c1\u08c2\7a\2\2\u08c2\u08c3") - buf.write("\7q\2\2\u08c3\u08c4\7p\2\2\u08c4\u08c5\7a\2\2\u08c5\u08c6") - buf.write("\7x\2\2\u08c6\u08c7\7c\2\2\u08c7\u08c8\7n\2\2\u08c8\u08c9") - buf.write("\7w\2\2\u08c9\u08ca\7g\2\2\u08ca\u08cb\7f\2\2\u08cb\u08cc") - buf.write("\7q\2\2\u08cc\u08cd\7o\2\2\u08cd\u08ce\7c\2\2\u08ce\u08cf") - buf.write("\7k\2\2\u08cf\u08d0\7p\2\2\u08d0\u08d1\7u\2\2\u08d1\u01dc") - buf.write("\3\2\2\2\u08d2\u08d3\7j\2\2\u08d3\u08d4\7k\2\2\u08d4\u08d5") - buf.write("\7g\2\2\u08d5\u08d6\7t\2\2\u08d6\u08d7\7c\2\2\u08d7\u08d8") - buf.write("\7t\2\2\u08d8\u08d9\7e\2\2\u08d9\u08da\7j\2\2\u08da\u08db") - buf.write("\7k\2\2\u08db\u08dc\7e\2\2\u08dc\u08dd\7c\2\2\u08dd\u08de") - buf.write("\7n\2\2\u08de\u08df\7a\2\2\u08df\u08e0\7q\2\2\u08e0\u08e1") - buf.write("\7p\2\2\u08e1\u08e2\7a\2\2\u08e2\u08e3\7x\2\2\u08e3\u08e4") - buf.write("\7c\2\2\u08e4\u08e5\7t\2\2\u08e5\u08e6\7k\2\2\u08e6\u08e7") - buf.write("\7c\2\2\u08e7\u08e8\7d\2\2\u08e8\u08e9\7n\2\2\u08e9\u08ea") - buf.write("\7g\2\2\u08ea\u08eb\7u\2\2\u08eb\u01de\3\2\2\2\u08ec\u08ed") - buf.write("\7u\2\2\u08ed\u08ee\7g\2\2\u08ee\u08ef\7v\2\2\u08ef\u01e0") - buf.write("\3\2\2\2\u08f0\u08f1\7n\2\2\u08f1\u08f2\7c\2\2\u08f2\u08f3") - buf.write("\7p\2\2\u08f3\u08f4\7i\2\2\u08f4\u08f5\7w\2\2\u08f5\u08f6") - buf.write("\7c\2\2\u08f6\u08f7\7i\2\2\u08f7\u08f8\7g\2\2\u08f8\u01e2") - buf.write("\3\2\2\2\u08f9\u08fa\t\2\2\2\u08fa\u01e4\3\2\2\2\u08fb") - buf.write("\u08fc\4\62;\2\u08fc\u01e6\3\2\2\2\u08fd\u08ff\5\u01e5") - buf.write("\u00f3\2\u08fe\u08fd\3\2\2\2\u08ff\u0900\3\2\2\2\u0900") - buf.write("\u08fe\3\2\2\2\u0900\u0901\3\2\2\2\u0901\u01e8\3\2\2\2") - buf.write("\u0902\u0903\5\u01e7\u00f4\2\u0903\u0904\7\60\2\2\u0904") - buf.write("\u0905\5\u01e7\u00f4\2\u0905\u01ea\3\2\2\2\u0906\u0907") - buf.write("\7v\2\2\u0907\u0908\7t\2\2\u0908\u0909\7w\2\2\u0909\u0910") - buf.write("\7g\2\2\u090a\u090b\7h\2\2\u090b\u090c\7c\2\2\u090c\u090d") - buf.write("\7n\2\2\u090d\u090e\7u\2\2\u090e\u0910\7g\2\2\u090f\u0906") - buf.write("\3\2\2\2\u090f\u090a\3\2\2\2\u0910\u01ec\3\2\2\2\u0911") - buf.write("\u0915\7$\2\2\u0912\u0914\n\3\2\2\u0913\u0912\3\2\2\2") - buf.write("\u0914\u0917\3\2\2\2\u0915\u0913\3\2\2\2\u0915\u0916\3") - buf.write("\2\2\2\u0916\u0918\3\2\2\2\u0917\u0915\3\2\2\2\u0918\u0919") - buf.write("\7$\2\2\u0919\u01ee\3\2\2\2\u091a\u091e\5\u01e3\u00f2") - buf.write("\2\u091b\u091d\t\4\2\2\u091c\u091b\3\2\2\2\u091d\u0920") - buf.write("\3\2\2\2\u091e\u091c\3\2\2\2\u091e\u091f\3\2\2\2\u091f") - buf.write("\u0930\3\2\2\2\u0920\u091e\3\2\2\2\u0921\u0923\5\u01e5") - buf.write("\u00f3\2\u0922\u0924\t\4\2\2\u0923\u0922\3\2\2\2\u0924") - buf.write("\u0925\3\2\2\2\u0925\u0923\3\2\2\2\u0925\u0926\3\2\2\2") - buf.write("\u0926\u0930\3\2\2\2\u0927\u092b\7)\2\2\u0928\u092a\13") - buf.write("\2\2\2\u0929\u0928\3\2\2\2\u092a\u092d\3\2\2\2\u092b\u092c") - buf.write("\3\2\2\2\u092b\u0929\3\2\2\2\u092c\u092e\3\2\2\2\u092d") - buf.write("\u092b\3\2\2\2\u092e\u0930\7)\2\2\u092f\u091a\3\2\2\2") - buf.write("\u092f\u0921\3\2\2\2\u092f\u0927\3\2\2\2\u0930\u01f0\3") - buf.write("\2\2\2\u0931\u0933\t\5\2\2\u0932\u0931\3\2\2\2\u0933\u0934") - buf.write("\3\2\2\2\u0934\u0932\3\2\2\2\u0934\u0935\3\2\2\2\u0935") - buf.write("\u0936\3\2\2\2\u0936\u0937\b\u00f9\2\2\u0937\u01f2\3\2") - buf.write("\2\2\u0938\u0939\7=\2\2\u0939\u01f4\3\2\2\2\u093a\u093b") - buf.write("\7\61\2\2\u093b\u093c\7,\2\2\u093c\u0940\3\2\2\2\u093d") - buf.write("\u093f\13\2\2\2\u093e\u093d\3\2\2\2\u093f\u0942\3\2\2") - buf.write("\2\u0940\u0941\3\2\2\2\u0940\u093e\3\2\2\2\u0941\u0943") - buf.write("\3\2\2\2\u0942\u0940\3\2\2\2\u0943\u0944\7,\2\2\u0944") - buf.write("\u0945\7\61\2\2\u0945\u0946\3\2\2\2\u0946\u0947\b\u00fb") - buf.write("\3\2\u0947\u01f6\3\2\2\2\u0948\u0949\7\61\2\2\u0949\u094a") - buf.write("\7\61\2\2\u094a\u094e\3\2\2\2\u094b\u094d\n\6\2\2\u094c") - buf.write("\u094b\3\2\2\2\u094d\u0950\3\2\2\2\u094e\u094c\3\2\2\2") - buf.write("\u094e\u094f\3\2\2\2\u094f\u0951\3\2\2\2\u0950\u094e\3") - buf.write("\2\2\2\u0951\u0952\b\u00fc\3\2\u0952\u01f8\3\2\2\2\r\2") - buf.write("\u0900\u090f\u0915\u091e\u0925\u092b\u092f\u0934\u0940") - buf.write("\u094e\4\2\3\2\2\4\2") + buf.write("\3\u00ef\3\u00ef\3\u00ef\3\u00ef\3\u00ef\3\u00f0\3\u00f0") + buf.write("\3\u00f0\3\u00f0\3\u00f0\3\u00f0\3\u00f0\3\u00f0\3\u00f0") + buf.write("\3\u00f0\3\u00f0\3\u00f0\3\u00f0\3\u00f0\3\u00f0\3\u00f0") + buf.write("\3\u00f0\3\u00f0\3\u00f0\3\u00f0\3\u00f0\3\u00f0\3\u00f0") + buf.write("\3\u00f0\3\u00f0\3\u00f0\3\u00f1\3\u00f1\3\u00f1\3\u00f1") + buf.write("\3\u00f2\3\u00f2\3\u00f2\3\u00f2\3\u00f2\3\u00f2\3\u00f2") + buf.write("\3\u00f2\3\u00f2\3\u00f3\3\u00f3\3\u00f4\3\u00f4\3\u00f5") + buf.write("\6\u00f5\u090d\n\u00f5\r\u00f5\16\u00f5\u090e\3\u00f6") + buf.write("\3\u00f6\3\u00f6\3\u00f6\3\u00f7\3\u00f7\3\u00f7\3\u00f7") + buf.write("\3\u00f7\3\u00f7\3\u00f7\3\u00f7\3\u00f7\5\u00f7\u091e") + buf.write("\n\u00f7\3\u00f8\3\u00f8\7\u00f8\u0922\n\u00f8\f\u00f8") + buf.write("\16\u00f8\u0925\13\u00f8\3\u00f8\3\u00f8\3\u00f9\3\u00f9") + buf.write("\7\u00f9\u092b\n\u00f9\f\u00f9\16\u00f9\u092e\13\u00f9") + buf.write("\3\u00f9\3\u00f9\6\u00f9\u0932\n\u00f9\r\u00f9\16\u00f9") + buf.write("\u0933\3\u00f9\3\u00f9\7\u00f9\u0938\n\u00f9\f\u00f9\16") + buf.write("\u00f9\u093b\13\u00f9\3\u00f9\5\u00f9\u093e\n\u00f9\3") + buf.write("\u00fa\6\u00fa\u0941\n\u00fa\r\u00fa\16\u00fa\u0942\3") + buf.write("\u00fa\3\u00fa\3\u00fb\3\u00fb\3\u00fc\3\u00fc\3\u00fc") + buf.write("\3\u00fc\7\u00fc\u094d\n\u00fc\f\u00fc\16\u00fc\u0950") + buf.write("\13\u00fc\3\u00fc\3\u00fc\3\u00fc\3\u00fc\3\u00fc\3\u00fd") + buf.write("\3\u00fd\3\u00fd\3\u00fd\7\u00fd\u095b\n\u00fd\f\u00fd") + buf.write("\16\u00fd\u095e\13\u00fd\3\u00fd\3\u00fd\4\u0939\u094e") + buf.write("\2\u00fe\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f") + buf.write("\27\r\31\16\33\17\35\20\37\21!\22#\23%\24'\25)\26+\27") + buf.write('-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A"C#E$G%') + buf.write("I&K'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67") + buf.write("m8o9q:s;u{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089") + buf.write("F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097M\u0099") + buf.write("N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9") + buf.write("V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9") + buf.write("^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5d\u00c7e\u00c9") + buf.write("f\u00cbg\u00cdh\u00cfi\u00d1j\u00d3k\u00d5l\u00d7m\u00d9") + buf.write("n\u00dbo\u00ddp\u00dfq\u00e1r\u00e3s\u00e5t\u00e7u\u00e9") + buf.write("v\u00ebw\u00edx\u00efy\u00f1z\u00f3{\u00f5|\u00f7}\u00f9") + buf.write("~\u00fb\177\u00fd\u0080\u00ff\u0081\u0101\u0082\u0103") + buf.write("\u0083\u0105\u0084\u0107\u0085\u0109\u0086\u010b\u0087") + buf.write("\u010d\u0088\u010f\u0089\u0111\u008a\u0113\u008b\u0115") + buf.write("\u008c\u0117\u008d\u0119\u008e\u011b\u008f\u011d\u0090") + buf.write("\u011f\u0091\u0121\u0092\u0123\u0093\u0125\u0094\u0127") + buf.write("\u0095\u0129\u0096\u012b\u0097\u012d\u0098\u012f\u0099") + buf.write("\u0131\u009a\u0133\u009b\u0135\u009c\u0137\u009d\u0139") + buf.write("\u009e\u013b\u009f\u013d\u00a0\u013f\u00a1\u0141\u00a2") + buf.write("\u0143\u00a3\u0145\u00a4\u0147\u00a5\u0149\u00a6\u014b") + buf.write("\u00a7\u014d\u00a8\u014f\u00a9\u0151\u00aa\u0153\u00ab") + buf.write("\u0155\u00ac\u0157\u00ad\u0159\u00ae\u015b\u00af\u015d") + buf.write("\u00b0\u015f\u00b1\u0161\u00b2\u0163\u00b3\u0165\u00b4") + buf.write("\u0167\u00b5\u0169\u00b6\u016b\u00b7\u016d\u00b8\u016f") + buf.write("\u00b9\u0171\u00ba\u0173\u00bb\u0175\u00bc\u0177\u00bd") + buf.write("\u0179\u00be\u017b\u00bf\u017d\u00c0\u017f\u00c1\u0181") + buf.write("\u00c2\u0183\u00c3\u0185\u00c4\u0187\u00c5\u0189\u00c6") + buf.write("\u018b\u00c7\u018d\u00c8\u018f\u00c9\u0191\u00ca\u0193") + buf.write("\u00cb\u0195\u00cc\u0197\u00cd\u0199\u00ce\u019b\u00cf") + buf.write("\u019d\u00d0\u019f\u00d1\u01a1\u00d2\u01a3\u00d3\u01a5") + buf.write("\u00d4\u01a7\u00d5\u01a9\u00d6\u01ab\u00d7\u01ad\u00d8") + buf.write("\u01af\u00d9\u01b1\u00da\u01b3\u00db\u01b5\u00dc\u01b7") + buf.write("\u00dd\u01b9\u00de\u01bb\u00df\u01bd\u00e0\u01bf\u00e1") + buf.write("\u01c1\u00e2\u01c3\u00e3\u01c5\u00e4\u01c7\u00e5\u01c9") + buf.write("\u00e6\u01cb\u00e7\u01cd\u00e8\u01cf\u00e9\u01d1\u00ea") + buf.write("\u01d3\u00eb\u01d5\u00ec\u01d7\u00ed\u01d9\u00ee\u01db") + buf.write("\u00ef\u01dd\u00f0\u01df\u00f1\u01e1\u00f2\u01e3\u00f3") + buf.write("\u01e5\2\u01e7\2\u01e9\u00f4\u01eb\u00f5\u01ed\u00f6\u01ef") + buf.write("\u00f7\u01f1\u00f8\u01f3\u00f9\u01f5\u00fa\u01f7\u00fb") + buf.write("\u01f9\u00fc\3\2\7\4\2C\\c|\3\2$$\7\2\60\60\62;C\\aac") + buf.write('|\5\2\13\f\16\17""\4\2\f\f\17\17\2\u0969\2\3\3\2\2\2') + buf.write("\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r") + buf.write("\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3") + buf.write("\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2") + buf.write("\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2'") + buf.write("\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") + buf.write("\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29") + buf.write("\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2") + buf.write("C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2") + buf.write("\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2") + buf.write("\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2") + buf.write("\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3") + buf.write("\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s") + buf.write("\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2") + buf.write("}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2") + buf.write("\2\2\u0085\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b") + buf.write("\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2\2\u0091\3\2\2") + buf.write("\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099") + buf.write("\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2") + buf.write("\2\2\u00a1\3\2\2\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7") + buf.write("\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2") + buf.write("\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2\2\2\u00b5") + buf.write("\3\2\2\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb\3\2\2") + buf.write("\2\2\u00bd\3\2\2\2\2\u00bf\3\2\2\2\2\u00c1\3\2\2\2\2\u00c3") + buf.write("\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9\3\2\2") + buf.write("\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2\2\2\u00cf\3\2\2\2\2\u00d1") + buf.write("\3\2\2\2\2\u00d3\3\2\2\2\2\u00d5\3\2\2\2\2\u00d7\3\2\2") + buf.write("\2\2\u00d9\3\2\2\2\2\u00db\3\2\2\2\2\u00dd\3\2\2\2\2\u00df") + buf.write("\3\2\2\2\2\u00e1\3\2\2\2\2\u00e3\3\2\2\2\2\u00e5\3\2\2") + buf.write("\2\2\u00e7\3\2\2\2\2\u00e9\3\2\2\2\2\u00eb\3\2\2\2\2\u00ed") + buf.write("\3\2\2\2\2\u00ef\3\2\2\2\2\u00f1\3\2\2\2\2\u00f3\3\2\2") + buf.write("\2\2\u00f5\3\2\2\2\2\u00f7\3\2\2\2\2\u00f9\3\2\2\2\2\u00fb") + buf.write("\3\2\2\2\2\u00fd\3\2\2\2\2\u00ff\3\2\2\2\2\u0101\3\2\2") + buf.write("\2\2\u0103\3\2\2\2\2\u0105\3\2\2\2\2\u0107\3\2\2\2\2\u0109") + buf.write("\3\2\2\2\2\u010b\3\2\2\2\2\u010d\3\2\2\2\2\u010f\3\2\2") + buf.write("\2\2\u0111\3\2\2\2\2\u0113\3\2\2\2\2\u0115\3\2\2\2\2\u0117") + buf.write("\3\2\2\2\2\u0119\3\2\2\2\2\u011b\3\2\2\2\2\u011d\3\2\2") + buf.write("\2\2\u011f\3\2\2\2\2\u0121\3\2\2\2\2\u0123\3\2\2\2\2\u0125") + buf.write("\3\2\2\2\2\u0127\3\2\2\2\2\u0129\3\2\2\2\2\u012b\3\2\2") + buf.write("\2\2\u012d\3\2\2\2\2\u012f\3\2\2\2\2\u0131\3\2\2\2\2\u0133") + buf.write("\3\2\2\2\2\u0135\3\2\2\2\2\u0137\3\2\2\2\2\u0139\3\2\2") + buf.write("\2\2\u013b\3\2\2\2\2\u013d\3\2\2\2\2\u013f\3\2\2\2\2\u0141") + buf.write("\3\2\2\2\2\u0143\3\2\2\2\2\u0145\3\2\2\2\2\u0147\3\2\2") + buf.write("\2\2\u0149\3\2\2\2\2\u014b\3\2\2\2\2\u014d\3\2\2\2\2\u014f") + buf.write("\3\2\2\2\2\u0151\3\2\2\2\2\u0153\3\2\2\2\2\u0155\3\2\2") + buf.write("\2\2\u0157\3\2\2\2\2\u0159\3\2\2\2\2\u015b\3\2\2\2\2\u015d") + buf.write("\3\2\2\2\2\u015f\3\2\2\2\2\u0161\3\2\2\2\2\u0163\3\2\2") + buf.write("\2\2\u0165\3\2\2\2\2\u0167\3\2\2\2\2\u0169\3\2\2\2\2\u016b") + buf.write("\3\2\2\2\2\u016d\3\2\2\2\2\u016f\3\2\2\2\2\u0171\3\2\2") + buf.write("\2\2\u0173\3\2\2\2\2\u0175\3\2\2\2\2\u0177\3\2\2\2\2\u0179") + buf.write("\3\2\2\2\2\u017b\3\2\2\2\2\u017d\3\2\2\2\2\u017f\3\2\2") + buf.write("\2\2\u0181\3\2\2\2\2\u0183\3\2\2\2\2\u0185\3\2\2\2\2\u0187") + buf.write("\3\2\2\2\2\u0189\3\2\2\2\2\u018b\3\2\2\2\2\u018d\3\2\2") + buf.write("\2\2\u018f\3\2\2\2\2\u0191\3\2\2\2\2\u0193\3\2\2\2\2\u0195") + buf.write("\3\2\2\2\2\u0197\3\2\2\2\2\u0199\3\2\2\2\2\u019b\3\2\2") + buf.write("\2\2\u019d\3\2\2\2\2\u019f\3\2\2\2\2\u01a1\3\2\2\2\2\u01a3") + buf.write("\3\2\2\2\2\u01a5\3\2\2\2\2\u01a7\3\2\2\2\2\u01a9\3\2\2") + buf.write("\2\2\u01ab\3\2\2\2\2\u01ad\3\2\2\2\2\u01af\3\2\2\2\2\u01b1") + buf.write("\3\2\2\2\2\u01b3\3\2\2\2\2\u01b5\3\2\2\2\2\u01b7\3\2\2") + buf.write("\2\2\u01b9\3\2\2\2\2\u01bb\3\2\2\2\2\u01bd\3\2\2\2\2\u01bf") + buf.write("\3\2\2\2\2\u01c1\3\2\2\2\2\u01c3\3\2\2\2\2\u01c5\3\2\2") + buf.write("\2\2\u01c7\3\2\2\2\2\u01c9\3\2\2\2\2\u01cb\3\2\2\2\2\u01cd") + buf.write("\3\2\2\2\2\u01cf\3\2\2\2\2\u01d1\3\2\2\2\2\u01d3\3\2\2") + buf.write("\2\2\u01d5\3\2\2\2\2\u01d7\3\2\2\2\2\u01d9\3\2\2\2\2\u01db") + buf.write("\3\2\2\2\2\u01dd\3\2\2\2\2\u01df\3\2\2\2\2\u01e1\3\2\2") + buf.write("\2\2\u01e3\3\2\2\2\2\u01e9\3\2\2\2\2\u01eb\3\2\2\2\2\u01ed") + buf.write("\3\2\2\2\2\u01ef\3\2\2\2\2\u01f1\3\2\2\2\2\u01f3\3\2\2") + buf.write("\2\2\u01f5\3\2\2\2\2\u01f7\3\2\2\2\2\u01f9\3\2\2\2\3\u01fb") + buf.write("\3\2\2\2\5\u01fd\3\2\2\2\7\u01ff\3\2\2\2\t\u0201\3\2\2") + buf.write("\2\13\u0203\3\2\2\2\r\u0205\3\2\2\2\17\u0207\3\2\2\2\21") + buf.write("\u0209\3\2\2\2\23\u020b\3\2\2\2\25\u020d\3\2\2\2\27\u0210") + buf.write("\3\2\2\2\31\u0213\3\2\2\2\33\u0216\3\2\2\2\35\u0218\3") + buf.write("\2\2\2\37\u021a\3\2\2\2!\u021c\3\2\2\2#\u021e\3\2\2\2") + buf.write("%\u0220\3\2\2\2'\u0223\3\2\2\2)\u0225\3\2\2\2+\u0228") + buf.write("\3\2\2\2-\u022a\3\2\2\2/\u022f\3\2\2\2\61\u0232\3\2\2") + buf.write("\2\63\u0237\3\2\2\2\65\u023c\3\2\2\2\67\u0241\3\2\2\2") + buf.write("9\u0247\3\2\2\2;\u024c\3\2\2\2=\u0259\3\2\2\2?\u0262\3") + buf.write("\2\2\2A\u026a\3\2\2\2C\u0272\3\2\2\2E\u027b\3\2\2\2G\u0286") + buf.write("\3\2\2\2I\u0290\3\2\2\2K\u029a\3\2\2\2M\u02a5\3\2\2\2") + buf.write("O\u02af\3\2\2\2Q\u02ba\3\2\2\2S\u02bd\3\2\2\2U\u02c2\3") + buf.write("\2\2\2W\u02c7\3\2\2\2Y\u02cc\3\2\2\2[\u02d5\3\2\2\2]\u02dc") + buf.write("\3\2\2\2_\u02df\3\2\2\2a\u02e3\3\2\2\2c\u02e6\3\2\2\2") + buf.write("e\u02ea\3\2\2\2g\u02ee\3\2\2\2i\u02f6\3\2\2\2k\u02f9\3") + buf.write("\2\2\2m\u0300\3\2\2\2o\u0305\3\2\2\2q\u030c\3\2\2\2s\u030f") + buf.write("\3\2\2\2u\u0315\3\2\2\2w\u031a\3\2\2\2y\u0322\3\2\2\2") + buf.write("{\u032c\3\2\2\2}\u0333\3\2\2\2\177\u0338\3\2\2\2\u0081") + buf.write("\u0340\3\2\2\2\u0083\u0349\3\2\2\2\u0085\u0350\3\2\2\2") + buf.write("\u0087\u0356\3\2\2\2\u0089\u0360\3\2\2\2\u008b\u0363\3") + buf.write("\2\2\2\u008d\u036a\3\2\2\2\u008f\u0374\3\2\2\2\u0091\u037e") + buf.write("\3\2\2\2\u0093\u0382\3\2\2\2\u0095\u0387\3\2\2\2\u0097") + buf.write("\u0392\3\2\2\2\u0099\u0398\3\2\2\2\u009b\u039b\3\2\2\2") + buf.write("\u009d\u03a0\3\2\2\2\u009f\u03a4\3\2\2\2\u00a1\u03a9\3") + buf.write("\2\2\2\u00a3\u03ad\3\2\2\2\u00a5\u03b1\3\2\2\2\u00a7\u03b7") + buf.write("\3\2\2\2\u00a9\u03bc\3\2\2\2\u00ab\u03c4\3\2\2\2\u00ad") + buf.write("\u03c8\3\2\2\2\u00af\u03cc\3\2\2\2\u00b1\u03cf\3\2\2\2") + buf.write("\u00b3\u03d3\3\2\2\2\u00b5\u03d9\3\2\2\2\u00b7\u03df\3") + buf.write("\2\2\2\u00b9\u03e5\3\2\2\2\u00bb\u03e9\3\2\2\2\u00bd\u03f0") + buf.write("\3\2\2\2\u00bf\u03f3\3\2\2\2\u00c1\u03f8\3\2\2\2\u00c3") + buf.write("\u03fe\3\2\2\2\u00c5\u0404\3\2\2\2\u00c7\u040b\3\2\2\2") + buf.write("\u00c9\u040f\3\2\2\2\u00cb\u0413\3\2\2\2\u00cd\u041a\3") + buf.write("\2\2\2\u00cf\u0420\3\2\2\2\u00d1\u042b\3\2\2\2\u00d3\u0433") + buf.write("\3\2\2\2\u00d5\u043d\3\2\2\2\u00d7\u0444\3\2\2\2\u00d9") + buf.write("\u044a\3\2\2\2\u00db\u044e\3\2\2\2\u00dd\u045c\3\2\2\2") + buf.write("\u00df\u0462\3\2\2\2\u00e1\u046e\3\2\2\2\u00e3\u047f\3") + buf.write("\2\2\2\u00e5\u0484\3\2\2\2\u00e7\u0488\3\2\2\2\u00e9\u0492") + buf.write("\3\2\2\2\u00eb\u0494\3\2\2\2\u00ed\u049c\3\2\2\2\u00ef") + buf.write("\u04a8\3\2\2\2\u00f1\u04b1\3\2\2\2\u00f3\u04b6\3\2\2\2") + buf.write("\u00f5\u04c0\3\2\2\2\u00f7\u04c8\3\2\2\2\u00f9\u04d1\3") + buf.write("\2\2\2\u00fb\u04d8\3\2\2\2\u00fd\u04db\3\2\2\2\u00ff\u04e5") + buf.write("\3\2\2\2\u0101\u04f2\3\2\2\2\u0103\u04fa\3\2\2\2\u0105") + buf.write("\u04ff\3\2\2\2\u0107\u0503\3\2\2\2\u0109\u0510\3\2\2\2") + buf.write("\u010b\u0516\3\2\2\2\u010d\u051c\3\2\2\2\u010f\u0522\3") + buf.write("\2\2\2\u0111\u052a\3\2\2\2\u0113\u052f\3\2\2\2\u0115\u0535") + buf.write("\3\2\2\2\u0117\u053a\3\2\2\2\u0119\u053e\3\2\2\2\u011b") + buf.write("\u0546\3\2\2\2\u011d\u0551\3\2\2\2\u011f\u055d\3\2\2\2") + buf.write("\u0121\u0565\3\2\2\2\u0123\u056e\3\2\2\2\u0125\u0574\3") + buf.write("\2\2\2\u0127\u057b\3\2\2\2\u0129\u0582\3\2\2\2\u012b\u058e") + buf.write("\3\2\2\2\u012d\u0599\3\2\2\2\u012f\u059d\3\2\2\2\u0131") + buf.write("\u05a2\3\2\2\2\u0133\u05b2\3\2\2\2\u0135\u05b7\3\2\2\2") + buf.write("\u0137\u05c1\3\2\2\2\u0139\u05cb\3\2\2\2\u013b\u05d5\3") + buf.write("\2\2\2\u013d\u05df\3\2\2\2\u013f\u05e4\3\2\2\2\u0141\u05ea") + buf.write("\3\2\2\2\u0143\u05f2\3\2\2\2\u0145\u05f8\3\2\2\2\u0147") + buf.write("\u0609\3\2\2\2\u0149\u0617\3\2\2\2\u014b\u0625\3\2\2\2") + buf.write("\u014d\u062f\3\2\2\2\u014f\u0638\3\2\2\2\u0151\u0644\3") + buf.write("\2\2\2\u0153\u064e\3\2\2\2\u0155\u0656\3\2\2\2\u0157\u065b") + buf.write("\3\2\2\2\u0159\u0667\3\2\2\2\u015b\u066e\3\2\2\2\u015d") + buf.write("\u0675\3\2\2\2\u015f\u067a\3\2\2\2\u0161\u0682\3\2\2\2") + buf.write("\u0163\u0688\3\2\2\2\u0165\u068d\3\2\2\2\u0167\u0694\3") + buf.write("\2\2\2\u0169\u069d\3\2\2\2\u016b\u06a2\3\2\2\2\u016d\u06a5") + buf.write("\3\2\2\2\u016f\u06a8\3\2\2\2\u0171\u06b2\3\2\2\2\u0173") + buf.write("\u06b9\3\2\2\2\u0175\u06bc\3\2\2\2\u0177\u06c1\3\2\2\2") + buf.write("\u0179\u06c6\3\2\2\2\u017b\u06d1\3\2\2\2\u017d\u06d8\3") + buf.write("\2\2\2\u017f\u06de\3\2\2\2\u0181\u06e4\3\2\2\2\u0183\u06ec") + buf.write("\3\2\2\2\u0185\u06f3\3\2\2\2\u0187\u06fe\3\2\2\2\u0189") + buf.write("\u0708\3\2\2\2\u018b\u0713\3\2\2\2\u018d\u071d\3\2\2\2") + buf.write("\u018f\u0727\3\2\2\2\u0191\u072f\3\2\2\2\u0193\u0736\3") + buf.write("\2\2\2\u0195\u073f\3\2\2\2\u0197\u0747\3\2\2\2\u0199\u074d") + buf.write("\3\2\2\2\u019b\u0759\3\2\2\2\u019d\u0761\3\2\2\2\u019f") + buf.write("\u0765\3\2\2\2\u01a1\u076b\3\2\2\2\u01a3\u0777\3\2\2\2") + buf.write("\u01a5\u0788\3\2\2\2\u01a7\u078f\3\2\2\2\u01a9\u0798\3") + buf.write("\2\2\2\u01ab\u07a1\3\2\2\2\u01ad\u07a6\3\2\2\2\u01af\u07ac") + buf.write("\3\2\2\2\u01b1\u07b9\3\2\2\2\u01b3\u07c3\3\2\2\2\u01b5") + buf.write("\u07c9\3\2\2\2\u01b7\u07d0\3\2\2\2\u01b9\u07d5\3\2\2\2") + buf.write("\u01bb\u07e3\3\2\2\2\u01bd\u07f4\3\2\2\2\u01bf\u07fc\3") + buf.write("\2\2\2\u01c1\u080c\3\2\2\2\u01c3\u081c\3\2\2\2\u01c5\u0825") + buf.write("\3\2\2\2\u01c7\u082e\3\2\2\2\u01c9\u0837\3\2\2\2\u01cb") + buf.write("\u0844\3\2\2\2\u01cd\u0851\3\2\2\2\u01cf\u085d\3\2\2\2") + buf.write("\u01d1\u0869\3\2\2\2\u01d3\u0874\3\2\2\2\u01d5\u0881\3") + buf.write("\2\2\2\u01d7\u0888\3\2\2\2\u01d9\u0892\3\2\2\2\u01db\u08ac") + buf.write("\3\2\2\2\u01dd\u08c3\3\2\2\2\u01df\u08e0\3\2\2\2\u01e1") + buf.write("\u08fa\3\2\2\2\u01e3\u08fe\3\2\2\2\u01e5\u0907\3\2\2\2") + buf.write("\u01e7\u0909\3\2\2\2\u01e9\u090c\3\2\2\2\u01eb\u0910\3") + buf.write("\2\2\2\u01ed\u091d\3\2\2\2\u01ef\u091f\3\2\2\2\u01f1\u093d") + buf.write("\3\2\2\2\u01f3\u0940\3\2\2\2\u01f5\u0946\3\2\2\2\u01f7") + buf.write("\u0948\3\2\2\2\u01f9\u0956\3\2\2\2\u01fb\u01fc\7*\2\2") + buf.write("\u01fc\4\3\2\2\2\u01fd\u01fe\7+\2\2\u01fe\6\3\2\2\2\u01ff") + buf.write("\u0200\7]\2\2\u0200\b\3\2\2\2\u0201\u0202\7_\2\2\u0202") + buf.write("\n\3\2\2\2\u0203\u0204\7}\2\2\u0204\f\3\2\2\2\u0205\u0206") + buf.write("\7\177\2\2\u0206\16\3\2\2\2\u0207\u0208\7?\2\2\u0208\20") + buf.write("\3\2\2\2\u0209\u020a\7>\2\2\u020a\22\3\2\2\2\u020b\u020c") + buf.write("\7@\2\2\u020c\24\3\2\2\2\u020d\u020e\7@\2\2\u020e\u020f") + buf.write("\7?\2\2\u020f\26\3\2\2\2\u0210\u0211\7>\2\2\u0211\u0212") + buf.write("\7@\2\2\u0212\30\3\2\2\2\u0213\u0214\7>\2\2\u0214\u0215") + buf.write("\7?\2\2\u0215\32\3\2\2\2\u0216\u0217\7-\2\2\u0217\34\3") + buf.write("\2\2\2\u0218\u0219\7/\2\2\u0219\36\3\2\2\2\u021a\u021b") + buf.write('\7,\2\2\u021b \3\2\2\2\u021c\u021d\7\61\2\2\u021d"\3') + buf.write("\2\2\2\u021e\u021f\7.\2\2\u021f$\3\2\2\2\u0220\u0221\7") + buf.write("/\2\2\u0221\u0222\7@\2\2\u0222&\3\2\2\2\u0223\u0224\7") + buf.write("<\2\2\u0224(\3\2\2\2\u0225\u0226\7<\2\2\u0226\u0227\7") + buf.write("?\2\2\u0227*\3\2\2\2\u0228\u0229\7%\2\2\u0229,\3\2\2\2") + buf.write("\u022a\u022b\7g\2\2\u022b\u022c\7x\2\2\u022c\u022d\7c") + buf.write("\2\2\u022d\u022e\7n\2\2\u022e.\3\2\2\2\u022f\u0230\7k") + buf.write("\2\2\u0230\u0231\7h\2\2\u0231\60\3\2\2\2\u0232\u0233\7") + buf.write("e\2\2\u0233\u0234\7c\2\2\u0234\u0235\7u\2\2\u0235\u0236") + buf.write("\7g\2\2\u0236\62\3\2\2\2\u0237\u0238\7v\2\2\u0238\u0239") + buf.write("\7j\2\2\u0239\u023a\7g\2\2\u023a\u023b\7p\2\2\u023b\64") + buf.write("\3\2\2\2\u023c\u023d\7g\2\2\u023d\u023e\7n\2\2\u023e\u023f") + buf.write("\7u\2\2\u023f\u0240\7g\2\2\u0240\66\3\2\2\2\u0241\u0242") + buf.write("\7w\2\2\u0242\u0243\7u\2\2\u0243\u0244\7k\2\2\u0244\u0245") + buf.write("\7p\2\2\u0245\u0246\7i\2\2\u02468\3\2\2\2\u0247\u0248") + buf.write("\7y\2\2\u0248\u0249\7k\2\2\u0249\u024a\7v\2\2\u024a\u024b") + buf.write("\7j\2\2\u024b:\3\2\2\2\u024c\u024d\7e\2\2\u024d\u024e") + buf.write("\7w\2\2\u024e\u024f\7t\2\2\u024f\u0250\7t\2\2\u0250\u0251") + buf.write("\7g\2\2\u0251\u0252\7p\2\2\u0252\u0253\7v\2\2\u0253\u0254") + buf.write("\7a\2\2\u0254\u0255\7f\2\2\u0255\u0256\7c\2\2\u0256\u0257") + buf.write("\7v\2\2\u0257\u0258\7g\2\2\u0258<\3\2\2\2\u0259\u025a") + buf.write("\7f\2\2\u025a\u025b\7c\2\2\u025b\u025c\7v\2\2\u025c\u025d") + buf.write("\7g\2\2\u025d\u025e\7f\2\2\u025e\u025f\7k\2\2\u025f\u0260") + buf.write("\7h\2\2\u0260\u0261\7h\2\2\u0261>\3\2\2\2\u0262\u0263") + buf.write("\7f\2\2\u0263\u0264\7c\2\2\u0264\u0265\7v\2\2\u0265\u0266") + buf.write("\7g\2\2\u0266\u0267\7c\2\2\u0267\u0268\7f\2\2\u0268\u0269") + buf.write("\7f\2\2\u0269@\3\2\2\2\u026a\u026b\7i\2\2\u026b\u026c") + buf.write("\7g\2\2\u026c\u026d\7v\2\2\u026d\u026e\7{\2\2\u026e\u026f") + buf.write("\7g\2\2\u026f\u0270\7c\2\2\u0270\u0271\7t\2\2\u0271B\3") + buf.write("\2\2\2\u0272\u0273\7i\2\2\u0273\u0274\7g\2\2\u0274\u0275") + buf.write("\7v\2\2\u0275\u0276\7o\2\2\u0276\u0277\7q\2\2\u0277\u0278") + buf.write("\7p\2\2\u0278\u0279\7v\2\2\u0279\u027a\7j\2\2\u027aD\3") + buf.write("\2\2\2\u027b\u027c\7f\2\2\u027c\u027d\7c\2\2\u027d\u027e") + buf.write("\7{\2\2\u027e\u027f\7q\2\2\u027f\u0280\7h\2\2\u0280\u0281") + buf.write("\7o\2\2\u0281\u0282\7q\2\2\u0282\u0283\7p\2\2\u0283\u0284") + buf.write("\7v\2\2\u0284\u0285\7j\2\2\u0285F\3\2\2\2\u0286\u0287") + buf.write("\7f\2\2\u0287\u0288\7c\2\2\u0288\u0289\7{\2\2\u0289\u028a") + buf.write("\7q\2\2\u028a\u028b\7h\2\2\u028b\u028c\7{\2\2\u028c\u028d") + buf.write("\7g\2\2\u028d\u028e\7c\2\2\u028e\u028f\7t\2\2\u028fH\3") + buf.write("\2\2\2\u0290\u0291\7f\2\2\u0291\u0292\7c\2\2\u0292\u0293") + buf.write("\7{\2\2\u0293\u0294\7v\2\2\u0294\u0295\7q\2\2\u0295\u0296") + buf.write("\7{\2\2\u0296\u0297\7g\2\2\u0297\u0298\7c\2\2\u0298\u0299") + buf.write("\7t\2\2\u0299J\3\2\2\2\u029a\u029b\7f\2\2\u029b\u029c") + buf.write("\7c\2\2\u029c\u029d\7{\2\2\u029d\u029e\7v\2\2\u029e\u029f") + buf.write("\7q\2\2\u029f\u02a0\7o\2\2\u02a0\u02a1\7q\2\2\u02a1\u02a2") + buf.write("\7p\2\2\u02a2\u02a3\7v\2\2\u02a3\u02a4\7j\2\2\u02a4L\3") + buf.write("\2\2\2\u02a5\u02a6\7{\2\2\u02a6\u02a7\7g\2\2\u02a7\u02a8") + buf.write("\7c\2\2\u02a8\u02a9\7t\2\2\u02a9\u02aa\7v\2\2\u02aa\u02ab") + buf.write("\7q\2\2\u02ab\u02ac\7f\2\2\u02ac\u02ad\7c\2\2\u02ad\u02ae") + buf.write("\7{\2\2\u02aeN\3\2\2\2\u02af\u02b0\7o\2\2\u02b0\u02b1") + buf.write("\7q\2\2\u02b1\u02b2\7p\2\2\u02b2\u02b3\7v\2\2\u02b3\u02b4") + buf.write("\7j\2\2\u02b4\u02b5\7v\2\2\u02b5\u02b6\7q\2\2\u02b6\u02b7") + buf.write("\7f\2\2\u02b7\u02b8\7c\2\2\u02b8\u02b9\7{\2\2\u02b9P\3") + buf.write("\2\2\2\u02ba\u02bb\7q\2\2\u02bb\u02bc\7p\2\2\u02bcR\3") + buf.write("\2\2\2\u02bd\u02be\7f\2\2\u02be\u02bf\7t\2\2\u02bf\u02c0") + buf.write("\7q\2\2\u02c0\u02c1\7r\2\2\u02c1T\3\2\2\2\u02c2\u02c3") + buf.write("\7m\2\2\u02c3\u02c4\7g\2\2\u02c4\u02c5\7g\2\2\u02c5\u02c6") + buf.write("\7r\2\2\u02c6V\3\2\2\2\u02c7\u02c8\7e\2\2\u02c8\u02c9") + buf.write("\7c\2\2\u02c9\u02ca\7n\2\2\u02ca\u02cb\7e\2\2\u02cbX\3") + buf.write("\2\2\2\u02cc\u02cd\7c\2\2\u02cd\u02ce\7v\2\2\u02ce\u02cf") + buf.write("\7v\2\2\u02cf\u02d0\7t\2\2\u02d0\u02d1\7e\2\2\u02d1\u02d2") + buf.write("\7c\2\2\u02d2\u02d3\7n\2\2\u02d3\u02d4\7e\2\2\u02d4Z\3") + buf.write("\2\2\2\u02d5\u02d6\7t\2\2\u02d6\u02d7\7g\2\2\u02d7\u02d8") + buf.write("\7p\2\2\u02d8\u02d9\7c\2\2\u02d9\u02da\7o\2\2\u02da\u02db") + buf.write("\7g\2\2\u02db\\\3\2\2\2\u02dc\u02dd\7c\2\2\u02dd\u02de") + buf.write("\7u\2\2\u02de^\3\2\2\2\u02df\u02e0\7c\2\2\u02e0\u02e1") + buf.write("\7p\2\2\u02e1\u02e2\7f\2\2\u02e2`\3\2\2\2\u02e3\u02e4") + buf.write("\7q\2\2\u02e4\u02e5\7t\2\2\u02e5b\3\2\2\2\u02e6\u02e7") + buf.write("\7z\2\2\u02e7\u02e8\7q\2\2\u02e8\u02e9\7t\2\2\u02e9d\3") + buf.write("\2\2\2\u02ea\u02eb\7p\2\2\u02eb\u02ec\7q\2\2\u02ec\u02ed") + buf.write("\7v\2\2\u02edf\3\2\2\2\u02ee\u02ef\7d\2\2\u02ef\u02f0") + buf.write("\7g\2\2\u02f0\u02f1\7v\2\2\u02f1\u02f2\7y\2\2\u02f2\u02f3") + buf.write("\7g\2\2\u02f3\u02f4\7g\2\2\u02f4\u02f5\7p\2\2\u02f5h\3") + buf.write("\2\2\2\u02f6\u02f7\7k\2\2\u02f7\u02f8\7p\2\2\u02f8j\3") + buf.write("\2\2\2\u02f9\u02fa\7p\2\2\u02fa\u02fb\7q\2\2\u02fb\u02fc") + buf.write("\7v\2\2\u02fc\u02fd\7a\2\2\u02fd\u02fe\7k\2\2\u02fe\u02ff") + buf.write("\7p\2\2\u02ffl\3\2\2\2\u0300\u0301\7p\2\2\u0301\u0302") + buf.write("\7w\2\2\u0302\u0303\7n\2\2\u0303\u0304\7n\2\2\u0304n\3") + buf.write("\2\2\2\u0305\u0306\7k\2\2\u0306\u0307\7u\2\2\u0307\u0308") + buf.write("\7p\2\2\u0308\u0309\7w\2\2\u0309\u030a\7n\2\2\u030a\u030b") + buf.write("\7n\2\2\u030bp\3\2\2\2\u030c\u030d\7g\2\2\u030d\u030e") + buf.write("\7z\2\2\u030er\3\2\2\2\u030f\u0310\7w\2\2\u0310\u0311") + buf.write("\7p\2\2\u0311\u0312\7k\2\2\u0312\u0313\7q\2\2\u0313\u0314") + buf.write("\7p\2\2\u0314t\3\2\2\2\u0315\u0316\7f\2\2\u0316\u0317") + buf.write("\7k\2\2\u0317\u0318\7h\2\2\u0318\u0319\7h\2\2\u0319v\3") + buf.write("\2\2\2\u031a\u031b\7u\2\2\u031b\u031c\7{\2\2\u031c\u031d") + buf.write("\7o\2\2\u031d\u031e\7f\2\2\u031e\u031f\7k\2\2\u031f\u0320") + buf.write("\7h\2\2\u0320\u0321\7h\2\2\u0321x\3\2\2\2\u0322\u0323") + buf.write("\7k\2\2\u0323\u0324\7p\2\2\u0324\u0325\7v\2\2\u0325\u0326") + buf.write("\7g\2\2\u0326\u0327\7t\2\2\u0327\u0328\7u\2\2\u0328\u0329") + buf.write("\7g\2\2\u0329\u032a\7e\2\2\u032a\u032b\7v\2\2\u032bz\3") + buf.write("\2\2\2\u032c\u032d\7t\2\2\u032d\u032e\7c\2\2\u032e\u032f") + buf.write("\7p\2\2\u032f\u0330\7f\2\2\u0330\u0331\7q\2\2\u0331\u0332") + buf.write("\7o\2\2\u0332|\3\2\2\2\u0333\u0334\7m\2\2\u0334\u0335") + buf.write("\7g\2\2\u0335\u0336\7{\2\2\u0336\u0337\7u\2\2\u0337~\3") + buf.write("\2\2\2\u0338\u0339\7k\2\2\u0339\u033a\7p\2\2\u033a\u033b") + buf.write("\7v\2\2\u033b\u033c\7{\2\2\u033c\u033d\7g\2\2\u033d\u033e") + buf.write("\7c\2\2\u033e\u033f\7t\2\2\u033f\u0080\3\2\2\2\u0340\u0341") + buf.write("\7k\2\2\u0341\u0342\7p\2\2\u0342\u0343\7v\2\2\u0343\u0344") + buf.write("\7o\2\2\u0344\u0345\7q\2\2\u0345\u0346\7p\2\2\u0346\u0347") + buf.write("\7v\2\2\u0347\u0348\7j\2\2\u0348\u0082\3\2\2\2\u0349\u034a") + buf.write("\7k\2\2\u034a\u034b\7p\2\2\u034b\u034c\7v\2\2\u034c\u034d") + buf.write("\7f\2\2\u034d\u034e\7c\2\2\u034e\u034f\7{\2\2\u034f\u0084") + buf.write("\3\2\2\2\u0350\u0351\7e\2\2\u0351\u0352\7j\2\2\u0352\u0353") + buf.write("\7g\2\2\u0353\u0354\7e\2\2\u0354\u0355\7m\2\2\u0355\u0086") + buf.write("\3\2\2\2\u0356\u0357\7g\2\2\u0357\u0358\7z\2\2\u0358\u0359") + buf.write("\7k\2\2\u0359\u035a\7u\2\2\u035a\u035b\7v\2\2\u035b\u035c") + buf.write("\7u\2\2\u035c\u035d\7a\2\2\u035d\u035e\7k\2\2\u035e\u035f") + buf.write("\7p\2\2\u035f\u0088\3\2\2\2\u0360\u0361\7v\2\2\u0361\u0362") + buf.write("\7q\2\2\u0362\u008a\3\2\2\2\u0363\u0364\7t\2\2\u0364\u0365") + buf.write("\7g\2\2\u0365\u0366\7v\2\2\u0366\u0367\7w\2\2\u0367\u0368") + buf.write("\7t\2\2\u0368\u0369\7p\2\2\u0369\u008c\3\2\2\2\u036a\u036b") + buf.write("\7k\2\2\u036b\u036c\7o\2\2\u036c\u036d\7d\2\2\u036d\u036e") + buf.write("\7c\2\2\u036e\u036f\7n\2\2\u036f\u0370\7c\2\2\u0370\u0371") + buf.write("\7p\2\2\u0371\u0372\7e\2\2\u0372\u0373\7g\2\2\u0373\u008e") + buf.write("\3\2\2\2\u0374\u0375\7g\2\2\u0375\u0376\7t\2\2\u0376\u0377") + buf.write("\7t\2\2\u0377\u0378\7q\2\2\u0378\u0379\7t\2\2\u0379\u037a") + buf.write("\7e\2\2\u037a\u037b\7q\2\2\u037b\u037c\7f\2\2\u037c\u037d") + buf.write("\7g\2\2\u037d\u0090\3\2\2\2\u037e\u037f\7c\2\2\u037f\u0380") + buf.write("\7n\2\2\u0380\u0381\7n\2\2\u0381\u0092\3\2\2\2\u0382\u0383") + buf.write("\7c\2\2\u0383\u0384\7i\2\2\u0384\u0385\7i\2\2\u0385\u0386") + buf.write("\7t\2\2\u0386\u0094\3\2\2\2\u0387\u0388\7g\2\2\u0388\u0389") + buf.write("\7t\2\2\u0389\u038a\7t\2\2\u038a\u038b\7q\2\2\u038b\u038c") + buf.write("\7t\2\2\u038c\u038d\7n\2\2\u038d\u038e\7g\2\2\u038e\u038f") + buf.write("\7x\2\2\u038f\u0390\7g\2\2\u0390\u0391\7n\2\2\u0391\u0096") + buf.write("\3\2\2\2\u0392\u0393\7q\2\2\u0393\u0394\7t\2\2\u0394\u0395") + buf.write("\7f\2\2\u0395\u0396\7g\2\2\u0396\u0397\7t\2\2\u0397\u0098") + buf.write("\3\2\2\2\u0398\u0399\7d\2\2\u0399\u039a\7{\2\2\u039a\u009a") + buf.write("\3\2\2\2\u039b\u039c\7t\2\2\u039c\u039d\7c\2\2\u039d\u039e") + buf.write("\7p\2\2\u039e\u039f\7m\2\2\u039f\u009c\3\2\2\2\u03a0\u03a1") + buf.write("\7c\2\2\u03a1\u03a2\7u\2\2\u03a2\u03a3\7e\2\2\u03a3\u009e") + buf.write("\3\2\2\2\u03a4\u03a5\7f\2\2\u03a5\u03a6\7g\2\2\u03a6\u03a7") + buf.write("\7u\2\2\u03a7\u03a8\7e\2\2\u03a8\u00a0\3\2\2\2\u03a9\u03aa") + buf.write("\7o\2\2\u03aa\u03ab\7k\2\2\u03ab\u03ac\7p\2\2\u03ac\u00a2") + buf.write("\3\2\2\2\u03ad\u03ae\7o\2\2\u03ae\u03af\7c\2\2\u03af\u03b0") + buf.write("\7z\2\2\u03b0\u00a4\3\2\2\2\u03b1\u03b2\7h\2\2\u03b2\u03b3") + buf.write("\7k\2\2\u03b3\u03b4\7t\2\2\u03b4\u03b5\7u\2\2\u03b5\u03b6") + buf.write("\7v\2\2\u03b6\u00a6\3\2\2\2\u03b7\u03b8\7n\2\2\u03b8\u03b9") + buf.write("\7c\2\2\u03b9\u03ba\7u\2\2\u03ba\u03bb\7v\2\2\u03bb\u00a8") + buf.write("\3\2\2\2\u03bc\u03bd\7k\2\2\u03bd\u03be\7p\2\2\u03be\u03bf") + buf.write("\7f\2\2\u03bf\u03c0\7g\2\2\u03c0\u03c1\7z\2\2\u03c1\u03c2") + buf.write("\7q\2\2\u03c2\u03c3\7h\2\2\u03c3\u00aa\3\2\2\2\u03c4\u03c5") + buf.write("\7c\2\2\u03c5\u03c6\7d\2\2\u03c6\u03c7\7u\2\2\u03c7\u00ac") + buf.write("\3\2\2\2\u03c8\u03c9\7m\2\2\u03c9\u03ca\7g\2\2\u03ca\u03cb") + buf.write("\7{\2\2\u03cb\u00ae\3\2\2\2\u03cc\u03cd\7n\2\2\u03cd\u03ce") + buf.write("\7p\2\2\u03ce\u00b0\3\2\2\2\u03cf\u03d0\7n\2\2\u03d0\u03d1") + buf.write("\7q\2\2\u03d1\u03d2\7i\2\2\u03d2\u00b2\3\2\2\2\u03d3\u03d4") + buf.write("\7v\2\2\u03d4\u03d5\7t\2\2\u03d5\u03d6\7w\2\2\u03d6\u03d7") + buf.write("\7p\2\2\u03d7\u03d8\7e\2\2\u03d8\u00b4\3\2\2\2\u03d9\u03da") + buf.write("\7t\2\2\u03da\u03db\7q\2\2\u03db\u03dc\7w\2\2\u03dc\u03dd") + buf.write("\7p\2\2\u03dd\u03de\7f\2\2\u03de\u00b6\3\2\2\2\u03df\u03e0") + buf.write("\7r\2\2\u03e0\u03e1\7q\2\2\u03e1\u03e2\7y\2\2\u03e2\u03e3") + buf.write("\7g\2\2\u03e3\u03e4\7t\2\2\u03e4\u00b8\3\2\2\2\u03e5\u03e6") + buf.write("\7o\2\2\u03e6\u03e7\7q\2\2\u03e7\u03e8\7f\2\2\u03e8\u00ba") + buf.write("\3\2\2\2\u03e9\u03ea\7n\2\2\u03ea\u03eb\7g\2\2\u03eb\u03ec") + buf.write("\7p\2\2\u03ec\u03ed\7i\2\2\u03ed\u03ee\7v\2\2\u03ee\u03ef") + buf.write("\7j\2\2\u03ef\u00bc\3\2\2\2\u03f0\u03f1\7~\2\2\u03f1\u03f2") + buf.write("\7~\2\2\u03f2\u00be\3\2\2\2\u03f3\u03f4\7v\2\2\u03f4\u03f5") + buf.write("\7t\2\2\u03f5\u03f6\7k\2\2\u03f6\u03f7\7o\2\2\u03f7\u00c0") + buf.write("\3\2\2\2\u03f8\u03f9\7w\2\2\u03f9\u03fa\7r\2\2\u03fa\u03fb") + buf.write("\7r\2\2\u03fb\u03fc\7g\2\2\u03fc\u03fd\7t\2\2\u03fd\u00c2") + buf.write("\3\2\2\2\u03fe\u03ff\7n\2\2\u03ff\u0400\7q\2\2\u0400\u0401") + buf.write("\7y\2\2\u0401\u0402\7g\2\2\u0402\u0403\7t\2\2\u0403\u00c4") + buf.write("\3\2\2\2\u0404\u0405\7u\2\2\u0405\u0406\7w\2\2\u0406\u0407") + buf.write("\7d\2\2\u0407\u0408\7u\2\2\u0408\u0409\7v\2\2\u0409\u040a") + buf.write("\7t\2\2\u040a\u00c6\3\2\2\2\u040b\u040c\7u\2\2\u040c\u040d") + buf.write("\7w\2\2\u040d\u040e\7o\2\2\u040e\u00c8\3\2\2\2\u040f\u0410") + buf.write("\7c\2\2\u0410\u0411\7x\2\2\u0411\u0412\7i\2\2\u0412\u00ca") + buf.write("\3\2\2\2\u0413\u0414\7o\2\2\u0414\u0415\7g\2\2\u0415\u0416") + buf.write("\7f\2\2\u0416\u0417\7k\2\2\u0417\u0418\7c\2\2\u0418\u0419") + buf.write("\7p\2\2\u0419\u00cc\3\2\2\2\u041a\u041b\7e\2\2\u041b\u041c") + buf.write("\7q\2\2\u041c\u041d\7w\2\2\u041d\u041e\7p\2\2\u041e\u041f") + buf.write("\7v\2\2\u041f\u00ce\3\2\2\2\u0420\u0421\7k\2\2\u0421\u0422") + buf.write("\7f\2\2\u0422\u0423\7g\2\2\u0423\u0424\7p\2\2\u0424\u0425") + buf.write("\7v\2\2\u0425\u0426\7k\2\2\u0426\u0427\7h\2\2\u0427\u0428") + buf.write("\7k\2\2\u0428\u0429\7g\2\2\u0429\u042a\7t\2\2\u042a\u00d0") + buf.write("\3\2\2\2\u042b\u042c\7o\2\2\u042c\u042d\7g\2\2\u042d\u042e") + buf.write("\7c\2\2\u042e\u042f\7u\2\2\u042f\u0430\7w\2\2\u0430\u0431") + buf.write("\7t\2\2\u0431\u0432\7g\2\2\u0432\u00d2\3\2\2\2\u0433\u0434") + buf.write("\7c\2\2\u0434\u0435\7v\2\2\u0435\u0436\7v\2\2\u0436\u0437") + buf.write("\7t\2\2\u0437\u0438\7k\2\2\u0438\u0439\7d\2\2\u0439\u043a") + buf.write("\7w\2\2\u043a\u043b\7v\2\2\u043b\u043c\7g\2\2\u043c\u00d4") + buf.write("\3\2\2\2\u043d\u043e\7h\2\2\u043e\u043f\7k\2\2\u043f\u0440") + buf.write("\7n\2\2\u0440\u0441\7v\2\2\u0441\u0442\7g\2\2\u0442\u0443") + buf.write("\7t\2\2\u0443\u00d6\3\2\2\2\u0444\u0445\7o\2\2\u0445\u0446") + buf.write("\7g\2\2\u0446\u0447\7t\2\2\u0447\u0448\7i\2\2\u0448\u0449") + buf.write("\7g\2\2\u0449\u00d8\3\2\2\2\u044a\u044b\7g\2\2\u044b\u044c") + buf.write("\7z\2\2\u044c\u044d\7r\2\2\u044d\u00da\3\2\2\2\u044e\u044f") + buf.write("\7e\2\2\u044f\u0450\7q\2\2\u0450\u0451\7o\2\2\u0451\u0452") + buf.write("\7r\2\2\u0452\u0453\7q\2\2\u0453\u0454\7p\2\2\u0454\u0455") + buf.write("\7g\2\2\u0455\u0456\7p\2\2\u0456\u0457\7v\2\2\u0457\u0458") + buf.write("\7T\2\2\u0458\u0459\7q\2\2\u0459\u045a\7n\2\2\u045a\u045b") + buf.write("\7g\2\2\u045b\u00dc\3\2\2\2\u045c\u045d\7x\2\2\u045d\u045e") + buf.write("\7k\2\2\u045e\u045f\7t\2\2\u045f\u0460\7c\2\2\u0460\u0461") + buf.write("\7n\2\2\u0461\u00de\3\2\2\2\u0462\u0463\7r\2\2\u0463\u0464") + buf.write("\7t\2\2\u0464\u0465\7q\2\2\u0465\u0466\7r\2\2\u0466\u0467") + buf.write("\7c\2\2\u0467\u0468\7i\2\2\u0468\u0469\7c\2\2\u0469\u046a") + buf.write("\7v\2\2\u046a\u046b\7k\2\2\u046b\u046c\7q\2\2\u046c\u046d") + buf.write("\7p\2\2\u046d\u00e0\3\2\2\2\u046e\u046f\7o\2\2\u046f\u0470") + buf.write("\7c\2\2\u0470\u0471\7v\2\2\u0471\u0472\7e\2\2\u0472\u0473") + buf.write("\7j\2\2\u0473\u0474\7a\2\2\u0474\u0475\7e\2\2\u0475\u0476") + buf.write("\7j\2\2\u0476\u0477\7c\2\2\u0477\u0478\7t\2\2\u0478\u0479") + buf.write("\7c\2\2\u0479\u047a\7e\2\2\u047a\u047b\7v\2\2\u047b\u047c") + buf.write("\7g\2\2\u047c\u047d\7t\2\2\u047d\u047e\7u\2\2\u047e\u00e2") + buf.write("\3\2\2\2\u047f\u0480\7v\2\2\u0480\u0481\7{\2\2\u0481\u0482") + buf.write("\7r\2\2\u0482\u0483\7g\2\2\u0483\u00e4\3\2\2\2\u0484\u0485") + buf.write("\7p\2\2\u0485\u0486\7x\2\2\u0486\u0487\7n\2\2\u0487\u00e6") + buf.write("\3\2\2\2\u0488\u0489\7j\2\2\u0489\u048a\7k\2\2\u048a\u048b") + buf.write("\7g\2\2\u048b\u048c\7t\2\2\u048c\u048d\7c\2\2\u048d\u048e") + buf.write("\7t\2\2\u048e\u048f\7e\2\2\u048f\u0490\7j\2\2\u0490\u0491") + buf.write("\7{\2\2\u0491\u00e8\3\2\2\2\u0492\u0493\7a\2\2\u0493\u00ea") + buf.write("\3\2\2\2\u0494\u0495\7k\2\2\u0495\u0496\7p\2\2\u0496\u0497") + buf.write("\7x\2\2\u0497\u0498\7c\2\2\u0498\u0499\7n\2\2\u0499\u049a") + buf.write("\7k\2\2\u049a\u049b\7f\2\2\u049b\u00ec\3\2\2\2\u049c\u049d") + buf.write("\7x\2\2\u049d\u049e\7c\2\2\u049e\u049f\7n\2\2\u049f\u04a0") + buf.write("\7w\2\2\u04a0\u04a1\7g\2\2\u04a1\u04a2\7f\2\2\u04a2\u04a3") + buf.write("\7q\2\2\u04a3\u04a4\7o\2\2\u04a4\u04a5\7c\2\2\u04a5\u04a6") + buf.write("\7k\2\2\u04a6\u04a7\7p\2\2\u04a7\u00ee\3\2\2\2\u04a8\u04a9") + buf.write("\7x\2\2\u04a9\u04aa\7c\2\2\u04aa\u04ab\7t\2\2\u04ab\u04ac") + buf.write("\7k\2\2\u04ac\u04ad\7c\2\2\u04ad\u04ae\7d\2\2\u04ae\u04af") + buf.write("\7n\2\2\u04af\u04b0\7g\2\2\u04b0\u00f0\3\2\2\2\u04b1\u04b2") + buf.write("\7f\2\2\u04b2\u04b3\7c\2\2\u04b3\u04b4\7v\2\2\u04b4\u04b5") + buf.write("\7c\2\2\u04b5\u00f2\3\2\2\2\u04b6\u04b7\7u\2\2\u04b7\u04b8") + buf.write("\7v\2\2\u04b8\u04b9\7t\2\2\u04b9\u04ba\7w\2\2\u04ba\u04bb") + buf.write("\7e\2\2\u04bb\u04bc\7v\2\2\u04bc\u04bd\7w\2\2\u04bd\u04be") + buf.write("\7t\2\2\u04be\u04bf\7g\2\2\u04bf\u00f4\3\2\2\2\u04c0\u04c1") + buf.write("\7f\2\2\u04c1\u04c2\7c\2\2\u04c2\u04c3\7v\2\2\u04c3\u04c4") + buf.write("\7c\2\2\u04c4\u04c5\7u\2\2\u04c5\u04c6\7g\2\2\u04c6\u04c7") + buf.write("\7v\2\2\u04c7\u00f6\3\2\2\2\u04c8\u04c9\7q\2\2\u04c9\u04ca") + buf.write("\7r\2\2\u04ca\u04cb\7g\2\2\u04cb\u04cc\7t\2\2\u04cc\u04cd") + buf.write("\7c\2\2\u04cd\u04ce\7v\2\2\u04ce\u04cf\7q\2\2\u04cf\u04d0") + buf.write("\7t\2\2\u04d0\u00f8\3\2\2\2\u04d1\u04d2\7f\2\2\u04d2\u04d3") + buf.write("\7g\2\2\u04d3\u04d4\7h\2\2\u04d4\u04d5\7k\2\2\u04d5\u04d6") + buf.write("\7p\2\2\u04d6\u04d7\7g\2\2\u04d7\u00fa\3\2\2\2\u04d8\u04d9") + buf.write("\7>\2\2\u04d9\u04da\7/\2\2\u04da\u00fc\3\2\2\2\u04db\u04dc") + buf.write("\7f\2\2\u04dc\u04dd\7c\2\2\u04dd\u04de\7v\2\2\u04de\u04df") + buf.write("\7c\2\2\u04df\u04e0\7r\2\2\u04e0\u04e1\7q\2\2\u04e1\u04e2") + buf.write("\7k\2\2\u04e2\u04e3\7p\2\2\u04e3\u04e4\7v\2\2\u04e4\u00fe") + buf.write("\3\2\2\2\u04e5\u04e6\7j\2\2\u04e6\u04e7\7k\2\2\u04e7\u04e8") + buf.write("\7g\2\2\u04e8\u04e9\7t\2\2\u04e9\u04ea\7c\2\2\u04ea\u04eb") + buf.write("\7t\2\2\u04eb\u04ec\7e\2\2\u04ec\u04ed\7j\2\2\u04ed\u04ee") + buf.write("\7k\2\2\u04ee\u04ef\7e\2\2\u04ef\u04f0\7c\2\2\u04f0\u04f1") + buf.write("\7n\2\2\u04f1\u0100\3\2\2\2\u04f2\u04f3\7t\2\2\u04f3\u04f4") + buf.write("\7w\2\2\u04f4\u04f5\7n\2\2\u04f5\u04f6\7g\2\2\u04f6\u04f7") + buf.write("\7u\2\2\u04f7\u04f8\7g\2\2\u04f8\u04f9\7v\2\2\u04f9\u0102") + buf.write("\3\2\2\2\u04fa\u04fb\7t\2\2\u04fb\u04fc\7w\2\2\u04fc\u04fd") + buf.write("\7n\2\2\u04fd\u04fe\7g\2\2\u04fe\u0104\3\2\2\2\u04ff\u0500") + buf.write("\7g\2\2\u0500\u0501\7p\2\2\u0501\u0502\7f\2\2\u0502\u0106") + buf.write("\3\2\2\2\u0503\u0504\7c\2\2\u0504\u0505\7n\2\2\u0505\u0506") + buf.write("\7v\2\2\u0506\u0507\7g\2\2\u0507\u0508\7t\2\2\u0508\u0509") + buf.write("\7F\2\2\u0509\u050a\7c\2\2\u050a\u050b\7v\2\2\u050b\u050c") + buf.write("\7c\2\2\u050c\u050d\7u\2\2\u050d\u050e\7g\2\2\u050e\u050f") + buf.write("\7v\2\2\u050f\u0108\3\2\2\2\u0510\u0511\7n\2\2\u0511\u0512") + buf.write("\7v\2\2\u0512\u0513\7t\2\2\u0513\u0514\7k\2\2\u0514\u0515") + buf.write("\7o\2\2\u0515\u010a\3\2\2\2\u0516\u0517\7t\2\2\u0517\u0518") + buf.write("\7v\2\2\u0518\u0519\7t\2\2\u0519\u051a\7k\2\2\u051a\u051b") + buf.write("\7o\2\2\u051b\u010c\3\2\2\2\u051c\u051d\7k\2\2\u051d\u051e") + buf.write("\7p\2\2\u051e\u051f\7u\2\2\u051f\u0520\7v\2\2\u0520\u0521") + buf.write("\7t\2\2\u0521\u010e\3\2\2\2\u0522\u0523\7t\2\2\u0523\u0524") + buf.write("\7g\2\2\u0524\u0525\7r\2\2\u0525\u0526\7n\2\2\u0526\u0527") + buf.write("\7c\2\2\u0527\u0528\7e\2\2\u0528\u0529\7g\2\2\u0529\u0110") + buf.write("\3\2\2\2\u052a\u052b\7e\2\2\u052b\u052c\7g\2\2\u052c\u052d") + buf.write("\7k\2\2\u052d\u052e\7n\2\2\u052e\u0112\3\2\2\2\u052f\u0530") + buf.write("\7h\2\2\u0530\u0531\7n\2\2\u0531\u0532\7q\2\2\u0532\u0533") + buf.write("\7q\2\2\u0533\u0534\7t\2\2\u0534\u0114\3\2\2\2\u0535\u0536") + buf.write("\7u\2\2\u0536\u0537\7s\2\2\u0537\u0538\7t\2\2\u0538\u0539") + buf.write("\7v\2\2\u0539\u0116\3\2\2\2\u053a\u053b\7c\2\2\u053b\u053c") + buf.write("\7p\2\2\u053c\u053d\7{\2\2\u053d\u0118\3\2\2\2\u053e\u053f") + buf.write("\7u\2\2\u053f\u0540\7g\2\2\u0540\u0541\7v\2\2\u0541\u0542") + buf.write("\7f\2\2\u0542\u0543\7k\2\2\u0543\u0544\7h\2\2\u0544\u0545") + buf.write("\7h\2\2\u0545\u011a\3\2\2\2\u0546\u0547\7u\2\2\u0547\u0548") + buf.write("\7v\2\2\u0548\u0549\7f\2\2\u0549\u054a\7f\2\2\u054a\u054b") + buf.write("\7g\2\2\u054b\u054c\7x\2\2\u054c\u054d\7a\2\2\u054d\u054e") + buf.write("\7r\2\2\u054e\u054f\7q\2\2\u054f\u0550\7r\2\2\u0550\u011c") + buf.write("\3\2\2\2\u0551\u0552\7u\2\2\u0552\u0553\7v\2\2\u0553\u0554") + buf.write("\7f\2\2\u0554\u0555\7f\2\2\u0555\u0556\7g\2\2\u0556\u0557") + buf.write("\7x\2\2\u0557\u0558\7a\2\2\u0558\u0559\7u\2\2\u0559\u055a") + buf.write("\7c\2\2\u055a\u055b\7o\2\2\u055b\u055c\7r\2\2\u055c\u011e") + buf.write("\3\2\2\2\u055d\u055e\7x\2\2\u055e\u055f\7c\2\2\u055f\u0560") + buf.write("\7t\2\2\u0560\u0561\7a\2\2\u0561\u0562\7r\2\2\u0562\u0563") + buf.write("\7q\2\2\u0563\u0564\7r\2\2\u0564\u0120\3\2\2\2\u0565\u0566") + buf.write("\7x\2\2\u0566\u0567\7c\2\2\u0567\u0568\7t\2\2\u0568\u0569") + buf.write("\7a\2\2\u0569\u056a\7u\2\2\u056a\u056b\7c\2\2\u056b\u056c") + buf.write("\7o\2\2\u056c\u056d\7r\2\2\u056d\u0122\3\2\2\2\u056e\u056f") + buf.write("\7i\2\2\u056f\u0570\7t\2\2\u0570\u0571\7q\2\2\u0571\u0572") + buf.write("\7w\2\2\u0572\u0573\7r\2\2\u0573\u0124\3\2\2\2\u0574\u0575") + buf.write("\7g\2\2\u0575\u0576\7z\2\2\u0576\u0577\7e\2\2\u0577\u0578") + buf.write("\7g\2\2\u0578\u0579\7r\2\2\u0579\u057a\7v\2\2\u057a\u0126") + buf.write("\3\2\2\2\u057b\u057c\7j\2\2\u057c\u057d\7c\2\2\u057d\u057e") + buf.write("\7x\2\2\u057e\u057f\7k\2\2\u057f\u0580\7p\2\2\u0580\u0581") + buf.write("\7i\2\2\u0581\u0128\3\2\2\2\u0582\u0583\7h\2\2\u0583\u0584") + buf.write("\7k\2\2\u0584\u0585\7t\2\2\u0585\u0586\7u\2\2\u0586\u0587") + buf.write("\7v\2\2\u0587\u0588\7a\2\2\u0588\u0589\7x\2\2\u0589\u058a") + buf.write("\7c\2\2\u058a\u058b\7n\2\2\u058b\u058c\7w\2\2\u058c\u058d") + buf.write("\7g\2\2\u058d\u012a\3\2\2\2\u058e\u058f\7n\2\2\u058f\u0590") + buf.write("\7c\2\2\u0590\u0591\7u\2\2\u0591\u0592\7v\2\2\u0592\u0593") + buf.write("\7a\2\2\u0593\u0594\7x\2\2\u0594\u0595\7c\2\2\u0595\u0596") + buf.write("\7n\2\2\u0596\u0597\7w\2\2\u0597\u0598\7g\2\2\u0598\u012c") + buf.write("\3\2\2\2\u0599\u059a\7n\2\2\u059a\u059b\7c\2\2\u059b\u059c") + buf.write("\7i\2\2\u059c\u012e\3\2\2\2\u059d\u059e\7n\2\2\u059e\u059f") + buf.write("\7g\2\2\u059f\u05a0\7c\2\2\u05a0\u05a1\7f\2\2\u05a1\u0130") + buf.write("\3\2\2\2\u05a2\u05a3\7t\2\2\u05a3\u05a4\7c\2\2\u05a4\u05a5") + buf.write("\7v\2\2\u05a5\u05a6\7k\2\2\u05a6\u05a7\7q\2\2\u05a7\u05a8") + buf.write("\7a\2\2\u05a8\u05a9\7v\2\2\u05a9\u05aa\7q\2\2\u05aa\u05ab") + buf.write("\7a\2\2\u05ab\u05ac\7t\2\2\u05ac\u05ad\7g\2\2\u05ad\u05ae") + buf.write("\7r\2\2\u05ae\u05af\7q\2\2\u05af\u05b0\7t\2\2\u05b0\u05b1") + buf.write("\7v\2\2\u05b1\u0132\3\2\2\2\u05b2\u05b3\7q\2\2\u05b3\u05b4") + buf.write("\7x\2\2\u05b4\u05b5\7g\2\2\u05b5\u05b6\7t\2\2\u05b6\u0134") + buf.write("\3\2\2\2\u05b7\u05b8\7r\2\2\u05b8\u05b9\7t\2\2\u05b9\u05ba") + buf.write("\7g\2\2\u05ba\u05bb\7e\2\2\u05bb\u05bc\7g\2\2\u05bc\u05bd") + buf.write("\7f\2\2\u05bd\u05be\7k\2\2\u05be\u05bf\7p\2\2\u05bf\u05c0") + buf.write("\7i\2\2\u05c0\u0136\3\2\2\2\u05c1\u05c2\7h\2\2\u05c2\u05c3") + buf.write("\7q\2\2\u05c3\u05c4\7n\2\2\u05c4\u05c5\7n\2\2\u05c5\u05c6") + buf.write("\7q\2\2\u05c6\u05c7\7y\2\2\u05c7\u05c8\7k\2\2\u05c8\u05c9") + buf.write("\7p\2\2\u05c9\u05ca\7i\2\2\u05ca\u0138\3\2\2\2\u05cb\u05cc") + buf.write("\7w\2\2\u05cc\u05cd\7p\2\2\u05cd\u05ce\7d\2\2\u05ce\u05cf") + buf.write("\7q\2\2\u05cf\u05d0\7w\2\2\u05d0\u05d1\7p\2\2\u05d1\u05d2") + buf.write("\7f\2\2\u05d2\u05d3\7g\2\2\u05d3\u05d4\7f\2\2\u05d4\u013a") + buf.write("\3\2\2\2\u05d5\u05d6\7r\2\2\u05d6\u05d7\7c\2\2\u05d7\u05d8") + buf.write("\7t\2\2\u05d8\u05d9\7v\2\2\u05d9\u05da\7k\2\2\u05da\u05db") + buf.write("\7v\2\2\u05db\u05dc\7k\2\2\u05dc\u05dd\7q\2\2\u05dd\u05de") + buf.write("\7p\2\2\u05de\u013c\3\2\2\2\u05df\u05e0\7t\2\2\u05e0\u05e1") + buf.write("\7q\2\2\u05e1\u05e2\7y\2\2\u05e2\u05e3\7u\2\2\u05e3\u013e") + buf.write("\3\2\2\2\u05e4\u05e5\7t\2\2\u05e5\u05e6\7c\2\2\u05e6\u05e7") + buf.write("\7p\2\2\u05e7\u05e8\7i\2\2\u05e8\u05e9\7g\2\2\u05e9\u0140") + buf.write("\3\2\2\2\u05ea\u05eb\7e\2\2\u05eb\u05ec\7w\2\2\u05ec\u05ed") + buf.write("\7t\2\2\u05ed\u05ee\7t\2\2\u05ee\u05ef\7g\2\2\u05ef\u05f0") + buf.write("\7p\2\2\u05f0\u05f1\7v\2\2\u05f1\u0142\3\2\2\2\u05f2\u05f3") + buf.write("\7x\2\2\u05f3\u05f4\7c\2\2\u05f4\u05f5\7n\2\2\u05f5\u05f6") + buf.write("\7k\2\2\u05f6\u05f7\7f\2\2\u05f7\u0144\3\2\2\2\u05f8\u05f9") + buf.write("\7h\2\2\u05f9\u05fa\7k\2\2\u05fa\u05fb\7n\2\2\u05fb\u05fc") + buf.write("\7n\2\2\u05fc\u05fd\7a\2\2\u05fd\u05fe\7v\2\2\u05fe\u05ff") + buf.write("\7k\2\2\u05ff\u0600\7o\2\2\u0600\u0601\7g\2\2\u0601\u0602") + buf.write("\7a\2\2\u0602\u0603\7u\2\2\u0603\u0604\7g\2\2\u0604\u0605") + buf.write("\7t\2\2\u0605\u0606\7k\2\2\u0606\u0607\7g\2\2\u0607\u0608") + buf.write("\7u\2\2\u0608\u0146\3\2\2\2\u0609\u060a\7h\2\2\u060a\u060b") + buf.write("\7n\2\2\u060b\u060c\7q\2\2\u060c\u060d\7y\2\2\u060d\u060e") + buf.write("\7a\2\2\u060e\u060f\7v\2\2\u060f\u0610\7q\2\2\u0610\u0611") + buf.write("\7a\2\2\u0611\u0612\7u\2\2\u0612\u0613\7v\2\2\u0613\u0614") + buf.write("\7q\2\2\u0614\u0615\7e\2\2\u0615\u0616\7m\2\2\u0616\u0148") + buf.write("\3\2\2\2\u0617\u0618\7u\2\2\u0618\u0619\7v\2\2\u0619\u061a") + buf.write("\7q\2\2\u061a\u061b\7e\2\2\u061b\u061c\7m\2\2\u061c\u061d") + buf.write("\7a\2\2\u061d\u061e\7v\2\2\u061e\u061f\7q\2\2\u061f\u0620") + buf.write("\7a\2\2\u0620\u0621\7h\2\2\u0621\u0622\7n\2\2\u0622\u0623") + buf.write("\7q\2\2\u0623\u0624\7y\2\2\u0624\u014a\3\2\2\2\u0625\u0626") + buf.write("\7v\2\2\u0626\u0627\7k\2\2\u0627\u0628\7o\2\2\u0628\u0629") + buf.write("\7g\2\2\u0629\u062a\7u\2\2\u062a\u062b\7j\2\2\u062b\u062c") + buf.write("\7k\2\2\u062c\u062d\7h\2\2\u062d\u062e\7v\2\2\u062e\u014c") + buf.write("\3\2\2\2\u062f\u0630\7o\2\2\u0630\u0631\7g\2\2\u0631\u0632") + buf.write("\7c\2\2\u0632\u0633\7u\2\2\u0633\u0634\7w\2\2\u0634\u0635") + buf.write("\7t\2\2\u0635\u0636\7g\2\2\u0636\u0637\7u\2\2\u0637\u014e") + buf.write("\3\2\2\2\u0638\u0639\7p\2\2\u0639\u063a\7q\2\2\u063a\u063b") + buf.write("\7a\2\2\u063b\u063c\7o\2\2\u063c\u063d\7g\2\2\u063d\u063e") + buf.write("\7c\2\2\u063e\u063f\7u\2\2\u063f\u0640\7w\2\2\u0640\u0641") + buf.write("\7t\2\2\u0641\u0642\7g\2\2\u0642\u0643\7u\2\2\u0643\u0150") + buf.write("\3\2\2\2\u0644\u0645\7e\2\2\u0645\u0646\7q\2\2\u0646\u0647") + buf.write("\7p\2\2\u0647\u0648\7f\2\2\u0648\u0649\7k\2\2\u0649\u064a") + buf.write("\7v\2\2\u064a\u064b\7k\2\2\u064b\u064c\7q\2\2\u064c\u064d") + buf.write("\7p\2\2\u064d\u0152\3\2\2\2\u064e\u064f\7d\2\2\u064f\u0650") + buf.write("\7q\2\2\u0650\u0651\7q\2\2\u0651\u0652\7n\2\2\u0652\u0653") + buf.write("\7g\2\2\u0653\u0654\7c\2\2\u0654\u0655\7p\2\2\u0655\u0154") + buf.write("\3\2\2\2\u0656\u0657\7f\2\2\u0657\u0658\7c\2\2\u0658\u0659") + buf.write("\7v\2\2\u0659\u065a\7g\2\2\u065a\u0156\3\2\2\2\u065b\u065c") + buf.write("\7v\2\2\u065c\u065d\7k\2\2\u065d\u065e\7o\2\2\u065e\u065f") + buf.write("\7g\2\2\u065f\u0660\7a\2\2\u0660\u0661\7r\2\2\u0661\u0662") + buf.write("\7g\2\2\u0662\u0663\7t\2\2\u0663\u0664\7k\2\2\u0664\u0665") + buf.write("\7q\2\2\u0665\u0666\7f\2\2\u0666\u0158\3\2\2\2\u0667\u0668") + buf.write("\7p\2\2\u0668\u0669\7w\2\2\u0669\u066a\7o\2\2\u066a\u066b") + buf.write("\7d\2\2\u066b\u066c\7g\2\2\u066c\u066d\7t\2\2\u066d\u015a") + buf.write("\3\2\2\2\u066e\u066f\7u\2\2\u066f\u0670\7v\2\2\u0670\u0671") + buf.write("\7t\2\2\u0671\u0672\7k\2\2\u0672\u0673\7p\2\2\u0673\u0674") + buf.write("\7i\2\2\u0674\u015c\3\2\2\2\u0675\u0676\7v\2\2\u0676\u0677") + buf.write("\7k\2\2\u0677\u0678\7o\2\2\u0678\u0679\7g\2\2\u0679\u015e") + buf.write("\3\2\2\2\u067a\u067b\7k\2\2\u067b\u067c\7p\2\2\u067c\u067d") + buf.write("\7v\2\2\u067d\u067e\7g\2\2\u067e\u067f\7i\2\2\u067f\u0680") + buf.write("\7g\2\2\u0680\u0681\7t\2\2\u0681\u0160\3\2\2\2\u0682\u0683") + buf.write("\7h\2\2\u0683\u0684\7n\2\2\u0684\u0685\7q\2\2\u0685\u0686") + buf.write("\7c\2\2\u0686\u0687\7v\2\2\u0687\u0162\3\2\2\2\u0688\u0689") + buf.write("\7n\2\2\u0689\u068a\7k\2\2\u068a\u068b\7u\2\2\u068b\u068c") + buf.write("\7v\2\2\u068c\u0164\3\2\2\2\u068d\u068e\7t\2\2\u068e\u068f") + buf.write("\7g\2\2\u068f\u0690\7e\2\2\u0690\u0691\7q\2\2\u0691\u0692") + buf.write("\7t\2\2\u0692\u0693\7f\2\2\u0693\u0166\3\2\2\2\u0694\u0695") + buf.write("\7t\2\2\u0695\u0696\7g\2\2\u0696\u0697\7u\2\2\u0697\u0698") + buf.write("\7v\2\2\u0698\u0699\7t\2\2\u0699\u069a\7k\2\2\u069a\u069b") + buf.write("\7e\2\2\u069b\u069c\7v\2\2\u069c\u0168\3\2\2\2\u069d\u069e") + buf.write("\7{\2\2\u069e\u069f\7{\2\2\u069f\u06a0\7{\2\2\u06a0\u06a1") + buf.write("\7{\2\2\u06a1\u016a\3\2\2\2\u06a2\u06a3\7o\2\2\u06a3\u06a4") + buf.write("\7o\2\2\u06a4\u016c\3\2\2\2\u06a5\u06a6\7f\2\2\u06a6\u06a7") + buf.write("\7f\2\2\u06a7\u016e\3\2\2\2\u06a8\u06a9\7o\2\2\u06a9\u06aa") + buf.write("\7c\2\2\u06aa\u06ab\7z\2\2\u06ab\u06ac\7N\2\2\u06ac\u06ad") + buf.write("\7g\2\2\u06ad\u06ae\7p\2\2\u06ae\u06af\7i\2\2\u06af\u06b0") + buf.write("\7v\2\2\u06b0\u06b1\7j\2\2\u06b1\u0170\3\2\2\2\u06b2\u06b3") + buf.write("\7t\2\2\u06b3\u06b4\7g\2\2\u06b4\u06b5\7i\2\2\u06b5\u06b6") + buf.write("\7g\2\2\u06b6\u06b7\7z\2\2\u06b7\u06b8\7r\2\2\u06b8\u0172") + buf.write("\3\2\2\2\u06b9\u06ba\7k\2\2\u06ba\u06bb\7u\2\2\u06bb\u0174") + buf.write("\3\2\2\2\u06bc\u06bd\7y\2\2\u06bd\u06be\7j\2\2\u06be\u06bf") + buf.write("\7g\2\2\u06bf\u06c0\7p\2\2\u06c0\u0176\3\2\2\2\u06c1\u06c2") + buf.write("\7h\2\2\u06c2\u06c3\7t\2\2\u06c3\u06c4\7q\2\2\u06c4\u06c5") + buf.write("\7o\2\2\u06c5\u0178\3\2\2\2\u06c6\u06c7\7c\2\2\u06c7\u06c8") + buf.write("\7i\2\2\u06c8\u06c9\7i\2\2\u06c9\u06ca\7t\2\2\u06ca\u06cb") + buf.write("\7g\2\2\u06cb\u06cc\7i\2\2\u06cc\u06cd\7c\2\2\u06cd\u06ce") + buf.write("\7v\2\2\u06ce\u06cf\7g\2\2\u06cf\u06d0\7u\2\2\u06d0\u017a") + buf.write("\3\2\2\2\u06d1\u06d2\7r\2\2\u06d2\u06d3\7q\2\2\u06d3\u06d4") + buf.write("\7k\2\2\u06d4\u06d5\7p\2\2\u06d5\u06d6\7v\2\2\u06d6\u06d7") + buf.write("\7u\2\2\u06d7\u017c\3\2\2\2\u06d8\u06d9\7r\2\2\u06d9\u06da") + buf.write("\7q\2\2\u06da\u06db\7k\2\2\u06db\u06dc\7p\2\2\u06dc\u06dd") + buf.write("\7v\2\2\u06dd\u017e\3\2\2\2\u06de\u06df\7v\2\2\u06df\u06e0") + buf.write("\7q\2\2\u06e0\u06e1\7v\2\2\u06e1\u06e2\7c\2\2\u06e2\u06e3") + buf.write("\7n\2\2\u06e3\u0180\3\2\2\2\u06e4\u06e5\7r\2\2\u06e5\u06e6") + buf.write("\7c\2\2\u06e6\u06e7\7t\2\2\u06e7\u06e8\7v\2\2\u06e8\u06e9") + buf.write("\7k\2\2\u06e9\u06ea\7c\2\2\u06ea\u06eb\7n\2\2\u06eb\u0182") + buf.write("\3\2\2\2\u06ec\u06ed\7c\2\2\u06ed\u06ee\7n\2\2\u06ee\u06ef") + buf.write("\7y\2\2\u06ef\u06f0\7c\2\2\u06f0\u06f1\7{\2\2\u06f1\u06f2") + buf.write("\7u\2\2\u06f2\u0184\3\2\2\2\u06f3\u06f4\7k\2\2\u06f4\u06f5") + buf.write("\7p\2\2\u06f5\u06f6\7p\2\2\u06f6\u06f7\7g\2\2\u06f7\u06f8") + buf.write("\7t\2\2\u06f8\u06f9\7a\2\2\u06f9\u06fa\7l\2\2\u06fa\u06fb") + buf.write("\7q\2\2\u06fb\u06fc\7k\2\2\u06fc\u06fd\7p\2\2\u06fd\u0186") + buf.write("\3\2\2\2\u06fe\u06ff\7n\2\2\u06ff\u0700\7g\2\2\u0700\u0701") + buf.write("\7h\2\2\u0701\u0702\7v\2\2\u0702\u0703\7a\2\2\u0703\u0704") + buf.write("\7l\2\2\u0704\u0705\7q\2\2\u0705\u0706\7k\2\2\u0706\u0707") + buf.write("\7p\2\2\u0707\u0188\3\2\2\2\u0708\u0709\7e\2\2\u0709\u070a") + buf.write("\7t\2\2\u070a\u070b\7q\2\2\u070b\u070c\7u\2\2\u070c\u070d") + buf.write("\7u\2\2\u070d\u070e\7a\2\2\u070e\u070f\7l\2\2\u070f\u0710") + buf.write("\7q\2\2\u0710\u0711\7k\2\2\u0711\u0712\7p\2\2\u0712\u018a") + buf.write("\3\2\2\2\u0713\u0714\7h\2\2\u0714\u0715\7w\2\2\u0715\u0716") + buf.write("\7n\2\2\u0716\u0717\7n\2\2\u0717\u0718\7a\2\2\u0718\u0719") + buf.write("\7l\2\2\u0719\u071a\7q\2\2\u071a\u071b\7k\2\2\u071b\u071c") + buf.write("\7p\2\2\u071c\u018c\3\2\2\2\u071d\u071e\7o\2\2\u071e\u071f") + buf.write("\7c\2\2\u071f\u0720\7r\2\2\u0720\u0721\7u\2\2\u0721\u0722") + buf.write("\7a\2\2\u0722\u0723\7h\2\2\u0723\u0724\7t\2\2\u0724\u0725") + buf.write("\7q\2\2\u0725\u0726\7o\2\2\u0726\u018e\3\2\2\2\u0727\u0728") + buf.write("\7o\2\2\u0728\u0729\7c\2\2\u0729\u072a\7r\2\2\u072a\u072b") + buf.write("\7u\2\2\u072b\u072c\7a\2\2\u072c\u072d\7v\2\2\u072d\u072e") + buf.write("\7q\2\2\u072e\u0190\3\2\2\2\u072f\u0730\7o\2\2\u0730\u0731") + buf.write("\7c\2\2\u0731\u0732\7r\2\2\u0732\u0733\7a\2\2\u0733\u0734") + buf.write("\7v\2\2\u0734\u0735\7q\2\2\u0735\u0192\3\2\2\2\u0736\u0737") + buf.write("\7o\2\2\u0737\u0738\7c\2\2\u0738\u0739\7r\2\2\u0739\u073a") + buf.write("\7a\2\2\u073a\u073b\7h\2\2\u073b\u073c\7t\2\2\u073c\u073d") + buf.write("\7q\2\2\u073d\u073e\7o\2\2\u073e\u0194\3\2\2\2\u073f\u0740") + buf.write("\7t\2\2\u0740\u0741\7g\2\2\u0741\u0742\7v\2\2\u0742\u0743") + buf.write("\7w\2\2\u0743\u0744\7t\2\2\u0744\u0745\7p\2\2\u0745\u0746") + buf.write("\7u\2\2\u0746\u0196\3\2\2\2\u0747\u0748\7r\2\2\u0748\u0749") + buf.write("\7k\2\2\u0749\u074a\7x\2\2\u074a\u074b\7q\2\2\u074b\u074c") + buf.write("\7v\2\2\u074c\u0198\3\2\2\2\u074d\u074e\7e\2\2\u074e\u074f") + buf.write("\7w\2\2\u074f\u0750\7u\2\2\u0750\u0751\7v\2\2\u0751\u0752") + buf.write("\7q\2\2\u0752\u0753\7o\2\2\u0753\u0754\7R\2\2\u0754\u0755") + buf.write("\7k\2\2\u0755\u0756\7x\2\2\u0756\u0757\7q\2\2\u0757\u0758") + buf.write("\7v\2\2\u0758\u019a\3\2\2\2\u0759\u075a\7w\2\2\u075a\u075b") + buf.write("\7p\2\2\u075b\u075c\7r\2\2\u075c\u075d\7k\2\2\u075d\u075e") + buf.write("\7x\2\2\u075e\u075f\7q\2\2\u075f\u0760\7v\2\2\u0760\u019c") + buf.write("\3\2\2\2\u0761\u0762\7u\2\2\u0762\u0763\7w\2\2\u0763\u0764") + buf.write("\7d\2\2\u0764\u019e\3\2\2\2\u0765\u0766\7c\2\2\u0766\u0767") + buf.write("\7r\2\2\u0767\u0768\7r\2\2\u0768\u0769\7n\2\2\u0769\u076a") + buf.write("\7{\2\2\u076a\u01a0\3\2\2\2\u076b\u076c\7e\2\2\u076c\u076d") + buf.write("\7q\2\2\u076d\u076e\7p\2\2\u076e\u076f\7f\2\2\u076f\u0770") + buf.write("\7k\2\2\u0770\u0771\7v\2\2\u0771\u0772\7k\2\2\u0772\u0773") + buf.write("\7q\2\2\u0773\u0774\7p\2\2\u0774\u0775\7g\2\2\u0775\u0776") + buf.write("\7f\2\2\u0776\u01a2\3\2\2\2\u0777\u0778\7r\2\2\u0778\u0779") + buf.write("\7g\2\2\u0779\u077a\7t\2\2\u077a\u077b\7k\2\2\u077b\u077c") + buf.write("\7q\2\2\u077c\u077d\7f\2\2\u077d\u077e\7a\2\2\u077e\u077f") + buf.write("\7k\2\2\u077f\u0780\7p\2\2\u0780\u0781\7f\2\2\u0781\u0782") + buf.write("\7k\2\2\u0782\u0783\7e\2\2\u0783\u0784\7c\2\2\u0784\u0785") + buf.write("\7v\2\2\u0785\u0786\7q\2\2\u0786\u0787\7t\2\2\u0787\u01a4") + buf.write("\3\2\2\2\u0788\u0789\7u\2\2\u0789\u078a\7k\2\2\u078a\u078b") + buf.write("\7p\2\2\u078b\u078c\7i\2\2\u078c\u078d\7n\2\2\u078d\u078e") + buf.write("\7g\2\2\u078e\u01a6\3\2\2\2\u078f\u0790\7f\2\2\u0790\u0791") + buf.write("\7w\2\2\u0791\u0792\7t\2\2\u0792\u0793\7c\2\2\u0793\u0794") + buf.write("\7v\2\2\u0794\u0795\7k\2\2\u0795\u0796\7q\2\2\u0796\u0797") + buf.write("\7p\2\2\u0797\u01a8\3\2\2\2\u0798\u0799\7v\2\2\u0799\u079a") + buf.write("\7k\2\2\u079a\u079b\7o\2\2\u079b\u079c\7g\2\2\u079c\u079d") + buf.write("\7a\2\2\u079d\u079e\7c\2\2\u079e\u079f\7i\2\2\u079f\u07a0") + buf.write("\7i\2\2\u07a0\u01aa\3\2\2\2\u07a1\u07a2\7w\2\2\u07a2\u07a3") + buf.write("\7p\2\2\u07a3\u07a4\7k\2\2\u07a4\u07a5\7v\2\2\u07a5\u01ac") + buf.write("\3\2\2\2\u07a6\u07a7\7X\2\2\u07a7\u07a8\7c\2\2\u07a8\u07a9") + buf.write("\7n\2\2\u07a9\u07aa\7w\2\2\u07aa\u07ab\7g\2\2\u07ab\u01ae") + buf.write("\3\2\2\2\u07ac\u07ad\7x\2\2\u07ad\u07ae\7c\2\2\u07ae\u07af") + buf.write("\7n\2\2\u07af\u07b0\7w\2\2\u07b0\u07b1\7g\2\2\u07b1\u07b2") + buf.write("\7f\2\2\u07b2\u07b3\7q\2\2\u07b3\u07b4\7o\2\2\u07b4\u07b5") + buf.write("\7c\2\2\u07b5\u07b6\7k\2\2\u07b6\u07b7\7p\2\2\u07b7\u07b8") + buf.write("\7u\2\2\u07b8\u01b0\3\2\2\2\u07b9\u07ba\7x\2\2\u07ba\u07bb") + buf.write("\7c\2\2\u07bb\u07bc\7t\2\2\u07bc\u07bd\7k\2\2\u07bd\u07be") + buf.write("\7c\2\2\u07be\u07bf\7d\2\2\u07bf\u07c0\7n\2\2\u07c0\u07c1") + buf.write("\7g\2\2\u07c1\u07c2\7u\2\2\u07c2\u01b2\3\2\2\2\u07c3\u07c4") + buf.write("\7k\2\2\u07c4\u07c5\7p\2\2\u07c5\u07c6\7r\2\2\u07c6\u07c7") + buf.write("\7w\2\2\u07c7\u07c8\7v\2\2\u07c8\u01b4\3\2\2\2\u07c9\u07ca") + buf.write("\7q\2\2\u07ca\u07cb\7w\2\2\u07cb\u07cc\7v\2\2\u07cc\u07cd") + buf.write("\7r\2\2\u07cd\u07ce\7w\2\2\u07ce\u07cf\7v\2\2\u07cf\u01b6") + buf.write("\3\2\2\2\u07d0\u07d1\7e\2\2\u07d1\u07d2\7c\2\2\u07d2\u07d3") + buf.write("\7u\2\2\u07d3\u07d4\7v\2\2\u07d4\u01b8\3\2\2\2\u07d5\u07d6") + buf.write("\7t\2\2\u07d6\u07d7\7w\2\2\u07d7\u07d8\7n\2\2\u07d8\u07d9") + buf.write("\7g\2\2\u07d9\u07da\7a\2\2\u07da\u07db\7r\2\2\u07db\u07dc") + buf.write("\7t\2\2\u07dc\u07dd\7k\2\2\u07dd\u07de\7q\2\2\u07de\u07df") + buf.write("\7t\2\2\u07df\u07e0\7k\2\2\u07e0\u07e1\7v\2\2\u07e1\u07e2") + buf.write("\7{\2\2\u07e2\u01ba\3\2\2\2\u07e3\u07e4\7f\2\2\u07e4\u07e5") + buf.write("\7c\2\2\u07e5\u07e6\7v\2\2\u07e6\u07e7\7c\2\2\u07e7\u07e8") + buf.write("\7u\2\2\u07e8\u07e9\7g\2\2\u07e9\u07ea\7v\2\2\u07ea\u07eb") + buf.write("\7a\2\2\u07eb\u07ec\7r\2\2\u07ec\u07ed\7t\2\2\u07ed\u07ee") + buf.write("\7k\2\2\u07ee\u07ef\7q\2\2\u07ef\u07f0\7t\2\2\u07f0\u07f1") + buf.write("\7k\2\2\u07f1\u07f2\7v\2\2\u07f2\u07f3\7{\2\2\u07f3\u01bc") + buf.write("\3\2\2\2\u07f4\u07f5\7f\2\2\u07f5\u07f6\7g\2\2\u07f6\u07f7") + buf.write("\7h\2\2\u07f7\u07f8\7c\2\2\u07f8\u07f9\7w\2\2\u07f9\u07fa") + buf.write("\7n\2\2\u07fa\u07fb\7v\2\2\u07fb\u01be\3\2\2\2\u07fc\u07fd") + buf.write("\7e\2\2\u07fd\u07fe\7j\2\2\u07fe\u07ff\7g\2\2\u07ff\u0800") + buf.write("\7e\2\2\u0800\u0801\7m\2\2\u0801\u0802\7a\2\2\u0802\u0803") + buf.write("\7f\2\2\u0803\u0804\7c\2\2\u0804\u0805\7v\2\2\u0805\u0806") + buf.write("\7c\2\2\u0806\u0807\7r\2\2\u0807\u0808\7q\2\2\u0808\u0809") + buf.write("\7k\2\2\u0809\u080a\7p\2\2\u080a\u080b\7v\2\2\u080b\u01c0") + buf.write("\3\2\2\2\u080c\u080d\7e\2\2\u080d\u080e\7j\2\2\u080e\u080f") + buf.write("\7g\2\2\u080f\u0810\7e\2\2\u0810\u0811\7m\2\2\u0811\u0812") + buf.write("\7a\2\2\u0812\u0813\7j\2\2\u0813\u0814\7k\2\2\u0814\u0815") + buf.write("\7g\2\2\u0815\u0816\7t\2\2\u0816\u0817\7c\2\2\u0817\u0818") + buf.write("\7t\2\2\u0818\u0819\7e\2\2\u0819\u081a\7j\2\2\u081a\u081b") + buf.write("\7{\2\2\u081b\u01c2\3\2\2\2\u081c\u081d\7e\2\2\u081d\u081e") + buf.write("\7q\2\2\u081e\u081f\7o\2\2\u081f\u0820\7r\2\2\u0820\u0821") + buf.write("\7w\2\2\u0821\u0822\7v\2\2\u0822\u0823\7g\2\2\u0823\u0824") + buf.write("\7f\2\2\u0824\u01c4\3\2\2\2\u0825\u0826\7p\2\2\u0826\u0827") + buf.write("\7q\2\2\u0827\u0828\7p\2\2\u0828\u0829\7a\2\2\u0829\u082a") + buf.write("\7p\2\2\u082a\u082b\7w\2\2\u082b\u082c\7n\2\2\u082c\u082d") + buf.write("\7n\2\2\u082d\u01c6\3\2\2\2\u082e\u082f\7p\2\2\u082f\u0830") + buf.write("\7q\2\2\u0830\u0831\7p\2\2\u0831\u0832\7a\2\2\u0832\u0833") + buf.write("\7|\2\2\u0833\u0834\7g\2\2\u0834\u0835\7t\2\2\u0835\u0836") + buf.write("\7q\2\2\u0836\u01c8\3\2\2\2\u0837\u0838\7r\2\2\u0838\u0839") + buf.write("\7c\2\2\u0839\u083a\7t\2\2\u083a\u083b\7v\2\2\u083b\u083c") + buf.write("\7k\2\2\u083c\u083d\7c\2\2\u083d\u083e\7n\2\2\u083e\u083f") + buf.write("\7a\2\2\u083f\u0840\7p\2\2\u0840\u0841\7w\2\2\u0841\u0842") + buf.write("\7n\2\2\u0842\u0843\7n\2\2\u0843\u01ca\3\2\2\2\u0844\u0845") + buf.write("\7r\2\2\u0845\u0846\7c\2\2\u0846\u0847\7t\2\2\u0847\u0848") + buf.write("\7v\2\2\u0848\u0849\7k\2\2\u0849\u084a\7c\2\2\u084a\u084b") + buf.write("\7n\2\2\u084b\u084c\7a\2\2\u084c\u084d\7|\2\2\u084d\u084e") + buf.write("\7g\2\2\u084e\u084f\7t\2\2\u084f\u0850\7q\2\2\u0850\u01cc") + buf.write("\3\2\2\2\u0851\u0852\7c\2\2\u0852\u0853\7n\2\2\u0853\u0854") + buf.write("\7y\2\2\u0854\u0855\7c\2\2\u0855\u0856\7{\2\2\u0856\u0857") + buf.write("\7u\2\2\u0857\u0858\7a\2\2\u0858\u0859\7p\2\2\u0859\u085a") + buf.write("\7w\2\2\u085a\u085b\7n\2\2\u085b\u085c\7n\2\2\u085c\u01ce") + buf.write("\3\2\2\2\u085d\u085e\7c\2\2\u085e\u085f\7n\2\2\u085f\u0860") + buf.write("\7y\2\2\u0860\u0861\7c\2\2\u0861\u0862\7{\2\2\u0862\u0863") + buf.write("\7u\2\2\u0863\u0864\7a\2\2\u0864\u0865\7|\2\2\u0865\u0866") + buf.write("\7g\2\2\u0866\u0867\7t\2\2\u0867\u0868\7q\2\2\u0868\u01d0") + buf.write("\3\2\2\2\u0869\u086a\7e\2\2\u086a\u086b\7q\2\2\u086b\u086c") + buf.write("\7o\2\2\u086c\u086d\7r\2\2\u086d\u086e\7q\2\2\u086e\u086f") + buf.write("\7p\2\2\u086f\u0870\7g\2\2\u0870\u0871\7p\2\2\u0871\u0872") + buf.write("\7v\2\2\u0872\u0873\7u\2\2\u0873\u01d2\3\2\2\2\u0874\u0875") + buf.write("\7c\2\2\u0875\u0876\7n\2\2\u0876\u0877\7n\2\2\u0877\u0878") + buf.write("\7a\2\2\u0878\u0879\7o\2\2\u0879\u087a\7g\2\2\u087a\u087b") + buf.write("\7c\2\2\u087b\u087c\7u\2\2\u087c\u087d\7w\2\2\u087d\u087e") + buf.write("\7t\2\2\u087e\u087f\7g\2\2\u087f\u0880\7u\2\2\u0880\u01d4") + buf.write("\3\2\2\2\u0881\u0882\7u\2\2\u0882\u0883\7e\2\2\u0883\u0884") + buf.write("\7c\2\2\u0884\u0885\7n\2\2\u0885\u0886\7c\2\2\u0886\u0887") + buf.write("\7t\2\2\u0887\u01d6\3\2\2\2\u0888\u0889\7e\2\2\u0889\u088a") + buf.write("\7q\2\2\u088a\u088b\7o\2\2\u088b\u088c\7r\2\2\u088c\u088d") + buf.write("\7q\2\2\u088d\u088e\7p\2\2\u088e\u088f\7g\2\2\u088f\u0890") + buf.write("\7p\2\2\u0890\u0891\7v\2\2\u0891\u01d8\3\2\2\2\u0892\u0893") + buf.write("\7f\2\2\u0893\u0894\7c\2\2\u0894\u0895\7v\2\2\u0895\u0896") + buf.write("\7c\2\2\u0896\u0897\7r\2\2\u0897\u0898\7q\2\2\u0898\u0899") + buf.write("\7k\2\2\u0899\u089a\7p\2\2\u089a\u089b\7v\2\2\u089b\u089c") + buf.write("\7a\2\2\u089c\u089d\7q\2\2\u089d\u089e\7p\2\2\u089e\u089f") + buf.write("\7a\2\2\u089f\u08a0\7x\2\2\u08a0\u08a1\7c\2\2\u08a1\u08a2") + buf.write("\7n\2\2\u08a2\u08a3\7w\2\2\u08a3\u08a4\7g\2\2\u08a4\u08a5") + buf.write("\7f\2\2\u08a5\u08a6\7q\2\2\u08a6\u08a7\7o\2\2\u08a7\u08a8") + buf.write("\7c\2\2\u08a8\u08a9\7k\2\2\u08a9\u08aa\7p\2\2\u08aa\u08ab") + buf.write("\7u\2\2\u08ab\u01da\3\2\2\2\u08ac\u08ad\7f\2\2\u08ad\u08ae") + buf.write("\7c\2\2\u08ae\u08af\7v\2\2\u08af\u08b0\7c\2\2\u08b0\u08b1") + buf.write("\7r\2\2\u08b1\u08b2\7q\2\2\u08b2\u08b3\7k\2\2\u08b3\u08b4") + buf.write("\7p\2\2\u08b4\u08b5\7v\2\2\u08b5\u08b6\7a\2\2\u08b6\u08b7") + buf.write("\7q\2\2\u08b7\u08b8\7p\2\2\u08b8\u08b9\7a\2\2\u08b9\u08ba") + buf.write("\7x\2\2\u08ba\u08bb\7c\2\2\u08bb\u08bc\7t\2\2\u08bc\u08bd") + buf.write("\7k\2\2\u08bd\u08be\7c\2\2\u08be\u08bf\7d\2\2\u08bf\u08c0") + buf.write("\7n\2\2\u08c0\u08c1\7g\2\2\u08c1\u08c2\7u\2\2\u08c2\u01dc") + buf.write("\3\2\2\2\u08c3\u08c4\7j\2\2\u08c4\u08c5\7k\2\2\u08c5\u08c6") + buf.write("\7g\2\2\u08c6\u08c7\7t\2\2\u08c7\u08c8\7c\2\2\u08c8\u08c9") + buf.write("\7t\2\2\u08c9\u08ca\7e\2\2\u08ca\u08cb\7j\2\2\u08cb\u08cc") + buf.write("\7k\2\2\u08cc\u08cd\7e\2\2\u08cd\u08ce\7c\2\2\u08ce\u08cf") + buf.write("\7n\2\2\u08cf\u08d0\7a\2\2\u08d0\u08d1\7q\2\2\u08d1\u08d2") + buf.write("\7p\2\2\u08d2\u08d3\7a\2\2\u08d3\u08d4\7x\2\2\u08d4\u08d5") + buf.write("\7c\2\2\u08d5\u08d6\7n\2\2\u08d6\u08d7\7w\2\2\u08d7\u08d8") + buf.write("\7g\2\2\u08d8\u08d9\7f\2\2\u08d9\u08da\7q\2\2\u08da\u08db") + buf.write("\7o\2\2\u08db\u08dc\7c\2\2\u08dc\u08dd\7k\2\2\u08dd\u08de") + buf.write("\7p\2\2\u08de\u08df\7u\2\2\u08df\u01de\3\2\2\2\u08e0\u08e1") + buf.write("\7j\2\2\u08e1\u08e2\7k\2\2\u08e2\u08e3\7g\2\2\u08e3\u08e4") + buf.write("\7t\2\2\u08e4\u08e5\7c\2\2\u08e5\u08e6\7t\2\2\u08e6\u08e7") + buf.write("\7e\2\2\u08e7\u08e8\7j\2\2\u08e8\u08e9\7k\2\2\u08e9\u08ea") + buf.write("\7e\2\2\u08ea\u08eb\7c\2\2\u08eb\u08ec\7n\2\2\u08ec\u08ed") + buf.write("\7a\2\2\u08ed\u08ee\7q\2\2\u08ee\u08ef\7p\2\2\u08ef\u08f0") + buf.write("\7a\2\2\u08f0\u08f1\7x\2\2\u08f1\u08f2\7c\2\2\u08f2\u08f3") + buf.write("\7t\2\2\u08f3\u08f4\7k\2\2\u08f4\u08f5\7c\2\2\u08f5\u08f6") + buf.write("\7d\2\2\u08f6\u08f7\7n\2\2\u08f7\u08f8\7g\2\2\u08f8\u08f9") + buf.write("\7u\2\2\u08f9\u01e0\3\2\2\2\u08fa\u08fb\7u\2\2\u08fb\u08fc") + buf.write("\7g\2\2\u08fc\u08fd\7v\2\2\u08fd\u01e2\3\2\2\2\u08fe\u08ff") + buf.write("\7n\2\2\u08ff\u0900\7c\2\2\u0900\u0901\7p\2\2\u0901\u0902") + buf.write("\7i\2\2\u0902\u0903\7w\2\2\u0903\u0904\7c\2\2\u0904\u0905") + buf.write("\7i\2\2\u0905\u0906\7g\2\2\u0906\u01e4\3\2\2\2\u0907\u0908") + buf.write("\t\2\2\2\u0908\u01e6\3\2\2\2\u0909\u090a\4\62;\2\u090a") + buf.write("\u01e8\3\2\2\2\u090b\u090d\5\u01e7\u00f4\2\u090c\u090b") + buf.write("\3\2\2\2\u090d\u090e\3\2\2\2\u090e\u090c\3\2\2\2\u090e") + buf.write("\u090f\3\2\2\2\u090f\u01ea\3\2\2\2\u0910\u0911\5\u01e9") + buf.write("\u00f5\2\u0911\u0912\7\60\2\2\u0912\u0913\5\u01e9\u00f5") + buf.write("\2\u0913\u01ec\3\2\2\2\u0914\u0915\7v\2\2\u0915\u0916") + buf.write("\7t\2\2\u0916\u0917\7w\2\2\u0917\u091e\7g\2\2\u0918\u0919") + buf.write("\7h\2\2\u0919\u091a\7c\2\2\u091a\u091b\7n\2\2\u091b\u091c") + buf.write("\7u\2\2\u091c\u091e\7g\2\2\u091d\u0914\3\2\2\2\u091d\u0918") + buf.write("\3\2\2\2\u091e\u01ee\3\2\2\2\u091f\u0923\7$\2\2\u0920") + buf.write("\u0922\n\3\2\2\u0921\u0920\3\2\2\2\u0922\u0925\3\2\2\2") + buf.write("\u0923\u0921\3\2\2\2\u0923\u0924\3\2\2\2\u0924\u0926\3") + buf.write("\2\2\2\u0925\u0923\3\2\2\2\u0926\u0927\7$\2\2\u0927\u01f0") + buf.write("\3\2\2\2\u0928\u092c\5\u01e5\u00f3\2\u0929\u092b\t\4\2") + buf.write("\2\u092a\u0929\3\2\2\2\u092b\u092e\3\2\2\2\u092c\u092a") + buf.write("\3\2\2\2\u092c\u092d\3\2\2\2\u092d\u093e\3\2\2\2\u092e") + buf.write("\u092c\3\2\2\2\u092f\u0931\5\u01e7\u00f4\2\u0930\u0932") + buf.write("\t\4\2\2\u0931\u0930\3\2\2\2\u0932\u0933\3\2\2\2\u0933") + buf.write("\u0931\3\2\2\2\u0933\u0934\3\2\2\2\u0934\u093e\3\2\2\2") + buf.write("\u0935\u0939\7)\2\2\u0936\u0938\13\2\2\2\u0937\u0936\3") + buf.write("\2\2\2\u0938\u093b\3\2\2\2\u0939\u093a\3\2\2\2\u0939\u0937") + buf.write("\3\2\2\2\u093a\u093c\3\2\2\2\u093b\u0939\3\2\2\2\u093c") + buf.write("\u093e\7)\2\2\u093d\u0928\3\2\2\2\u093d\u092f\3\2\2\2") + buf.write("\u093d\u0935\3\2\2\2\u093e\u01f2\3\2\2\2\u093f\u0941\t") + buf.write("\5\2\2\u0940\u093f\3\2\2\2\u0941\u0942\3\2\2\2\u0942\u0940") + buf.write("\3\2\2\2\u0942\u0943\3\2\2\2\u0943\u0944\3\2\2\2\u0944") + buf.write("\u0945\b\u00fa\2\2\u0945\u01f4\3\2\2\2\u0946\u0947\7=") + buf.write("\2\2\u0947\u01f6\3\2\2\2\u0948\u0949\7\61\2\2\u0949\u094a") + buf.write("\7,\2\2\u094a\u094e\3\2\2\2\u094b\u094d\13\2\2\2\u094c") + buf.write("\u094b\3\2\2\2\u094d\u0950\3\2\2\2\u094e\u094f\3\2\2\2") + buf.write("\u094e\u094c\3\2\2\2\u094f\u0951\3\2\2\2\u0950\u094e\3") + buf.write("\2\2\2\u0951\u0952\7,\2\2\u0952\u0953\7\61\2\2\u0953\u0954") + buf.write("\3\2\2\2\u0954\u0955\b\u00fc\3\2\u0955\u01f8\3\2\2\2\u0956") + buf.write("\u0957\7\61\2\2\u0957\u0958\7\61\2\2\u0958\u095c\3\2\2") + buf.write("\2\u0959\u095b\n\6\2\2\u095a\u0959\3\2\2\2\u095b\u095e") + buf.write("\3\2\2\2\u095c\u095a\3\2\2\2\u095c\u095d\3\2\2\2\u095d") + buf.write("\u095f\3\2\2\2\u095e\u095c\3\2\2\2\u095f\u0960\b\u00fd") + buf.write("\3\2\u0960\u01fa\3\2\2\2\r\2\u090e\u091d\u0923\u092c\u0933") + buf.write("\u0939\u093d\u0942\u094e\u095c\4\2\3\2\2\4\2") return buf.getvalue() @@ -1232,145 +1234,146 @@ class Lexer(ANTLRLexer): EXP = 108 ROLE = 109 VIRAL = 110 - CHARSET_MATCH = 111 - TYPE = 112 - NVL = 113 - HIERARCHY = 114 - OPTIONAL = 115 - INVALID = 116 - VALUE_DOMAIN = 117 - VARIABLE = 118 - DATA = 119 - STRUCTURE = 120 - DATASET = 121 - OPERATOR = 122 - DEFINE = 123 - PUT_SYMBOL = 124 - DATAPOINT = 125 - HIERARCHICAL = 126 - RULESET = 127 - RULE = 128 - END = 129 - ALTER_DATASET = 130 - LTRIM = 131 - RTRIM = 132 - INSTR = 133 - REPLACE = 134 - CEIL = 135 - FLOOR = 136 - SQRT = 137 - ANY = 138 - SETDIFF = 139 - STDDEV_POP = 140 - STDDEV_SAMP = 141 - VAR_POP = 142 - VAR_SAMP = 143 - GROUP = 144 - EXCEPT = 145 - HAVING = 146 - FIRST_VALUE = 147 - LAST_VALUE = 148 - LAG = 149 - LEAD = 150 - RATIO_TO_REPORT = 151 - OVER = 152 - PRECEDING = 153 - FOLLOWING = 154 - UNBOUNDED = 155 - PARTITION = 156 - ROWS = 157 - RANGE = 158 - CURRENT = 159 - VALID = 160 - FILL_TIME_SERIES = 161 - FLOW_TO_STOCK = 162 - STOCK_TO_FLOW = 163 - TIMESHIFT = 164 - MEASURES = 165 - NO_MEASURES = 166 - CONDITION = 167 - BOOLEAN = 168 - DATE = 169 - TIME_PERIOD = 170 - NUMBER = 171 - STRING = 172 - TIME = 173 - INTEGER = 174 - FLOAT = 175 - LIST = 176 - RECORD = 177 - RESTRICT = 178 - YYYY = 179 - MM = 180 - DD = 181 - MAX_LENGTH = 182 - REGEXP = 183 - IS = 184 - WHEN = 185 - FROM = 186 - AGGREGATES = 187 - POINTS = 188 - POINT = 189 - TOTAL = 190 - PARTIAL = 191 - ALWAYS = 192 - INNER_JOIN = 193 - LEFT_JOIN = 194 - CROSS_JOIN = 195 - FULL_JOIN = 196 - MAPS_FROM = 197 - MAPS_TO = 198 - MAP_TO = 199 - MAP_FROM = 200 - RETURNS = 201 - PIVOT = 202 - CUSTOMPIVOT = 203 - UNPIVOT = 204 - SUBSPACE = 205 - APPLY = 206 - CONDITIONED = 207 - PERIOD_INDICATOR = 208 - SINGLE = 209 - DURATION = 210 - TIME_AGG = 211 - UNIT = 212 - VALUE = 213 - VALUEDOMAINS = 214 - VARIABLES = 215 - INPUT = 216 - OUTPUT = 217 - CAST = 218 - RULE_PRIORITY = 219 - DATASET_PRIORITY = 220 - DEFAULT = 221 - CHECK_DATAPOINT = 222 - CHECK_HIERARCHY = 223 - COMPUTED = 224 - NON_NULL = 225 - NON_ZERO = 226 - PARTIAL_NULL = 227 - PARTIAL_ZERO = 228 - ALWAYS_NULL = 229 - ALWAYS_ZERO = 230 - COMPONENTS = 231 - ALL_MEASURES = 232 - SCALAR = 233 - COMPONENT = 234 - DATAPOINT_ON_VD = 235 - DATAPOINT_ON_VAR = 236 - HIERARCHICAL_ON_VD = 237 - HIERARCHICAL_ON_VAR = 238 - SET = 239 - LANGUAGE = 240 - INTEGER_CONSTANT = 241 - NUMBER_CONSTANT = 242 - BOOLEAN_CONSTANT = 243 - STRING_CONSTANT = 244 - IDENTIFIER = 245 - WS = 246 - EOL = 247 - ML_COMMENT = 248 - SL_COMMENT = 249 + PROPAGATION = 111 + CHARSET_MATCH = 112 + TYPE = 113 + NVL = 114 + HIERARCHY = 115 + OPTIONAL = 116 + INVALID = 117 + VALUE_DOMAIN = 118 + VARIABLE = 119 + DATA = 120 + STRUCTURE = 121 + DATASET = 122 + OPERATOR = 123 + DEFINE = 124 + PUT_SYMBOL = 125 + DATAPOINT = 126 + HIERARCHICAL = 127 + RULESET = 128 + RULE = 129 + END = 130 + ALTER_DATASET = 131 + LTRIM = 132 + RTRIM = 133 + INSTR = 134 + REPLACE = 135 + CEIL = 136 + FLOOR = 137 + SQRT = 138 + ANY = 139 + SETDIFF = 140 + STDDEV_POP = 141 + STDDEV_SAMP = 142 + VAR_POP = 143 + VAR_SAMP = 144 + GROUP = 145 + EXCEPT = 146 + HAVING = 147 + FIRST_VALUE = 148 + LAST_VALUE = 149 + LAG = 150 + LEAD = 151 + RATIO_TO_REPORT = 152 + OVER = 153 + PRECEDING = 154 + FOLLOWING = 155 + UNBOUNDED = 156 + PARTITION = 157 + ROWS = 158 + RANGE = 159 + CURRENT = 160 + VALID = 161 + FILL_TIME_SERIES = 162 + FLOW_TO_STOCK = 163 + STOCK_TO_FLOW = 164 + TIMESHIFT = 165 + MEASURES = 166 + NO_MEASURES = 167 + CONDITION = 168 + BOOLEAN = 169 + DATE = 170 + TIME_PERIOD = 171 + NUMBER = 172 + STRING = 173 + TIME = 174 + INTEGER = 175 + FLOAT = 176 + LIST = 177 + RECORD = 178 + RESTRICT = 179 + YYYY = 180 + MM = 181 + DD = 182 + MAX_LENGTH = 183 + REGEXP = 184 + IS = 185 + WHEN = 186 + FROM = 187 + AGGREGATES = 188 + POINTS = 189 + POINT = 190 + TOTAL = 191 + PARTIAL = 192 + ALWAYS = 193 + INNER_JOIN = 194 + LEFT_JOIN = 195 + CROSS_JOIN = 196 + FULL_JOIN = 197 + MAPS_FROM = 198 + MAPS_TO = 199 + MAP_TO = 200 + MAP_FROM = 201 + RETURNS = 202 + PIVOT = 203 + CUSTOMPIVOT = 204 + UNPIVOT = 205 + SUBSPACE = 206 + APPLY = 207 + CONDITIONED = 208 + PERIOD_INDICATOR = 209 + SINGLE = 210 + DURATION = 211 + TIME_AGG = 212 + UNIT = 213 + VALUE = 214 + VALUEDOMAINS = 215 + VARIABLES = 216 + INPUT = 217 + OUTPUT = 218 + CAST = 219 + RULE_PRIORITY = 220 + DATASET_PRIORITY = 221 + DEFAULT = 222 + CHECK_DATAPOINT = 223 + CHECK_HIERARCHY = 224 + COMPUTED = 225 + NON_NULL = 226 + NON_ZERO = 227 + PARTIAL_NULL = 228 + PARTIAL_ZERO = 229 + ALWAYS_NULL = 230 + ALWAYS_ZERO = 231 + COMPONENTS = 232 + ALL_MEASURES = 233 + SCALAR = 234 + COMPONENT = 235 + DATAPOINT_ON_VD = 236 + DATAPOINT_ON_VAR = 237 + HIERARCHICAL_ON_VD = 238 + HIERARCHICAL_ON_VAR = 239 + SET = 240 + LANGUAGE = 241 + INTEGER_CONSTANT = 242 + NUMBER_CONSTANT = 243 + BOOLEAN_CONSTANT = 244 + STRING_CONSTANT = 245 + IDENTIFIER = 246 + WS = 247 + EOL = 248 + ML_COMMENT = 249 + SL_COMMENT = 250 channelNames = ["DEFAULT_TOKEN_CHANNEL", "HIDDEN"] @@ -1488,6 +1491,7 @@ class Lexer(ANTLRLexer): "'exp'", "'componentRole'", "'viral'", + "'propagation'", "'match_characters'", "'type'", "'nvl'", @@ -1733,6 +1737,7 @@ class Lexer(ANTLRLexer): "EXP", "ROLE", "VIRAL", + "PROPAGATION", "CHARSET_MATCH", "TYPE", "NVL", @@ -1985,6 +1990,7 @@ class Lexer(ANTLRLexer): "EXP", "ROLE", "VIRAL", + "PROPAGATION", "CHARSET_MATCH", "TYPE", "NVL", diff --git a/src/vtlengine/AST/Grammar/parser.py b/src/vtlengine/AST/Grammar/parser.py index f73f1314b..68d6200ba 100644 --- a/src/vtlengine/AST/Grammar/parser.py +++ b/src/vtlengine/AST/Grammar/parser.py @@ -1,18 +1,17 @@ # Generated from Vtl.g4 by ANTLR 4.9.3 # encoding: utf-8 -import sys -from io import StringIO -from typing import Any, TextIO - -from antlr4 import * from antlr4 import Parser as ANTLRParser from antlr4.atn.ATN import ATN +from antlr4 import * +from io import StringIO +import sys +from typing import Any, TextIO def serializedATN(): with StringIO() as buf: - buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\u00fb") - buf.write("\u0763\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\u00fc") + buf.write("\u079a\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") buf.write("\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") buf.write("\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23\t\23") buf.write("\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31") @@ -26,970 +25,991 @@ def serializedATN(): buf.write("M\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\tT\4U\tU\4V\t") buf.write("V\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4") buf.write("_\t_\4`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4") - buf.write("h\th\4i\ti\4j\tj\4k\tk\4l\tl\4m\tm\4n\tn\4o\to\4p\tp\3") - buf.write("\2\3\2\3\2\7\2\u00e4\n\2\f\2\16\2\u00e7\13\2\3\2\3\2\3") - buf.write("\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\5\3\u00f4\n\3\3\4\3") - buf.write("\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4") - buf.write("\3\4\3\4\3\4\3\4\3\4\3\4\6\4\u010b\n\4\r\4\16\4\u010c") - buf.write("\3\4\3\4\3\4\3\4\3\4\5\4\u0114\n\4\3\4\3\4\3\4\3\4\3\4") + buf.write("h\th\4i\ti\4j\tj\4k\tk\4l\tl\4m\tm\4n\tn\4o\to\4p\tp\4") + buf.write("q\tq\4r\tr\4s\ts\4t\tt\3\2\3\2\3\2\7\2\u00ec\n\2\f\2\16") + buf.write("\2\u00ef\13\2\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3") + buf.write("\3\3\5\3\u00fc\n\3\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4") + buf.write("\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\6\4\u0113") + buf.write("\n\4\r\4\16\4\u0114\3\4\3\4\3\4\3\4\3\4\5\4\u011c\n\4") buf.write("\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3") - buf.write("\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\5\4\u0132\n\4\7") - buf.write("\4\u0134\n\4\f\4\16\4\u0137\13\4\3\5\3\5\3\5\3\5\3\5\3") + buf.write("\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4") + buf.write("\3\4\5\4\u013a\n\4\7\4\u013c\n\4\f\4\16\4\u013f\13\4\3") buf.write("\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5") - buf.write("\3\5\3\5\6\5\u014e\n\5\r\5\16\5\u014f\3\5\3\5\3\5\3\5") - buf.write("\3\5\5\5\u0157\n\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5") - buf.write("\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\5\5\u016d") - buf.write("\n\5\7\5\u016f\n\5\f\5\16\5\u0172\13\5\3\6\3\6\3\6\3\6") - buf.write("\3\6\3\6\3\6\3\6\5\6\u017c\n\6\3\7\3\7\3\7\3\7\3\7\3\7") - buf.write("\3\7\3\7\3\7\3\7\3\7\3\7\5\7\u018a\n\7\3\b\3\b\3\b\3\b") - buf.write("\3\b\3\b\3\b\5\b\u0193\n\b\3\t\3\t\3\t\3\t\7\t\u0199\n") - buf.write("\t\f\t\16\t\u019c\13\t\3\n\3\n\3\n\3\n\5\n\u01a2\n\n\5") - buf.write("\n\u01a4\n\n\3\13\3\13\3\13\3\f\3\f\3\f\3\f\7\f\u01ad") - buf.write("\n\f\f\f\16\f\u01b0\13\f\3\r\3\r\3\r\3\r\7\r\u01b6\n\r") - buf.write("\f\r\16\r\u01b9\13\r\3\16\3\16\3\16\3\16\3\16\3\17\3\17") - buf.write("\3\17\3\17\3\17\3\17\3\17\3\17\7\17\u01c8\n\17\f\17\16") - buf.write("\17\u01cb\13\17\3\20\3\20\3\20\3\20\7\20\u01d1\n\20\f") - buf.write("\20\16\20\u01d4\13\20\3\21\3\21\3\21\3\21\3\21\3\21\3") - buf.write("\21\3\21\3\21\3\21\3\21\3\21\5\21\u01e2\n\21\3\22\3\22") - buf.write("\3\22\3\22\3\22\3\22\3\22\7\22\u01eb\n\22\f\22\16\22\u01ee") - buf.write("\13\22\5\22\u01f0\n\22\3\22\3\22\3\22\5\22\u01f5\n\22") + buf.write("\3\5\3\5\3\5\3\5\3\5\3\5\3\5\6\5\u0156\n\5\r\5\16\5\u0157") + buf.write("\3\5\3\5\3\5\3\5\3\5\5\5\u015f\n\5\3\5\3\5\3\5\3\5\3\5") + buf.write("\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3") + buf.write("\5\3\5\5\5\u0175\n\5\7\5\u0177\n\5\f\5\16\5\u017a\13\5") + buf.write("\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\5\6\u0184\n\6\3\7\3\7") + buf.write("\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\5\7\u0192\n\7") + buf.write("\3\b\3\b\3\b\3\b\3\b\3\b\3\b\5\b\u019b\n\b\3\t\3\t\3\t") + buf.write("\3\t\7\t\u01a1\n\t\f\t\16\t\u01a4\13\t\3\n\3\n\3\n\3\n") + buf.write("\5\n\u01aa\n\n\5\n\u01ac\n\n\3\13\3\13\3\13\3\f\3\f\3") + buf.write("\f\3\f\7\f\u01b5\n\f\f\f\16\f\u01b8\13\f\3\r\3\r\3\r\3") + buf.write("\r\7\r\u01be\n\r\f\r\16\r\u01c1\13\r\3\16\3\16\3\16\3") + buf.write("\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\7\17") + buf.write("\u01d0\n\17\f\17\16\17\u01d3\13\17\3\20\3\20\3\20\3\20") + buf.write("\7\20\u01d9\n\20\f\20\16\20\u01dc\13\20\3\21\3\21\3\21") + buf.write("\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\5\21\u01ea") + buf.write("\n\21\3\22\3\22\3\22\3\22\3\22\3\22\3\22\7\22\u01f3\n") + buf.write("\22\f\22\16\22\u01f6\13\22\5\22\u01f8\n\22\3\22\3\22\3") + buf.write("\22\5\22\u01fd\n\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22") + buf.write("\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22") buf.write("\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22") buf.write("\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22") - buf.write("\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\5\22\u0216") - buf.write("\n\22\3\23\3\23\3\23\3\23\3\23\7\23\u021d\n\23\f\23\16") - buf.write("\23\u0220\13\23\5\23\u0222\n\23\3\23\3\23\3\23\3\23\3") - buf.write("\23\3\23\3\23\3\23\5\23\u022c\n\23\3\23\3\23\3\23\5\23") - buf.write("\u0231\n\23\7\23\u0233\n\23\f\23\16\23\u0236\13\23\3\23") - buf.write("\3\23\3\23\5\23\u023b\n\23\3\23\3\23\5\23\u023f\n\23\3") - buf.write("\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u0249\n\23") - buf.write("\3\23\3\23\5\23\u024d\n\23\3\23\3\23\5\23\u0251\n\23\3") - buf.write("\24\3\24\3\24\3\24\3\24\7\24\u0258\n\24\f\24\16\24\u025b") - buf.write("\13\24\5\24\u025d\n\24\3\24\3\24\3\24\3\24\3\24\3\24\3") - buf.write("\24\3\24\5\24\u0267\n\24\3\24\3\24\5\24\u026b\n\24\3\24") - buf.write("\3\24\3\24\3\24\3\24\3\24\3\24\3\24\5\24\u0275\n\24\3") - buf.write("\24\3\24\3\24\5\24\u027a\n\24\7\24\u027c\n\24\f\24\16") - buf.write("\24\u027f\13\24\3\24\3\24\3\24\5\24\u0284\n\24\3\24\3") - buf.write("\24\5\24\u0288\n\24\3\24\3\24\5\24\u028c\n\24\3\25\3\25") - buf.write("\5\25\u0290\n\25\3\26\3\26\5\26\u0294\n\26\3\27\3\27\3") - buf.write("\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27") - buf.write("\3\27\5\27\u02a4\n\27\3\27\3\27\5\27\u02a8\n\27\3\27\3") - buf.write("\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\5\27\u02b3\n\27") - buf.write("\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\5\27\u02be") - buf.write("\n\27\3\27\3\27\5\27\u02c2\n\27\3\27\3\27\5\27\u02c6\n") - buf.write("\27\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30") - buf.write("\3\30\3\30\3\30\3\30\5\30\u02d6\n\30\3\30\3\30\5\30\u02da") - buf.write("\n\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\5\30") - buf.write("\u02e5\n\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3") - buf.write("\30\5\30\u02f0\n\30\3\30\3\30\5\30\u02f4\n\30\3\30\3\30") - buf.write("\5\30\u02f8\n\30\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3") - buf.write("\31\3\31\3\31\5\31\u0304\n\31\3\31\3\31\3\31\3\31\3\31") - buf.write("\3\31\3\31\3\31\3\31\5\31\u030f\n\31\3\32\3\32\3\32\3") - buf.write("\32\3\32\3\32\3\32\3\32\3\32\3\32\5\32\u031b\n\32\3\32") - buf.write("\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\5\32\u0326\n") - buf.write("\32\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33") - buf.write("\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33") - buf.write("\3\33\3\33\3\33\3\33\3\33\3\33\3\33\5\33\u0344\n\33\3") - buf.write("\33\3\33\5\33\u0348\n\33\3\34\3\34\3\34\3\34\3\34\3\34") - buf.write("\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34") - buf.write("\3\34\3\34\3\34\3\34\5\34\u035f\n\34\3\35\3\35\3\35\5") - buf.write("\35\u0364\n\35\3\35\3\35\3\35\3\35\3\35\3\35\5\35\u036c") - buf.write("\n\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35") - buf.write("\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\5\35\u0381") - buf.write("\n\35\3\35\3\35\5\35\u0385\n\35\3\35\3\35\5\35\u0389\n") - buf.write("\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35") - buf.write("\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35") - buf.write("\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35") - buf.write("\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35") - buf.write("\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35") - buf.write("\3\35\3\35\3\35\3\35\3\35\3\35\5\35\u03c7\n\35\3\36\3") - buf.write("\36\3\36\5\36\u03cc\n\36\3\36\3\36\3\36\3\36\3\36\3\36") - buf.write("\5\36\u03d4\n\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3") - buf.write("\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36") - buf.write("\3\36\5\36\u03e9\n\36\3\36\3\36\5\36\u03ed\n\36\3\36\3") - buf.write("\36\5\36\u03f1\n\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36") - buf.write("\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36") - buf.write("\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36") - buf.write("\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36") - buf.write("\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36") - buf.write("\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\5\36\u042f") - buf.write("\n\36\3\37\3\37\3\37\3\37\3\37\6\37\u0436\n\37\r\37\16") - buf.write("\37\u0437\3\37\3\37\3\37\3\37\3\37\3\37\3\37\6\37\u0441") - buf.write("\n\37\r\37\16\37\u0442\3\37\3\37\3\37\3\37\3\37\3\37\3") - buf.write("\37\3\37\3\37\5\37\u044e\n\37\3 \3 \3 \3 \3 \3 \5 \u0456") - buf.write("\n \3 \3 \5 \u045a\n \3 \5 \u045d\n \3 \5 \u0460\n \3") - buf.write(" \5 \u0463\n \3 \3 \3!\3!\3!\3!\3!\3!\3!\3!\3!\7!\u0470") - buf.write("\n!\f!\16!\u0473\13!\5!\u0475\n!\3!\5!\u0478\n!\3!\3!") - buf.write("\3!\3!\3!\3!\3!\3!\5!\u0482\n!\3!\3!\5!\u0486\n!\3!\5") - buf.write("!\u0489\n!\3!\5!\u048c\n!\3!\5!\u048f\n!\3!\3!\3!\3!\3") - buf.write("!\3!\5!\u0497\n!\3!\5!\u049a\n!\3!\5!\u049d\n!\3!\5!\u04a0") - buf.write('\n!\3!\3!\5!\u04a4\n!\3"\3"\3"\3"\3"\3"\3"\3#\3') - buf.write("#\3#\3#\3#\3#\3#\3$\3$\3$\3$\3$\3$\3$\3$\5$\u04bc\n$\3") - buf.write("%\3%\3%\3%\3%\5%\u04c3\n%\5%\u04c5\n%\3%\3%\3&\3&\3&\3") - buf.write("&\3&\3&\5&\u04cf\n&\3&\5&\u04d2\n&\3&\5&\u04d5\n&\3&\3") - buf.write("&\3&\3&\3&\3&\3&\3&\3&\3&\5&\u04e1\n&\5&\u04e3\n&\3&\3") - buf.write("&\3&\5&\u04e8\n&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3") - buf.write("&\3&\5&\u04f8\n&\3'\3'\3'\3'\3'\3'\5'\u0500\n'") - buf.write("\3'\5'\u0503\n'\3'\5'\u0506\n'\3'\3'\3'\3'\3") - buf.write("'\3'\3'\3'\3'\5'\u0511\n'\5'\u0513\n'\3'\3'") - buf.write("\3'\5'\u0518\n'\3'\3'\3'\3'\3'\3'\3'\3'\3'") - buf.write("\3'\5'\u0524\n'\3'\3'\3'\3'\3'\3'\3'\3'\3'") - buf.write("\3'\3'\3'\3'\3'\5'\u0534\n'\3(\3(\3(\3(\3)\3)\3") - buf.write(")\7)\u053d\n)\f)\16)\u0540\13)\3*\5*\u0543\n*\3*\3*\3") - buf.write("*\3*\3+\5+\u054a\n+\3+\3+\3+\3+\3,\3,\3,\3,\3-\3-\3-\3") - buf.write("-\3-\3-\3-\3-\5-\u055c\n-\3-\3-\5-\u0560\n-\3.\3.\3.\7") - buf.write(".\u0565\n.\f.\16.\u0568\13.\3/\3/\3/\7/\u056d\n/\f/\16") - buf.write("/\u0570\13/\3/\3/\3/\3/\7/\u0576\n/\f/\16/\u0579\13/\5") - buf.write("/\u057b\n/\3\60\3\60\3\60\5\60\u0580\n\60\3\61\5\61\u0583") - buf.write("\n\61\3\61\3\61\3\61\5\61\u0588\n\61\3\61\5\61\u058b\n") - buf.write("\61\3\61\5\61\u058e\n\61\3\62\3\62\3\62\3\63\3\63\3\63") - buf.write("\3\63\3\63\7\63\u0598\n\63\f\63\16\63\u059b\13\63\3\64") - buf.write("\3\64\3\64\3\64\3\64\7\64\u05a2\n\64\f\64\16\64\u05a5") - buf.write("\13\64\3\65\3\65\5\65\u05a9\n\65\3\66\3\66\3\66\5\66\u05ae") - buf.write("\n\66\3\66\3\66\3\66\3\66\3\66\3\67\5\67\u05b6\n\67\3") - buf.write("\67\3\67\38\58\u05bb\n8\38\38\39\39\39\39\39\39\39\39") - buf.write("\39\39\39\39\39\59\u05cc\n9\3:\3:\3:\3:\3:\7:\u05d3\n") - buf.write(":\f:\16:\u05d6\13:\3:\3:\3:\3:\3:\5:\u05dd\n:\3:\5:\u05e0") - buf.write("\n:\3:\3:\3:\3:\3:\3:\3:\5:\u05e9\n:\3:\5:\u05ec\n:\5") - buf.write(":\u05ee\n:\3;\3;\3;\3<\3<\3<\3<\5<\u05f7\n<\3=\3=\3=\5") - buf.write("=\u05fc\n=\3>\3>\5>\u0600\n>\3?\3?\3?\3?\3?\5?\u0607\n") - buf.write("?\3@\3@\3@\5@\u060c\n@\3A\3A\5A\u0610\nA\3A\5A\u0613\n") - buf.write("A\3A\5A\u0616\nA\3A\5A\u0619\nA\3B\3B\3B\3B\3B\5B\u0620") - buf.write("\nB\3C\3C\3C\3C\3C\7C\u0627\nC\fC\16C\u062a\13C\3C\3C") - buf.write("\5C\u062e\nC\3D\3D\5D\u0632\nD\3E\3E\3E\3E\3E\5E\u0639") - buf.write("\nE\3F\3F\3F\3F\3F\3F\7F\u0641\nF\fF\16F\u0644\13F\3F") - buf.write("\3F\5F\u0648\nF\3F\3F\3F\3F\3F\7F\u064f\nF\fF\16F\u0652") - buf.write("\13F\3F\3F\5F\u0656\nF\5F\u0658\nF\3G\3G\3G\3G\3G\3G\3") - buf.write("G\3G\7G\u0662\nG\fG\16G\u0665\13G\3G\3G\5G\u0669\nG\3") - buf.write("G\5G\u066c\nG\3G\3G\3G\3G\3G\3G\3G\7G\u0675\nG\fG\16G") - buf.write("\u0678\13G\3G\3G\5G\u067c\nG\3G\3G\5G\u0680\nG\5G\u0682") - buf.write("\nG\3H\3H\3I\3I\3J\3J\3J\3J\7J\u068c\nJ\fJ\16J\u068f\13") - buf.write("J\3K\3K\3K\5K\u0694\nK\3L\3L\3L\7L\u0699\nL\fL\16L\u069c") - buf.write("\13L\3M\3M\5M\u06a0\nM\3M\3M\3M\3M\5M\u06a6\nM\3M\3M\5") - buf.write("M\u06aa\nM\3M\5M\u06ad\nM\3N\3N\3N\7N\u06b2\nN\fN\16N") - buf.write("\u06b5\13N\3O\3O\5O\u06b9\nO\3O\3O\5O\u06bd\nO\3O\5O\u06c0") - buf.write("\nO\3P\3P\3P\5P\u06c5\nP\3P\3P\3P\3Q\3Q\3Q\7Q\u06cd\n") - buf.write("Q\fQ\16Q\u06d0\13Q\3R\3R\3R\3R\5R\u06d6\nR\3R\3R\5R\u06da") - buf.write("\nR\3R\3R\7R\u06de\nR\fR\16R\u06e1\13R\3S\5S\u06e4\nS") - buf.write("\3S\3S\3S\3S\3S\5S\u06eb\nS\3T\3T\3T\5T\u06f0\nT\3U\3") - buf.write("U\3U\3U\3U\3U\3U\3U\7U\u06fa\nU\fU\16U\u06fd\13U\3U\3") - buf.write("U\5U\u0701\nU\3V\3V\3V\5V\u0706\nV\3W\3W\5W\u070a\nW\3") - buf.write("X\3X\3Y\3Y\3Z\3Z\3Z\3Z\7Z\u0714\nZ\fZ\16Z\u0717\13Z\3") - buf.write("[\3[\3\\\3\\\3\\\3]\3]\3^\3^\3_\3_\3`\3`\3a\3a\3b\3b\3") - buf.write("b\5b\u072b\nb\3c\3c\3c\3c\7c\u0731\nc\fc\16c\u0734\13") - buf.write("c\3c\3c\3d\3d\3d\3e\3e\3e\3f\3f\3g\3g\5g\u0742\ng\3h\3") - buf.write("h\5h\u0746\nh\3i\3i\3i\3i\3i\5i\u074d\ni\3j\3j\3j\3k\3") - buf.write("k\3l\3l\3m\3m\3n\3n\3n\3n\3n\5n\u075d\nn\3o\3o\3p\3p\3") - buf.write('p\2\4\6\bq\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 "$') + buf.write("\3\22\3\22\3\22\3\22\5\22\u022b\n\22\3\23\3\23\3\23\3") + buf.write("\23\5\23\u0231\n\23\3\24\3\24\3\24\7\24\u0236\n\24\f\24") + buf.write("\16\24\u0239\13\24\3\25\3\25\5\25\u023d\n\25\3\25\3\25") + buf.write("\3\25\3\25\3\25\3\25\3\25\3\25\3\25\5\25\u0248\n\25\3") + buf.write("\26\3\26\3\26\5\26\u024d\n\26\3\27\3\27\3\27\3\27\3\27") + buf.write("\7\27\u0254\n\27\f\27\16\27\u0257\13\27\5\27\u0259\n\27") + buf.write("\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\5\27\u0263\n") + buf.write("\27\3\27\3\27\3\27\5\27\u0268\n\27\7\27\u026a\n\27\f\27") + buf.write("\16\27\u026d\13\27\3\27\3\27\3\27\5\27\u0272\n\27\3\27") + buf.write("\3\27\5\27\u0276\n\27\3\27\3\27\3\27\3\27\3\27\3\27\3") + buf.write("\27\3\27\5\27\u0280\n\27\3\27\3\27\5\27\u0284\n\27\3\27") + buf.write("\3\27\5\27\u0288\n\27\3\30\3\30\3\30\3\30\3\30\7\30\u028f") + buf.write("\n\30\f\30\16\30\u0292\13\30\5\30\u0294\n\30\3\30\3\30") + buf.write("\3\30\3\30\3\30\3\30\3\30\3\30\5\30\u029e\n\30\3\30\3") + buf.write("\30\5\30\u02a2\n\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30") + buf.write("\3\30\5\30\u02ac\n\30\3\30\3\30\3\30\5\30\u02b1\n\30\7") + buf.write("\30\u02b3\n\30\f\30\16\30\u02b6\13\30\3\30\3\30\3\30\5") + buf.write("\30\u02bb\n\30\3\30\3\30\5\30\u02bf\n\30\3\30\3\30\5\30") + buf.write("\u02c3\n\30\3\31\3\31\5\31\u02c7\n\31\3\32\3\32\5\32\u02cb") + buf.write("\n\32\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33") + buf.write("\3\33\3\33\3\33\3\33\5\33\u02db\n\33\3\33\3\33\5\33\u02df") + buf.write("\n\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\5\33") + buf.write("\u02ea\n\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3") + buf.write("\33\5\33\u02f5\n\33\3\33\3\33\5\33\u02f9\n\33\3\33\3\33") + buf.write("\5\33\u02fd\n\33\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3") + buf.write("\34\3\34\3\34\3\34\3\34\3\34\3\34\5\34\u030d\n\34\3\34") + buf.write("\3\34\5\34\u0311\n\34\3\34\3\34\3\34\3\34\3\34\3\34\3") + buf.write("\34\3\34\3\34\5\34\u031c\n\34\3\34\3\34\3\34\3\34\3\34") + buf.write("\3\34\3\34\3\34\3\34\5\34\u0327\n\34\3\34\3\34\5\34\u032b") + buf.write("\n\34\3\34\3\34\5\34\u032f\n\34\3\35\3\35\3\35\3\35\3") + buf.write("\35\3\35\3\35\3\35\3\35\3\35\5\35\u033b\n\35\3\35\3\35") + buf.write("\3\35\3\35\3\35\3\35\3\35\3\35\3\35\5\35\u0346\n\35\3") + buf.write("\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\5\36") + buf.write("\u0352\n\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3") + buf.write("\36\5\36\u035d\n\36\3\37\3\37\3\37\3\37\3\37\3\37\3\37") + buf.write("\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37") + buf.write("\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\5\37") + buf.write("\u037b\n\37\3\37\3\37\5\37\u037f\n\37\3 \3 \3 \3 \3 \3") + buf.write(" \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \5 \u0396") + buf.write("\n \3!\3!\3!\5!\u039b\n!\3!\3!\3!\3!\3!\3!\5!\u03a3\n") + buf.write("!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3") + buf.write("!\3!\5!\u03b8\n!\3!\3!\5!\u03bc\n!\3!\3!\5!\u03c0\n!\3") + buf.write("!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3") + buf.write("!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3") + buf.write("!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3") + buf.write('!\3!\3!\3!\3!\3!\5!\u03fe\n!\3"\3"\3"\5"\u0403\n"') + buf.write('\3"\3"\3"\3"\3"\3"\5"\u040b\n"\3"\3"\3"\3"') + buf.write('\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3') + buf.write('"\3"\5"\u0420\n"\3"\3"\5"\u0424\n"\3"\3"\5"') + buf.write('\u0428\n"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"') + buf.write('\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3') + buf.write('"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"') + buf.write('\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3"\3') + buf.write('"\3"\3"\3"\3"\3"\3"\3"\3"\5"\u0466\n"\3#\3') + buf.write("#\3#\3#\3#\6#\u046d\n#\r#\16#\u046e\3#\3#\3#\3#\3#\3#") + buf.write("\3#\6#\u0478\n#\r#\16#\u0479\3#\3#\3#\3#\3#\3#\3#\3#\3") + buf.write("#\5#\u0485\n#\3$\3$\3$\3$\3$\3$\5$\u048d\n$\3$\3$\5$\u0491") + buf.write("\n$\3$\5$\u0494\n$\3$\5$\u0497\n$\3$\5$\u049a\n$\3$\3") + buf.write("$\3%\3%\3%\3%\3%\3%\3%\3%\3%\7%\u04a7\n%\f%\16%\u04aa") + buf.write("\13%\5%\u04ac\n%\3%\5%\u04af\n%\3%\3%\3%\3%\3%\3%\3%\3") + buf.write("%\5%\u04b9\n%\3%\3%\5%\u04bd\n%\3%\5%\u04c0\n%\3%\5%\u04c3") + buf.write("\n%\3%\5%\u04c6\n%\3%\3%\3%\3%\3%\3%\5%\u04ce\n%\3%\5") + buf.write("%\u04d1\n%\3%\5%\u04d4\n%\3%\5%\u04d7\n%\3%\3%\5%\u04db") + buf.write("\n%\3&\3&\3&\3&\3&\3&\3&\3'\3'\3'\3'\3'\3'\3'\3") + buf.write("(\3(\3(\3(\3(\3(\3(\3(\5(\u04f3\n(\3)\3)\3)\3)\3)\5)\u04fa") + buf.write("\n)\5)\u04fc\n)\3)\3)\3*\3*\3*\3*\3*\3*\5*\u0506\n*\3") + buf.write("*\5*\u0509\n*\3*\5*\u050c\n*\3*\3*\3*\3*\3*\3*\3*\3*\3") + buf.write("*\3*\5*\u0518\n*\5*\u051a\n*\3*\3*\3*\5*\u051f\n*\3*\3") + buf.write("*\3*\3*\3*\3*\3*\3*\3*\3*\3*\3*\3*\3*\5*\u052f\n*\3+\3") + buf.write("+\3+\3+\3+\3+\5+\u0537\n+\3+\5+\u053a\n+\3+\5+\u053d\n") + buf.write("+\3+\3+\3+\3+\3+\3+\3+\3+\3+\5+\u0548\n+\5+\u054a\n+\3") + buf.write("+\3+\3+\5+\u054f\n+\3+\3+\3+\3+\3+\3+\3+\3+\3+\3+\5+\u055b") + buf.write("\n+\3+\3+\3+\3+\3+\3+\3+\3+\3+\3+\3+\3+\3+\3+\5+\u056b") + buf.write("\n+\3,\3,\3,\3,\3-\3-\3-\7-\u0574\n-\f-\16-\u0577\13-") + buf.write("\3.\5.\u057a\n.\3.\3.\3.\3.\3/\5/\u0581\n/\3/\3/\3/\3") + buf.write("/\3\60\3\60\3\60\3\60\3\61\3\61\3\61\3\61\3\61\3\61\3") + buf.write("\61\3\61\5\61\u0593\n\61\3\61\3\61\5\61\u0597\n\61\3\62") + buf.write("\3\62\3\62\7\62\u059c\n\62\f\62\16\62\u059f\13\62\3\63") + buf.write("\3\63\3\63\7\63\u05a4\n\63\f\63\16\63\u05a7\13\63\3\63") + buf.write("\3\63\3\63\3\63\7\63\u05ad\n\63\f\63\16\63\u05b0\13\63") + buf.write("\5\63\u05b2\n\63\3\64\3\64\3\64\5\64\u05b7\n\64\3\65\5") + buf.write("\65\u05ba\n\65\3\65\3\65\3\65\5\65\u05bf\n\65\3\65\5\65") + buf.write("\u05c2\n\65\3\65\5\65\u05c5\n\65\3\66\3\66\3\66\3\67\3") + buf.write("\67\3\67\3\67\3\67\7\67\u05cf\n\67\f\67\16\67\u05d2\13") + buf.write("\67\38\38\38\38\38\78\u05d9\n8\f8\168\u05dc\138\39\39") + buf.write("\59\u05e0\n9\3:\3:\3:\5:\u05e5\n:\3:\3:\3:\3:\3:\3;\5") + buf.write(";\u05ed\n;\3;\3;\3<\5<\u05f2\n<\3<\3<\3=\3=\3=\3=\3=\3") + buf.write("=\3=\3=\3=\3=\3=\3=\3=\5=\u0603\n=\3>\3>\3>\3>\3>\7>\u060a") + buf.write("\n>\f>\16>\u060d\13>\3>\3>\3>\3>\3>\5>\u0614\n>\3>\5>") + buf.write("\u0617\n>\3>\3>\3>\3>\3>\3>\3>\5>\u0620\n>\3>\5>\u0623") + buf.write("\n>\5>\u0625\n>\3?\3?\3?\3@\3@\3@\3@\5@\u062e\n@\3A\3") + buf.write("A\3A\5A\u0633\nA\3B\3B\5B\u0637\nB\3C\3C\3C\3C\3C\5C\u063e") + buf.write("\nC\3D\3D\3D\5D\u0643\nD\3E\3E\5E\u0647\nE\3E\5E\u064a") + buf.write("\nE\3E\5E\u064d\nE\3E\5E\u0650\nE\3F\3F\3F\3F\3F\5F\u0657") + buf.write("\nF\3G\3G\3G\3G\3G\7G\u065e\nG\fG\16G\u0661\13G\3G\3G") + buf.write("\5G\u0665\nG\3H\3H\5H\u0669\nH\3I\3I\3I\3I\3I\5I\u0670") + buf.write("\nI\3J\3J\3J\3J\3J\3J\7J\u0678\nJ\fJ\16J\u067b\13J\3J") + buf.write("\3J\5J\u067f\nJ\3J\3J\3J\3J\3J\7J\u0686\nJ\fJ\16J\u0689") + buf.write("\13J\3J\3J\5J\u068d\nJ\5J\u068f\nJ\3K\3K\3K\3K\3K\3K\3") + buf.write("K\3K\7K\u0699\nK\fK\16K\u069c\13K\3K\3K\5K\u06a0\nK\3") + buf.write("K\5K\u06a3\nK\3K\3K\3K\3K\3K\3K\3K\7K\u06ac\nK\fK\16K") + buf.write("\u06af\13K\3K\3K\5K\u06b3\nK\3K\3K\5K\u06b7\nK\5K\u06b9") + buf.write("\nK\3L\3L\3M\3M\3N\3N\3N\3N\7N\u06c3\nN\fN\16N\u06c6\13") + buf.write("N\3O\3O\3O\5O\u06cb\nO\3P\3P\3P\7P\u06d0\nP\fP\16P\u06d3") + buf.write("\13P\3Q\3Q\5Q\u06d7\nQ\3Q\3Q\3Q\3Q\5Q\u06dd\nQ\3Q\3Q\5") + buf.write("Q\u06e1\nQ\3Q\5Q\u06e4\nQ\3R\3R\3R\7R\u06e9\nR\fR\16R") + buf.write("\u06ec\13R\3S\3S\5S\u06f0\nS\3S\3S\5S\u06f4\nS\3S\5S\u06f7") + buf.write("\nS\3T\3T\3T\5T\u06fc\nT\3T\3T\3T\3U\3U\3U\7U\u0704\n") + buf.write("U\fU\16U\u0707\13U\3V\3V\3V\3V\5V\u070d\nV\3V\3V\5V\u0711") + buf.write("\nV\3V\3V\7V\u0715\nV\fV\16V\u0718\13V\3W\5W\u071b\nW") + buf.write("\3W\3W\3W\3W\3W\5W\u0722\nW\3X\3X\3X\5X\u0727\nX\3Y\3") + buf.write("Y\3Y\3Y\3Y\3Y\3Y\3Y\7Y\u0731\nY\fY\16Y\u0734\13Y\3Y\3") + buf.write("Y\5Y\u0738\nY\3Z\3Z\3Z\5Z\u073d\nZ\3[\3[\5[\u0741\n[\3") + buf.write("\\\3\\\3]\3]\3^\3^\3^\3^\7^\u074b\n^\f^\16^\u074e\13^") + buf.write("\3_\3_\3`\3`\3`\3a\3a\3b\3b\3c\3c\3d\3d\3e\3e\3f\3f\3") + buf.write("f\5f\u0762\nf\3g\3g\3g\3g\7g\u0768\ng\fg\16g\u076b\13") + buf.write("g\3g\3g\3h\3h\3h\3i\3i\3i\3j\3j\3k\3k\5k\u0779\nk\3l\3") + buf.write("l\5l\u077d\nl\3m\3m\3m\3m\3m\5m\u0784\nm\3n\3n\3n\3o\3") + buf.write("o\3p\3p\3q\3q\3r\3r\3r\3r\3r\5r\u0794\nr\3s\3s\3t\3t\3") + buf.write('t\2\4\6\bu\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 "$') buf.write("&(*,.\60\62\64\668:<>@BDFHJLNPRTVXZ\\^`bdfhjlnprtvxz|") buf.write("~\u0080\u0082\u0084\u0086\u0088\u008a\u008c\u008e\u0090") buf.write("\u0092\u0094\u0096\u0098\u009a\u009c\u009e\u00a0\u00a2") buf.write("\u00a4\u00a6\u00a8\u00aa\u00ac\u00ae\u00b0\u00b2\u00b4") buf.write("\u00b6\u00b8\u00ba\u00bc\u00be\u00c0\u00c2\u00c4\u00c6") buf.write("\u00c8\u00ca\u00cc\u00ce\u00d0\u00d2\u00d4\u00d6\u00d8") - buf.write("\u00da\u00dc\u00de\2%\4\2\17\20\64\64\3\2\21\22\4\2\17") - buf.write("\20``\3\2\62\63\3\2\66\67\3\2+,\4\2\u00cc\u00cc\u00ce") - buf.write("\u00ce\3\2\u00c3\u00c4\3\2\u00c5\u00c6\5\2__ac\u0085\u0086") - buf.write("\6\2WWYYnn\u0089\u008b\3\2[\\\5\2??ZZ]^\4\2JJ\u00d3\u00d3") - buf.write("\3\2\u00a4\u00a5\4\2uu\u00f6\u00f6\3\2TU\4\2==\u008d\u008d") - buf.write("\4\2JJvv\5\2RSeh\u008e\u0091\6\2RSeh\u008e\u0091\u0095") - buf.write("\u0096\3\2\u0097\u0098\3\2PQ\3\2\17\20\4\2NN\u0093\u0093") - buf.write("\3\2wx\4\2\17\17\21\21\5\2JJvv\u00ea\u00ea\3\2\u00e3\u00e8") - buf.write("\4\2{{\u00de\u00de\5\2{{\u0082\u0082\u00dd\u00dd\4\2J") - buf.write("J\u00e2\u00e2\3\2\t\16\5\2\u00aa\u00b0\u00d4\u00d4\u00eb") - buf.write("\u00eb\4\2JJ\u00f5\u00f5\2\u0829\2\u00e5\3\2\2\2\4\u00f3") - buf.write("\3\2\2\2\6\u0113\3\2\2\2\b\u0156\3\2\2\2\n\u017b\3\2\2") - buf.write("\2\f\u0189\3\2\2\2\16\u0192\3\2\2\2\20\u0194\3\2\2\2\22") - buf.write("\u019d\3\2\2\2\24\u01a5\3\2\2\2\26\u01a8\3\2\2\2\30\u01b1") - buf.write("\3\2\2\2\32\u01ba\3\2\2\2\34\u01bf\3\2\2\2\36\u01cc\3") - buf.write('\2\2\2 \u01e1\3\2\2\2"\u0215\3\2\2\2$\u0250\3\2\2\2&') - buf.write("\u028b\3\2\2\2(\u028f\3\2\2\2*\u0293\3\2\2\2,\u02c5\3") - buf.write("\2\2\2.\u02f7\3\2\2\2\60\u030e\3\2\2\2\62\u0325\3\2\2") - buf.write("\2\64\u0347\3\2\2\2\66\u035e\3\2\2\28\u03c6\3\2\2\2:\u042e") - buf.write("\3\2\2\2<\u044d\3\2\2\2>\u044f\3\2\2\2@\u04a3\3\2\2\2") - buf.write("B\u04a5\3\2\2\2D\u04ac\3\2\2\2F\u04bb\3\2\2\2H\u04bd\3") - buf.write("\2\2\2J\u04f7\3\2\2\2L\u0533\3\2\2\2N\u0535\3\2\2\2P\u0539") - buf.write("\3\2\2\2R\u0542\3\2\2\2T\u0549\3\2\2\2V\u054f\3\2\2\2") - buf.write("X\u055f\3\2\2\2Z\u0561\3\2\2\2\\\u0569\3\2\2\2^\u057c") - buf.write("\3\2\2\2`\u0582\3\2\2\2b\u058f\3\2\2\2d\u0592\3\2\2\2") - buf.write("f\u059c\3\2\2\2h\u05a6\3\2\2\2j\u05ad\3\2\2\2l\u05b5\3") - buf.write("\2\2\2n\u05ba\3\2\2\2p\u05cb\3\2\2\2r\u05ed\3\2\2\2t\u05ef") - buf.write("\3\2\2\2v\u05f2\3\2\2\2x\u05fb\3\2\2\2z\u05ff\3\2\2\2") - buf.write("|\u0606\3\2\2\2~\u060b\3\2\2\2\u0080\u060f\3\2\2\2\u0082") - buf.write("\u061a\3\2\2\2\u0084\u0621\3\2\2\2\u0086\u0631\3\2\2\2") - buf.write("\u0088\u0633\3\2\2\2\u008a\u0657\3\2\2\2\u008c\u0681\3") - buf.write("\2\2\2\u008e\u0683\3\2\2\2\u0090\u0685\3\2\2\2\u0092\u0687") - buf.write("\3\2\2\2\u0094\u0690\3\2\2\2\u0096\u0695\3\2\2\2\u0098") - buf.write("\u069f\3\2\2\2\u009a\u06ae\3\2\2\2\u009c\u06b8\3\2\2\2") - buf.write("\u009e\u06c1\3\2\2\2\u00a0\u06c9\3\2\2\2\u00a2\u06d5\3") - buf.write("\2\2\2\u00a4\u06e3\3\2\2\2\u00a6\u06ef\3\2\2\2\u00a8\u0700") - buf.write("\3\2\2\2\u00aa\u0702\3\2\2\2\u00ac\u0707\3\2\2\2\u00ae") - buf.write("\u070b\3\2\2\2\u00b0\u070d\3\2\2\2\u00b2\u070f\3\2\2\2") - buf.write("\u00b4\u0718\3\2\2\2\u00b6\u071a\3\2\2\2\u00b8\u071d\3") - buf.write("\2\2\2\u00ba\u071f\3\2\2\2\u00bc\u0721\3\2\2\2\u00be\u0723") - buf.write("\3\2\2\2\u00c0\u0725\3\2\2\2\u00c2\u0727\3\2\2\2\u00c4") - buf.write("\u072c\3\2\2\2\u00c6\u0737\3\2\2\2\u00c8\u073a\3\2\2\2") - buf.write("\u00ca\u073d\3\2\2\2\u00cc\u0741\3\2\2\2\u00ce\u0745\3") - buf.write("\2\2\2\u00d0\u074c\3\2\2\2\u00d2\u074e\3\2\2\2\u00d4\u0751") - buf.write("\3\2\2\2\u00d6\u0753\3\2\2\2\u00d8\u0755\3\2\2\2\u00da") - buf.write("\u075c\3\2\2\2\u00dc\u075e\3\2\2\2\u00de\u0760\3\2\2\2") - buf.write("\u00e0\u00e1\5\4\3\2\u00e1\u00e2\7\u00f9\2\2\u00e2\u00e4") - buf.write("\3\2\2\2\u00e3\u00e0\3\2\2\2\u00e4\u00e7\3\2\2\2\u00e5") - buf.write("\u00e3\3\2\2\2\u00e5\u00e6\3\2\2\2\u00e6\u00e8\3\2\2\2") - buf.write("\u00e7\u00e5\3\2\2\2\u00e8\u00e9\7\2\2\3\u00e9\3\3\2\2") - buf.write("\2\u00ea\u00eb\5\u00be`\2\u00eb\u00ec\7\26\2\2\u00ec\u00ed") - buf.write("\5\6\4\2\u00ed\u00f4\3\2\2\2\u00ee\u00ef\5\u00be`\2\u00ef") - buf.write("\u00f0\7~\2\2\u00f0\u00f1\5\6\4\2\u00f1\u00f4\3\2\2\2") - buf.write('\u00f2\u00f4\5"\22\2\u00f3\u00ea\3\2\2\2\u00f3\u00ee') - buf.write("\3\2\2\2\u00f3\u00f2\3\2\2\2\u00f4\5\3\2\2\2\u00f5\u00f6") - buf.write("\b\4\1\2\u00f6\u00f7\7\3\2\2\u00f7\u00f8\5\6\4\2\u00f8") - buf.write("\u00f9\7\4\2\2\u00f9\u0114\3\2\2\2\u00fa\u0114\5\f\7\2") - buf.write("\u00fb\u00fc\t\2\2\2\u00fc\u0114\5\6\4\r\u00fd\u00fe\7") - buf.write("\31\2\2\u00fe\u00ff\5\6\4\2\u00ff\u0100\7\33\2\2\u0100") - buf.write("\u0101\5\6\4\2\u0101\u0102\7\34\2\2\u0102\u0103\5\6\4") - buf.write("\6\u0103\u0114\3\2\2\2\u0104\u010a\7\32\2\2\u0105\u0106") - buf.write("\7\u00bb\2\2\u0106\u0107\5\6\4\2\u0107\u0108\7\33\2\2") - buf.write("\u0108\u0109\5\6\4\2\u0109\u010b\3\2\2\2\u010a\u0105\3") - buf.write("\2\2\2\u010b\u010c\3\2\2\2\u010c\u010a\3\2\2\2\u010c\u010d") - buf.write("\3\2\2\2\u010d\u010e\3\2\2\2\u010e\u010f\7\34\2\2\u010f") - buf.write("\u0110\5\6\4\5\u0110\u0114\3\2\2\2\u0111\u0114\5\u00da") - buf.write("n\2\u0112\u0114\5\u00be`\2\u0113\u00f5\3\2\2\2\u0113\u00fa") - buf.write("\3\2\2\2\u0113\u00fb\3\2\2\2\u0113\u00fd\3\2\2\2\u0113") - buf.write("\u0104\3\2\2\2\u0113\u0111\3\2\2\2\u0113\u0112\3\2\2\2") - buf.write("\u0114\u0135\3\2\2\2\u0115\u0116\f\f\2\2\u0116\u0117\t") - buf.write("\3\2\2\u0117\u0134\5\6\4\r\u0118\u0119\f\13\2\2\u0119") - buf.write("\u011a\t\4\2\2\u011a\u0134\5\6\4\f\u011b\u011c\f\n\2\2") - buf.write("\u011c\u011d\5\u00caf\2\u011d\u011e\5\6\4\13\u011e\u0134") - buf.write("\3\2\2\2\u011f\u0120\f\b\2\2\u0120\u0121\7\61\2\2\u0121") - buf.write("\u0134\5\6\4\t\u0122\u0123\f\7\2\2\u0123\u0124\t\5\2\2") - buf.write("\u0124\u0134\5\6\4\b\u0125\u0126\f\17\2\2\u0126\u0127") - buf.write("\7\5\2\2\u0127\u0128\5\16\b\2\u0128\u0129\7\6\2\2\u0129") - buf.write("\u0134\3\2\2\2\u012a\u012b\f\16\2\2\u012b\u012c\7\27\2") - buf.write("\2\u012c\u0134\5\u00c0a\2\u012d\u012e\f\t\2\2\u012e\u0131") - buf.write("\t\6\2\2\u012f\u0132\5\u00c4c\2\u0130\u0132\5\u00d4k\2") - buf.write("\u0131\u012f\3\2\2\2\u0131\u0130\3\2\2\2\u0132\u0134\3") - buf.write("\2\2\2\u0133\u0115\3\2\2\2\u0133\u0118\3\2\2\2\u0133\u011b") - buf.write("\3\2\2\2\u0133\u011f\3\2\2\2\u0133\u0122\3\2\2\2\u0133") - buf.write("\u0125\3\2\2\2\u0133\u012a\3\2\2\2\u0133\u012d\3\2\2\2") - buf.write("\u0134\u0137\3\2\2\2\u0135\u0133\3\2\2\2\u0135\u0136\3") - buf.write("\2\2\2\u0136\7\3\2\2\2\u0137\u0135\3\2\2\2\u0138\u0139") - buf.write("\b\5\1\2\u0139\u013a\7\3\2\2\u013a\u013b\5\b\5\2\u013b") - buf.write("\u013c\7\4\2\2\u013c\u0157\3\2\2\2\u013d\u0157\5\n\6\2") - buf.write("\u013e\u013f\t\2\2\2\u013f\u0157\5\b\5\r\u0140\u0141\7") - buf.write("\31\2\2\u0141\u0142\5\b\5\2\u0142\u0143\7\33\2\2\u0143") - buf.write("\u0144\5\b\5\2\u0144\u0145\7\34\2\2\u0145\u0146\5\b\5") - buf.write("\6\u0146\u0157\3\2\2\2\u0147\u014d\7\32\2\2\u0148\u0149") - buf.write("\7\u00bb\2\2\u0149\u014a\5\b\5\2\u014a\u014b\7\33\2\2") - buf.write("\u014b\u014c\5\b\5\2\u014c\u014e\3\2\2\2\u014d\u0148\3") - buf.write("\2\2\2\u014e\u014f\3\2\2\2\u014f\u014d\3\2\2\2\u014f\u0150") - buf.write("\3\2\2\2\u0150\u0151\3\2\2\2\u0151\u0152\7\34\2\2\u0152") - buf.write("\u0153\5\b\5\5\u0153\u0157\3\2\2\2\u0154\u0157\5\u00da") - buf.write("n\2\u0155\u0157\5\u00c2b\2\u0156\u0138\3\2\2\2\u0156\u013d") - buf.write("\3\2\2\2\u0156\u013e\3\2\2\2\u0156\u0140\3\2\2\2\u0156") - buf.write("\u0147\3\2\2\2\u0156\u0154\3\2\2\2\u0156\u0155\3\2\2\2") - buf.write("\u0157\u0170\3\2\2\2\u0158\u0159\f\f\2\2\u0159\u015a\t") - buf.write("\3\2\2\u015a\u016f\5\b\5\r\u015b\u015c\f\13\2\2\u015c") - buf.write("\u015d\t\4\2\2\u015d\u016f\5\b\5\f\u015e\u015f\f\n\2\2") - buf.write("\u015f\u0160\5\u00caf\2\u0160\u0161\5\b\5\13\u0161\u016f") - buf.write("\3\2\2\2\u0162\u0163\f\b\2\2\u0163\u0164\7\61\2\2\u0164") - buf.write("\u016f\5\b\5\t\u0165\u0166\f\7\2\2\u0166\u0167\t\5\2\2") - buf.write("\u0167\u016f\5\b\5\b\u0168\u0169\f\t\2\2\u0169\u016c\t") - buf.write("\6\2\2\u016a\u016d\5\u00c4c\2\u016b\u016d\5\u00d4k\2\u016c") - buf.write("\u016a\3\2\2\2\u016c\u016b\3\2\2\2\u016d\u016f\3\2\2\2") - buf.write("\u016e\u0158\3\2\2\2\u016e\u015b\3\2\2\2\u016e\u015e\3") - buf.write("\2\2\2\u016e\u0162\3\2\2\2\u016e\u0165\3\2\2\2\u016e\u0168") - buf.write("\3\2\2\2\u016f\u0172\3\2\2\2\u0170\u016e\3\2\2\2\u0170") - buf.write("\u0171\3\2\2\2\u0171\t\3\2\2\2\u0172\u0170\3\2\2\2\u0173") - buf.write("\u017c\5&\24\2\u0174\u017c\5.\30\2\u0175\u017c\5\62\32") - buf.write("\2\u0176\u017c\5\66\34\2\u0177\u017c\5:\36\2\u0178\u017c") - buf.write("\5D#\2\u0179\u017c\5F$\2\u017a\u017c\5L'\2\u017b\u0173") - buf.write("\3\2\2\2\u017b\u0174\3\2\2\2\u017b\u0175\3\2\2\2\u017b") - buf.write("\u0176\3\2\2\2\u017b\u0177\3\2\2\2\u017b\u0178\3\2\2\2") - buf.write("\u017b\u0179\3\2\2\2\u017b\u017a\3\2\2\2\u017c\13\3\2") - buf.write("\2\2\u017d\u018a\5 \21\2\u017e\u018a\5$\23\2\u017f\u018a") - buf.write("\5,\27\2\u0180\u018a\5\60\31\2\u0181\u018a\5\64\33\2\u0182") - buf.write("\u018a\58\35\2\u0183\u018a\5<\37\2\u0184\u018a\5> \2\u0185") - buf.write('\u018a\5@!\2\u0186\u018a\5B"\2\u0187\u018a\5H%\2\u0188') - buf.write("\u018a\5J&\2\u0189\u017d\3\2\2\2\u0189\u017e\3\2\2\2\u0189") - buf.write("\u017f\3\2\2\2\u0189\u0180\3\2\2\2\u0189\u0181\3\2\2\2") - buf.write("\u0189\u0182\3\2\2\2\u0189\u0183\3\2\2\2\u0189\u0184\3") - buf.write("\2\2\2\u0189\u0185\3\2\2\2\u0189\u0186\3\2\2\2\u0189\u0187") - buf.write("\3\2\2\2\u0189\u0188\3\2\2\2\u018a\r\3\2\2\2\u018b\u0193") - buf.write("\5\20\t\2\u018c\u0193\5\22\n\2\u018d\u0193\5\24\13\2\u018e") - buf.write("\u0193\5\26\f\2\u018f\u0193\5\30\r\2\u0190\u0193\5\32") - buf.write("\16\2\u0191\u0193\5\36\20\2\u0192\u018b\3\2\2\2\u0192") - buf.write("\u018c\3\2\2\2\u0192\u018d\3\2\2\2\u0192\u018e\3\2\2\2") - buf.write("\u0192\u018f\3\2\2\2\u0192\u0190\3\2\2\2\u0192\u0191\3") - buf.write("\2\2\2\u0193\17\3\2\2\2\u0194\u0195\7/\2\2\u0195\u019a") - buf.write("\5N(\2\u0196\u0197\7\23\2\2\u0197\u0199\5N(\2\u0198\u0196") - buf.write("\3\2\2\2\u0199\u019c\3\2\2\2\u019a\u0198\3\2\2\2\u019a") - buf.write("\u019b\3\2\2\2\u019b\21\3\2\2\2\u019c\u019a\3\2\2\2\u019d") - buf.write("\u019e\7K\2\2\u019e\u01a3\5P)\2\u019f\u01a1\5r:\2\u01a0") - buf.write("\u01a2\5t;\2\u01a1\u01a0\3\2\2\2\u01a1\u01a2\3\2\2\2\u01a2") - buf.write("\u01a4\3\2\2\2\u01a3\u019f\3\2\2\2\u01a3\u01a4\3\2\2\2") - buf.write("\u01a4\23\3\2\2\2\u01a5\u01a6\7l\2\2\u01a6\u01a7\5\b\5") - buf.write("\2\u01a7\25\3\2\2\2\u01a8\u01a9\7-\2\2\u01a9\u01ae\5T") - buf.write("+\2\u01aa\u01ab\7\23\2\2\u01ab\u01ad\5T+\2\u01ac\u01aa") - buf.write("\3\2\2\2\u01ad\u01b0\3\2\2\2\u01ae\u01ac\3\2\2\2\u01ae") - buf.write("\u01af\3\2\2\2\u01af\27\3\2\2\2\u01b0\u01ae\3\2\2\2\u01b1") - buf.write("\u01b2\t\7\2\2\u01b2\u01b7\5\u00c2b\2\u01b3\u01b4\7\23") - buf.write("\2\2\u01b4\u01b6\5\u00c2b\2\u01b5\u01b3\3\2\2\2\u01b6") - buf.write("\u01b9\3\2\2\2\u01b7\u01b5\3\2\2\2\u01b7\u01b8\3\2\2\2") - buf.write("\u01b8\31\3\2\2\2\u01b9\u01b7\3\2\2\2\u01ba\u01bb\t\b") - buf.write("\2\2\u01bb\u01bc\5\u00c2b\2\u01bc\u01bd\7\23\2\2\u01bd") - buf.write("\u01be\5\u00c2b\2\u01be\33\3\2\2\2\u01bf\u01c0\7\u00cd") - buf.write("\2\2\u01c0\u01c1\5\u00c2b\2\u01c1\u01c2\7\23\2\2\u01c2") - buf.write("\u01c3\5\u00c2b\2\u01c3\u01c4\7\66\2\2\u01c4\u01c9\5\u00da") - buf.write("n\2\u01c5\u01c6\7\23\2\2\u01c6\u01c8\5\u00dan\2\u01c7") - buf.write("\u01c5\3\2\2\2\u01c8\u01cb\3\2\2\2\u01c9\u01c7\3\2\2\2") - buf.write("\u01c9\u01ca\3\2\2\2\u01ca\35\3\2\2\2\u01cb\u01c9\3\2") - buf.write("\2\2\u01cc\u01cd\7\u00cf\2\2\u01cd\u01d2\5V,\2\u01ce\u01cf") - buf.write("\7\23\2\2\u01cf\u01d1\5V,\2\u01d0\u01ce\3\2\2\2\u01d1") - buf.write("\u01d4\3\2\2\2\u01d2\u01d0\3\2\2\2\u01d2\u01d3\3\2\2\2") - buf.write("\u01d3\37\3\2\2\2\u01d4\u01d2\3\2\2\2\u01d5\u01d6\t\t") - buf.write("\2\2\u01d6\u01d7\7\3\2\2\u01d7\u01d8\5\\/\2\u01d8\u01d9") - buf.write("\5`\61\2\u01d9\u01da\7\4\2\2\u01da\u01e2\3\2\2\2\u01db") - buf.write("\u01dc\t\n\2\2\u01dc\u01dd\7\3\2\2\u01dd\u01de\5Z.\2\u01de") - buf.write("\u01df\5`\61\2\u01df\u01e0\7\4\2\2\u01e0\u01e2\3\2\2\2") - buf.write("\u01e1\u01d5\3\2\2\2\u01e1\u01db\3\2\2\2\u01e2!\3\2\2") - buf.write("\2\u01e3\u01e4\7}\2\2\u01e4\u01e5\7|\2\2\u01e5\u01e6\5") - buf.write("\u00d6l\2\u01e6\u01ef\7\3\2\2\u01e7\u01ec\5v<\2\u01e8") - buf.write("\u01e9\7\23\2\2\u01e9\u01eb\5v<\2\u01ea\u01e8\3\2\2\2") - buf.write("\u01eb\u01ee\3\2\2\2\u01ec\u01ea\3\2\2\2\u01ec\u01ed\3") - buf.write("\2\2\2\u01ed\u01f0\3\2\2\2\u01ee\u01ec\3\2\2\2\u01ef\u01e7") - buf.write("\3\2\2\2\u01ef\u01f0\3\2\2\2\u01f0\u01f1\3\2\2\2\u01f1") - buf.write("\u01f4\7\4\2\2\u01f2\u01f3\7\u00cb\2\2\u01f3\u01f5\5x") - buf.write("=\2\u01f4\u01f2\3\2\2\2\u01f4\u01f5\3\2\2\2\u01f5\u01f6") - buf.write("\3\2\2\2\u01f6\u01f7\7\u00ba\2\2\u01f7\u01f8\5\6\4\2\u01f8") - buf.write("\u01f9\7\u0083\2\2\u01f9\u01fa\7|\2\2\u01fa\u0216\3\2") - buf.write("\2\2\u01fb\u01fc\7}\2\2\u01fc\u01fd\7\177\2\2\u01fd\u01fe") - buf.write("\7\u0081\2\2\u01fe\u01ff\5\u0090I\2\u01ff\u0200\7\3\2") - buf.write("\2\u0200\u0201\5\u0092J\2\u0201\u0202\7\4\2\2\u0202\u0203") - buf.write("\7\u00ba\2\2\u0203\u0204\5\u0096L\2\u0204\u0205\7\u0083") - buf.write("\2\2\u0205\u0206\7\177\2\2\u0206\u0207\7\u0081\2\2\u0207") - buf.write("\u0216\3\2\2\2\u0208\u0209\7}\2\2\u0209\u020a\7\u0080") - buf.write("\2\2\u020a\u020b\7\u0081\2\2\u020b\u020c\5\u0090I\2\u020c") - buf.write("\u020d\7\3\2\2\u020d\u020e\5\u009eP\2\u020e\u020f\7\4") - buf.write("\2\2\u020f\u0210\7\u00ba\2\2\u0210\u0211\5\u009aN\2\u0211") - buf.write("\u0212\7\u0083\2\2\u0212\u0213\7\u0080\2\2\u0213\u0214") - buf.write("\7\u0081\2\2\u0214\u0216\3\2\2\2\u0215\u01e3\3\2\2\2\u0215") - buf.write("\u01fb\3\2\2\2\u0215\u0208\3\2\2\2\u0216#\3\2\2\2\u0217") - buf.write("\u0218\5\u00d6l\2\u0218\u0221\7\3\2\2\u0219\u021e\5*\26") - buf.write("\2\u021a\u021b\7\23\2\2\u021b\u021d\5*\26\2\u021c\u021a") - buf.write("\3\2\2\2\u021d\u0220\3\2\2\2\u021e\u021c\3\2\2\2\u021e") - buf.write("\u021f\3\2\2\2\u021f\u0222\3\2\2\2\u0220\u021e\3\2\2\2") - buf.write("\u0221\u0219\3\2\2\2\u0221\u0222\3\2\2\2\u0222\u0223\3") - buf.write("\2\2\2\u0223\u0224\7\4\2\2\u0224\u0251\3\2\2\2\u0225\u0226") - buf.write("\7\30\2\2\u0226\u0227\7\3\2\2\u0227\u0228\5\u00d8m\2\u0228") - buf.write("\u022b\7\3\2\2\u0229\u022c\5\u00be`\2\u022a\u022c\5X-") - buf.write("\2\u022b\u0229\3\2\2\2\u022b\u022a\3\2\2\2\u022b\u022c") - buf.write("\3\2\2\2\u022c\u0234\3\2\2\2\u022d\u0230\7\23\2\2\u022e") - buf.write("\u0231\5\u00be`\2\u022f\u0231\5X-\2\u0230\u022e\3\2\2") - buf.write("\2\u0230\u022f\3\2\2\2\u0231\u0233\3\2\2\2\u0232\u022d") - buf.write("\3\2\2\2\u0233\u0236\3\2\2\2\u0234\u0232\3\2\2\2\u0234") - buf.write("\u0235\3\2\2\2\u0235\u0237\3\2\2\2\u0236\u0234\3\2\2\2") - buf.write("\u0237\u023a\7\4\2\2\u0238\u0239\7\u00f2\2\2\u0239\u023b") - buf.write("\7\u00f6\2\2\u023a\u0238\3\2\2\2\u023a\u023b\3\2\2\2\u023b") - buf.write("\u023e\3\2\2\2\u023c\u023d\7\u00cb\2\2\u023d\u023f\5\u0086") - buf.write("D\2\u023e\u023c\3\2\2\2\u023e\u023f\3\2\2\2\u023f\u0240") - buf.write("\3\2\2\2\u0240\u0241\7\4\2\2\u0241\u0251\3\2\2\2\u0242") - buf.write("\u0243\7\u00dc\2\2\u0243\u0244\7\3\2\2\u0244\u0245\5\6") - buf.write("\4\2\u0245\u0248\7\23\2\2\u0246\u0249\5\u00dco\2\u0247") - buf.write("\u0249\5\u008eH\2\u0248\u0246\3\2\2\2\u0248\u0247\3\2") - buf.write("\2\2\u0249\u024c\3\2\2\2\u024a\u024b\7\23\2\2\u024b\u024d") - buf.write("\7\u00f6\2\2\u024c\u024a\3\2\2\2\u024c\u024d\3\2\2\2\u024d") - buf.write("\u024e\3\2\2\2\u024e\u024f\7\4\2\2\u024f\u0251\3\2\2\2") - buf.write("\u0250\u0217\3\2\2\2\u0250\u0225\3\2\2\2\u0250\u0242\3") - buf.write("\2\2\2\u0251%\3\2\2\2\u0252\u0253\5\u00d6l\2\u0253\u025c") - buf.write("\7\3\2\2\u0254\u0259\5(\25\2\u0255\u0256\7\23\2\2\u0256") - buf.write("\u0258\5(\25\2\u0257\u0255\3\2\2\2\u0258\u025b\3\2\2\2") - buf.write("\u0259\u0257\3\2\2\2\u0259\u025a\3\2\2\2\u025a\u025d\3") - buf.write("\2\2\2\u025b\u0259\3\2\2\2\u025c\u0254\3\2\2\2\u025c\u025d") - buf.write("\3\2\2\2\u025d\u025e\3\2\2\2\u025e\u025f\7\4\2\2\u025f") - buf.write("\u028c\3\2\2\2\u0260\u0261\7\u00dc\2\2\u0261\u0262\7\3") - buf.write("\2\2\u0262\u0263\5\b\5\2\u0263\u0266\7\23\2\2\u0264\u0267") - buf.write("\5\u00dco\2\u0265\u0267\5\u008eH\2\u0266\u0264\3\2\2\2") - buf.write("\u0266\u0265\3\2\2\2\u0267\u026a\3\2\2\2\u0268\u0269\7") - buf.write("\23\2\2\u0269\u026b\7\u00f6\2\2\u026a\u0268\3\2\2\2\u026a") - buf.write("\u026b\3\2\2\2\u026b\u026c\3\2\2\2\u026c\u026d\7\4\2\2") - buf.write("\u026d\u028c\3\2\2\2\u026e\u026f\7\30\2\2\u026f\u0270") - buf.write("\7\3\2\2\u0270\u0271\5\u00d8m\2\u0271\u0274\7\3\2\2\u0272") - buf.write("\u0275\5\u00c2b\2\u0273\u0275\5X-\2\u0274\u0272\3\2\2") - buf.write("\2\u0274\u0273\3\2\2\2\u0274\u0275\3\2\2\2\u0275\u027d") - buf.write("\3\2\2\2\u0276\u0279\7\23\2\2\u0277\u027a\5\u00c2b\2\u0278") - buf.write("\u027a\5X-\2\u0279\u0277\3\2\2\2\u0279\u0278\3\2\2\2\u027a") - buf.write("\u027c\3\2\2\2\u027b\u0276\3\2\2\2\u027c\u027f\3\2\2\2") - buf.write("\u027d\u027b\3\2\2\2\u027d\u027e\3\2\2\2\u027e\u0280\3") - buf.write("\2\2\2\u027f\u027d\3\2\2\2\u0280\u0283\7\4\2\2\u0281\u0282") - buf.write("\7\u00f2\2\2\u0282\u0284\7\u00f6\2\2\u0283\u0281\3\2\2") - buf.write("\2\u0283\u0284\3\2\2\2\u0284\u0287\3\2\2\2\u0285\u0286") - buf.write("\7\u00cb\2\2\u0286\u0288\5z>\2\u0287\u0285\3\2\2\2\u0287") - buf.write("\u0288\3\2\2\2\u0288\u0289\3\2\2\2\u0289\u028a\7\4\2\2") - buf.write("\u028a\u028c\3\2\2\2\u028b\u0252\3\2\2\2\u028b\u0260\3") - buf.write("\2\2\2\u028b\u026e\3\2\2\2\u028c'\3\2\2\2\u028d\u0290") - buf.write("\5\b\5\2\u028e\u0290\7u\2\2\u028f\u028d\3\2\2\2\u028f") - buf.write("\u028e\3\2\2\2\u0290)\3\2\2\2\u0291\u0294\5\6\4\2\u0292") - buf.write("\u0294\7u\2\2\u0293\u0291\3\2\2\2\u0293\u0292\3\2\2\2") - buf.write("\u0294+\3\2\2\2\u0295\u0296\t\13\2\2\u0296\u0297\7\3\2") - buf.write("\2\u0297\u0298\5\6\4\2\u0298\u0299\7\4\2\2\u0299\u02c6") - buf.write("\3\2\2\2\u029a\u029b\7d\2\2\u029b\u029c\7\3\2\2\u029c") - buf.write("\u02a7\5\6\4\2\u029d\u029e\7\23\2\2\u029e\u029f\5\u00cc") - buf.write("g\2\u029f\u02a0\3\2\2\2\u02a0\u02a1\7\23\2\2\u02a1\u02a2") - buf.write("\5\u00ccg\2\u02a2\u02a4\3\2\2\2\u02a3\u029d\3\2\2\2\u02a3") - buf.write("\u02a4\3\2\2\2\u02a4\u02a8\3\2\2\2\u02a5\u02a6\7\23\2") - buf.write("\2\u02a6\u02a8\5\u00ccg\2\u02a7\u02a3\3\2\2\2\u02a7\u02a5") - buf.write("\3\2\2\2\u02a8\u02a9\3\2\2\2\u02a9\u02aa\7\4\2\2\u02aa") - buf.write("\u02c6\3\2\2\2\u02ab\u02ac\7\u0088\2\2\u02ac\u02ad\7\3") - buf.write("\2\2\u02ad\u02ae\5\6\4\2\u02ae\u02af\7\23\2\2\u02af\u02b2") - buf.write("\5\6\4\2\u02b0\u02b1\7\23\2\2\u02b1\u02b3\5\u00ccg\2\u02b2") - buf.write("\u02b0\3\2\2\2\u02b2\u02b3\3\2\2\2\u02b3\u02b4\3\2\2\2") - buf.write("\u02b4\u02b5\7\4\2\2\u02b5\u02c6\3\2\2\2\u02b6\u02b7\7") - buf.write("\u0087\2\2\u02b7\u02b8\7\3\2\2\u02b8\u02b9\5\6\4\2\u02b9") - buf.write("\u02ba\7\23\2\2\u02ba\u02bd\5\6\4\2\u02bb\u02bc\7\23\2") - buf.write("\2\u02bc\u02be\5\u00ccg\2\u02bd\u02bb\3\2\2\2\u02bd\u02be") - buf.write("\3\2\2\2\u02be\u02c1\3\2\2\2\u02bf\u02c0\7\23\2\2\u02c0") - buf.write("\u02c2\5\u00ccg\2\u02c1\u02bf\3\2\2\2\u02c1\u02c2\3\2") - buf.write("\2\2\u02c2\u02c3\3\2\2\2\u02c3\u02c4\7\4\2\2\u02c4\u02c6") - buf.write("\3\2\2\2\u02c5\u0295\3\2\2\2\u02c5\u029a\3\2\2\2\u02c5") - buf.write("\u02ab\3\2\2\2\u02c5\u02b6\3\2\2\2\u02c6-\3\2\2\2\u02c7") - buf.write("\u02c8\t\13\2\2\u02c8\u02c9\7\3\2\2\u02c9\u02ca\5\b\5") - buf.write("\2\u02ca\u02cb\7\4\2\2\u02cb\u02f8\3\2\2\2\u02cc\u02cd") - buf.write("\7d\2\2\u02cd\u02ce\7\3\2\2\u02ce\u02d9\5\b\5\2\u02cf") - buf.write("\u02d0\7\23\2\2\u02d0\u02d1\5\u00ceh\2\u02d1\u02d2\3\2") - buf.write("\2\2\u02d2\u02d3\7\23\2\2\u02d3\u02d4\5\u00ceh\2\u02d4") - buf.write("\u02d6\3\2\2\2\u02d5\u02cf\3\2\2\2\u02d5\u02d6\3\2\2\2") - buf.write("\u02d6\u02da\3\2\2\2\u02d7\u02d8\7\23\2\2\u02d8\u02da") - buf.write("\5\u00ceh\2\u02d9\u02d5\3\2\2\2\u02d9\u02d7\3\2\2\2\u02da") - buf.write("\u02db\3\2\2\2\u02db\u02dc\7\4\2\2\u02dc\u02f8\3\2\2\2") - buf.write("\u02dd\u02de\7\u0088\2\2\u02de\u02df\7\3\2\2\u02df\u02e0") - buf.write("\5\b\5\2\u02e0\u02e1\7\23\2\2\u02e1\u02e4\5\b\5\2\u02e2") - buf.write("\u02e3\7\23\2\2\u02e3\u02e5\5\u00ceh\2\u02e4\u02e2\3\2") - buf.write("\2\2\u02e4\u02e5\3\2\2\2\u02e5\u02e6\3\2\2\2\u02e6\u02e7") - buf.write("\7\4\2\2\u02e7\u02f8\3\2\2\2\u02e8\u02e9\7\u0087\2\2\u02e9") - buf.write("\u02ea\7\3\2\2\u02ea\u02eb\5\b\5\2\u02eb\u02ec\7\23\2") - buf.write("\2\u02ec\u02ef\5\b\5\2\u02ed\u02ee\7\23\2\2\u02ee\u02f0") - buf.write("\5\u00ceh\2\u02ef\u02ed\3\2\2\2\u02ef\u02f0\3\2\2\2\u02f0") - buf.write("\u02f3\3\2\2\2\u02f1\u02f2\7\23\2\2\u02f2\u02f4\5\u00ce") - buf.write("h\2\u02f3\u02f1\3\2\2\2\u02f3\u02f4\3\2\2\2\u02f4\u02f5") - buf.write("\3\2\2\2\u02f5\u02f6\7\4\2\2\u02f6\u02f8\3\2\2\2\u02f7") - buf.write("\u02c7\3\2\2\2\u02f7\u02cc\3\2\2\2\u02f7\u02dd\3\2\2\2") - buf.write("\u02f7\u02e8\3\2\2\2\u02f8/\3\2\2\2\u02f9\u02fa\t\f\2") - buf.write("\2\u02fa\u02fb\7\3\2\2\u02fb\u02fc\5\6\4\2\u02fc\u02fd") - buf.write("\7\4\2\2\u02fd\u030f\3\2\2\2\u02fe\u02ff\t\r\2\2\u02ff") - buf.write("\u0300\7\3\2\2\u0300\u0303\5\6\4\2\u0301\u0302\7\23\2") - buf.write("\2\u0302\u0304\5\u00ccg\2\u0303\u0301\3\2\2\2\u0303\u0304") - buf.write("\3\2\2\2\u0304\u0305\3\2\2\2\u0305\u0306\7\4\2\2\u0306") - buf.write("\u030f\3\2\2\2\u0307\u0308\t\16\2\2\u0308\u0309\7\3\2") - buf.write("\2\u0309\u030a\5\6\4\2\u030a\u030b\7\23\2\2\u030b\u030c") - buf.write("\5\6\4\2\u030c\u030d\7\4\2\2\u030d\u030f\3\2\2\2\u030e") - buf.write("\u02f9\3\2\2\2\u030e\u02fe\3\2\2\2\u030e\u0307\3\2\2\2") - buf.write("\u030f\61\3\2\2\2\u0310\u0311\t\f\2\2\u0311\u0312\7\3") - buf.write("\2\2\u0312\u0313\5\b\5\2\u0313\u0314\7\4\2\2\u0314\u0326") - buf.write("\3\2\2\2\u0315\u0316\t\r\2\2\u0316\u0317\7\3\2\2\u0317") - buf.write("\u031a\5\b\5\2\u0318\u0319\7\23\2\2\u0319\u031b\5\u00ce") - buf.write("h\2\u031a\u0318\3\2\2\2\u031a\u031b\3\2\2\2\u031b\u031c") - buf.write("\3\2\2\2\u031c\u031d\7\4\2\2\u031d\u0326\3\2\2\2\u031e") - buf.write("\u031f\t\16\2\2\u031f\u0320\7\3\2\2\u0320\u0321\5\b\5") - buf.write("\2\u0321\u0322\7\23\2\2\u0322\u0323\5\b\5\2\u0323\u0324") - buf.write("\7\4\2\2\u0324\u0326\3\2\2\2\u0325\u0310\3\2\2\2\u0325") - buf.write("\u0315\3\2\2\2\u0325\u031e\3\2\2\2\u0326\63\3\2\2\2\u0327") - buf.write("\u0328\7\65\2\2\u0328\u0329\7\3\2\2\u0329\u032a\5\6\4") - buf.write("\2\u032a\u032b\7\23\2\2\u032b\u032c\5\6\4\2\u032c\u032d") - buf.write("\7\23\2\2\u032d\u032e\5\6\4\2\u032e\u032f\7\4\2\2\u032f") - buf.write("\u0348\3\2\2\2\u0330\u0331\7q\2\2\u0331\u0332\7\3\2\2") - buf.write("\u0332\u0333\5\6\4\2\u0333\u0334\7\23\2\2\u0334\u0335") - buf.write("\5\6\4\2\u0335\u0336\7\4\2\2\u0336\u0348\3\2\2\2\u0337") - buf.write("\u0338\79\2\2\u0338\u0339\7\3\2\2\u0339\u033a\5\6\4\2") - buf.write("\u033a\u033b\7\4\2\2\u033b\u0348\3\2\2\2\u033c\u033d\7") - buf.write("E\2\2\u033d\u033e\7\3\2\2\u033e\u033f\5\6\4\2\u033f\u0340") - buf.write("\7\23\2\2\u0340\u0343\5\6\4\2\u0341\u0342\7\23\2\2\u0342") - buf.write("\u0344\5\u00dep\2\u0343\u0341\3\2\2\2\u0343\u0344\3\2") - buf.write("\2\2\u0344\u0345\3\2\2\2\u0345\u0346\7\4\2\2\u0346\u0348") - buf.write("\3\2\2\2\u0347\u0327\3\2\2\2\u0347\u0330\3\2\2\2\u0347") - buf.write("\u0337\3\2\2\2\u0347\u033c\3\2\2\2\u0348\65\3\2\2\2\u0349") - buf.write("\u034a\7\65\2\2\u034a\u034b\7\3\2\2\u034b\u034c\5\b\5") - buf.write("\2\u034c\u034d\7\23\2\2\u034d\u034e\5\b\5\2\u034e\u034f") - buf.write("\7\23\2\2\u034f\u0350\5\b\5\2\u0350\u0351\7\4\2\2\u0351") - buf.write("\u035f\3\2\2\2\u0352\u0353\7q\2\2\u0353\u0354\7\3\2\2") - buf.write("\u0354\u0355\5\b\5\2\u0355\u0356\7\23\2\2\u0356\u0357") - buf.write("\5\b\5\2\u0357\u0358\7\4\2\2\u0358\u035f\3\2\2\2\u0359") - buf.write("\u035a\79\2\2\u035a\u035b\7\3\2\2\u035b\u035c\5\b\5\2") - buf.write("\u035c\u035d\7\4\2\2\u035d\u035f\3\2\2\2\u035e\u0349\3") - buf.write("\2\2\2\u035e\u0352\3\2\2\2\u035e\u0359\3\2\2\2\u035f\67") - buf.write("\3\2\2\2\u0360\u0361\7\u00d2\2\2\u0361\u0363\7\3\2\2\u0362") - buf.write("\u0364\5\6\4\2\u0363\u0362\3\2\2\2\u0363\u0364\3\2\2\2") - buf.write("\u0364\u0365\3\2\2\2\u0365\u03c7\7\4\2\2\u0366\u0367\7") - buf.write("\u00a3\2\2\u0367\u0368\7\3\2\2\u0368\u036b\5\6\4\2\u0369") - buf.write("\u036a\7\23\2\2\u036a\u036c\t\17\2\2\u036b\u0369\3\2\2") - buf.write("\2\u036b\u036c\3\2\2\2\u036c\u036d\3\2\2\2\u036d\u036e") - buf.write("\7\4\2\2\u036e\u03c7\3\2\2\2\u036f\u0370\t\20\2\2\u0370") - buf.write("\u0371\7\3\2\2\u0371\u0372\5\6\4\2\u0372\u0373\7\4\2\2") - buf.write("\u0373\u03c7\3\2\2\2\u0374\u0375\7\u00a6\2\2\u0375\u0376") - buf.write("\7\3\2\2\u0376\u0377\5\6\4\2\u0377\u0378\7\23\2\2\u0378") - buf.write("\u0379\5l\67\2\u0379\u037a\7\4\2\2\u037a\u03c7\3\2\2\2") - buf.write("\u037b\u037c\7\u00d5\2\2\u037c\u037d\7\3\2\2\u037d\u0380") - buf.write("\7\u00f6\2\2\u037e\u037f\7\23\2\2\u037f\u0381\t\21\2\2") - buf.write("\u0380\u037e\3\2\2\2\u0380\u0381\3\2\2\2\u0381\u0384\3") - buf.write("\2\2\2\u0382\u0383\7\23\2\2\u0383\u0385\5\u00ccg\2\u0384") - buf.write("\u0382\3\2\2\2\u0384\u0385\3\2\2\2\u0385\u0388\3\2\2\2") - buf.write("\u0386\u0387\7\23\2\2\u0387\u0389\t\22\2\2\u0388\u0386") - buf.write("\3\2\2\2\u0388\u0389\3\2\2\2\u0389\u038a\3\2\2\2\u038a") - buf.write("\u03c7\7\4\2\2\u038b\u038c\7\37\2\2\u038c\u038d\7\3\2") - buf.write("\2\u038d\u03c7\7\4\2\2\u038e\u038f\7 \2\2\u038f\u0390") - buf.write("\7\3\2\2\u0390\u0391\5\6\4\2\u0391\u0392\7\23\2\2\u0392") - buf.write("\u0393\5\6\4\2\u0393\u0394\7\4\2\2\u0394\u03c7\3\2\2\2") - buf.write("\u0395\u0396\7!\2\2\u0396\u0397\7\3\2\2\u0397\u0398\5") - buf.write("\6\4\2\u0398\u0399\7\23\2\2\u0399\u039a\5\6\4\2\u039a") - buf.write("\u039b\7\23\2\2\u039b\u039c\5\6\4\2\u039c\u039d\7\4\2") - buf.write('\2\u039d\u03c7\3\2\2\2\u039e\u039f\7"\2\2\u039f\u03a0') - buf.write("\7\3\2\2\u03a0\u03a1\5\6\4\2\u03a1\u03a2\7\4\2\2\u03a2") - buf.write("\u03c7\3\2\2\2\u03a3\u03a4\7#\2\2\u03a4\u03a5\7\3\2\2") - buf.write("\u03a5\u03a6\5\6\4\2\u03a6\u03a7\7\4\2\2\u03a7\u03c7\3") - buf.write("\2\2\2\u03a8\u03a9\7$\2\2\u03a9\u03aa\7\3\2\2\u03aa\u03ab") - buf.write("\5\6\4\2\u03ab\u03ac\7\4\2\2\u03ac\u03c7\3\2\2\2\u03ad") - buf.write("\u03ae\7%\2\2\u03ae\u03af\7\3\2\2\u03af\u03b0\5\6\4\2") - buf.write("\u03b0\u03b1\7\4\2\2\u03b1\u03c7\3\2\2\2\u03b2\u03b3\7") - buf.write("&\2\2\u03b3\u03b4\7\3\2\2\u03b4\u03b5\5\6\4\2\u03b5\u03b6") - buf.write("\7\4\2\2\u03b6\u03c7\3\2\2\2\u03b7\u03b8\7'\2\2\u03b8") - buf.write("\u03b9\7\3\2\2\u03b9\u03ba\5\6\4\2\u03ba\u03bb\7\4\2\2") - buf.write("\u03bb\u03c7\3\2\2\2\u03bc\u03bd\7(\2\2\u03bd\u03be\7") - buf.write("\3\2\2\u03be\u03bf\5\6\4\2\u03bf\u03c0\7\4\2\2\u03c0\u03c7") - buf.write("\3\2\2\2\u03c1\u03c2\7)\2\2\u03c2\u03c3\7\3\2\2\u03c3") - buf.write("\u03c4\5\6\4\2\u03c4\u03c5\7\4\2\2\u03c5\u03c7\3\2\2\2") - buf.write("\u03c6\u0360\3\2\2\2\u03c6\u0366\3\2\2\2\u03c6\u036f\3") - buf.write("\2\2\2\u03c6\u0374\3\2\2\2\u03c6\u037b\3\2\2\2\u03c6\u038b") - buf.write("\3\2\2\2\u03c6\u038e\3\2\2\2\u03c6\u0395\3\2\2\2\u03c6") - buf.write("\u039e\3\2\2\2\u03c6\u03a3\3\2\2\2\u03c6\u03a8\3\2\2\2") - buf.write("\u03c6\u03ad\3\2\2\2\u03c6\u03b2\3\2\2\2\u03c6\u03b7\3") - buf.write("\2\2\2\u03c6\u03bc\3\2\2\2\u03c6\u03c1\3\2\2\2\u03c79") - buf.write("\3\2\2\2\u03c8\u03c9\7\u00d2\2\2\u03c9\u03cb\7\3\2\2\u03ca") - buf.write("\u03cc\5\b\5\2\u03cb\u03ca\3\2\2\2\u03cb\u03cc\3\2\2\2") - buf.write("\u03cc\u03cd\3\2\2\2\u03cd\u042f\7\4\2\2\u03ce\u03cf\7") - buf.write("\u00a3\2\2\u03cf\u03d0\7\3\2\2\u03d0\u03d3\5\b\5\2\u03d1") - buf.write("\u03d2\7\23\2\2\u03d2\u03d4\t\17\2\2\u03d3\u03d1\3\2\2") - buf.write("\2\u03d3\u03d4\3\2\2\2\u03d4\u03d5\3\2\2\2\u03d5\u03d6") - buf.write("\7\4\2\2\u03d6\u042f\3\2\2\2\u03d7\u03d8\t\20\2\2\u03d8") - buf.write("\u03d9\7\3\2\2\u03d9\u03da\5\b\5\2\u03da\u03db\7\4\2\2") - buf.write("\u03db\u042f\3\2\2\2\u03dc\u03dd\7\u00a6\2\2\u03dd\u03de") - buf.write("\7\3\2\2\u03de\u03df\5\b\5\2\u03df\u03e0\7\23\2\2\u03e0") - buf.write("\u03e1\5l\67\2\u03e1\u03e2\7\4\2\2\u03e2\u042f\3\2\2\2") - buf.write("\u03e3\u03e4\7\u00d5\2\2\u03e4\u03e5\7\3\2\2\u03e5\u03e8") - buf.write("\7\u00f6\2\2\u03e6\u03e7\7\23\2\2\u03e7\u03e9\t\21\2\2") - buf.write("\u03e8\u03e6\3\2\2\2\u03e8\u03e9\3\2\2\2\u03e9\u03ec\3") - buf.write("\2\2\2\u03ea\u03eb\7\23\2\2\u03eb\u03ed\5\u00ceh\2\u03ec") - buf.write("\u03ea\3\2\2\2\u03ec\u03ed\3\2\2\2\u03ed\u03f0\3\2\2\2") - buf.write("\u03ee\u03ef\7\23\2\2\u03ef\u03f1\t\22\2\2\u03f0\u03ee") - buf.write("\3\2\2\2\u03f0\u03f1\3\2\2\2\u03f1\u03f2\3\2\2\2\u03f2") - buf.write("\u042f\7\4\2\2\u03f3\u03f4\7\37\2\2\u03f4\u03f5\7\3\2") - buf.write("\2\u03f5\u042f\7\4\2\2\u03f6\u03f7\7 \2\2\u03f7\u03f8") - buf.write("\7\3\2\2\u03f8\u03f9\5\b\5\2\u03f9\u03fa\7\23\2\2\u03fa") - buf.write("\u03fb\5\6\4\2\u03fb\u03fc\7\4\2\2\u03fc\u042f\3\2\2\2") - buf.write("\u03fd\u03fe\7!\2\2\u03fe\u03ff\7\3\2\2\u03ff\u0400\5") - buf.write("\b\5\2\u0400\u0401\7\23\2\2\u0401\u0402\5\b\5\2\u0402") - buf.write("\u0403\7\23\2\2\u0403\u0404\5\b\5\2\u0404\u0405\7\4\2") - buf.write('\2\u0405\u042f\3\2\2\2\u0406\u0407\7"\2\2\u0407\u0408') - buf.write("\7\3\2\2\u0408\u0409\5\b\5\2\u0409\u040a\7\4\2\2\u040a") - buf.write("\u042f\3\2\2\2\u040b\u040c\7#\2\2\u040c\u040d\7\3\2\2") - buf.write("\u040d\u040e\5\b\5\2\u040e\u040f\7\4\2\2\u040f\u042f\3") - buf.write("\2\2\2\u0410\u0411\7$\2\2\u0411\u0412\7\3\2\2\u0412\u0413") - buf.write("\5\b\5\2\u0413\u0414\7\4\2\2\u0414\u042f\3\2\2\2\u0415") - buf.write("\u0416\7%\2\2\u0416\u0417\7\3\2\2\u0417\u0418\5\b\5\2") - buf.write("\u0418\u0419\7\4\2\2\u0419\u042f\3\2\2\2\u041a\u041b\7") - buf.write("&\2\2\u041b\u041c\7\3\2\2\u041c\u041d\5\b\5\2\u041d\u041e") - buf.write("\7\4\2\2\u041e\u042f\3\2\2\2\u041f\u0420\7'\2\2\u0420") - buf.write("\u0421\7\3\2\2\u0421\u0422\5\b\5\2\u0422\u0423\7\4\2\2") - buf.write("\u0423\u042f\3\2\2\2\u0424\u0425\7(\2\2\u0425\u0426\7") - buf.write("\3\2\2\u0426\u0427\5\b\5\2\u0427\u0428\7\4\2\2\u0428\u042f") - buf.write("\3\2\2\2\u0429\u042a\7)\2\2\u042a\u042b\7\3\2\2\u042b") - buf.write("\u042c\5\b\5\2\u042c\u042d\7\4\2\2\u042d\u042f\3\2\2\2") - buf.write("\u042e\u03c8\3\2\2\2\u042e\u03ce\3\2\2\2\u042e\u03d7\3") - buf.write("\2\2\2\u042e\u03dc\3\2\2\2\u042e\u03e3\3\2\2\2\u042e\u03f3") - buf.write("\3\2\2\2\u042e\u03f6\3\2\2\2\u042e\u03fd\3\2\2\2\u042e") - buf.write("\u0406\3\2\2\2\u042e\u040b\3\2\2\2\u042e\u0410\3\2\2\2") - buf.write("\u042e\u0415\3\2\2\2\u042e\u041a\3\2\2\2\u042e\u041f\3") - buf.write("\2\2\2\u042e\u0424\3\2\2\2\u042e\u0429\3\2\2\2\u042f;") - buf.write("\3\2\2\2\u0430\u0431\7;\2\2\u0431\u0432\7\3\2\2\u0432") - buf.write("\u0435\5\6\4\2\u0433\u0434\7\23\2\2\u0434\u0436\5\6\4") - buf.write("\2\u0435\u0433\3\2\2\2\u0436\u0437\3\2\2\2\u0437\u0435") - buf.write("\3\2\2\2\u0437\u0438\3\2\2\2\u0438\u0439\3\2\2\2\u0439") - buf.write("\u043a\7\4\2\2\u043a\u044e\3\2\2\2\u043b\u043c\7>\2\2") - buf.write("\u043c\u043d\7\3\2\2\u043d\u0440\5\6\4\2\u043e\u043f\7") - buf.write("\23\2\2\u043f\u0441\5\6\4\2\u0440\u043e\3\2\2\2\u0441") - buf.write("\u0442\3\2\2\2\u0442\u0440\3\2\2\2\u0442\u0443\3\2\2\2") - buf.write("\u0443\u0444\3\2\2\2\u0444\u0445\7\4\2\2\u0445\u044e\3") - buf.write("\2\2\2\u0446\u0447\t\23\2\2\u0447\u0448\7\3\2\2\u0448") - buf.write("\u0449\5\6\4\2\u0449\u044a\7\23\2\2\u044a\u044b\5\6\4") - buf.write("\2\u044b\u044c\7\4\2\2\u044c\u044e\3\2\2\2\u044d\u0430") - buf.write("\3\2\2\2\u044d\u043b\3\2\2\2\u044d\u0446\3\2\2\2\u044e") - buf.write("=\3\2\2\2\u044f\u0450\7t\2\2\u0450\u0451\7\3\2\2\u0451") - buf.write("\u0452\5\6\4\2\u0452\u0453\7\23\2\2\u0453\u0455\7\u00f7") - buf.write("\2\2\u0454\u0456\5\u00b2Z\2\u0455\u0454\3\2\2\2\u0455") - buf.write("\u0456\3\2\2\2\u0456\u0459\3\2\2\2\u0457\u0458\7\u0082") - buf.write("\2\2\u0458\u045a\5\u00c2b\2\u0459\u0457\3\2\2\2\u0459") - buf.write("\u045a\3\2\2\2\u045a\u045c\3\2\2\2\u045b\u045d\5\u00b0") - buf.write("Y\2\u045c\u045b\3\2\2\2\u045c\u045d\3\2\2\2\u045d\u045f") - buf.write("\3\2\2\2\u045e\u0460\5\u00b8]\2\u045f\u045e\3\2\2\2\u045f") - buf.write("\u0460\3\2\2\2\u0460\u0462\3\2\2\2\u0461\u0463\5\u00ba") - buf.write("^\2\u0462\u0461\3\2\2\2\u0462\u0463\3\2\2\2\u0463\u0464") - buf.write("\3\2\2\2\u0464\u0465\7\4\2\2\u0465?\3\2\2\2\u0466\u0467") - buf.write("\7\u00e0\2\2\u0467\u0468\7\3\2\2\u0468\u0469\5\6\4\2\u0469") - buf.write("\u046a\7\23\2\2\u046a\u0474\7\u00f7\2\2\u046b\u046c\7") - buf.write("\u00e9\2\2\u046c\u0471\5\u00c2b\2\u046d\u046e\7\23\2\2") - buf.write("\u046e\u0470\5\u00c2b\2\u046f\u046d\3\2\2\2\u0470\u0473") - buf.write("\3\2\2\2\u0471\u046f\3\2\2\2\u0471\u0472\3\2\2\2\u0472") - buf.write("\u0475\3\2\2\2\u0473\u0471\3\2\2\2\u0474\u046b\3\2\2\2") - buf.write("\u0474\u0475\3\2\2\2\u0475\u0477\3\2\2\2\u0476\u0478\5") - buf.write("\u00aeX\2\u0477\u0476\3\2\2\2\u0477\u0478\3\2\2\2\u0478") - buf.write("\u0479\3\2\2\2\u0479\u047a\7\4\2\2\u047a\u04a4\3\2\2\2") - buf.write("\u047b\u047c\7\u00e1\2\2\u047c\u047d\7\3\2\2\u047d\u047e") - buf.write("\5\6\4\2\u047e\u047f\7\23\2\2\u047f\u0481\7\u00f7\2\2") - buf.write("\u0480\u0482\5\u00b2Z\2\u0481\u0480\3\2\2\2\u0481\u0482") - buf.write("\3\2\2\2\u0482\u0485\3\2\2\2\u0483\u0484\7\u0082\2\2\u0484") - buf.write("\u0486\5\u00c2b\2\u0485\u0483\3\2\2\2\u0485\u0486\3\2") - buf.write("\2\2\u0486\u0488\3\2\2\2\u0487\u0489\5\u00b0Y\2\u0488") - buf.write("\u0487\3\2\2\2\u0488\u0489\3\2\2\2\u0489\u048b\3\2\2\2") - buf.write("\u048a\u048c\5\u00b4[\2\u048b\u048a\3\2\2\2\u048b\u048c") - buf.write("\3\2\2\2\u048c\u048e\3\2\2\2\u048d\u048f\5\u00aeX\2\u048e") - buf.write("\u048d\3\2\2\2\u048e\u048f\3\2\2\2\u048f\u0490\3\2\2\2") - buf.write("\u0490\u0491\7\4\2\2\u0491\u04a4\3\2\2\2\u0492\u0493\7") - buf.write("D\2\2\u0493\u0494\7\3\2\2\u0494\u0496\5\6\4\2\u0495\u0497") - buf.write("\5\u00c6d\2\u0496\u0495\3\2\2\2\u0496\u0497\3\2\2\2\u0497") - buf.write("\u0499\3\2\2\2\u0498\u049a\5\u00c8e\2\u0499\u0498\3\2") - buf.write("\2\2\u0499\u049a\3\2\2\2\u049a\u049c\3\2\2\2\u049b\u049d") - buf.write("\5\u00b6\\\2\u049c\u049b\3\2\2\2\u049c\u049d\3\2\2\2\u049d") - buf.write("\u049f\3\2\2\2\u049e\u04a0\t\24\2\2\u049f\u049e\3\2\2") - buf.write("\2\u049f\u04a0\3\2\2\2\u04a0\u04a1\3\2\2\2\u04a1\u04a2") - buf.write("\7\4\2\2\u04a2\u04a4\3\2\2\2\u04a3\u0466\3\2\2\2\u04a3") - buf.write("\u047b\3\2\2\2\u04a3\u0492\3\2\2\2\u04a4A\3\2\2\2\u04a5") - buf.write("\u04a6\7s\2\2\u04a6\u04a7\7\3\2\2\u04a7\u04a8\5\6\4\2") - buf.write("\u04a8\u04a9\7\23\2\2\u04a9\u04aa\5\6\4\2\u04aa\u04ab") - buf.write("\7\4\2\2\u04abC\3\2\2\2\u04ac\u04ad\7s\2\2\u04ad\u04ae") - buf.write("\7\3\2\2\u04ae\u04af\5\b\5\2\u04af\u04b0\7\23\2\2\u04b0") - buf.write("\u04b1\5\b\5\2\u04b1\u04b2\7\4\2\2\u04b2E\3\2\2\2\u04b3") - buf.write("\u04b4\t\25\2\2\u04b4\u04b5\7\3\2\2\u04b5\u04b6\5\b\5") - buf.write("\2\u04b6\u04b7\7\4\2\2\u04b7\u04bc\3\2\2\2\u04b8\u04b9") - buf.write("\7h\2\2\u04b9\u04ba\7\3\2\2\u04ba\u04bc\7\4\2\2\u04bb") - buf.write("\u04b3\3\2\2\2\u04bb\u04b8\3\2\2\2\u04bcG\3\2\2\2\u04bd") - buf.write("\u04be\t\25\2\2\u04be\u04bf\7\3\2\2\u04bf\u04c4\5\6\4") - buf.write("\2\u04c0\u04c2\5r:\2\u04c1\u04c3\5t;\2\u04c2\u04c1\3\2") - buf.write("\2\2\u04c2\u04c3\3\2\2\2\u04c3\u04c5\3\2\2\2\u04c4\u04c0") - buf.write("\3\2\2\2\u04c4\u04c5\3\2\2\2\u04c5\u04c6\3\2\2\2\u04c6") - buf.write("\u04c7\7\4\2\2\u04c7I\3\2\2\2\u04c8\u04c9\t\26\2\2\u04c9") - buf.write("\u04ca\7\3\2\2\u04ca\u04cb\5\6\4\2\u04cb\u04cc\7\u009a") - buf.write("\2\2\u04cc\u04ce\7\3\2\2\u04cd\u04cf\5d\63\2\u04ce\u04cd") - buf.write("\3\2\2\2\u04ce\u04cf\3\2\2\2\u04cf\u04d1\3\2\2\2\u04d0") - buf.write("\u04d2\5f\64\2\u04d1\u04d0\3\2\2\2\u04d1\u04d2\3\2\2\2") - buf.write("\u04d2\u04d4\3\2\2\2\u04d3\u04d5\5j\66\2\u04d4\u04d3\3") - buf.write("\2\2\2\u04d4\u04d5\3\2\2\2\u04d5\u04d6\3\2\2\2\u04d6\u04d7") - buf.write("\7\4\2\2\u04d7\u04d8\7\4\2\2\u04d8\u04f8\3\2\2\2\u04d9") - buf.write("\u04da\t\27\2\2\u04da\u04db\7\3\2\2\u04db\u04e2\5\6\4") - buf.write("\2\u04dc\u04dd\7\23\2\2\u04dd\u04e0\5l\67\2\u04de\u04df") - buf.write("\7\23\2\2\u04df\u04e1\5X-\2\u04e0\u04de\3\2\2\2\u04e0") - buf.write("\u04e1\3\2\2\2\u04e1\u04e3\3\2\2\2\u04e2\u04dc\3\2\2\2") - buf.write("\u04e2\u04e3\3\2\2\2\u04e3\u04e4\3\2\2\2\u04e4\u04e5\7") - buf.write("\u009a\2\2\u04e5\u04e7\7\3\2\2\u04e6\u04e8\5d\63\2\u04e7") - buf.write("\u04e6\3\2\2\2\u04e7\u04e8\3\2\2\2\u04e8\u04e9\3\2\2\2") - buf.write("\u04e9\u04ea\5f\64\2\u04ea\u04eb\3\2\2\2\u04eb\u04ec\7") - buf.write("\4\2\2\u04ec\u04ed\7\4\2\2\u04ed\u04f8\3\2\2\2\u04ee\u04ef") - buf.write("\7\u0099\2\2\u04ef\u04f0\7\3\2\2\u04f0\u04f1\5\6\4\2\u04f1") - buf.write("\u04f2\7\u009a\2\2\u04f2\u04f3\7\3\2\2\u04f3\u04f4\5d") - buf.write("\63\2\u04f4\u04f5\7\4\2\2\u04f5\u04f6\7\4\2\2\u04f6\u04f8") - buf.write("\3\2\2\2\u04f7\u04c8\3\2\2\2\u04f7\u04d9\3\2\2\2\u04f7") - buf.write("\u04ee\3\2\2\2\u04f8K\3\2\2\2\u04f9\u04fa\t\26\2\2\u04fa") - buf.write("\u04fb\7\3\2\2\u04fb\u04fc\5\b\5\2\u04fc\u04fd\7\u009a") - buf.write("\2\2\u04fd\u04ff\7\3\2\2\u04fe\u0500\5d\63\2\u04ff\u04fe") - buf.write("\3\2\2\2\u04ff\u0500\3\2\2\2\u0500\u0502\3\2\2\2\u0501") - buf.write("\u0503\5f\64\2\u0502\u0501\3\2\2\2\u0502\u0503\3\2\2\2") - buf.write("\u0503\u0505\3\2\2\2\u0504\u0506\5j\66\2\u0505\u0504\3") - buf.write("\2\2\2\u0505\u0506\3\2\2\2\u0506\u0507\3\2\2\2\u0507\u0508") - buf.write("\7\4\2\2\u0508\u0509\7\4\2\2\u0509\u0534\3\2\2\2\u050a") - buf.write("\u050b\t\27\2\2\u050b\u050c\7\3\2\2\u050c\u0512\5\b\5") - buf.write("\2\u050d\u050e\7\23\2\2\u050e\u0510\5l\67\2\u050f\u0511") - buf.write("\5X-\2\u0510\u050f\3\2\2\2\u0510\u0511\3\2\2\2\u0511\u0513") - buf.write("\3\2\2\2\u0512\u050d\3\2\2\2\u0512\u0513\3\2\2\2\u0513") - buf.write("\u0514\3\2\2\2\u0514\u0515\7\u009a\2\2\u0515\u0517\7\3") - buf.write("\2\2\u0516\u0518\5d\63\2\u0517\u0516\3\2\2\2\u0517\u0518") - buf.write("\3\2\2\2\u0518\u0519\3\2\2\2\u0519\u051a\5f\64\2\u051a") - buf.write("\u051b\3\2\2\2\u051b\u051c\7\4\2\2\u051c\u051d\7\4\2\2") - buf.write("\u051d\u0534\3\2\2\2\u051e\u051f\7O\2\2\u051f\u0520\7") - buf.write("\3\2\2\u0520\u0521\7\u009a\2\2\u0521\u0523\7\3\2\2\u0522") - buf.write("\u0524\5d\63\2\u0523\u0522\3\2\2\2\u0523\u0524\3\2\2\2") - buf.write("\u0524\u0525\3\2\2\2\u0525\u0526\5f\64\2\u0526\u0527\3") - buf.write("\2\2\2\u0527\u0528\7\4\2\2\u0528\u0529\7\4\2\2\u0529\u0534") - buf.write("\3\2\2\2\u052a\u052b\7\u0099\2\2\u052b\u052c\7\3\2\2\u052c") - buf.write("\u052d\5\b\5\2\u052d\u052e\7\u009a\2\2\u052e\u052f\7\3") - buf.write("\2\2\u052f\u0530\5d\63\2\u0530\u0531\7\4\2\2\u0531\u0532") - buf.write("\7\4\2\2\u0532\u0534\3\2\2\2\u0533\u04f9\3\2\2\2\u0533") - buf.write("\u050a\3\2\2\2\u0533\u051e\3\2\2\2\u0533\u052a\3\2\2\2") - buf.write("\u0534M\3\2\2\2\u0535\u0536\5\u00c2b\2\u0536\u0537\7F") - buf.write("\2\2\u0537\u0538\5\u00c2b\2\u0538O\3\2\2\2\u0539\u053e") - buf.write("\5R*\2\u053a\u053b\7\23\2\2\u053b\u053d\5R*\2\u053c\u053a") - buf.write("\3\2\2\2\u053d\u0540\3\2\2\2\u053e\u053c\3\2\2\2\u053e") - buf.write("\u053f\3\2\2\2\u053fQ\3\2\2\2\u0540\u053e\3\2\2\2\u0541") - buf.write("\u0543\5\u00d0i\2\u0542\u0541\3\2\2\2\u0542\u0543\3\2") - buf.write("\2\2\u0543\u0544\3\2\2\2\u0544\u0545\5\u00c2b\2\u0545") - buf.write("\u0546\7\26\2\2\u0546\u0547\5F$\2\u0547S\3\2\2\2\u0548") - buf.write("\u054a\5\u00d0i\2\u0549\u0548\3\2\2\2\u0549\u054a\3\2") - buf.write("\2\2\u054a\u054b\3\2\2\2\u054b\u054c\5\u00c2b\2\u054c") - buf.write("\u054d\7\26\2\2\u054d\u054e\5\b\5\2\u054eU\3\2\2\2\u054f") - buf.write("\u0550\5\u00c2b\2\u0550\u0551\7\t\2\2\u0551\u0552\5X-") - buf.write("\2\u0552W\3\2\2\2\u0553\u0560\5\u00dan\2\u0554\u0555\7") - buf.write("\u00dc\2\2\u0555\u0556\7\3\2\2\u0556\u0557\5\u00dan\2") - buf.write("\u0557\u0558\7\23\2\2\u0558\u055b\5\u00dco\2\u0559\u055a") - buf.write("\7\23\2\2\u055a\u055c\7\u00f6\2\2\u055b\u0559\3\2\2\2") - buf.write("\u055b\u055c\3\2\2\2\u055c\u055d\3\2\2\2\u055d\u055e\7") - buf.write("\4\2\2\u055e\u0560\3\2\2\2\u055f\u0553\3\2\2\2\u055f\u0554") - buf.write("\3\2\2\2\u0560Y\3\2\2\2\u0561\u0566\5^\60\2\u0562\u0563") - buf.write("\7\23\2\2\u0563\u0565\5^\60\2\u0564\u0562\3\2\2\2\u0565") - buf.write("\u0568\3\2\2\2\u0566\u0564\3\2\2\2\u0566\u0567\3\2\2\2") - buf.write("\u0567[\3\2\2\2\u0568\u0566\3\2\2\2\u0569\u056e\5^\60") - buf.write("\2\u056a\u056b\7\23\2\2\u056b\u056d\5^\60\2\u056c\u056a") - buf.write("\3\2\2\2\u056d\u0570\3\2\2\2\u056e\u056c\3\2\2\2\u056e") - buf.write("\u056f\3\2\2\2\u056f\u057a\3\2\2\2\u0570\u056e\3\2\2\2") - buf.write("\u0571\u0572\7\35\2\2\u0572\u0577\5\u00c2b\2\u0573\u0574") - buf.write("\7\23\2\2\u0574\u0576\5\u00c2b\2\u0575\u0573\3\2\2\2\u0576") - buf.write("\u0579\3\2\2\2\u0577\u0575\3\2\2\2\u0577\u0578\3\2\2\2") - buf.write("\u0578\u057b\3\2\2\2\u0579\u0577\3\2\2\2\u057a\u0571\3") - buf.write("\2\2\2\u057a\u057b\3\2\2\2\u057b]\3\2\2\2\u057c\u057f") - buf.write("\5\6\4\2\u057d\u057e\7\60\2\2\u057e\u0580\5\u00bc_\2\u057f") - buf.write("\u057d\3\2\2\2\u057f\u0580\3\2\2\2\u0580_\3\2\2\2\u0581") - buf.write("\u0583\5\24\13\2\u0582\u0581\3\2\2\2\u0582\u0583\3\2\2") - buf.write("\2\u0583\u0587\3\2\2\2\u0584\u0588\5\26\f\2\u0585\u0588") - buf.write("\5b\62\2\u0586\u0588\5\22\n\2\u0587\u0584\3\2\2\2\u0587") - buf.write("\u0585\3\2\2\2\u0587\u0586\3\2\2\2\u0587\u0588\3\2\2\2") - buf.write("\u0588\u058a\3\2\2\2\u0589\u058b\5\30\r\2\u058a\u0589") - buf.write("\3\2\2\2\u058a\u058b\3\2\2\2\u058b\u058d\3\2\2\2\u058c") - buf.write("\u058e\5\20\t\2\u058d\u058c\3\2\2\2\u058d\u058e\3\2\2") - buf.write("\2\u058ea\3\2\2\2\u058f\u0590\7\u00d0\2\2\u0590\u0591") - buf.write("\5\6\4\2\u0591c\3\2\2\2\u0592\u0593\7\u009e\2\2\u0593") - buf.write("\u0594\7N\2\2\u0594\u0599\5\u00c2b\2\u0595\u0596\7\23") - buf.write("\2\2\u0596\u0598\5\u00c2b\2\u0597\u0595\3\2\2\2\u0598") - buf.write("\u059b\3\2\2\2\u0599\u0597\3\2\2\2\u0599\u059a\3\2\2\2") - buf.write("\u059ae\3\2\2\2\u059b\u0599\3\2\2\2\u059c\u059d\7M\2\2") - buf.write("\u059d\u059e\7N\2\2\u059e\u05a3\5h\65\2\u059f\u05a0\7") - buf.write("\23\2\2\u05a0\u05a2\5h\65\2\u05a1\u059f\3\2\2\2\u05a2") - buf.write("\u05a5\3\2\2\2\u05a3\u05a1\3\2\2\2\u05a3\u05a4\3\2\2\2") - buf.write("\u05a4g\3\2\2\2\u05a5\u05a3\3\2\2\2\u05a6\u05a8\5\u00c2") - buf.write("b\2\u05a7\u05a9\t\30\2\2\u05a8\u05a7\3\2\2\2\u05a8\u05a9") - buf.write("\3\2\2\2\u05a9i\3\2\2\2\u05aa\u05ab\7y\2\2\u05ab\u05ae") - buf.write("\7\u00be\2\2\u05ac\u05ae\7\u00a0\2\2\u05ad\u05aa\3\2\2") - buf.write("\2\u05ad\u05ac\3\2\2\2\u05ae\u05af\3\2\2\2\u05af\u05b0") - buf.write("\7\65\2\2\u05b0\u05b1\5p9\2\u05b1\u05b2\7\61\2\2\u05b2") - buf.write("\u05b3\5p9\2\u05b3k\3\2\2\2\u05b4\u05b6\t\31\2\2\u05b5") - buf.write("\u05b4\3\2\2\2\u05b5\u05b6\3\2\2\2\u05b6\u05b7\3\2\2\2") - buf.write("\u05b7\u05b8\7\u00f3\2\2\u05b8m\3\2\2\2\u05b9\u05bb\t") - buf.write("\31\2\2\u05ba\u05b9\3\2\2\2\u05ba\u05bb\3\2\2\2\u05bb") - buf.write("\u05bc\3\2\2\2\u05bc\u05bd\7\u00f4\2\2\u05bdo\3\2\2\2") - buf.write("\u05be\u05bf\5l\67\2\u05bf\u05c0\7\u009b\2\2\u05c0\u05cc") - buf.write("\3\2\2\2\u05c1\u05c2\5l\67\2\u05c2\u05c3\7\u009c\2\2\u05c3") - buf.write("\u05cc\3\2\2\2\u05c4\u05c5\7\u00a1\2\2\u05c5\u05c6\7y") - buf.write("\2\2\u05c6\u05cc\7\u00bf\2\2\u05c7\u05c8\7\u009d\2\2\u05c8") - buf.write("\u05cc\7\u009b\2\2\u05c9\u05ca\7\u009d\2\2\u05ca\u05cc") - buf.write("\7\u009c\2\2\u05cb\u05be\3\2\2\2\u05cb\u05c1\3\2\2\2\u05cb") - buf.write("\u05c4\3\2\2\2\u05cb\u05c7\3\2\2\2\u05cb\u05c9\3\2\2\2") - buf.write("\u05ccq\3\2\2\2\u05cd\u05ce\7\u0092\2\2\u05ce\u05cf\t") - buf.write("\32\2\2\u05cf\u05d4\5\u00c2b\2\u05d0\u05d1\7\23\2\2\u05d1") - buf.write("\u05d3\5\u00c2b\2\u05d2\u05d0\3\2\2\2\u05d3\u05d6\3\2") - buf.write("\2\2\u05d4\u05d2\3\2\2\2\u05d4\u05d5\3\2\2\2\u05d5\u05df") - buf.write("\3\2\2\2\u05d6\u05d4\3\2\2\2\u05d7\u05d8\7\u00d5\2\2\u05d8") - buf.write("\u05d9\7\3\2\2\u05d9\u05dc\7\u00f6\2\2\u05da\u05db\7\23") - buf.write("\2\2\u05db\u05dd\t\22\2\2\u05dc\u05da\3\2\2\2\u05dc\u05dd") - buf.write("\3\2\2\2\u05dd\u05de\3\2\2\2\u05de\u05e0\7\4\2\2\u05df") - buf.write("\u05d7\3\2\2\2\u05df\u05e0\3\2\2\2\u05e0\u05ee\3\2\2\2") - buf.write("\u05e1\u05e2\7\u0092\2\2\u05e2\u05eb\7J\2\2\u05e3\u05e4") - buf.write("\7\u00d5\2\2\u05e4\u05e5\7\3\2\2\u05e5\u05e8\7\u00f6\2") - buf.write("\2\u05e6\u05e7\7\23\2\2\u05e7\u05e9\t\22\2\2\u05e8\u05e6") - buf.write("\3\2\2\2\u05e8\u05e9\3\2\2\2\u05e9\u05ea\3\2\2\2\u05ea") - buf.write("\u05ec\7\4\2\2\u05eb\u05e3\3\2\2\2\u05eb\u05ec\3\2\2\2") - buf.write("\u05ec\u05ee\3\2\2\2\u05ed\u05cd\3\2\2\2\u05ed\u05e1\3") - buf.write("\2\2\2\u05ees\3\2\2\2\u05ef\u05f0\7\u0094\2\2\u05f0\u05f1") - buf.write("\5\b\5\2\u05f1u\3\2\2\2\u05f2\u05f3\5\u00be`\2\u05f3\u05f6") - buf.write("\5|?\2\u05f4\u05f5\7\u00df\2\2\u05f5\u05f7\5X-\2\u05f6") - buf.write("\u05f4\3\2\2\2\u05f6\u05f7\3\2\2\2\u05f7w\3\2\2\2\u05f8") - buf.write("\u05fc\5\u0080A\2\u05f9\u05fc\5\u0084C\2\u05fa\u05fc\5") - buf.write("\u0082B\2\u05fb\u05f8\3\2\2\2\u05fb\u05f9\3\2\2\2\u05fb") - buf.write("\u05fa\3\2\2\2\u05fcy\3\2\2\2\u05fd\u0600\5\u0082B\2\u05fe") - buf.write("\u0600\5\u0080A\2\u05ff\u05fd\3\2\2\2\u05ff\u05fe\3\2") - buf.write("\2\2\u0600{\3\2\2\2\u0601\u0607\5\u0080A\2\u0602\u0607") - buf.write("\5\u0084C\2\u0603\u0607\5\u0088E\2\u0604\u0607\5~@\2\u0605") - buf.write("\u0607\5\u0082B\2\u0606\u0601\3\2\2\2\u0606\u0602\3\2") - buf.write("\2\2\u0606\u0603\3\2\2\2\u0606\u0604\3\2\2\2\u0606\u0605") - buf.write("\3\2\2\2\u0607}\3\2\2\2\u0608\u060c\7\u0081\2\2\u0609") - buf.write("\u060c\5\u008aF\2\u060a\u060c\5\u008cG\2\u060b\u0608\3") - buf.write("\2\2\2\u060b\u0609\3\2\2\2\u060b\u060a\3\2\2\2\u060c\177") - buf.write("\3\2\2\2\u060d\u0610\5\u00dco\2\u060e\u0610\5\u008eH\2") - buf.write("\u060f\u060d\3\2\2\2\u060f\u060e\3\2\2\2\u0610\u0612\3") - buf.write("\2\2\2\u0611\u0613\5\u00a8U\2\u0612\u0611\3\2\2\2\u0612") - buf.write("\u0613\3\2\2\2\u0613\u0618\3\2\2\2\u0614\u0616\7\64\2") - buf.write("\2\u0615\u0614\3\2\2\2\u0615\u0616\3\2\2\2\u0616\u0617") - buf.write("\3\2\2\2\u0617\u0619\78\2\2\u0618\u0615\3\2\2\2\u0618") - buf.write("\u0619\3\2\2\2\u0619\u0081\3\2\2\2\u061a\u061f\5\u00d0") - buf.write("i\2\u061b\u061c\7\n\2\2\u061c\u061d\5\u0080A\2\u061d\u061e") - buf.write("\7\13\2\2\u061e\u0620\3\2\2\2\u061f\u061b\3\2\2\2\u061f") - buf.write("\u0620\3\2\2\2\u0620\u0083\3\2\2\2\u0621\u062d\7{\2\2") - buf.write("\u0622\u0623\7\7\2\2\u0623\u0628\5\u00aaV\2\u0624\u0625") - buf.write("\7\23\2\2\u0625\u0627\5\u00aaV\2\u0626\u0624\3\2\2\2\u0627") - buf.write("\u062a\3\2\2\2\u0628\u0626\3\2\2\2\u0628\u0629\3\2\2\2") - buf.write("\u0629\u062b\3\2\2\2\u062a\u0628\3\2\2\2\u062b\u062c\7") - buf.write("\b\2\2\u062c\u062e\3\2\2\2\u062d\u0622\3\2\2\2\u062d\u062e") - buf.write("\3\2\2\2\u062e\u0085\3\2\2\2\u062f\u0632\5\u0084C\2\u0630") - buf.write("\u0632\5\u0080A\2\u0631\u062f\3\2\2\2\u0631\u0630\3\2") - buf.write("\2\2\u0632\u0087\3\2\2\2\u0633\u0638\7\u00f1\2\2\u0634") - buf.write("\u0635\7\n\2\2\u0635\u0636\5\u0080A\2\u0636\u0637\7\13") - buf.write("\2\2\u0637\u0639\3\2\2\2\u0638\u0634\3\2\2\2\u0638\u0639") - buf.write("\3\2\2\2\u0639\u0089\3\2\2\2\u063a\u0658\7\177\2\2\u063b") - buf.write("\u0647\7\u00ed\2\2\u063c\u063d\7\7\2\2\u063d\u0642\5\u008e") - buf.write("H\2\u063e\u063f\7\21\2\2\u063f\u0641\5\u008eH\2\u0640") - buf.write("\u063e\3\2\2\2\u0641\u0644\3\2\2\2\u0642\u0640\3\2\2\2") - buf.write("\u0642\u0643\3\2\2\2\u0643\u0645\3\2\2\2\u0644\u0642\3") - buf.write("\2\2\2\u0645\u0646\7\b\2\2\u0646\u0648\3\2\2\2\u0647\u063c") - buf.write("\3\2\2\2\u0647\u0648\3\2\2\2\u0648\u0658\3\2\2\2\u0649") - buf.write("\u0655\7\u00ee\2\2\u064a\u064b\7\7\2\2\u064b\u0650\5\u00be") - buf.write("`\2\u064c\u064d\7\21\2\2\u064d\u064f\5\u00be`\2\u064e") - buf.write("\u064c\3\2\2\2\u064f\u0652\3\2\2\2\u0650\u064e\3\2\2\2") - buf.write("\u0650\u0651\3\2\2\2\u0651\u0653\3\2\2\2\u0652\u0650\3") - buf.write("\2\2\2\u0653\u0654\7\b\2\2\u0654\u0656\3\2\2\2\u0655\u064a") - buf.write("\3\2\2\2\u0655\u0656\3\2\2\2\u0656\u0658\3\2\2\2\u0657") - buf.write("\u063a\3\2\2\2\u0657\u063b\3\2\2\2\u0657\u0649\3\2\2\2") - buf.write("\u0658\u008b\3\2\2\2\u0659\u0682\7\u0080\2\2\u065a\u066b") - buf.write("\7\u00ef\2\2\u065b\u065c\7\7\2\2\u065c\u0668\7\u00f7\2") - buf.write("\2\u065d\u065e\7\3\2\2\u065e\u0663\5\u008eH\2\u065f\u0660") - buf.write("\7\21\2\2\u0660\u0662\5\u008eH\2\u0661\u065f\3\2\2\2\u0662") - buf.write("\u0665\3\2\2\2\u0663\u0661\3\2\2\2\u0663\u0664\3\2\2\2") - buf.write("\u0664\u0666\3\2\2\2\u0665\u0663\3\2\2\2\u0666\u0667\7") - buf.write("\4\2\2\u0667\u0669\3\2\2\2\u0668\u065d\3\2\2\2\u0668\u0669") - buf.write("\3\2\2\2\u0669\u066a\3\2\2\2\u066a\u066c\7\b\2\2\u066b") - buf.write("\u065b\3\2\2\2\u066b\u066c\3\2\2\2\u066c\u0682\3\2\2\2") - buf.write("\u066d\u067f\7\u00f0\2\2\u066e\u066f\7\7\2\2\u066f\u067b") - buf.write("\5\u00be`\2\u0670\u0671\7\3\2\2\u0671\u0676\5\u00be`\2") - buf.write("\u0672\u0673\7\21\2\2\u0673\u0675\5\u00be`\2\u0674\u0672") - buf.write("\3\2\2\2\u0675\u0678\3\2\2\2\u0676\u0674\3\2\2\2\u0676") - buf.write("\u0677\3\2\2\2\u0677\u0679\3\2\2\2\u0678\u0676\3\2\2\2") - buf.write("\u0679\u067a\7\4\2\2\u067a\u067c\3\2\2\2\u067b\u0670\3") - buf.write("\2\2\2\u067b\u067c\3\2\2\2\u067c\u067d\3\2\2\2\u067d\u067e") - buf.write("\7\b\2\2\u067e\u0680\3\2\2\2\u067f\u066e\3\2\2\2\u067f") - buf.write("\u0680\3\2\2\2\u0680\u0682\3\2\2\2\u0681\u0659\3\2\2\2") - buf.write("\u0681\u065a\3\2\2\2\u0681\u066d\3\2\2\2\u0682\u008d\3") - buf.write("\2\2\2\u0683\u0684\7\u00f7\2\2\u0684\u008f\3\2\2\2\u0685") - buf.write("\u0686\7\u00f7\2\2\u0686\u0091\3\2\2\2\u0687\u0688\t\33") - buf.write("\2\2\u0688\u068d\5\u0094K\2\u0689\u068a\7\23\2\2\u068a") - buf.write("\u068c\5\u0094K\2\u068b\u0689\3\2\2\2\u068c\u068f\3\2") - buf.write("\2\2\u068d\u068b\3\2\2\2\u068d\u068e\3\2\2\2\u068e\u0093") - buf.write("\3\2\2\2\u068f\u068d\3\2\2\2\u0690\u0693\5\u00be`\2\u0691") - buf.write("\u0692\7\60\2\2\u0692\u0694\5\u00bc_\2\u0693\u0691\3\2") - buf.write("\2\2\u0693\u0694\3\2\2\2\u0694\u0095\3\2\2\2\u0695\u069a") - buf.write("\5\u0098M\2\u0696\u0697\7\u00f9\2\2\u0697\u0699\5\u0098") - buf.write("M\2\u0698\u0696\3\2\2\2\u0699\u069c\3\2\2\2\u069a\u0698") - buf.write("\3\2\2\2\u069a\u069b\3\2\2\2\u069b\u0097\3\2\2\2\u069c") - buf.write("\u069a\3\2\2\2\u069d\u069e\7\u00f7\2\2\u069e\u06a0\7\25") - buf.write("\2\2\u069f\u069d\3\2\2\2\u069f\u06a0\3\2\2\2\u06a0\u06a5") - buf.write("\3\2\2\2\u06a1\u06a2\7\u00bb\2\2\u06a2\u06a3\5\b\5\2\u06a3") - buf.write("\u06a4\7\33\2\2\u06a4\u06a6\3\2\2\2\u06a5\u06a1\3\2\2") - buf.write("\2\u06a5\u06a6\3\2\2\2\u06a6\u06a7\3\2\2\2\u06a7\u06a9") - buf.write("\5\b\5\2\u06a8\u06aa\5\u00c6d\2\u06a9\u06a8\3\2\2\2\u06a9") - buf.write("\u06aa\3\2\2\2\u06aa\u06ac\3\2\2\2\u06ab\u06ad\5\u00c8") - buf.write("e\2\u06ac\u06ab\3\2\2\2\u06ac\u06ad\3\2\2\2\u06ad\u0099") - buf.write("\3\2\2\2\u06ae\u06b3\5\u009cO\2\u06af\u06b0\7\u00f9\2") - buf.write("\2\u06b0\u06b2\5\u009cO\2\u06b1\u06af\3\2\2\2\u06b2\u06b5") - buf.write("\3\2\2\2\u06b3\u06b1\3\2\2\2\u06b3\u06b4\3\2\2\2\u06b4") - buf.write("\u009b\3\2\2\2\u06b5\u06b3\3\2\2\2\u06b6\u06b7\7\u00f7") - buf.write("\2\2\u06b7\u06b9\7\25\2\2\u06b8\u06b6\3\2\2\2\u06b8\u06b9") - buf.write("\3\2\2\2\u06b9\u06ba\3\2\2\2\u06ba\u06bc\5\u00a2R\2\u06bb") - buf.write("\u06bd\5\u00c6d\2\u06bc\u06bb\3\2\2\2\u06bc\u06bd\3\2") - buf.write("\2\2\u06bd\u06bf\3\2\2\2\u06be\u06c0\5\u00c8e\2\u06bf") - buf.write("\u06be\3\2\2\2\u06bf\u06c0\3\2\2\2\u06c0\u009d\3\2\2\2") - buf.write("\u06c1\u06c4\t\33\2\2\u06c2\u06c3\7\u00a9\2\2\u06c3\u06c5") - buf.write("\5\u00a0Q\2\u06c4\u06c2\3\2\2\2\u06c4\u06c5\3\2\2\2\u06c5") - buf.write("\u06c6\3\2\2\2\u06c6\u06c7\7\u0082\2\2\u06c7\u06c8\7\u00f7") - buf.write("\2\2\u06c8\u009f\3\2\2\2\u06c9\u06ce\5\u0094K\2\u06ca") - buf.write("\u06cb\7\23\2\2\u06cb\u06cd\5\u0094K\2\u06cc\u06ca\3\2") - buf.write("\2\2\u06cd\u06d0\3\2\2\2\u06ce\u06cc\3\2\2\2\u06ce\u06cf") - buf.write("\3\2\2\2\u06cf\u00a1\3\2\2\2\u06d0\u06ce\3\2\2\2\u06d1") - buf.write("\u06d2\7\u00bb\2\2\u06d2\u06d3\5\b\5\2\u06d3\u06d4\7\33") - buf.write("\2\2\u06d4\u06d6\3\2\2\2\u06d5\u06d1\3\2\2\2\u06d5\u06d6") - buf.write("\3\2\2\2\u06d6\u06d7\3\2\2\2\u06d7\u06d9\5\u00a6T\2\u06d8") - buf.write("\u06da\5\u00caf\2\u06d9\u06d8\3\2\2\2\u06d9\u06da\3\2") - buf.write("\2\2\u06da\u06db\3\2\2\2\u06db\u06df\5\u00a4S\2\u06dc") - buf.write("\u06de\5\u00a4S\2\u06dd\u06dc\3\2\2\2\u06de\u06e1\3\2") - buf.write("\2\2\u06df\u06dd\3\2\2\2\u06df\u06e0\3\2\2\2\u06e0\u00a3") - buf.write("\3\2\2\2\u06e1\u06df\3\2\2\2\u06e2\u06e4\t\31\2\2\u06e3") - buf.write("\u06e2\3\2\2\2\u06e3\u06e4\3\2\2\2\u06e4\u06e5\3\2\2\2") - buf.write("\u06e5\u06ea\5\u00a6T\2\u06e6\u06e7\7\5\2\2\u06e7\u06e8") - buf.write("\5\b\5\2\u06e8\u06e9\7\6\2\2\u06e9\u06eb\3\2\2\2\u06ea") - buf.write("\u06e6\3\2\2\2\u06ea\u06eb\3\2\2\2\u06eb\u00a5\3\2\2\2") - buf.write("\u06ec\u06f0\7\u00f7\2\2\u06ed\u06f0\5l\67\2\u06ee\u06f0") - buf.write("\5n8\2\u06ef\u06ec\3\2\2\2\u06ef\u06ed\3\2\2\2\u06ef\u06ee") - buf.write("\3\2\2\2\u06f0\u00a7\3\2\2\2\u06f1\u06f2\7\5\2\2\u06f2") - buf.write("\u06f3\5\b\5\2\u06f3\u06f4\7\6\2\2\u06f4\u0701\3\2\2\2") - buf.write("\u06f5\u06f6\7\7\2\2\u06f6\u06fb\5X-\2\u06f7\u06f8\7\23") - buf.write("\2\2\u06f8\u06fa\5X-\2\u06f9\u06f7\3\2\2\2\u06fa\u06fd") - buf.write("\3\2\2\2\u06fb\u06f9\3\2\2\2\u06fb\u06fc\3\2\2\2\u06fc") - buf.write("\u06fe\3\2\2\2\u06fd\u06fb\3\2\2\2\u06fe\u06ff\7\b\2\2") - buf.write("\u06ff\u0701\3\2\2\2\u0700\u06f1\3\2\2\2\u0700\u06f5\3") - buf.write("\2\2\2\u0701\u00a9\3\2\2\2\u0702\u0705\5\u0082B\2\u0703") - buf.write("\u0706\5\u00c2b\2\u0704\u0706\5\u00acW\2\u0705\u0703\3") - buf.write("\2\2\2\u0705\u0704\3\2\2\2\u0706\u00ab\3\2\2\2\u0707\u0709") - buf.write("\7u\2\2\u0708\u070a\t\34\2\2\u0709\u0708\3\2\2\2\u0709") - buf.write("\u070a\3\2\2\2\u070a\u00ad\3\2\2\2\u070b\u070c\t\35\2") - buf.write("\2\u070c\u00af\3\2\2\2\u070d\u070e\t\36\2\2\u070e\u00b1") - buf.write("\3\2\2\2\u070f\u0710\7\u00a9\2\2\u0710\u0715\5\u00c2b") - buf.write("\2\u0711\u0712\7\23\2\2\u0712\u0714\5\u00c2b\2\u0713\u0711") - buf.write("\3\2\2\2\u0714\u0717\3\2\2\2\u0715\u0713\3\2\2\2\u0715") - buf.write("\u0716\3\2\2\2\u0716\u00b3\3\2\2\2\u0717\u0715\3\2\2\2") - buf.write("\u0718\u0719\t\37\2\2\u0719\u00b5\3\2\2\2\u071a\u071b") - buf.write("\7H\2\2\u071b\u071c\5\6\4\2\u071c\u00b7\3\2\2\2\u071d") - buf.write("\u071e\t \2\2\u071e\u00b9\3\2\2\2\u071f\u0720\t!\2\2\u0720") - buf.write("\u00bb\3\2\2\2\u0721\u0722\7\u00f7\2\2\u0722\u00bd\3\2") - buf.write("\2\2\u0723\u0724\7\u00f7\2\2\u0724\u00bf\3\2\2\2\u0725") - buf.write("\u0726\7\u00f7\2\2\u0726\u00c1\3\2\2\2\u0727\u072a\7\u00f7") - buf.write("\2\2\u0728\u0729\7\27\2\2\u0729\u072b\7\u00f7\2\2\u072a") - buf.write("\u0728\3\2\2\2\u072a\u072b\3\2\2\2\u072b\u00c3\3\2\2\2") - buf.write("\u072c\u072d\7\7\2\2\u072d\u0732\5X-\2\u072e\u072f\7\23") - buf.write("\2\2\u072f\u0731\5X-\2\u0730\u072e\3\2\2\2\u0731\u0734") - buf.write("\3\2\2\2\u0732\u0730\3\2\2\2\u0732\u0733\3\2\2\2\u0733") - buf.write("\u0735\3\2\2\2\u0734\u0732\3\2\2\2\u0735\u0736\7\b\2\2") - buf.write("\u0736\u00c5\3\2\2\2\u0737\u0738\7I\2\2\u0738\u0739\5") - buf.write("\u00dan\2\u0739\u00c7\3\2\2\2\u073a\u073b\7L\2\2\u073b") - buf.write('\u073c\5\u00dan\2\u073c\u00c9\3\2\2\2\u073d\u073e\t"') - buf.write("\2\2\u073e\u00cb\3\2\2\2\u073f\u0742\5\6\4\2\u0740\u0742") - buf.write("\7u\2\2\u0741\u073f\3\2\2\2\u0741\u0740\3\2\2\2\u0742") - buf.write("\u00cd\3\2\2\2\u0743\u0746\5\b\5\2\u0744\u0746\7u\2\2") - buf.write("\u0745\u0743\3\2\2\2\u0745\u0744\3\2\2\2\u0746\u00cf\3") - buf.write("\2\2\2\u0747\u074d\7j\2\2\u0748\u074d\7\u00ec\2\2\u0749") - buf.write("\u074d\7i\2\2\u074a\u074d\7k\2\2\u074b\u074d\5\u00d2j") - buf.write("\2\u074c\u0747\3\2\2\2\u074c\u0748\3\2\2\2\u074c\u0749") - buf.write("\3\2\2\2\u074c\u074a\3\2\2\2\u074c\u074b\3\2\2\2\u074d") - buf.write("\u00d1\3\2\2\2\u074e\u074f\7p\2\2\u074f\u0750\7k\2\2\u0750") - buf.write("\u00d3\3\2\2\2\u0751\u0752\7\u00f7\2\2\u0752\u00d5\3\2") - buf.write("\2\2\u0753\u0754\7\u00f7\2\2\u0754\u00d7\3\2\2\2\u0755") - buf.write("\u0756\7\u00f7\2\2\u0756\u00d9\3\2\2\2\u0757\u075d\5l") - buf.write("\67\2\u0758\u075d\5n8\2\u0759\u075d\7\u00f5\2\2\u075a") - buf.write("\u075d\7\u00f6\2\2\u075b\u075d\78\2\2\u075c\u0757\3\2") - buf.write("\2\2\u075c\u0758\3\2\2\2\u075c\u0759\3\2\2\2\u075c\u075a") - buf.write("\3\2\2\2\u075c\u075b\3\2\2\2\u075d\u00db\3\2\2\2\u075e") - buf.write("\u075f\t#\2\2\u075f\u00dd\3\2\2\2\u0760\u0761\t$\2\2\u0761") - buf.write("\u00df\3\2\2\2\u00cc\u00e5\u00f3\u010c\u0113\u0131\u0133") - buf.write("\u0135\u014f\u0156\u016c\u016e\u0170\u017b\u0189\u0192") - buf.write("\u019a\u01a1\u01a3\u01ae\u01b7\u01c9\u01d2\u01e1\u01ec") - buf.write("\u01ef\u01f4\u0215\u021e\u0221\u022b\u0230\u0234\u023a") - buf.write("\u023e\u0248\u024c\u0250\u0259\u025c\u0266\u026a\u0274") - buf.write("\u0279\u027d\u0283\u0287\u028b\u028f\u0293\u02a3\u02a7") - buf.write("\u02b2\u02bd\u02c1\u02c5\u02d5\u02d9\u02e4\u02ef\u02f3") - buf.write("\u02f7\u0303\u030e\u031a\u0325\u0343\u0347\u035e\u0363") - buf.write("\u036b\u0380\u0384\u0388\u03c6\u03cb\u03d3\u03e8\u03ec") - buf.write("\u03f0\u042e\u0437\u0442\u044d\u0455\u0459\u045c\u045f") - buf.write("\u0462\u0471\u0474\u0477\u0481\u0485\u0488\u048b\u048e") - buf.write("\u0496\u0499\u049c\u049f\u04a3\u04bb\u04c2\u04c4\u04ce") - buf.write("\u04d1\u04d4\u04e0\u04e2\u04e7\u04f7\u04ff\u0502\u0505") - buf.write("\u0510\u0512\u0517\u0523\u0533\u053e\u0542\u0549\u055b") - buf.write("\u055f\u0566\u056e\u0577\u057a\u057f\u0582\u0587\u058a") - buf.write("\u058d\u0599\u05a3\u05a8\u05ad\u05b5\u05ba\u05cb\u05d4") - buf.write("\u05dc\u05df\u05e8\u05eb\u05ed\u05f6\u05fb\u05ff\u0606") - buf.write("\u060b\u060f\u0612\u0615\u0618\u061f\u0628\u062d\u0631") - buf.write("\u0638\u0642\u0647\u0650\u0655\u0657\u0663\u0668\u066b") - buf.write("\u0676\u067b\u067f\u0681\u068d\u0693\u069a\u069f\u06a5") - buf.write("\u06a9\u06ac\u06b3\u06b8\u06bc\u06bf\u06c4\u06ce\u06d5") - buf.write("\u06d9\u06df\u06e3\u06ea\u06ef\u06fb\u0700\u0705\u0709") - buf.write("\u0715\u072a\u0732\u0741\u0745\u074c\u075c") + buf.write("\u00da\u00dc\u00de\u00e0\u00e2\u00e4\u00e6\2&\4\2\17\20") + buf.write("\64\64\3\2\21\22\4\2\17\20``\3\2\62\63\3\2\66\67\3\2+") + buf.write(",\4\2\u00cd\u00cd\u00cf\u00cf\3\2\u00c4\u00c5\3\2\u00c6") + buf.write("\u00c7\4\2RSef\5\2__ac\u0086\u0087\6\2WWYYnn\u008a\u008c") + buf.write("\3\2[\\\5\2??ZZ]^\4\2JJ\u00d4\u00d4\3\2\u00a5\u00a6\4") + buf.write("\2vv\u00f7\u00f7\3\2TU\4\2==\u008e\u008e\4\2JJww\5\2R") + buf.write("Seh\u008f\u0092\6\2RSeh\u008f\u0092\u0096\u0097\3\2\u0098") + buf.write("\u0099\3\2PQ\3\2\17\20\4\2NN\u0094\u0094\3\2xy\4\2\17") + buf.write("\17\21\21\5\2JJww\u00eb\u00eb\3\2\u00e4\u00e9\4\2||\u00df") + buf.write("\u00df\5\2||\u0083\u0083\u00de\u00de\4\2JJ\u00e3\u00e3") + buf.write("\3\2\t\16\5\2\u00ab\u00b1\u00d5\u00d5\u00ec\u00ec\4\2") + buf.write("JJ\u00f6\u00f6\2\u0863\2\u00ed\3\2\2\2\4\u00fb\3\2\2\2") + buf.write("\6\u011b\3\2\2\2\b\u015e\3\2\2\2\n\u0183\3\2\2\2\f\u0191") + buf.write("\3\2\2\2\16\u019a\3\2\2\2\20\u019c\3\2\2\2\22\u01a5\3") + buf.write("\2\2\2\24\u01ad\3\2\2\2\26\u01b0\3\2\2\2\30\u01b9\3\2") + buf.write("\2\2\32\u01c2\3\2\2\2\34\u01c7\3\2\2\2\36\u01d4\3\2\2") + buf.write('\2 \u01e9\3\2\2\2"\u022a\3\2\2\2$\u0230\3\2\2\2&\u0232') + buf.write("\3\2\2\2(\u0247\3\2\2\2*\u0249\3\2\2\2,\u0287\3\2\2\2") + buf.write(".\u02c2\3\2\2\2\60\u02c6\3\2\2\2\62\u02ca\3\2\2\2\64\u02fc") + buf.write("\3\2\2\2\66\u032e\3\2\2\28\u0345\3\2\2\2:\u035c\3\2\2") + buf.write("\2<\u037e\3\2\2\2>\u0395\3\2\2\2@\u03fd\3\2\2\2B\u0465") + buf.write("\3\2\2\2D\u0484\3\2\2\2F\u0486\3\2\2\2H\u04da\3\2\2\2") + buf.write("J\u04dc\3\2\2\2L\u04e3\3\2\2\2N\u04f2\3\2\2\2P\u04f4\3") + buf.write("\2\2\2R\u052e\3\2\2\2T\u056a\3\2\2\2V\u056c\3\2\2\2X\u0570") + buf.write("\3\2\2\2Z\u0579\3\2\2\2\\\u0580\3\2\2\2^\u0586\3\2\2\2") + buf.write("`\u0596\3\2\2\2b\u0598\3\2\2\2d\u05a0\3\2\2\2f\u05b3\3") + buf.write("\2\2\2h\u05b9\3\2\2\2j\u05c6\3\2\2\2l\u05c9\3\2\2\2n\u05d3") + buf.write("\3\2\2\2p\u05dd\3\2\2\2r\u05e4\3\2\2\2t\u05ec\3\2\2\2") + buf.write("v\u05f1\3\2\2\2x\u0602\3\2\2\2z\u0624\3\2\2\2|\u0626\3") + buf.write("\2\2\2~\u0629\3\2\2\2\u0080\u0632\3\2\2\2\u0082\u0636") + buf.write("\3\2\2\2\u0084\u063d\3\2\2\2\u0086\u0642\3\2\2\2\u0088") + buf.write("\u0646\3\2\2\2\u008a\u0651\3\2\2\2\u008c\u0658\3\2\2\2") + buf.write("\u008e\u0668\3\2\2\2\u0090\u066a\3\2\2\2\u0092\u068e\3") + buf.write("\2\2\2\u0094\u06b8\3\2\2\2\u0096\u06ba\3\2\2\2\u0098\u06bc") + buf.write("\3\2\2\2\u009a\u06be\3\2\2\2\u009c\u06c7\3\2\2\2\u009e") + buf.write("\u06cc\3\2\2\2\u00a0\u06d6\3\2\2\2\u00a2\u06e5\3\2\2\2") + buf.write("\u00a4\u06ef\3\2\2\2\u00a6\u06f8\3\2\2\2\u00a8\u0700\3") + buf.write("\2\2\2\u00aa\u070c\3\2\2\2\u00ac\u071a\3\2\2\2\u00ae\u0726") + buf.write("\3\2\2\2\u00b0\u0737\3\2\2\2\u00b2\u0739\3\2\2\2\u00b4") + buf.write("\u073e\3\2\2\2\u00b6\u0742\3\2\2\2\u00b8\u0744\3\2\2\2") + buf.write("\u00ba\u0746\3\2\2\2\u00bc\u074f\3\2\2\2\u00be\u0751\3") + buf.write("\2\2\2\u00c0\u0754\3\2\2\2\u00c2\u0756\3\2\2\2\u00c4\u0758") + buf.write("\3\2\2\2\u00c6\u075a\3\2\2\2\u00c8\u075c\3\2\2\2\u00ca") + buf.write("\u075e\3\2\2\2\u00cc\u0763\3\2\2\2\u00ce\u076e\3\2\2\2") + buf.write("\u00d0\u0771\3\2\2\2\u00d2\u0774\3\2\2\2\u00d4\u0778\3") + buf.write("\2\2\2\u00d6\u077c\3\2\2\2\u00d8\u0783\3\2\2\2\u00da\u0785") + buf.write("\3\2\2\2\u00dc\u0788\3\2\2\2\u00de\u078a\3\2\2\2\u00e0") + buf.write("\u078c\3\2\2\2\u00e2\u0793\3\2\2\2\u00e4\u0795\3\2\2\2") + buf.write("\u00e6\u0797\3\2\2\2\u00e8\u00e9\5\4\3\2\u00e9\u00ea\7") + buf.write("\u00fa\2\2\u00ea\u00ec\3\2\2\2\u00eb\u00e8\3\2\2\2\u00ec") + buf.write("\u00ef\3\2\2\2\u00ed\u00eb\3\2\2\2\u00ed\u00ee\3\2\2\2") + buf.write("\u00ee\u00f0\3\2\2\2\u00ef\u00ed\3\2\2\2\u00f0\u00f1\7") + buf.write("\2\2\3\u00f1\3\3\2\2\2\u00f2\u00f3\5\u00c6d\2\u00f3\u00f4") + buf.write("\7\26\2\2\u00f4\u00f5\5\6\4\2\u00f5\u00fc\3\2\2\2\u00f6") + buf.write("\u00f7\5\u00c6d\2\u00f7\u00f8\7\177\2\2\u00f8\u00f9\5") + buf.write('\6\4\2\u00f9\u00fc\3\2\2\2\u00fa\u00fc\5"\22\2\u00fb') + buf.write("\u00f2\3\2\2\2\u00fb\u00f6\3\2\2\2\u00fb\u00fa\3\2\2\2") + buf.write("\u00fc\5\3\2\2\2\u00fd\u00fe\b\4\1\2\u00fe\u00ff\7\3\2") + buf.write("\2\u00ff\u0100\5\6\4\2\u0100\u0101\7\4\2\2\u0101\u011c") + buf.write("\3\2\2\2\u0102\u011c\5\f\7\2\u0103\u0104\t\2\2\2\u0104") + buf.write("\u011c\5\6\4\r\u0105\u0106\7\31\2\2\u0106\u0107\5\6\4") + buf.write("\2\u0107\u0108\7\33\2\2\u0108\u0109\5\6\4\2\u0109\u010a") + buf.write("\7\34\2\2\u010a\u010b\5\6\4\6\u010b\u011c\3\2\2\2\u010c") + buf.write("\u0112\7\32\2\2\u010d\u010e\7\u00bc\2\2\u010e\u010f\5") + buf.write("\6\4\2\u010f\u0110\7\33\2\2\u0110\u0111\5\6\4\2\u0111") + buf.write("\u0113\3\2\2\2\u0112\u010d\3\2\2\2\u0113\u0114\3\2\2\2") + buf.write("\u0114\u0112\3\2\2\2\u0114\u0115\3\2\2\2\u0115\u0116\3") + buf.write("\2\2\2\u0116\u0117\7\34\2\2\u0117\u0118\5\6\4\5\u0118") + buf.write("\u011c\3\2\2\2\u0119\u011c\5\u00e2r\2\u011a\u011c\5\u00c6") + buf.write("d\2\u011b\u00fd\3\2\2\2\u011b\u0102\3\2\2\2\u011b\u0103") + buf.write("\3\2\2\2\u011b\u0105\3\2\2\2\u011b\u010c\3\2\2\2\u011b") + buf.write("\u0119\3\2\2\2\u011b\u011a\3\2\2\2\u011c\u013d\3\2\2\2") + buf.write("\u011d\u011e\f\f\2\2\u011e\u011f\t\3\2\2\u011f\u013c\5") + buf.write("\6\4\r\u0120\u0121\f\13\2\2\u0121\u0122\t\4\2\2\u0122") + buf.write("\u013c\5\6\4\f\u0123\u0124\f\n\2\2\u0124\u0125\5\u00d2") + buf.write("j\2\u0125\u0126\5\6\4\13\u0126\u013c\3\2\2\2\u0127\u0128") + buf.write("\f\b\2\2\u0128\u0129\7\61\2\2\u0129\u013c\5\6\4\t\u012a") + buf.write("\u012b\f\7\2\2\u012b\u012c\t\5\2\2\u012c\u013c\5\6\4\b") + buf.write("\u012d\u012e\f\17\2\2\u012e\u012f\7\5\2\2\u012f\u0130") + buf.write("\5\16\b\2\u0130\u0131\7\6\2\2\u0131\u013c\3\2\2\2\u0132") + buf.write("\u0133\f\16\2\2\u0133\u0134\7\27\2\2\u0134\u013c\5\u00c8") + buf.write("e\2\u0135\u0136\f\t\2\2\u0136\u0139\t\6\2\2\u0137\u013a") + buf.write("\5\u00ccg\2\u0138\u013a\5\u00dco\2\u0139\u0137\3\2\2\2") + buf.write("\u0139\u0138\3\2\2\2\u013a\u013c\3\2\2\2\u013b\u011d\3") + buf.write("\2\2\2\u013b\u0120\3\2\2\2\u013b\u0123\3\2\2\2\u013b\u0127") + buf.write("\3\2\2\2\u013b\u012a\3\2\2\2\u013b\u012d\3\2\2\2\u013b") + buf.write("\u0132\3\2\2\2\u013b\u0135\3\2\2\2\u013c\u013f\3\2\2\2") + buf.write("\u013d\u013b\3\2\2\2\u013d\u013e\3\2\2\2\u013e\7\3\2\2") + buf.write("\2\u013f\u013d\3\2\2\2\u0140\u0141\b\5\1\2\u0141\u0142") + buf.write("\7\3\2\2\u0142\u0143\5\b\5\2\u0143\u0144\7\4\2\2\u0144") + buf.write("\u015f\3\2\2\2\u0145\u015f\5\n\6\2\u0146\u0147\t\2\2\2") + buf.write("\u0147\u015f\5\b\5\r\u0148\u0149\7\31\2\2\u0149\u014a") + buf.write("\5\b\5\2\u014a\u014b\7\33\2\2\u014b\u014c\5\b\5\2\u014c") + buf.write("\u014d\7\34\2\2\u014d\u014e\5\b\5\6\u014e\u015f\3\2\2") + buf.write("\2\u014f\u0155\7\32\2\2\u0150\u0151\7\u00bc\2\2\u0151") + buf.write("\u0152\5\b\5\2\u0152\u0153\7\33\2\2\u0153\u0154\5\b\5") + buf.write("\2\u0154\u0156\3\2\2\2\u0155\u0150\3\2\2\2\u0156\u0157") + buf.write("\3\2\2\2\u0157\u0155\3\2\2\2\u0157\u0158\3\2\2\2\u0158") + buf.write("\u0159\3\2\2\2\u0159\u015a\7\34\2\2\u015a\u015b\5\b\5") + buf.write("\5\u015b\u015f\3\2\2\2\u015c\u015f\5\u00e2r\2\u015d\u015f") + buf.write("\5\u00caf\2\u015e\u0140\3\2\2\2\u015e\u0145\3\2\2\2\u015e") + buf.write("\u0146\3\2\2\2\u015e\u0148\3\2\2\2\u015e\u014f\3\2\2\2") + buf.write("\u015e\u015c\3\2\2\2\u015e\u015d\3\2\2\2\u015f\u0178\3") + buf.write("\2\2\2\u0160\u0161\f\f\2\2\u0161\u0162\t\3\2\2\u0162\u0177") + buf.write("\5\b\5\r\u0163\u0164\f\13\2\2\u0164\u0165\t\4\2\2\u0165") + buf.write("\u0177\5\b\5\f\u0166\u0167\f\n\2\2\u0167\u0168\5\u00d2") + buf.write("j\2\u0168\u0169\5\b\5\13\u0169\u0177\3\2\2\2\u016a\u016b") + buf.write("\f\b\2\2\u016b\u016c\7\61\2\2\u016c\u0177\5\b\5\t\u016d") + buf.write("\u016e\f\7\2\2\u016e\u016f\t\5\2\2\u016f\u0177\5\b\5\b") + buf.write("\u0170\u0171\f\t\2\2\u0171\u0174\t\6\2\2\u0172\u0175\5") + buf.write("\u00ccg\2\u0173\u0175\5\u00dco\2\u0174\u0172\3\2\2\2\u0174") + buf.write("\u0173\3\2\2\2\u0175\u0177\3\2\2\2\u0176\u0160\3\2\2\2") + buf.write("\u0176\u0163\3\2\2\2\u0176\u0166\3\2\2\2\u0176\u016a\3") + buf.write("\2\2\2\u0176\u016d\3\2\2\2\u0176\u0170\3\2\2\2\u0177\u017a") + buf.write("\3\2\2\2\u0178\u0176\3\2\2\2\u0178\u0179\3\2\2\2\u0179") + buf.write("\t\3\2\2\2\u017a\u0178\3\2\2\2\u017b\u0184\5.\30\2\u017c") + buf.write("\u0184\5\66\34\2\u017d\u0184\5:\36\2\u017e\u0184\5> \2") + buf.write("\u017f\u0184\5B\"\2\u0180\u0184\5L'\2\u0181\u0184\5N") + buf.write("(\2\u0182\u0184\5T+\2\u0183\u017b\3\2\2\2\u0183\u017c") + buf.write("\3\2\2\2\u0183\u017d\3\2\2\2\u0183\u017e\3\2\2\2\u0183") + buf.write("\u017f\3\2\2\2\u0183\u0180\3\2\2\2\u0183\u0181\3\2\2\2") + buf.write("\u0183\u0182\3\2\2\2\u0184\13\3\2\2\2\u0185\u0192\5 \21") + buf.write("\2\u0186\u0192\5,\27\2\u0187\u0192\5\64\33\2\u0188\u0192") + buf.write("\58\35\2\u0189\u0192\5<\37\2\u018a\u0192\5@!\2\u018b\u0192") + buf.write("\5D#\2\u018c\u0192\5F$\2\u018d\u0192\5H%\2\u018e\u0192") + buf.write("\5J&\2\u018f\u0192\5P)\2\u0190\u0192\5R*\2\u0191\u0185") + buf.write("\3\2\2\2\u0191\u0186\3\2\2\2\u0191\u0187\3\2\2\2\u0191") + buf.write("\u0188\3\2\2\2\u0191\u0189\3\2\2\2\u0191\u018a\3\2\2\2") + buf.write("\u0191\u018b\3\2\2\2\u0191\u018c\3\2\2\2\u0191\u018d\3") + buf.write("\2\2\2\u0191\u018e\3\2\2\2\u0191\u018f\3\2\2\2\u0191\u0190") + buf.write("\3\2\2\2\u0192\r\3\2\2\2\u0193\u019b\5\20\t\2\u0194\u019b") + buf.write("\5\22\n\2\u0195\u019b\5\24\13\2\u0196\u019b\5\26\f\2\u0197") + buf.write("\u019b\5\30\r\2\u0198\u019b\5\32\16\2\u0199\u019b\5\36") + buf.write("\20\2\u019a\u0193\3\2\2\2\u019a\u0194\3\2\2\2\u019a\u0195") + buf.write("\3\2\2\2\u019a\u0196\3\2\2\2\u019a\u0197\3\2\2\2\u019a") + buf.write("\u0198\3\2\2\2\u019a\u0199\3\2\2\2\u019b\17\3\2\2\2\u019c") + buf.write("\u019d\7/\2\2\u019d\u01a2\5V,\2\u019e\u019f\7\23\2\2\u019f") + buf.write("\u01a1\5V,\2\u01a0\u019e\3\2\2\2\u01a1\u01a4\3\2\2\2\u01a2") + buf.write("\u01a0\3\2\2\2\u01a2\u01a3\3\2\2\2\u01a3\21\3\2\2\2\u01a4") + buf.write("\u01a2\3\2\2\2\u01a5\u01a6\7K\2\2\u01a6\u01ab\5X-\2\u01a7") + buf.write("\u01a9\5z>\2\u01a8\u01aa\5|?\2\u01a9\u01a8\3\2\2\2\u01a9") + buf.write("\u01aa\3\2\2\2\u01aa\u01ac\3\2\2\2\u01ab\u01a7\3\2\2\2") + buf.write("\u01ab\u01ac\3\2\2\2\u01ac\23\3\2\2\2\u01ad\u01ae\7l\2") + buf.write("\2\u01ae\u01af\5\b\5\2\u01af\25\3\2\2\2\u01b0\u01b1\7") + buf.write("-\2\2\u01b1\u01b6\5\\/\2\u01b2\u01b3\7\23\2\2\u01b3\u01b5") + buf.write("\5\\/\2\u01b4\u01b2\3\2\2\2\u01b5\u01b8\3\2\2\2\u01b6") + buf.write("\u01b4\3\2\2\2\u01b6\u01b7\3\2\2\2\u01b7\27\3\2\2\2\u01b8") + buf.write("\u01b6\3\2\2\2\u01b9\u01ba\t\7\2\2\u01ba\u01bf\5\u00ca") + buf.write("f\2\u01bb\u01bc\7\23\2\2\u01bc\u01be\5\u00caf\2\u01bd") + buf.write("\u01bb\3\2\2\2\u01be\u01c1\3\2\2\2\u01bf\u01bd\3\2\2\2") + buf.write("\u01bf\u01c0\3\2\2\2\u01c0\31\3\2\2\2\u01c1\u01bf\3\2") + buf.write("\2\2\u01c2\u01c3\t\b\2\2\u01c3\u01c4\5\u00caf\2\u01c4") + buf.write("\u01c5\7\23\2\2\u01c5\u01c6\5\u00caf\2\u01c6\33\3\2\2") + buf.write("\2\u01c7\u01c8\7\u00ce\2\2\u01c8\u01c9\5\u00caf\2\u01c9") + buf.write("\u01ca\7\23\2\2\u01ca\u01cb\5\u00caf\2\u01cb\u01cc\7\66") + buf.write("\2\2\u01cc\u01d1\5\u00e2r\2\u01cd\u01ce\7\23\2\2\u01ce") + buf.write("\u01d0\5\u00e2r\2\u01cf\u01cd\3\2\2\2\u01d0\u01d3\3\2") + buf.write("\2\2\u01d1\u01cf\3\2\2\2\u01d1\u01d2\3\2\2\2\u01d2\35") + buf.write("\3\2\2\2\u01d3\u01d1\3\2\2\2\u01d4\u01d5\7\u00d0\2\2\u01d5") + buf.write("\u01da\5^\60\2\u01d6\u01d7\7\23\2\2\u01d7\u01d9\5^\60") + buf.write("\2\u01d8\u01d6\3\2\2\2\u01d9\u01dc\3\2\2\2\u01da\u01d8") + buf.write("\3\2\2\2\u01da\u01db\3\2\2\2\u01db\37\3\2\2\2\u01dc\u01da") + buf.write("\3\2\2\2\u01dd\u01de\t\t\2\2\u01de\u01df\7\3\2\2\u01df") + buf.write("\u01e0\5d\63\2\u01e0\u01e1\5h\65\2\u01e1\u01e2\7\4\2\2") + buf.write("\u01e2\u01ea\3\2\2\2\u01e3\u01e4\t\n\2\2\u01e4\u01e5\7") + buf.write("\3\2\2\u01e5\u01e6\5b\62\2\u01e6\u01e7\5h\65\2\u01e7\u01e8") + buf.write("\7\4\2\2\u01e8\u01ea\3\2\2\2\u01e9\u01dd\3\2\2\2\u01e9") + buf.write("\u01e3\3\2\2\2\u01ea!\3\2\2\2\u01eb\u01ec\7~\2\2\u01ec") + buf.write("\u01ed\7}\2\2\u01ed\u01ee\5\u00dep\2\u01ee\u01f7\7\3\2") + buf.write("\2\u01ef\u01f4\5~@\2\u01f0\u01f1\7\23\2\2\u01f1\u01f3") + buf.write("\5~@\2\u01f2\u01f0\3\2\2\2\u01f3\u01f6\3\2\2\2\u01f4\u01f2") + buf.write("\3\2\2\2\u01f4\u01f5\3\2\2\2\u01f5\u01f8\3\2\2\2\u01f6") + buf.write("\u01f4\3\2\2\2\u01f7\u01ef\3\2\2\2\u01f7\u01f8\3\2\2\2") + buf.write("\u01f8\u01f9\3\2\2\2\u01f9\u01fc\7\4\2\2\u01fa\u01fb\7") + buf.write("\u00cc\2\2\u01fb\u01fd\5\u0080A\2\u01fc\u01fa\3\2\2\2") + buf.write("\u01fc\u01fd\3\2\2\2\u01fd\u01fe\3\2\2\2\u01fe\u01ff\7") + buf.write("\u00bb\2\2\u01ff\u0200\5\6\4\2\u0200\u0201\7\u0084\2\2") + buf.write("\u0201\u0202\7}\2\2\u0202\u022b\3\2\2\2\u0203\u0204\7") + buf.write("~\2\2\u0204\u0205\7\u0080\2\2\u0205\u0206\7\u0082\2\2") + buf.write("\u0206\u0207\5\u0098M\2\u0207\u0208\7\3\2\2\u0208\u0209") + buf.write("\5\u009aN\2\u0209\u020a\7\4\2\2\u020a\u020b\7\u00bb\2") + buf.write("\2\u020b\u020c\5\u009eP\2\u020c\u020d\7\u0084\2\2\u020d") + buf.write("\u020e\7\u0080\2\2\u020e\u020f\7\u0082\2\2\u020f\u022b") + buf.write("\3\2\2\2\u0210\u0211\7~\2\2\u0211\u0212\7\u0081\2\2\u0212") + buf.write("\u0213\7\u0082\2\2\u0213\u0214\5\u0098M\2\u0214\u0215") + buf.write("\7\3\2\2\u0215\u0216\5\u00a6T\2\u0216\u0217\7\4\2\2\u0217") + buf.write("\u0218\7\u00bb\2\2\u0218\u0219\5\u00a2R\2\u0219\u021a") + buf.write("\7\u0084\2\2\u021a\u021b\7\u0081\2\2\u021b\u021c\7\u0082") + buf.write("\2\2\u021c\u022b\3\2\2\2\u021d\u021e\7~\2\2\u021e\u021f") + buf.write("\7p\2\2\u021f\u0220\7q\2\2\u0220\u0221\5\u00c6d\2\u0221") + buf.write("\u0222\7\3\2\2\u0222\u0223\5$\23\2\u0223\u0224\7\4\2\2") + buf.write("\u0224\u0225\7\u00bb\2\2\u0225\u0226\5&\24\2\u0226\u0227") + buf.write("\7\u0084\2\2\u0227\u0228\7p\2\2\u0228\u0229\7q\2\2\u0229") + buf.write("\u022b\3\2\2\2\u022a\u01eb\3\2\2\2\u022a\u0203\3\2\2\2") + buf.write("\u022a\u0210\3\2\2\2\u022a\u021d\3\2\2\2\u022b#\3\2\2") + buf.write("\2\u022c\u022d\7x\2\2\u022d\u0231\5\u00c6d\2\u022e\u022f") + buf.write("\7y\2\2\u022f\u0231\5\u00c6d\2\u0230\u022c\3\2\2\2\u0230") + buf.write("\u022e\3\2\2\2\u0231%\3\2\2\2\u0232\u0237\5(\25\2\u0233") + buf.write("\u0234\7\u00fa\2\2\u0234\u0236\5(\25\2\u0235\u0233\3\2") + buf.write("\2\2\u0236\u0239\3\2\2\2\u0237\u0235\3\2\2\2\u0237\u0238") + buf.write("\3\2\2\2\u0238'\3\2\2\2\u0239\u0237\3\2\2\2\u023a\u023b") + buf.write("\7\u00f8\2\2\u023b\u023d\7\25\2\2\u023c\u023a\3\2\2\2") + buf.write("\u023c\u023d\3\2\2\2\u023d\u023e\3\2\2\2\u023e\u023f\7") + buf.write("\u00bc\2\2\u023f\u0240\5*\26\2\u0240\u0241\7\33\2\2\u0241") + buf.write("\u0242\5\u00e2r\2\u0242\u0248\3\2\2\2\u0243\u0244\7K\2") + buf.write("\2\u0244\u0248\t\13\2\2\u0245\u0246\7\34\2\2\u0246\u0248") + buf.write("\5\u00e2r\2\u0247\u023c\3\2\2\2\u0247\u0243\3\2\2\2\u0247") + buf.write("\u0245\3\2\2\2\u0248)\3\2\2\2\u0249\u024c\5\u00e2r\2\u024a") + buf.write("\u024b\7\61\2\2\u024b\u024d\5\u00e2r\2\u024c\u024a\3\2") + buf.write("\2\2\u024c\u024d\3\2\2\2\u024d+\3\2\2\2\u024e\u024f\5") + buf.write("\u00dep\2\u024f\u0258\7\3\2\2\u0250\u0255\5\62\32\2\u0251") + buf.write("\u0252\7\23\2\2\u0252\u0254\5\62\32\2\u0253\u0251\3\2") + buf.write("\2\2\u0254\u0257\3\2\2\2\u0255\u0253\3\2\2\2\u0255\u0256") + buf.write("\3\2\2\2\u0256\u0259\3\2\2\2\u0257\u0255\3\2\2\2\u0258") + buf.write("\u0250\3\2\2\2\u0258\u0259\3\2\2\2\u0259\u025a\3\2\2\2") + buf.write("\u025a\u025b\7\4\2\2\u025b\u0288\3\2\2\2\u025c\u025d\7") + buf.write("\30\2\2\u025d\u025e\7\3\2\2\u025e\u025f\5\u00e0q\2\u025f") + buf.write("\u0262\7\3\2\2\u0260\u0263\5\u00c6d\2\u0261\u0263\5`\61") + buf.write("\2\u0262\u0260\3\2\2\2\u0262\u0261\3\2\2\2\u0262\u0263") + buf.write("\3\2\2\2\u0263\u026b\3\2\2\2\u0264\u0267\7\23\2\2\u0265") + buf.write("\u0268\5\u00c6d\2\u0266\u0268\5`\61\2\u0267\u0265\3\2") + buf.write("\2\2\u0267\u0266\3\2\2\2\u0268\u026a\3\2\2\2\u0269\u0264") + buf.write("\3\2\2\2\u026a\u026d\3\2\2\2\u026b\u0269\3\2\2\2\u026b") + buf.write("\u026c\3\2\2\2\u026c\u026e\3\2\2\2\u026d\u026b\3\2\2\2") + buf.write("\u026e\u0271\7\4\2\2\u026f\u0270\7\u00f3\2\2\u0270\u0272") + buf.write("\7\u00f7\2\2\u0271\u026f\3\2\2\2\u0271\u0272\3\2\2\2\u0272") + buf.write("\u0275\3\2\2\2\u0273\u0274\7\u00cc\2\2\u0274\u0276\5\u008e") + buf.write("H\2\u0275\u0273\3\2\2\2\u0275\u0276\3\2\2\2\u0276\u0277") + buf.write("\3\2\2\2\u0277\u0278\7\4\2\2\u0278\u0288\3\2\2\2\u0279") + buf.write("\u027a\7\u00dd\2\2\u027a\u027b\7\3\2\2\u027b\u027c\5\6") + buf.write("\4\2\u027c\u027f\7\23\2\2\u027d\u0280\5\u00e4s\2\u027e") + buf.write("\u0280\5\u0096L\2\u027f\u027d\3\2\2\2\u027f\u027e\3\2") + buf.write("\2\2\u0280\u0283\3\2\2\2\u0281\u0282\7\23\2\2\u0282\u0284") + buf.write("\7\u00f7\2\2\u0283\u0281\3\2\2\2\u0283\u0284\3\2\2\2\u0284") + buf.write("\u0285\3\2\2\2\u0285\u0286\7\4\2\2\u0286\u0288\3\2\2\2") + buf.write("\u0287\u024e\3\2\2\2\u0287\u025c\3\2\2\2\u0287\u0279\3") + buf.write("\2\2\2\u0288-\3\2\2\2\u0289\u028a\5\u00dep\2\u028a\u0293") + buf.write("\7\3\2\2\u028b\u0290\5\60\31\2\u028c\u028d\7\23\2\2\u028d") + buf.write("\u028f\5\60\31\2\u028e\u028c\3\2\2\2\u028f\u0292\3\2\2") + buf.write("\2\u0290\u028e\3\2\2\2\u0290\u0291\3\2\2\2\u0291\u0294") + buf.write("\3\2\2\2\u0292\u0290\3\2\2\2\u0293\u028b\3\2\2\2\u0293") + buf.write("\u0294\3\2\2\2\u0294\u0295\3\2\2\2\u0295\u0296\7\4\2\2") + buf.write("\u0296\u02c3\3\2\2\2\u0297\u0298\7\u00dd\2\2\u0298\u0299") + buf.write("\7\3\2\2\u0299\u029a\5\b\5\2\u029a\u029d\7\23\2\2\u029b") + buf.write("\u029e\5\u00e4s\2\u029c\u029e\5\u0096L\2\u029d\u029b\3") + buf.write("\2\2\2\u029d\u029c\3\2\2\2\u029e\u02a1\3\2\2\2\u029f\u02a0") + buf.write("\7\23\2\2\u02a0\u02a2\7\u00f7\2\2\u02a1\u029f\3\2\2\2") + buf.write("\u02a1\u02a2\3\2\2\2\u02a2\u02a3\3\2\2\2\u02a3\u02a4\7") + buf.write("\4\2\2\u02a4\u02c3\3\2\2\2\u02a5\u02a6\7\30\2\2\u02a6") + buf.write("\u02a7\7\3\2\2\u02a7\u02a8\5\u00e0q\2\u02a8\u02ab\7\3") + buf.write("\2\2\u02a9\u02ac\5\u00caf\2\u02aa\u02ac\5`\61\2\u02ab") + buf.write("\u02a9\3\2\2\2\u02ab\u02aa\3\2\2\2\u02ab\u02ac\3\2\2\2") + buf.write("\u02ac\u02b4\3\2\2\2\u02ad\u02b0\7\23\2\2\u02ae\u02b1") + buf.write("\5\u00caf\2\u02af\u02b1\5`\61\2\u02b0\u02ae\3\2\2\2\u02b0") + buf.write("\u02af\3\2\2\2\u02b1\u02b3\3\2\2\2\u02b2\u02ad\3\2\2\2") + buf.write("\u02b3\u02b6\3\2\2\2\u02b4\u02b2\3\2\2\2\u02b4\u02b5\3") + buf.write("\2\2\2\u02b5\u02b7\3\2\2\2\u02b6\u02b4\3\2\2\2\u02b7\u02ba") + buf.write("\7\4\2\2\u02b8\u02b9\7\u00f3\2\2\u02b9\u02bb\7\u00f7\2") + buf.write("\2\u02ba\u02b8\3\2\2\2\u02ba\u02bb\3\2\2\2\u02bb\u02be") + buf.write("\3\2\2\2\u02bc\u02bd\7\u00cc\2\2\u02bd\u02bf\5\u0082B") + buf.write("\2\u02be\u02bc\3\2\2\2\u02be\u02bf\3\2\2\2\u02bf\u02c0") + buf.write("\3\2\2\2\u02c0\u02c1\7\4\2\2\u02c1\u02c3\3\2\2\2\u02c2") + buf.write("\u0289\3\2\2\2\u02c2\u0297\3\2\2\2\u02c2\u02a5\3\2\2\2") + buf.write("\u02c3/\3\2\2\2\u02c4\u02c7\5\b\5\2\u02c5\u02c7\7v\2\2") + buf.write("\u02c6\u02c4\3\2\2\2\u02c6\u02c5\3\2\2\2\u02c7\61\3\2") + buf.write("\2\2\u02c8\u02cb\5\6\4\2\u02c9\u02cb\7v\2\2\u02ca\u02c8") + buf.write("\3\2\2\2\u02ca\u02c9\3\2\2\2\u02cb\63\3\2\2\2\u02cc\u02cd") + buf.write("\t\f\2\2\u02cd\u02ce\7\3\2\2\u02ce\u02cf\5\6\4\2\u02cf") + buf.write("\u02d0\7\4\2\2\u02d0\u02fd\3\2\2\2\u02d1\u02d2\7d\2\2") + buf.write("\u02d2\u02d3\7\3\2\2\u02d3\u02de\5\6\4\2\u02d4\u02d5\7") + buf.write("\23\2\2\u02d5\u02d6\5\u00d4k\2\u02d6\u02d7\3\2\2\2\u02d7") + buf.write("\u02d8\7\23\2\2\u02d8\u02d9\5\u00d4k\2\u02d9\u02db\3\2") + buf.write("\2\2\u02da\u02d4\3\2\2\2\u02da\u02db\3\2\2\2\u02db\u02df") + buf.write("\3\2\2\2\u02dc\u02dd\7\23\2\2\u02dd\u02df\5\u00d4k\2\u02de") + buf.write("\u02da\3\2\2\2\u02de\u02dc\3\2\2\2\u02df\u02e0\3\2\2\2") + buf.write("\u02e0\u02e1\7\4\2\2\u02e1\u02fd\3\2\2\2\u02e2\u02e3\7") + buf.write("\u0089\2\2\u02e3\u02e4\7\3\2\2\u02e4\u02e5\5\6\4\2\u02e5") + buf.write("\u02e6\7\23\2\2\u02e6\u02e9\5\6\4\2\u02e7\u02e8\7\23\2") + buf.write("\2\u02e8\u02ea\5\u00d4k\2\u02e9\u02e7\3\2\2\2\u02e9\u02ea") + buf.write("\3\2\2\2\u02ea\u02eb\3\2\2\2\u02eb\u02ec\7\4\2\2\u02ec") + buf.write("\u02fd\3\2\2\2\u02ed\u02ee\7\u0088\2\2\u02ee\u02ef\7\3") + buf.write("\2\2\u02ef\u02f0\5\6\4\2\u02f0\u02f1\7\23\2\2\u02f1\u02f4") + buf.write("\5\6\4\2\u02f2\u02f3\7\23\2\2\u02f3\u02f5\5\u00d4k\2\u02f4") + buf.write("\u02f2\3\2\2\2\u02f4\u02f5\3\2\2\2\u02f5\u02f8\3\2\2\2") + buf.write("\u02f6\u02f7\7\23\2\2\u02f7\u02f9\5\u00d4k\2\u02f8\u02f6") + buf.write("\3\2\2\2\u02f8\u02f9\3\2\2\2\u02f9\u02fa\3\2\2\2\u02fa") + buf.write("\u02fb\7\4\2\2\u02fb\u02fd\3\2\2\2\u02fc\u02cc\3\2\2\2") + buf.write("\u02fc\u02d1\3\2\2\2\u02fc\u02e2\3\2\2\2\u02fc\u02ed\3") + buf.write("\2\2\2\u02fd\65\3\2\2\2\u02fe\u02ff\t\f\2\2\u02ff\u0300") + buf.write("\7\3\2\2\u0300\u0301\5\b\5\2\u0301\u0302\7\4\2\2\u0302") + buf.write("\u032f\3\2\2\2\u0303\u0304\7d\2\2\u0304\u0305\7\3\2\2") + buf.write("\u0305\u0310\5\b\5\2\u0306\u0307\7\23\2\2\u0307\u0308") + buf.write("\5\u00d6l\2\u0308\u0309\3\2\2\2\u0309\u030a\7\23\2\2\u030a") + buf.write("\u030b\5\u00d6l\2\u030b\u030d\3\2\2\2\u030c\u0306\3\2") + buf.write("\2\2\u030c\u030d\3\2\2\2\u030d\u0311\3\2\2\2\u030e\u030f") + buf.write("\7\23\2\2\u030f\u0311\5\u00d6l\2\u0310\u030c\3\2\2\2\u0310") + buf.write("\u030e\3\2\2\2\u0311\u0312\3\2\2\2\u0312\u0313\7\4\2\2") + buf.write("\u0313\u032f\3\2\2\2\u0314\u0315\7\u0089\2\2\u0315\u0316") + buf.write("\7\3\2\2\u0316\u0317\5\b\5\2\u0317\u0318\7\23\2\2\u0318") + buf.write("\u031b\5\b\5\2\u0319\u031a\7\23\2\2\u031a\u031c\5\u00d6") + buf.write("l\2\u031b\u0319\3\2\2\2\u031b\u031c\3\2\2\2\u031c\u031d") + buf.write("\3\2\2\2\u031d\u031e\7\4\2\2\u031e\u032f\3\2\2\2\u031f") + buf.write("\u0320\7\u0088\2\2\u0320\u0321\7\3\2\2\u0321\u0322\5\b") + buf.write("\5\2\u0322\u0323\7\23\2\2\u0323\u0326\5\b\5\2\u0324\u0325") + buf.write("\7\23\2\2\u0325\u0327\5\u00d6l\2\u0326\u0324\3\2\2\2\u0326") + buf.write("\u0327\3\2\2\2\u0327\u032a\3\2\2\2\u0328\u0329\7\23\2") + buf.write("\2\u0329\u032b\5\u00d6l\2\u032a\u0328\3\2\2\2\u032a\u032b") + buf.write("\3\2\2\2\u032b\u032c\3\2\2\2\u032c\u032d\7\4\2\2\u032d") + buf.write("\u032f\3\2\2\2\u032e\u02fe\3\2\2\2\u032e\u0303\3\2\2\2") + buf.write("\u032e\u0314\3\2\2\2\u032e\u031f\3\2\2\2\u032f\67\3\2") + buf.write("\2\2\u0330\u0331\t\r\2\2\u0331\u0332\7\3\2\2\u0332\u0333") + buf.write("\5\6\4\2\u0333\u0334\7\4\2\2\u0334\u0346\3\2\2\2\u0335") + buf.write("\u0336\t\16\2\2\u0336\u0337\7\3\2\2\u0337\u033a\5\6\4") + buf.write("\2\u0338\u0339\7\23\2\2\u0339\u033b\5\u00d4k\2\u033a\u0338") + buf.write("\3\2\2\2\u033a\u033b\3\2\2\2\u033b\u033c\3\2\2\2\u033c") + buf.write("\u033d\7\4\2\2\u033d\u0346\3\2\2\2\u033e\u033f\t\17\2") + buf.write("\2\u033f\u0340\7\3\2\2\u0340\u0341\5\6\4\2\u0341\u0342") + buf.write("\7\23\2\2\u0342\u0343\5\6\4\2\u0343\u0344\7\4\2\2\u0344") + buf.write("\u0346\3\2\2\2\u0345\u0330\3\2\2\2\u0345\u0335\3\2\2\2") + buf.write("\u0345\u033e\3\2\2\2\u03469\3\2\2\2\u0347\u0348\t\r\2") + buf.write("\2\u0348\u0349\7\3\2\2\u0349\u034a\5\b\5\2\u034a\u034b") + buf.write("\7\4\2\2\u034b\u035d\3\2\2\2\u034c\u034d\t\16\2\2\u034d") + buf.write("\u034e\7\3\2\2\u034e\u0351\5\b\5\2\u034f\u0350\7\23\2") + buf.write("\2\u0350\u0352\5\u00d6l\2\u0351\u034f\3\2\2\2\u0351\u0352") + buf.write("\3\2\2\2\u0352\u0353\3\2\2\2\u0353\u0354\7\4\2\2\u0354") + buf.write("\u035d\3\2\2\2\u0355\u0356\t\17\2\2\u0356\u0357\7\3\2") + buf.write("\2\u0357\u0358\5\b\5\2\u0358\u0359\7\23\2\2\u0359\u035a") + buf.write("\5\b\5\2\u035a\u035b\7\4\2\2\u035b\u035d\3\2\2\2\u035c") + buf.write("\u0347\3\2\2\2\u035c\u034c\3\2\2\2\u035c\u0355\3\2\2\2") + buf.write("\u035d;\3\2\2\2\u035e\u035f\7\65\2\2\u035f\u0360\7\3\2") + buf.write("\2\u0360\u0361\5\6\4\2\u0361\u0362\7\23\2\2\u0362\u0363") + buf.write("\5\6\4\2\u0363\u0364\7\23\2\2\u0364\u0365\5\6\4\2\u0365") + buf.write("\u0366\7\4\2\2\u0366\u037f\3\2\2\2\u0367\u0368\7r\2\2") + buf.write("\u0368\u0369\7\3\2\2\u0369\u036a\5\6\4\2\u036a\u036b\7") + buf.write("\23\2\2\u036b\u036c\5\6\4\2\u036c\u036d\7\4\2\2\u036d") + buf.write("\u037f\3\2\2\2\u036e\u036f\79\2\2\u036f\u0370\7\3\2\2") + buf.write("\u0370\u0371\5\6\4\2\u0371\u0372\7\4\2\2\u0372\u037f\3") + buf.write("\2\2\2\u0373\u0374\7E\2\2\u0374\u0375\7\3\2\2\u0375\u0376") + buf.write("\5\6\4\2\u0376\u0377\7\23\2\2\u0377\u037a\5\6\4\2\u0378") + buf.write("\u0379\7\23\2\2\u0379\u037b\5\u00e6t\2\u037a\u0378\3\2") + buf.write("\2\2\u037a\u037b\3\2\2\2\u037b\u037c\3\2\2\2\u037c\u037d") + buf.write("\7\4\2\2\u037d\u037f\3\2\2\2\u037e\u035e\3\2\2\2\u037e") + buf.write("\u0367\3\2\2\2\u037e\u036e\3\2\2\2\u037e\u0373\3\2\2\2") + buf.write("\u037f=\3\2\2\2\u0380\u0381\7\65\2\2\u0381\u0382\7\3\2") + buf.write("\2\u0382\u0383\5\b\5\2\u0383\u0384\7\23\2\2\u0384\u0385") + buf.write("\5\b\5\2\u0385\u0386\7\23\2\2\u0386\u0387\5\b\5\2\u0387") + buf.write("\u0388\7\4\2\2\u0388\u0396\3\2\2\2\u0389\u038a\7r\2\2") + buf.write("\u038a\u038b\7\3\2\2\u038b\u038c\5\b\5\2\u038c\u038d\7") + buf.write("\23\2\2\u038d\u038e\5\b\5\2\u038e\u038f\7\4\2\2\u038f") + buf.write("\u0396\3\2\2\2\u0390\u0391\79\2\2\u0391\u0392\7\3\2\2") + buf.write("\u0392\u0393\5\b\5\2\u0393\u0394\7\4\2\2\u0394\u0396\3") + buf.write("\2\2\2\u0395\u0380\3\2\2\2\u0395\u0389\3\2\2\2\u0395\u0390") + buf.write("\3\2\2\2\u0396?\3\2\2\2\u0397\u0398\7\u00d3\2\2\u0398") + buf.write("\u039a\7\3\2\2\u0399\u039b\5\6\4\2\u039a\u0399\3\2\2\2") + buf.write("\u039a\u039b\3\2\2\2\u039b\u039c\3\2\2\2\u039c\u03fe\7") + buf.write("\4\2\2\u039d\u039e\7\u00a4\2\2\u039e\u039f\7\3\2\2\u039f") + buf.write("\u03a2\5\6\4\2\u03a0\u03a1\7\23\2\2\u03a1\u03a3\t\20\2") + buf.write("\2\u03a2\u03a0\3\2\2\2\u03a2\u03a3\3\2\2\2\u03a3\u03a4") + buf.write("\3\2\2\2\u03a4\u03a5\7\4\2\2\u03a5\u03fe\3\2\2\2\u03a6") + buf.write("\u03a7\t\21\2\2\u03a7\u03a8\7\3\2\2\u03a8\u03a9\5\6\4") + buf.write("\2\u03a9\u03aa\7\4\2\2\u03aa\u03fe\3\2\2\2\u03ab\u03ac") + buf.write("\7\u00a7\2\2\u03ac\u03ad\7\3\2\2\u03ad\u03ae\5\6\4\2\u03ae") + buf.write("\u03af\7\23\2\2\u03af\u03b0\5t;\2\u03b0\u03b1\7\4\2\2") + buf.write("\u03b1\u03fe\3\2\2\2\u03b2\u03b3\7\u00d6\2\2\u03b3\u03b4") + buf.write("\7\3\2\2\u03b4\u03b7\7\u00f7\2\2\u03b5\u03b6\7\23\2\2") + buf.write("\u03b6\u03b8\t\22\2\2\u03b7\u03b5\3\2\2\2\u03b7\u03b8") + buf.write("\3\2\2\2\u03b8\u03bb\3\2\2\2\u03b9\u03ba\7\23\2\2\u03ba") + buf.write("\u03bc\5\u00d4k\2\u03bb\u03b9\3\2\2\2\u03bb\u03bc\3\2") + buf.write("\2\2\u03bc\u03bf\3\2\2\2\u03bd\u03be\7\23\2\2\u03be\u03c0") + buf.write("\t\23\2\2\u03bf\u03bd\3\2\2\2\u03bf\u03c0\3\2\2\2\u03c0") + buf.write("\u03c1\3\2\2\2\u03c1\u03fe\7\4\2\2\u03c2\u03c3\7\37\2") + buf.write("\2\u03c3\u03c4\7\3\2\2\u03c4\u03fe\7\4\2\2\u03c5\u03c6") + buf.write("\7 \2\2\u03c6\u03c7\7\3\2\2\u03c7\u03c8\5\6\4\2\u03c8") + buf.write("\u03c9\7\23\2\2\u03c9\u03ca\5\6\4\2\u03ca\u03cb\7\4\2") + buf.write("\2\u03cb\u03fe\3\2\2\2\u03cc\u03cd\7!\2\2\u03cd\u03ce") + buf.write("\7\3\2\2\u03ce\u03cf\5\6\4\2\u03cf\u03d0\7\23\2\2\u03d0") + buf.write("\u03d1\5\6\4\2\u03d1\u03d2\7\23\2\2\u03d2\u03d3\5\6\4") + buf.write("\2\u03d3\u03d4\7\4\2\2\u03d4\u03fe\3\2\2\2\u03d5\u03d6") + buf.write('\7"\2\2\u03d6\u03d7\7\3\2\2\u03d7\u03d8\5\6\4\2\u03d8') + buf.write("\u03d9\7\4\2\2\u03d9\u03fe\3\2\2\2\u03da\u03db\7#\2\2") + buf.write("\u03db\u03dc\7\3\2\2\u03dc\u03dd\5\6\4\2\u03dd\u03de\7") + buf.write("\4\2\2\u03de\u03fe\3\2\2\2\u03df\u03e0\7$\2\2\u03e0\u03e1") + buf.write("\7\3\2\2\u03e1\u03e2\5\6\4\2\u03e2\u03e3\7\4\2\2\u03e3") + buf.write("\u03fe\3\2\2\2\u03e4\u03e5\7%\2\2\u03e5\u03e6\7\3\2\2") + buf.write("\u03e6\u03e7\5\6\4\2\u03e7\u03e8\7\4\2\2\u03e8\u03fe\3") + buf.write("\2\2\2\u03e9\u03ea\7&\2\2\u03ea\u03eb\7\3\2\2\u03eb\u03ec") + buf.write("\5\6\4\2\u03ec\u03ed\7\4\2\2\u03ed\u03fe\3\2\2\2\u03ee") + buf.write("\u03ef\7'\2\2\u03ef\u03f0\7\3\2\2\u03f0\u03f1\5\6\4\2") + buf.write("\u03f1\u03f2\7\4\2\2\u03f2\u03fe\3\2\2\2\u03f3\u03f4\7") + buf.write("(\2\2\u03f4\u03f5\7\3\2\2\u03f5\u03f6\5\6\4\2\u03f6\u03f7") + buf.write("\7\4\2\2\u03f7\u03fe\3\2\2\2\u03f8\u03f9\7)\2\2\u03f9") + buf.write("\u03fa\7\3\2\2\u03fa\u03fb\5\6\4\2\u03fb\u03fc\7\4\2\2") + buf.write("\u03fc\u03fe\3\2\2\2\u03fd\u0397\3\2\2\2\u03fd\u039d\3") + buf.write("\2\2\2\u03fd\u03a6\3\2\2\2\u03fd\u03ab\3\2\2\2\u03fd\u03b2") + buf.write("\3\2\2\2\u03fd\u03c2\3\2\2\2\u03fd\u03c5\3\2\2\2\u03fd") + buf.write("\u03cc\3\2\2\2\u03fd\u03d5\3\2\2\2\u03fd\u03da\3\2\2\2") + buf.write("\u03fd\u03df\3\2\2\2\u03fd\u03e4\3\2\2\2\u03fd\u03e9\3") + buf.write("\2\2\2\u03fd\u03ee\3\2\2\2\u03fd\u03f3\3\2\2\2\u03fd\u03f8") + buf.write("\3\2\2\2\u03feA\3\2\2\2\u03ff\u0400\7\u00d3\2\2\u0400") + buf.write("\u0402\7\3\2\2\u0401\u0403\5\b\5\2\u0402\u0401\3\2\2\2") + buf.write("\u0402\u0403\3\2\2\2\u0403\u0404\3\2\2\2\u0404\u0466\7") + buf.write("\4\2\2\u0405\u0406\7\u00a4\2\2\u0406\u0407\7\3\2\2\u0407") + buf.write("\u040a\5\b\5\2\u0408\u0409\7\23\2\2\u0409\u040b\t\20\2") + buf.write("\2\u040a\u0408\3\2\2\2\u040a\u040b\3\2\2\2\u040b\u040c") + buf.write("\3\2\2\2\u040c\u040d\7\4\2\2\u040d\u0466\3\2\2\2\u040e") + buf.write("\u040f\t\21\2\2\u040f\u0410\7\3\2\2\u0410\u0411\5\b\5") + buf.write("\2\u0411\u0412\7\4\2\2\u0412\u0466\3\2\2\2\u0413\u0414") + buf.write("\7\u00a7\2\2\u0414\u0415\7\3\2\2\u0415\u0416\5\b\5\2\u0416") + buf.write("\u0417\7\23\2\2\u0417\u0418\5t;\2\u0418\u0419\7\4\2\2") + buf.write("\u0419\u0466\3\2\2\2\u041a\u041b\7\u00d6\2\2\u041b\u041c") + buf.write("\7\3\2\2\u041c\u041f\7\u00f7\2\2\u041d\u041e\7\23\2\2") + buf.write("\u041e\u0420\t\22\2\2\u041f\u041d\3\2\2\2\u041f\u0420") + buf.write("\3\2\2\2\u0420\u0423\3\2\2\2\u0421\u0422\7\23\2\2\u0422") + buf.write("\u0424\5\u00d6l\2\u0423\u0421\3\2\2\2\u0423\u0424\3\2") + buf.write("\2\2\u0424\u0427\3\2\2\2\u0425\u0426\7\23\2\2\u0426\u0428") + buf.write("\t\23\2\2\u0427\u0425\3\2\2\2\u0427\u0428\3\2\2\2\u0428") + buf.write("\u0429\3\2\2\2\u0429\u0466\7\4\2\2\u042a\u042b\7\37\2") + buf.write("\2\u042b\u042c\7\3\2\2\u042c\u0466\7\4\2\2\u042d\u042e") + buf.write("\7 \2\2\u042e\u042f\7\3\2\2\u042f\u0430\5\b\5\2\u0430") + buf.write("\u0431\7\23\2\2\u0431\u0432\5\6\4\2\u0432\u0433\7\4\2") + buf.write("\2\u0433\u0466\3\2\2\2\u0434\u0435\7!\2\2\u0435\u0436") + buf.write("\7\3\2\2\u0436\u0437\5\b\5\2\u0437\u0438\7\23\2\2\u0438") + buf.write("\u0439\5\b\5\2\u0439\u043a\7\23\2\2\u043a\u043b\5\b\5") + buf.write("\2\u043b\u043c\7\4\2\2\u043c\u0466\3\2\2\2\u043d\u043e") + buf.write('\7"\2\2\u043e\u043f\7\3\2\2\u043f\u0440\5\b\5\2\u0440') + buf.write("\u0441\7\4\2\2\u0441\u0466\3\2\2\2\u0442\u0443\7#\2\2") + buf.write("\u0443\u0444\7\3\2\2\u0444\u0445\5\b\5\2\u0445\u0446\7") + buf.write("\4\2\2\u0446\u0466\3\2\2\2\u0447\u0448\7$\2\2\u0448\u0449") + buf.write("\7\3\2\2\u0449\u044a\5\b\5\2\u044a\u044b\7\4\2\2\u044b") + buf.write("\u0466\3\2\2\2\u044c\u044d\7%\2\2\u044d\u044e\7\3\2\2") + buf.write("\u044e\u044f\5\b\5\2\u044f\u0450\7\4\2\2\u0450\u0466\3") + buf.write("\2\2\2\u0451\u0452\7&\2\2\u0452\u0453\7\3\2\2\u0453\u0454") + buf.write("\5\b\5\2\u0454\u0455\7\4\2\2\u0455\u0466\3\2\2\2\u0456") + buf.write("\u0457\7'\2\2\u0457\u0458\7\3\2\2\u0458\u0459\5\b\5\2") + buf.write("\u0459\u045a\7\4\2\2\u045a\u0466\3\2\2\2\u045b\u045c\7") + buf.write("(\2\2\u045c\u045d\7\3\2\2\u045d\u045e\5\b\5\2\u045e\u045f") + buf.write("\7\4\2\2\u045f\u0466\3\2\2\2\u0460\u0461\7)\2\2\u0461") + buf.write("\u0462\7\3\2\2\u0462\u0463\5\b\5\2\u0463\u0464\7\4\2\2") + buf.write("\u0464\u0466\3\2\2\2\u0465\u03ff\3\2\2\2\u0465\u0405\3") + buf.write("\2\2\2\u0465\u040e\3\2\2\2\u0465\u0413\3\2\2\2\u0465\u041a") + buf.write("\3\2\2\2\u0465\u042a\3\2\2\2\u0465\u042d\3\2\2\2\u0465") + buf.write("\u0434\3\2\2\2\u0465\u043d\3\2\2\2\u0465\u0442\3\2\2\2") + buf.write("\u0465\u0447\3\2\2\2\u0465\u044c\3\2\2\2\u0465\u0451\3") + buf.write("\2\2\2\u0465\u0456\3\2\2\2\u0465\u045b\3\2\2\2\u0465\u0460") + buf.write("\3\2\2\2\u0466C\3\2\2\2\u0467\u0468\7;\2\2\u0468\u0469") + buf.write("\7\3\2\2\u0469\u046c\5\6\4\2\u046a\u046b\7\23\2\2\u046b") + buf.write("\u046d\5\6\4\2\u046c\u046a\3\2\2\2\u046d\u046e\3\2\2\2") + buf.write("\u046e\u046c\3\2\2\2\u046e\u046f\3\2\2\2\u046f\u0470\3") + buf.write("\2\2\2\u0470\u0471\7\4\2\2\u0471\u0485\3\2\2\2\u0472\u0473") + buf.write("\7>\2\2\u0473\u0474\7\3\2\2\u0474\u0477\5\6\4\2\u0475") + buf.write("\u0476\7\23\2\2\u0476\u0478\5\6\4\2\u0477\u0475\3\2\2") + buf.write("\2\u0478\u0479\3\2\2\2\u0479\u0477\3\2\2\2\u0479\u047a") + buf.write("\3\2\2\2\u047a\u047b\3\2\2\2\u047b\u047c\7\4\2\2\u047c") + buf.write("\u0485\3\2\2\2\u047d\u047e\t\24\2\2\u047e\u047f\7\3\2") + buf.write("\2\u047f\u0480\5\6\4\2\u0480\u0481\7\23\2\2\u0481\u0482") + buf.write("\5\6\4\2\u0482\u0483\7\4\2\2\u0483\u0485\3\2\2\2\u0484") + buf.write("\u0467\3\2\2\2\u0484\u0472\3\2\2\2\u0484\u047d\3\2\2\2") + buf.write("\u0485E\3\2\2\2\u0486\u0487\7u\2\2\u0487\u0488\7\3\2\2") + buf.write("\u0488\u0489\5\6\4\2\u0489\u048a\7\23\2\2\u048a\u048c") + buf.write("\7\u00f8\2\2\u048b\u048d\5\u00ba^\2\u048c\u048b\3\2\2") + buf.write("\2\u048c\u048d\3\2\2\2\u048d\u0490\3\2\2\2\u048e\u048f") + buf.write("\7\u0083\2\2\u048f\u0491\5\u00caf\2\u0490\u048e\3\2\2") + buf.write("\2\u0490\u0491\3\2\2\2\u0491\u0493\3\2\2\2\u0492\u0494") + buf.write("\5\u00b8]\2\u0493\u0492\3\2\2\2\u0493\u0494\3\2\2\2\u0494") + buf.write("\u0496\3\2\2\2\u0495\u0497\5\u00c0a\2\u0496\u0495\3\2") + buf.write("\2\2\u0496\u0497\3\2\2\2\u0497\u0499\3\2\2\2\u0498\u049a") + buf.write("\5\u00c2b\2\u0499\u0498\3\2\2\2\u0499\u049a\3\2\2\2\u049a") + buf.write("\u049b\3\2\2\2\u049b\u049c\7\4\2\2\u049cG\3\2\2\2\u049d") + buf.write("\u049e\7\u00e1\2\2\u049e\u049f\7\3\2\2\u049f\u04a0\5\6") + buf.write("\4\2\u04a0\u04a1\7\23\2\2\u04a1\u04ab\7\u00f8\2\2\u04a2") + buf.write("\u04a3\7\u00ea\2\2\u04a3\u04a8\5\u00caf\2\u04a4\u04a5") + buf.write("\7\23\2\2\u04a5\u04a7\5\u00caf\2\u04a6\u04a4\3\2\2\2\u04a7") + buf.write("\u04aa\3\2\2\2\u04a8\u04a6\3\2\2\2\u04a8\u04a9\3\2\2\2") + buf.write("\u04a9\u04ac\3\2\2\2\u04aa\u04a8\3\2\2\2\u04ab\u04a2\3") + buf.write("\2\2\2\u04ab\u04ac\3\2\2\2\u04ac\u04ae\3\2\2\2\u04ad\u04af") + buf.write("\5\u00b6\\\2\u04ae\u04ad\3\2\2\2\u04ae\u04af\3\2\2\2\u04af") + buf.write("\u04b0\3\2\2\2\u04b0\u04b1\7\4\2\2\u04b1\u04db\3\2\2\2") + buf.write("\u04b2\u04b3\7\u00e2\2\2\u04b3\u04b4\7\3\2\2\u04b4\u04b5") + buf.write("\5\6\4\2\u04b5\u04b6\7\23\2\2\u04b6\u04b8\7\u00f8\2\2") + buf.write("\u04b7\u04b9\5\u00ba^\2\u04b8\u04b7\3\2\2\2\u04b8\u04b9") + buf.write("\3\2\2\2\u04b9\u04bc\3\2\2\2\u04ba\u04bb\7\u0083\2\2\u04bb") + buf.write("\u04bd\5\u00caf\2\u04bc\u04ba\3\2\2\2\u04bc\u04bd\3\2") + buf.write("\2\2\u04bd\u04bf\3\2\2\2\u04be\u04c0\5\u00b8]\2\u04bf") + buf.write("\u04be\3\2\2\2\u04bf\u04c0\3\2\2\2\u04c0\u04c2\3\2\2\2") + buf.write("\u04c1\u04c3\5\u00bc_\2\u04c2\u04c1\3\2\2\2\u04c2\u04c3") + buf.write("\3\2\2\2\u04c3\u04c5\3\2\2\2\u04c4\u04c6\5\u00b6\\\2\u04c5") + buf.write("\u04c4\3\2\2\2\u04c5\u04c6\3\2\2\2\u04c6\u04c7\3\2\2\2") + buf.write("\u04c7\u04c8\7\4\2\2\u04c8\u04db\3\2\2\2\u04c9\u04ca\7") + buf.write("D\2\2\u04ca\u04cb\7\3\2\2\u04cb\u04cd\5\6\4\2\u04cc\u04ce") + buf.write("\5\u00ceh\2\u04cd\u04cc\3\2\2\2\u04cd\u04ce\3\2\2\2\u04ce") + buf.write("\u04d0\3\2\2\2\u04cf\u04d1\5\u00d0i\2\u04d0\u04cf\3\2") + buf.write("\2\2\u04d0\u04d1\3\2\2\2\u04d1\u04d3\3\2\2\2\u04d2\u04d4") + buf.write("\5\u00be`\2\u04d3\u04d2\3\2\2\2\u04d3\u04d4\3\2\2\2\u04d4") + buf.write("\u04d6\3\2\2\2\u04d5\u04d7\t\25\2\2\u04d6\u04d5\3\2\2") + buf.write("\2\u04d6\u04d7\3\2\2\2\u04d7\u04d8\3\2\2\2\u04d8\u04d9") + buf.write("\7\4\2\2\u04d9\u04db\3\2\2\2\u04da\u049d\3\2\2\2\u04da") + buf.write("\u04b2\3\2\2\2\u04da\u04c9\3\2\2\2\u04dbI\3\2\2\2\u04dc") + buf.write("\u04dd\7t\2\2\u04dd\u04de\7\3\2\2\u04de\u04df\5\6\4\2") + buf.write("\u04df\u04e0\7\23\2\2\u04e0\u04e1\5\6\4\2\u04e1\u04e2") + buf.write("\7\4\2\2\u04e2K\3\2\2\2\u04e3\u04e4\7t\2\2\u04e4\u04e5") + buf.write("\7\3\2\2\u04e5\u04e6\5\b\5\2\u04e6\u04e7\7\23\2\2\u04e7") + buf.write("\u04e8\5\b\5\2\u04e8\u04e9\7\4\2\2\u04e9M\3\2\2\2\u04ea") + buf.write("\u04eb\t\26\2\2\u04eb\u04ec\7\3\2\2\u04ec\u04ed\5\b\5") + buf.write("\2\u04ed\u04ee\7\4\2\2\u04ee\u04f3\3\2\2\2\u04ef\u04f0") + buf.write("\7h\2\2\u04f0\u04f1\7\3\2\2\u04f1\u04f3\7\4\2\2\u04f2") + buf.write("\u04ea\3\2\2\2\u04f2\u04ef\3\2\2\2\u04f3O\3\2\2\2\u04f4") + buf.write("\u04f5\t\26\2\2\u04f5\u04f6\7\3\2\2\u04f6\u04fb\5\6\4") + buf.write("\2\u04f7\u04f9\5z>\2\u04f8\u04fa\5|?\2\u04f9\u04f8\3\2") + buf.write("\2\2\u04f9\u04fa\3\2\2\2\u04fa\u04fc\3\2\2\2\u04fb\u04f7") + buf.write("\3\2\2\2\u04fb\u04fc\3\2\2\2\u04fc\u04fd\3\2\2\2\u04fd") + buf.write("\u04fe\7\4\2\2\u04feQ\3\2\2\2\u04ff\u0500\t\27\2\2\u0500") + buf.write("\u0501\7\3\2\2\u0501\u0502\5\6\4\2\u0502\u0503\7\u009b") + buf.write("\2\2\u0503\u0505\7\3\2\2\u0504\u0506\5l\67\2\u0505\u0504") + buf.write("\3\2\2\2\u0505\u0506\3\2\2\2\u0506\u0508\3\2\2\2\u0507") + buf.write("\u0509\5n8\2\u0508\u0507\3\2\2\2\u0508\u0509\3\2\2\2\u0509") + buf.write("\u050b\3\2\2\2\u050a\u050c\5r:\2\u050b\u050a\3\2\2\2\u050b") + buf.write("\u050c\3\2\2\2\u050c\u050d\3\2\2\2\u050d\u050e\7\4\2\2") + buf.write("\u050e\u050f\7\4\2\2\u050f\u052f\3\2\2\2\u0510\u0511\t") + buf.write("\30\2\2\u0511\u0512\7\3\2\2\u0512\u0519\5\6\4\2\u0513") + buf.write("\u0514\7\23\2\2\u0514\u0517\5t;\2\u0515\u0516\7\23\2\2") + buf.write("\u0516\u0518\5`\61\2\u0517\u0515\3\2\2\2\u0517\u0518\3") + buf.write("\2\2\2\u0518\u051a\3\2\2\2\u0519\u0513\3\2\2\2\u0519\u051a") + buf.write("\3\2\2\2\u051a\u051b\3\2\2\2\u051b\u051c\7\u009b\2\2\u051c") + buf.write("\u051e\7\3\2\2\u051d\u051f\5l\67\2\u051e\u051d\3\2\2\2") + buf.write("\u051e\u051f\3\2\2\2\u051f\u0520\3\2\2\2\u0520\u0521\5") + buf.write("n8\2\u0521\u0522\3\2\2\2\u0522\u0523\7\4\2\2\u0523\u0524") + buf.write("\7\4\2\2\u0524\u052f\3\2\2\2\u0525\u0526\7\u009a\2\2\u0526") + buf.write("\u0527\7\3\2\2\u0527\u0528\5\6\4\2\u0528\u0529\7\u009b") + buf.write("\2\2\u0529\u052a\7\3\2\2\u052a\u052b\5l\67\2\u052b\u052c") + buf.write("\7\4\2\2\u052c\u052d\7\4\2\2\u052d\u052f\3\2\2\2\u052e") + buf.write("\u04ff\3\2\2\2\u052e\u0510\3\2\2\2\u052e\u0525\3\2\2\2") + buf.write("\u052fS\3\2\2\2\u0530\u0531\t\27\2\2\u0531\u0532\7\3\2") + buf.write("\2\u0532\u0533\5\b\5\2\u0533\u0534\7\u009b\2\2\u0534\u0536") + buf.write("\7\3\2\2\u0535\u0537\5l\67\2\u0536\u0535\3\2\2\2\u0536") + buf.write("\u0537\3\2\2\2\u0537\u0539\3\2\2\2\u0538\u053a\5n8\2\u0539") + buf.write("\u0538\3\2\2\2\u0539\u053a\3\2\2\2\u053a\u053c\3\2\2\2") + buf.write("\u053b\u053d\5r:\2\u053c\u053b\3\2\2\2\u053c\u053d\3\2") + buf.write("\2\2\u053d\u053e\3\2\2\2\u053e\u053f\7\4\2\2\u053f\u0540") + buf.write("\7\4\2\2\u0540\u056b\3\2\2\2\u0541\u0542\t\30\2\2\u0542") + buf.write("\u0543\7\3\2\2\u0543\u0549\5\b\5\2\u0544\u0545\7\23\2") + buf.write("\2\u0545\u0547\5t;\2\u0546\u0548\5`\61\2\u0547\u0546\3") + buf.write("\2\2\2\u0547\u0548\3\2\2\2\u0548\u054a\3\2\2\2\u0549\u0544") + buf.write("\3\2\2\2\u0549\u054a\3\2\2\2\u054a\u054b\3\2\2\2\u054b") + buf.write("\u054c\7\u009b\2\2\u054c\u054e\7\3\2\2\u054d\u054f\5l") + buf.write("\67\2\u054e\u054d\3\2\2\2\u054e\u054f\3\2\2\2\u054f\u0550") + buf.write("\3\2\2\2\u0550\u0551\5n8\2\u0551\u0552\3\2\2\2\u0552\u0553") + buf.write("\7\4\2\2\u0553\u0554\7\4\2\2\u0554\u056b\3\2\2\2\u0555") + buf.write("\u0556\7O\2\2\u0556\u0557\7\3\2\2\u0557\u0558\7\u009b") + buf.write("\2\2\u0558\u055a\7\3\2\2\u0559\u055b\5l\67\2\u055a\u0559") + buf.write("\3\2\2\2\u055a\u055b\3\2\2\2\u055b\u055c\3\2\2\2\u055c") + buf.write("\u055d\5n8\2\u055d\u055e\3\2\2\2\u055e\u055f\7\4\2\2\u055f") + buf.write("\u0560\7\4\2\2\u0560\u056b\3\2\2\2\u0561\u0562\7\u009a") + buf.write("\2\2\u0562\u0563\7\3\2\2\u0563\u0564\5\b\5\2\u0564\u0565") + buf.write("\7\u009b\2\2\u0565\u0566\7\3\2\2\u0566\u0567\5l\67\2\u0567") + buf.write("\u0568\7\4\2\2\u0568\u0569\7\4\2\2\u0569\u056b\3\2\2\2") + buf.write("\u056a\u0530\3\2\2\2\u056a\u0541\3\2\2\2\u056a\u0555\3") + buf.write("\2\2\2\u056a\u0561\3\2\2\2\u056bU\3\2\2\2\u056c\u056d") + buf.write("\5\u00caf\2\u056d\u056e\7F\2\2\u056e\u056f\5\u00caf\2") + buf.write("\u056fW\3\2\2\2\u0570\u0575\5Z.\2\u0571\u0572\7\23\2\2") + buf.write("\u0572\u0574\5Z.\2\u0573\u0571\3\2\2\2\u0574\u0577\3\2") + buf.write("\2\2\u0575\u0573\3\2\2\2\u0575\u0576\3\2\2\2\u0576Y\3") + buf.write("\2\2\2\u0577\u0575\3\2\2\2\u0578\u057a\5\u00d8m\2\u0579") + buf.write("\u0578\3\2\2\2\u0579\u057a\3\2\2\2\u057a\u057b\3\2\2\2") + buf.write("\u057b\u057c\5\u00caf\2\u057c\u057d\7\26\2\2\u057d\u057e") + buf.write("\5N(\2\u057e[\3\2\2\2\u057f\u0581\5\u00d8m\2\u0580\u057f") + buf.write("\3\2\2\2\u0580\u0581\3\2\2\2\u0581\u0582\3\2\2\2\u0582") + buf.write("\u0583\5\u00caf\2\u0583\u0584\7\26\2\2\u0584\u0585\5\b") + buf.write("\5\2\u0585]\3\2\2\2\u0586\u0587\5\u00caf\2\u0587\u0588") + buf.write("\7\t\2\2\u0588\u0589\5`\61\2\u0589_\3\2\2\2\u058a\u0597") + buf.write("\5\u00e2r\2\u058b\u058c\7\u00dd\2\2\u058c\u058d\7\3\2") + buf.write("\2\u058d\u058e\5\u00e2r\2\u058e\u058f\7\23\2\2\u058f\u0592") + buf.write("\5\u00e4s\2\u0590\u0591\7\23\2\2\u0591\u0593\7\u00f7\2") + buf.write("\2\u0592\u0590\3\2\2\2\u0592\u0593\3\2\2\2\u0593\u0594") + buf.write("\3\2\2\2\u0594\u0595\7\4\2\2\u0595\u0597\3\2\2\2\u0596") + buf.write("\u058a\3\2\2\2\u0596\u058b\3\2\2\2\u0597a\3\2\2\2\u0598") + buf.write("\u059d\5f\64\2\u0599\u059a\7\23\2\2\u059a\u059c\5f\64") + buf.write("\2\u059b\u0599\3\2\2\2\u059c\u059f\3\2\2\2\u059d\u059b") + buf.write("\3\2\2\2\u059d\u059e\3\2\2\2\u059ec\3\2\2\2\u059f\u059d") + buf.write("\3\2\2\2\u05a0\u05a5\5f\64\2\u05a1\u05a2\7\23\2\2\u05a2") + buf.write("\u05a4\5f\64\2\u05a3\u05a1\3\2\2\2\u05a4\u05a7\3\2\2\2") + buf.write("\u05a5\u05a3\3\2\2\2\u05a5\u05a6\3\2\2\2\u05a6\u05b1\3") + buf.write("\2\2\2\u05a7\u05a5\3\2\2\2\u05a8\u05a9\7\35\2\2\u05a9") + buf.write("\u05ae\5\u00caf\2\u05aa\u05ab\7\23\2\2\u05ab\u05ad\5\u00ca") + buf.write("f\2\u05ac\u05aa\3\2\2\2\u05ad\u05b0\3\2\2\2\u05ae\u05ac") + buf.write("\3\2\2\2\u05ae\u05af\3\2\2\2\u05af\u05b2\3\2\2\2\u05b0") + buf.write("\u05ae\3\2\2\2\u05b1\u05a8\3\2\2\2\u05b1\u05b2\3\2\2\2") + buf.write("\u05b2e\3\2\2\2\u05b3\u05b6\5\6\4\2\u05b4\u05b5\7\60\2") + buf.write("\2\u05b5\u05b7\5\u00c4c\2\u05b6\u05b4\3\2\2\2\u05b6\u05b7") + buf.write("\3\2\2\2\u05b7g\3\2\2\2\u05b8\u05ba\5\24\13\2\u05b9\u05b8") + buf.write("\3\2\2\2\u05b9\u05ba\3\2\2\2\u05ba\u05be\3\2\2\2\u05bb") + buf.write("\u05bf\5\26\f\2\u05bc\u05bf\5j\66\2\u05bd\u05bf\5\22\n") + buf.write("\2\u05be\u05bb\3\2\2\2\u05be\u05bc\3\2\2\2\u05be\u05bd") + buf.write("\3\2\2\2\u05be\u05bf\3\2\2\2\u05bf\u05c1\3\2\2\2\u05c0") + buf.write("\u05c2\5\30\r\2\u05c1\u05c0\3\2\2\2\u05c1\u05c2\3\2\2") + buf.write("\2\u05c2\u05c4\3\2\2\2\u05c3\u05c5\5\20\t\2\u05c4\u05c3") + buf.write("\3\2\2\2\u05c4\u05c5\3\2\2\2\u05c5i\3\2\2\2\u05c6\u05c7") + buf.write("\7\u00d1\2\2\u05c7\u05c8\5\6\4\2\u05c8k\3\2\2\2\u05c9") + buf.write("\u05ca\7\u009f\2\2\u05ca\u05cb\7N\2\2\u05cb\u05d0\5\u00ca") + buf.write("f\2\u05cc\u05cd\7\23\2\2\u05cd\u05cf\5\u00caf\2\u05ce") + buf.write("\u05cc\3\2\2\2\u05cf\u05d2\3\2\2\2\u05d0\u05ce\3\2\2\2") + buf.write("\u05d0\u05d1\3\2\2\2\u05d1m\3\2\2\2\u05d2\u05d0\3\2\2") + buf.write("\2\u05d3\u05d4\7M\2\2\u05d4\u05d5\7N\2\2\u05d5\u05da\5") + buf.write("p9\2\u05d6\u05d7\7\23\2\2\u05d7\u05d9\5p9\2\u05d8\u05d6") + buf.write("\3\2\2\2\u05d9\u05dc\3\2\2\2\u05da\u05d8\3\2\2\2\u05da") + buf.write("\u05db\3\2\2\2\u05dbo\3\2\2\2\u05dc\u05da\3\2\2\2\u05dd") + buf.write("\u05df\5\u00caf\2\u05de\u05e0\t\31\2\2\u05df\u05de\3\2") + buf.write("\2\2\u05df\u05e0\3\2\2\2\u05e0q\3\2\2\2\u05e1\u05e2\7") + buf.write("z\2\2\u05e2\u05e5\7\u00bf\2\2\u05e3\u05e5\7\u00a1\2\2") + buf.write("\u05e4\u05e1\3\2\2\2\u05e4\u05e3\3\2\2\2\u05e5\u05e6\3") + buf.write("\2\2\2\u05e6\u05e7\7\65\2\2\u05e7\u05e8\5x=\2\u05e8\u05e9") + buf.write("\7\61\2\2\u05e9\u05ea\5x=\2\u05eas\3\2\2\2\u05eb\u05ed") + buf.write("\t\32\2\2\u05ec\u05eb\3\2\2\2\u05ec\u05ed\3\2\2\2\u05ed") + buf.write("\u05ee\3\2\2\2\u05ee\u05ef\7\u00f4\2\2\u05efu\3\2\2\2") + buf.write("\u05f0\u05f2\t\32\2\2\u05f1\u05f0\3\2\2\2\u05f1\u05f2") + buf.write("\3\2\2\2\u05f2\u05f3\3\2\2\2\u05f3\u05f4\7\u00f5\2\2\u05f4") + buf.write("w\3\2\2\2\u05f5\u05f6\5t;\2\u05f6\u05f7\7\u009c\2\2\u05f7") + buf.write("\u0603\3\2\2\2\u05f8\u05f9\5t;\2\u05f9\u05fa\7\u009d\2") + buf.write("\2\u05fa\u0603\3\2\2\2\u05fb\u05fc\7\u00a2\2\2\u05fc\u05fd") + buf.write("\7z\2\2\u05fd\u0603\7\u00c0\2\2\u05fe\u05ff\7\u009e\2") + buf.write("\2\u05ff\u0603\7\u009c\2\2\u0600\u0601\7\u009e\2\2\u0601") + buf.write("\u0603\7\u009d\2\2\u0602\u05f5\3\2\2\2\u0602\u05f8\3\2") + buf.write("\2\2\u0602\u05fb\3\2\2\2\u0602\u05fe\3\2\2\2\u0602\u0600") + buf.write("\3\2\2\2\u0603y\3\2\2\2\u0604\u0605\7\u0093\2\2\u0605") + buf.write("\u0606\t\33\2\2\u0606\u060b\5\u00caf\2\u0607\u0608\7\23") + buf.write("\2\2\u0608\u060a\5\u00caf\2\u0609\u0607\3\2\2\2\u060a") + buf.write("\u060d\3\2\2\2\u060b\u0609\3\2\2\2\u060b\u060c\3\2\2\2") + buf.write("\u060c\u0616\3\2\2\2\u060d\u060b\3\2\2\2\u060e\u060f\7") + buf.write("\u00d6\2\2\u060f\u0610\7\3\2\2\u0610\u0613\7\u00f7\2\2") + buf.write("\u0611\u0612\7\23\2\2\u0612\u0614\t\23\2\2\u0613\u0611") + buf.write("\3\2\2\2\u0613\u0614\3\2\2\2\u0614\u0615\3\2\2\2\u0615") + buf.write("\u0617\7\4\2\2\u0616\u060e\3\2\2\2\u0616\u0617\3\2\2\2") + buf.write("\u0617\u0625\3\2\2\2\u0618\u0619\7\u0093\2\2\u0619\u0622") + buf.write("\7J\2\2\u061a\u061b\7\u00d6\2\2\u061b\u061c\7\3\2\2\u061c") + buf.write("\u061f\7\u00f7\2\2\u061d\u061e\7\23\2\2\u061e\u0620\t") + buf.write("\23\2\2\u061f\u061d\3\2\2\2\u061f\u0620\3\2\2\2\u0620") + buf.write("\u0621\3\2\2\2\u0621\u0623\7\4\2\2\u0622\u061a\3\2\2\2") + buf.write("\u0622\u0623\3\2\2\2\u0623\u0625\3\2\2\2\u0624\u0604\3") + buf.write("\2\2\2\u0624\u0618\3\2\2\2\u0625{\3\2\2\2\u0626\u0627") + buf.write("\7\u0095\2\2\u0627\u0628\5\b\5\2\u0628}\3\2\2\2\u0629") + buf.write("\u062a\5\u00c6d\2\u062a\u062d\5\u0084C\2\u062b\u062c\7") + buf.write("\u00e0\2\2\u062c\u062e\5`\61\2\u062d\u062b\3\2\2\2\u062d") + buf.write("\u062e\3\2\2\2\u062e\177\3\2\2\2\u062f\u0633\5\u0088E") + buf.write("\2\u0630\u0633\5\u008cG\2\u0631\u0633\5\u008aF\2\u0632") + buf.write("\u062f\3\2\2\2\u0632\u0630\3\2\2\2\u0632\u0631\3\2\2\2") + buf.write("\u0633\u0081\3\2\2\2\u0634\u0637\5\u008aF\2\u0635\u0637") + buf.write("\5\u0088E\2\u0636\u0634\3\2\2\2\u0636\u0635\3\2\2\2\u0637") + buf.write("\u0083\3\2\2\2\u0638\u063e\5\u0088E\2\u0639\u063e\5\u008c") + buf.write("G\2\u063a\u063e\5\u0090I\2\u063b\u063e\5\u0086D\2\u063c") + buf.write("\u063e\5\u008aF\2\u063d\u0638\3\2\2\2\u063d\u0639\3\2") + buf.write("\2\2\u063d\u063a\3\2\2\2\u063d\u063b\3\2\2\2\u063d\u063c") + buf.write("\3\2\2\2\u063e\u0085\3\2\2\2\u063f\u0643\7\u0082\2\2\u0640") + buf.write("\u0643\5\u0092J\2\u0641\u0643\5\u0094K\2\u0642\u063f\3") + buf.write("\2\2\2\u0642\u0640\3\2\2\2\u0642\u0641\3\2\2\2\u0643\u0087") + buf.write("\3\2\2\2\u0644\u0647\5\u00e4s\2\u0645\u0647\5\u0096L\2") + buf.write("\u0646\u0644\3\2\2\2\u0646\u0645\3\2\2\2\u0647\u0649\3") + buf.write("\2\2\2\u0648\u064a\5\u00b0Y\2\u0649\u0648\3\2\2\2\u0649") + buf.write("\u064a\3\2\2\2\u064a\u064f\3\2\2\2\u064b\u064d\7\64\2") + buf.write("\2\u064c\u064b\3\2\2\2\u064c\u064d\3\2\2\2\u064d\u064e") + buf.write("\3\2\2\2\u064e\u0650\78\2\2\u064f\u064c\3\2\2\2\u064f") + buf.write("\u0650\3\2\2\2\u0650\u0089\3\2\2\2\u0651\u0656\5\u00d8") + buf.write("m\2\u0652\u0653\7\n\2\2\u0653\u0654\5\u0088E\2\u0654\u0655") + buf.write("\7\13\2\2\u0655\u0657\3\2\2\2\u0656\u0652\3\2\2\2\u0656") + buf.write("\u0657\3\2\2\2\u0657\u008b\3\2\2\2\u0658\u0664\7|\2\2") + buf.write("\u0659\u065a\7\7\2\2\u065a\u065f\5\u00b2Z\2\u065b\u065c") + buf.write("\7\23\2\2\u065c\u065e\5\u00b2Z\2\u065d\u065b\3\2\2\2\u065e") + buf.write("\u0661\3\2\2\2\u065f\u065d\3\2\2\2\u065f\u0660\3\2\2\2") + buf.write("\u0660\u0662\3\2\2\2\u0661\u065f\3\2\2\2\u0662\u0663\7") + buf.write("\b\2\2\u0663\u0665\3\2\2\2\u0664\u0659\3\2\2\2\u0664\u0665") + buf.write("\3\2\2\2\u0665\u008d\3\2\2\2\u0666\u0669\5\u008cG\2\u0667") + buf.write("\u0669\5\u0088E\2\u0668\u0666\3\2\2\2\u0668\u0667\3\2") + buf.write("\2\2\u0669\u008f\3\2\2\2\u066a\u066f\7\u00f2\2\2\u066b") + buf.write("\u066c\7\n\2\2\u066c\u066d\5\u0088E\2\u066d\u066e\7\13") + buf.write("\2\2\u066e\u0670\3\2\2\2\u066f\u066b\3\2\2\2\u066f\u0670") + buf.write("\3\2\2\2\u0670\u0091\3\2\2\2\u0671\u068f\7\u0080\2\2\u0672") + buf.write("\u067e\7\u00ee\2\2\u0673\u0674\7\7\2\2\u0674\u0679\5\u0096") + buf.write("L\2\u0675\u0676\7\21\2\2\u0676\u0678\5\u0096L\2\u0677") + buf.write("\u0675\3\2\2\2\u0678\u067b\3\2\2\2\u0679\u0677\3\2\2\2") + buf.write("\u0679\u067a\3\2\2\2\u067a\u067c\3\2\2\2\u067b\u0679\3") + buf.write("\2\2\2\u067c\u067d\7\b\2\2\u067d\u067f\3\2\2\2\u067e\u0673") + buf.write("\3\2\2\2\u067e\u067f\3\2\2\2\u067f\u068f\3\2\2\2\u0680") + buf.write("\u068c\7\u00ef\2\2\u0681\u0682\7\7\2\2\u0682\u0687\5\u00c6") + buf.write("d\2\u0683\u0684\7\21\2\2\u0684\u0686\5\u00c6d\2\u0685") + buf.write("\u0683\3\2\2\2\u0686\u0689\3\2\2\2\u0687\u0685\3\2\2\2") + buf.write("\u0687\u0688\3\2\2\2\u0688\u068a\3\2\2\2\u0689\u0687\3") + buf.write("\2\2\2\u068a\u068b\7\b\2\2\u068b\u068d\3\2\2\2\u068c\u0681") + buf.write("\3\2\2\2\u068c\u068d\3\2\2\2\u068d\u068f\3\2\2\2\u068e") + buf.write("\u0671\3\2\2\2\u068e\u0672\3\2\2\2\u068e\u0680\3\2\2\2") + buf.write("\u068f\u0093\3\2\2\2\u0690\u06b9\7\u0081\2\2\u0691\u06a2") + buf.write("\7\u00f0\2\2\u0692\u0693\7\7\2\2\u0693\u069f\7\u00f8\2") + buf.write("\2\u0694\u0695\7\3\2\2\u0695\u069a\5\u0096L\2\u0696\u0697") + buf.write("\7\21\2\2\u0697\u0699\5\u0096L\2\u0698\u0696\3\2\2\2\u0699") + buf.write("\u069c\3\2\2\2\u069a\u0698\3\2\2\2\u069a\u069b\3\2\2\2") + buf.write("\u069b\u069d\3\2\2\2\u069c\u069a\3\2\2\2\u069d\u069e\7") + buf.write("\4\2\2\u069e\u06a0\3\2\2\2\u069f\u0694\3\2\2\2\u069f\u06a0") + buf.write("\3\2\2\2\u06a0\u06a1\3\2\2\2\u06a1\u06a3\7\b\2\2\u06a2") + buf.write("\u0692\3\2\2\2\u06a2\u06a3\3\2\2\2\u06a3\u06b9\3\2\2\2") + buf.write("\u06a4\u06b6\7\u00f1\2\2\u06a5\u06a6\7\7\2\2\u06a6\u06b2") + buf.write("\5\u00c6d\2\u06a7\u06a8\7\3\2\2\u06a8\u06ad\5\u00c6d\2") + buf.write("\u06a9\u06aa\7\21\2\2\u06aa\u06ac\5\u00c6d\2\u06ab\u06a9") + buf.write("\3\2\2\2\u06ac\u06af\3\2\2\2\u06ad\u06ab\3\2\2\2\u06ad") + buf.write("\u06ae\3\2\2\2\u06ae\u06b0\3\2\2\2\u06af\u06ad\3\2\2\2") + buf.write("\u06b0\u06b1\7\4\2\2\u06b1\u06b3\3\2\2\2\u06b2\u06a7\3") + buf.write("\2\2\2\u06b2\u06b3\3\2\2\2\u06b3\u06b4\3\2\2\2\u06b4\u06b5") + buf.write("\7\b\2\2\u06b5\u06b7\3\2\2\2\u06b6\u06a5\3\2\2\2\u06b6") + buf.write("\u06b7\3\2\2\2\u06b7\u06b9\3\2\2\2\u06b8\u0690\3\2\2\2") + buf.write("\u06b8\u0691\3\2\2\2\u06b8\u06a4\3\2\2\2\u06b9\u0095\3") + buf.write("\2\2\2\u06ba\u06bb\7\u00f8\2\2\u06bb\u0097\3\2\2\2\u06bc") + buf.write("\u06bd\7\u00f8\2\2\u06bd\u0099\3\2\2\2\u06be\u06bf\t\34") + buf.write("\2\2\u06bf\u06c4\5\u009cO\2\u06c0\u06c1\7\23\2\2\u06c1") + buf.write("\u06c3\5\u009cO\2\u06c2\u06c0\3\2\2\2\u06c3\u06c6\3\2") + buf.write("\2\2\u06c4\u06c2\3\2\2\2\u06c4\u06c5\3\2\2\2\u06c5\u009b") + buf.write("\3\2\2\2\u06c6\u06c4\3\2\2\2\u06c7\u06ca\5\u00c6d\2\u06c8") + buf.write("\u06c9\7\60\2\2\u06c9\u06cb\5\u00c4c\2\u06ca\u06c8\3\2") + buf.write("\2\2\u06ca\u06cb\3\2\2\2\u06cb\u009d\3\2\2\2\u06cc\u06d1") + buf.write("\5\u00a0Q\2\u06cd\u06ce\7\u00fa\2\2\u06ce\u06d0\5\u00a0") + buf.write("Q\2\u06cf\u06cd\3\2\2\2\u06d0\u06d3\3\2\2\2\u06d1\u06cf") + buf.write("\3\2\2\2\u06d1\u06d2\3\2\2\2\u06d2\u009f\3\2\2\2\u06d3") + buf.write("\u06d1\3\2\2\2\u06d4\u06d5\7\u00f8\2\2\u06d5\u06d7\7\25") + buf.write("\2\2\u06d6\u06d4\3\2\2\2\u06d6\u06d7\3\2\2\2\u06d7\u06dc") + buf.write("\3\2\2\2\u06d8\u06d9\7\u00bc\2\2\u06d9\u06da\5\b\5\2\u06da") + buf.write("\u06db\7\33\2\2\u06db\u06dd\3\2\2\2\u06dc\u06d8\3\2\2") + buf.write("\2\u06dc\u06dd\3\2\2\2\u06dd\u06de\3\2\2\2\u06de\u06e0") + buf.write("\5\b\5\2\u06df\u06e1\5\u00ceh\2\u06e0\u06df\3\2\2\2\u06e0") + buf.write("\u06e1\3\2\2\2\u06e1\u06e3\3\2\2\2\u06e2\u06e4\5\u00d0") + buf.write("i\2\u06e3\u06e2\3\2\2\2\u06e3\u06e4\3\2\2\2\u06e4\u00a1") + buf.write("\3\2\2\2\u06e5\u06ea\5\u00a4S\2\u06e6\u06e7\7\u00fa\2") + buf.write("\2\u06e7\u06e9\5\u00a4S\2\u06e8\u06e6\3\2\2\2\u06e9\u06ec") + buf.write("\3\2\2\2\u06ea\u06e8\3\2\2\2\u06ea\u06eb\3\2\2\2\u06eb") + buf.write("\u00a3\3\2\2\2\u06ec\u06ea\3\2\2\2\u06ed\u06ee\7\u00f8") + buf.write("\2\2\u06ee\u06f0\7\25\2\2\u06ef\u06ed\3\2\2\2\u06ef\u06f0") + buf.write("\3\2\2\2\u06f0\u06f1\3\2\2\2\u06f1\u06f3\5\u00aaV\2\u06f2") + buf.write("\u06f4\5\u00ceh\2\u06f3\u06f2\3\2\2\2\u06f3\u06f4\3\2") + buf.write("\2\2\u06f4\u06f6\3\2\2\2\u06f5\u06f7\5\u00d0i\2\u06f6") + buf.write("\u06f5\3\2\2\2\u06f6\u06f7\3\2\2\2\u06f7\u00a5\3\2\2\2") + buf.write("\u06f8\u06fb\t\34\2\2\u06f9\u06fa\7\u00aa\2\2\u06fa\u06fc") + buf.write("\5\u00a8U\2\u06fb\u06f9\3\2\2\2\u06fb\u06fc\3\2\2\2\u06fc") + buf.write("\u06fd\3\2\2\2\u06fd\u06fe\7\u0083\2\2\u06fe\u06ff\7\u00f8") + buf.write("\2\2\u06ff\u00a7\3\2\2\2\u0700\u0705\5\u009cO\2\u0701") + buf.write("\u0702\7\23\2\2\u0702\u0704\5\u009cO\2\u0703\u0701\3\2") + buf.write("\2\2\u0704\u0707\3\2\2\2\u0705\u0703\3\2\2\2\u0705\u0706") + buf.write("\3\2\2\2\u0706\u00a9\3\2\2\2\u0707\u0705\3\2\2\2\u0708") + buf.write("\u0709\7\u00bc\2\2\u0709\u070a\5\b\5\2\u070a\u070b\7\33") + buf.write("\2\2\u070b\u070d\3\2\2\2\u070c\u0708\3\2\2\2\u070c\u070d") + buf.write("\3\2\2\2\u070d\u070e\3\2\2\2\u070e\u0710\5\u00aeX\2\u070f") + buf.write("\u0711\5\u00d2j\2\u0710\u070f\3\2\2\2\u0710\u0711\3\2") + buf.write("\2\2\u0711\u0712\3\2\2\2\u0712\u0716\5\u00acW\2\u0713") + buf.write("\u0715\5\u00acW\2\u0714\u0713\3\2\2\2\u0715\u0718\3\2") + buf.write("\2\2\u0716\u0714\3\2\2\2\u0716\u0717\3\2\2\2\u0717\u00ab") + buf.write("\3\2\2\2\u0718\u0716\3\2\2\2\u0719\u071b\t\32\2\2\u071a") + buf.write("\u0719\3\2\2\2\u071a\u071b\3\2\2\2\u071b\u071c\3\2\2\2") + buf.write("\u071c\u0721\5\u00aeX\2\u071d\u071e\7\5\2\2\u071e\u071f") + buf.write("\5\b\5\2\u071f\u0720\7\6\2\2\u0720\u0722\3\2\2\2\u0721") + buf.write("\u071d\3\2\2\2\u0721\u0722\3\2\2\2\u0722\u00ad\3\2\2\2") + buf.write("\u0723\u0727\7\u00f8\2\2\u0724\u0727\5t;\2\u0725\u0727") + buf.write("\5v<\2\u0726\u0723\3\2\2\2\u0726\u0724\3\2\2\2\u0726\u0725") + buf.write("\3\2\2\2\u0727\u00af\3\2\2\2\u0728\u0729\7\5\2\2\u0729") + buf.write("\u072a\5\b\5\2\u072a\u072b\7\6\2\2\u072b\u0738\3\2\2\2") + buf.write("\u072c\u072d\7\7\2\2\u072d\u0732\5`\61\2\u072e\u072f\7") + buf.write("\23\2\2\u072f\u0731\5`\61\2\u0730\u072e\3\2\2\2\u0731") + buf.write("\u0734\3\2\2\2\u0732\u0730\3\2\2\2\u0732\u0733\3\2\2\2") + buf.write("\u0733\u0735\3\2\2\2\u0734\u0732\3\2\2\2\u0735\u0736\7") + buf.write("\b\2\2\u0736\u0738\3\2\2\2\u0737\u0728\3\2\2\2\u0737\u072c") + buf.write("\3\2\2\2\u0738\u00b1\3\2\2\2\u0739\u073c\5\u008aF\2\u073a") + buf.write("\u073d\5\u00caf\2\u073b\u073d\5\u00b4[\2\u073c\u073a\3") + buf.write("\2\2\2\u073c\u073b\3\2\2\2\u073d\u00b3\3\2\2\2\u073e\u0740") + buf.write("\7v\2\2\u073f\u0741\t\35\2\2\u0740\u073f\3\2\2\2\u0740") + buf.write("\u0741\3\2\2\2\u0741\u00b5\3\2\2\2\u0742\u0743\t\36\2") + buf.write("\2\u0743\u00b7\3\2\2\2\u0744\u0745\t\37\2\2\u0745\u00b9") + buf.write("\3\2\2\2\u0746\u0747\7\u00aa\2\2\u0747\u074c\5\u00caf") + buf.write("\2\u0748\u0749\7\23\2\2\u0749\u074b\5\u00caf\2\u074a\u0748") + buf.write("\3\2\2\2\u074b\u074e\3\2\2\2\u074c\u074a\3\2\2\2\u074c") + buf.write("\u074d\3\2\2\2\u074d\u00bb\3\2\2\2\u074e\u074c\3\2\2\2") + buf.write("\u074f\u0750\t \2\2\u0750\u00bd\3\2\2\2\u0751\u0752\7") + buf.write("H\2\2\u0752\u0753\5\6\4\2\u0753\u00bf\3\2\2\2\u0754\u0755") + buf.write('\t!\2\2\u0755\u00c1\3\2\2\2\u0756\u0757\t"\2\2\u0757') + buf.write("\u00c3\3\2\2\2\u0758\u0759\7\u00f8\2\2\u0759\u00c5\3\2") + buf.write("\2\2\u075a\u075b\7\u00f8\2\2\u075b\u00c7\3\2\2\2\u075c") + buf.write("\u075d\7\u00f8\2\2\u075d\u00c9\3\2\2\2\u075e\u0761\7\u00f8") + buf.write("\2\2\u075f\u0760\7\27\2\2\u0760\u0762\7\u00f8\2\2\u0761") + buf.write("\u075f\3\2\2\2\u0761\u0762\3\2\2\2\u0762\u00cb\3\2\2\2") + buf.write("\u0763\u0764\7\7\2\2\u0764\u0769\5`\61\2\u0765\u0766\7") + buf.write("\23\2\2\u0766\u0768\5`\61\2\u0767\u0765\3\2\2\2\u0768") + buf.write("\u076b\3\2\2\2\u0769\u0767\3\2\2\2\u0769\u076a\3\2\2\2") + buf.write("\u076a\u076c\3\2\2\2\u076b\u0769\3\2\2\2\u076c\u076d\7") + buf.write("\b\2\2\u076d\u00cd\3\2\2\2\u076e\u076f\7I\2\2\u076f\u0770") + buf.write("\5\u00e2r\2\u0770\u00cf\3\2\2\2\u0771\u0772\7L\2\2\u0772") + buf.write("\u0773\5\u00e2r\2\u0773\u00d1\3\2\2\2\u0774\u0775\t#\2") + buf.write("\2\u0775\u00d3\3\2\2\2\u0776\u0779\5\6\4\2\u0777\u0779") + buf.write("\7v\2\2\u0778\u0776\3\2\2\2\u0778\u0777\3\2\2\2\u0779") + buf.write("\u00d5\3\2\2\2\u077a\u077d\5\b\5\2\u077b\u077d\7v\2\2") + buf.write("\u077c\u077a\3\2\2\2\u077c\u077b\3\2\2\2\u077d\u00d7\3") + buf.write("\2\2\2\u077e\u0784\7j\2\2\u077f\u0784\7\u00ed\2\2\u0780") + buf.write("\u0784\7i\2\2\u0781\u0784\7k\2\2\u0782\u0784\5\u00dan") + buf.write("\2\u0783\u077e\3\2\2\2\u0783\u077f\3\2\2\2\u0783\u0780") + buf.write("\3\2\2\2\u0783\u0781\3\2\2\2\u0783\u0782\3\2\2\2\u0784") + buf.write("\u00d9\3\2\2\2\u0785\u0786\7p\2\2\u0786\u0787\7k\2\2\u0787") + buf.write("\u00db\3\2\2\2\u0788\u0789\7\u00f8\2\2\u0789\u00dd\3\2") + buf.write("\2\2\u078a\u078b\7\u00f8\2\2\u078b\u00df\3\2\2\2\u078c") + buf.write("\u078d\7\u00f8\2\2\u078d\u00e1\3\2\2\2\u078e\u0794\5t") + buf.write(";\2\u078f\u0794\5v<\2\u0790\u0794\7\u00f6\2\2\u0791\u0794") + buf.write("\7\u00f7\2\2\u0792\u0794\78\2\2\u0793\u078e\3\2\2\2\u0793") + buf.write("\u078f\3\2\2\2\u0793\u0790\3\2\2\2\u0793\u0791\3\2\2\2") + buf.write("\u0793\u0792\3\2\2\2\u0794\u00e3\3\2\2\2\u0795\u0796\t") + buf.write("$\2\2\u0796\u00e5\3\2\2\2\u0797\u0798\t%\2\2\u0798\u00e7") + buf.write("\3\2\2\2\u00d1\u00ed\u00fb\u0114\u011b\u0139\u013b\u013d") + buf.write("\u0157\u015e\u0174\u0176\u0178\u0183\u0191\u019a\u01a2") + buf.write("\u01a9\u01ab\u01b6\u01bf\u01d1\u01da\u01e9\u01f4\u01f7") + buf.write("\u01fc\u022a\u0230\u0237\u023c\u0247\u024c\u0255\u0258") + buf.write("\u0262\u0267\u026b\u0271\u0275\u027f\u0283\u0287\u0290") + buf.write("\u0293\u029d\u02a1\u02ab\u02b0\u02b4\u02ba\u02be\u02c2") + buf.write("\u02c6\u02ca\u02da\u02de\u02e9\u02f4\u02f8\u02fc\u030c") + buf.write("\u0310\u031b\u0326\u032a\u032e\u033a\u0345\u0351\u035c") + buf.write("\u037a\u037e\u0395\u039a\u03a2\u03b7\u03bb\u03bf\u03fd") + buf.write("\u0402\u040a\u041f\u0423\u0427\u0465\u046e\u0479\u0484") + buf.write("\u048c\u0490\u0493\u0496\u0499\u04a8\u04ab\u04ae\u04b8") + buf.write("\u04bc\u04bf\u04c2\u04c5\u04cd\u04d0\u04d3\u04d6\u04da") + buf.write("\u04f2\u04f9\u04fb\u0505\u0508\u050b\u0517\u0519\u051e") + buf.write("\u052e\u0536\u0539\u053c\u0547\u0549\u054e\u055a\u056a") + buf.write("\u0575\u0579\u0580\u0592\u0596\u059d\u05a5\u05ae\u05b1") + buf.write("\u05b6\u05b9\u05be\u05c1\u05c4\u05d0\u05da\u05df\u05e4") + buf.write("\u05ec\u05f1\u0602\u060b\u0613\u0616\u061f\u0622\u0624") + buf.write("\u062d\u0632\u0636\u063d\u0642\u0646\u0649\u064c\u064f") + buf.write("\u0656\u065f\u0664\u0668\u066f\u0679\u067e\u0687\u068c") + buf.write("\u068e\u069a\u069f\u06a2\u06ad\u06b2\u06b6\u06b8\u06c4") + buf.write("\u06ca\u06d1\u06d6\u06dc\u06e0\u06e3\u06ea\u06ef\u06f3") + buf.write("\u06f6\u06fb\u0705\u070c\u0710\u0716\u071a\u0721\u0726") + buf.write("\u0732\u0737\u073c\u0740\u074c\u0761\u0769\u0778\u077c") + buf.write("\u0783\u0793") return buf.getvalue() @@ -1114,6 +1134,7 @@ class Parser(ANTLRParser): "'exp'", "'componentRole'", "'viral'", + "'propagation'", "'match_characters'", "'type'", "'nvl'", @@ -1365,6 +1386,7 @@ class Parser(ANTLRParser): "EXP", "ROLE", "VIRAL", + "PROPAGATION", "CHARSET_MATCH", "TYPE", "NVL", @@ -1523,100 +1545,104 @@ class Parser(ANTLRParser): RULE_subspaceClause = 14 RULE_joinOperators = 15 RULE_defOperators = 16 - RULE_genericOperators = 17 - RULE_genericOperatorsComponent = 18 - RULE_parameterComponent = 19 - RULE_parameter = 20 - RULE_stringOperators = 21 - RULE_stringOperatorsComponent = 22 - RULE_numericOperators = 23 - RULE_numericOperatorsComponent = 24 - RULE_comparisonOperators = 25 - RULE_comparisonOperatorsComponent = 26 - RULE_timeOperators = 27 - RULE_timeOperatorsComponent = 28 - RULE_setOperators = 29 - RULE_hierarchyOperators = 30 - RULE_validationOperators = 31 - RULE_conditionalOperators = 32 - RULE_conditionalOperatorsComponent = 33 - RULE_aggrOperators = 34 - RULE_aggrOperatorsGrouping = 35 - RULE_anFunction = 36 - RULE_anFunctionComponent = 37 - RULE_renameClauseItem = 38 - RULE_aggregateClause = 39 - RULE_aggrFunctionClause = 40 - RULE_calcClauseItem = 41 - RULE_subspaceClauseItem = 42 - RULE_scalarItem = 43 - RULE_joinClauseWithoutUsing = 44 - RULE_joinClause = 45 - RULE_joinClauseItem = 46 - RULE_joinBody = 47 - RULE_joinApplyClause = 48 - RULE_partitionByClause = 49 - RULE_orderByClause = 50 - RULE_orderByItem = 51 - RULE_windowingClause = 52 - RULE_signedInteger = 53 - RULE_signedNumber = 54 - RULE_limitClauseItem = 55 - RULE_groupingClause = 56 - RULE_havingClause = 57 - RULE_parameterItem = 58 - RULE_outputParameterType = 59 - RULE_outputParameterTypeComponent = 60 - RULE_inputParameterType = 61 - RULE_rulesetType = 62 - RULE_scalarType = 63 - RULE_componentType = 64 - RULE_datasetType = 65 - RULE_evalDatasetType = 66 - RULE_scalarSetType = 67 - RULE_dpRuleset = 68 - RULE_hrRuleset = 69 - RULE_valueDomainName = 70 - RULE_rulesetID = 71 - RULE_rulesetSignature = 72 - RULE_signature = 73 - RULE_ruleClauseDatapoint = 74 - RULE_ruleItemDatapoint = 75 - RULE_ruleClauseHierarchical = 76 - RULE_ruleItemHierarchical = 77 - RULE_hierRuleSignature = 78 - RULE_valueDomainSignature = 79 - RULE_codeItemRelation = 80 - RULE_codeItemRelationClause = 81 - RULE_valueDomainValue = 82 - RULE_scalarTypeConstraint = 83 - RULE_compConstraint = 84 - RULE_multModifier = 85 - RULE_validationOutput = 86 - RULE_validationMode = 87 - RULE_conditionClause = 88 - RULE_inputMode = 89 - RULE_imbalanceExpr = 90 - RULE_inputModeHierarchy = 91 - RULE_outputModeHierarchy = 92 - RULE_alias = 93 - RULE_varID = 94 - RULE_simpleComponentId = 95 - RULE_componentID = 96 - RULE_lists = 97 - RULE_erCode = 98 - RULE_erLevel = 99 - RULE_comparisonOperand = 100 - RULE_optionalExpr = 101 - RULE_optionalExprComponent = 102 - RULE_componentRole = 103 - RULE_viralAttribute = 104 - RULE_valueDomainID = 105 - RULE_operatorID = 106 - RULE_routineName = 107 - RULE_constant = 108 - RULE_basicScalarType = 109 - RULE_retainType = 110 + RULE_vpSignature = 17 + RULE_vpBody = 18 + RULE_vpClause = 19 + RULE_vpCondition = 20 + RULE_genericOperators = 21 + RULE_genericOperatorsComponent = 22 + RULE_parameterComponent = 23 + RULE_parameter = 24 + RULE_stringOperators = 25 + RULE_stringOperatorsComponent = 26 + RULE_numericOperators = 27 + RULE_numericOperatorsComponent = 28 + RULE_comparisonOperators = 29 + RULE_comparisonOperatorsComponent = 30 + RULE_timeOperators = 31 + RULE_timeOperatorsComponent = 32 + RULE_setOperators = 33 + RULE_hierarchyOperators = 34 + RULE_validationOperators = 35 + RULE_conditionalOperators = 36 + RULE_conditionalOperatorsComponent = 37 + RULE_aggrOperators = 38 + RULE_aggrOperatorsGrouping = 39 + RULE_anFunction = 40 + RULE_anFunctionComponent = 41 + RULE_renameClauseItem = 42 + RULE_aggregateClause = 43 + RULE_aggrFunctionClause = 44 + RULE_calcClauseItem = 45 + RULE_subspaceClauseItem = 46 + RULE_scalarItem = 47 + RULE_joinClauseWithoutUsing = 48 + RULE_joinClause = 49 + RULE_joinClauseItem = 50 + RULE_joinBody = 51 + RULE_joinApplyClause = 52 + RULE_partitionByClause = 53 + RULE_orderByClause = 54 + RULE_orderByItem = 55 + RULE_windowingClause = 56 + RULE_signedInteger = 57 + RULE_signedNumber = 58 + RULE_limitClauseItem = 59 + RULE_groupingClause = 60 + RULE_havingClause = 61 + RULE_parameterItem = 62 + RULE_outputParameterType = 63 + RULE_outputParameterTypeComponent = 64 + RULE_inputParameterType = 65 + RULE_rulesetType = 66 + RULE_scalarType = 67 + RULE_componentType = 68 + RULE_datasetType = 69 + RULE_evalDatasetType = 70 + RULE_scalarSetType = 71 + RULE_dpRuleset = 72 + RULE_hrRuleset = 73 + RULE_valueDomainName = 74 + RULE_rulesetID = 75 + RULE_rulesetSignature = 76 + RULE_signature = 77 + RULE_ruleClauseDatapoint = 78 + RULE_ruleItemDatapoint = 79 + RULE_ruleClauseHierarchical = 80 + RULE_ruleItemHierarchical = 81 + RULE_hierRuleSignature = 82 + RULE_valueDomainSignature = 83 + RULE_codeItemRelation = 84 + RULE_codeItemRelationClause = 85 + RULE_valueDomainValue = 86 + RULE_scalarTypeConstraint = 87 + RULE_compConstraint = 88 + RULE_multModifier = 89 + RULE_validationOutput = 90 + RULE_validationMode = 91 + RULE_conditionClause = 92 + RULE_inputMode = 93 + RULE_imbalanceExpr = 94 + RULE_inputModeHierarchy = 95 + RULE_outputModeHierarchy = 96 + RULE_alias = 97 + RULE_varID = 98 + RULE_simpleComponentId = 99 + RULE_componentID = 100 + RULE_lists = 101 + RULE_erCode = 102 + RULE_erLevel = 103 + RULE_comparisonOperand = 104 + RULE_optionalExpr = 105 + RULE_optionalExprComponent = 106 + RULE_componentRole = 107 + RULE_viralAttribute = 108 + RULE_valueDomainID = 109 + RULE_operatorID = 110 + RULE_routineName = 111 + RULE_constant = 112 + RULE_basicScalarType = 113 + RULE_retainType = 114 ruleNames = [ "start", @@ -1636,6 +1662,10 @@ class Parser(ANTLRParser): "subspaceClause", "joinOperators", "defOperators", + "vpSignature", + "vpBody", + "vpClause", + "vpCondition", "genericOperators", "genericOperatorsComponent", "parameterComponent", @@ -1843,145 +1873,146 @@ class Parser(ANTLRParser): EXP = 108 ROLE = 109 VIRAL = 110 - CHARSET_MATCH = 111 - TYPE = 112 - NVL = 113 - HIERARCHY = 114 - OPTIONAL = 115 - INVALID = 116 - VALUE_DOMAIN = 117 - VARIABLE = 118 - DATA = 119 - STRUCTURE = 120 - DATASET = 121 - OPERATOR = 122 - DEFINE = 123 - PUT_SYMBOL = 124 - DATAPOINT = 125 - HIERARCHICAL = 126 - RULESET = 127 - RULE = 128 - END = 129 - ALTER_DATASET = 130 - LTRIM = 131 - RTRIM = 132 - INSTR = 133 - REPLACE = 134 - CEIL = 135 - FLOOR = 136 - SQRT = 137 - ANY = 138 - SETDIFF = 139 - STDDEV_POP = 140 - STDDEV_SAMP = 141 - VAR_POP = 142 - VAR_SAMP = 143 - GROUP = 144 - EXCEPT = 145 - HAVING = 146 - FIRST_VALUE = 147 - LAST_VALUE = 148 - LAG = 149 - LEAD = 150 - RATIO_TO_REPORT = 151 - OVER = 152 - PRECEDING = 153 - FOLLOWING = 154 - UNBOUNDED = 155 - PARTITION = 156 - ROWS = 157 - RANGE = 158 - CURRENT = 159 - VALID = 160 - FILL_TIME_SERIES = 161 - FLOW_TO_STOCK = 162 - STOCK_TO_FLOW = 163 - TIMESHIFT = 164 - MEASURES = 165 - NO_MEASURES = 166 - CONDITION = 167 - BOOLEAN = 168 - DATE = 169 - TIME_PERIOD = 170 - NUMBER = 171 - STRING = 172 - TIME = 173 - INTEGER = 174 - FLOAT = 175 - LIST = 176 - RECORD = 177 - RESTRICT = 178 - YYYY = 179 - MM = 180 - DD = 181 - MAX_LENGTH = 182 - REGEXP = 183 - IS = 184 - WHEN = 185 - FROM = 186 - AGGREGATES = 187 - POINTS = 188 - POINT = 189 - TOTAL = 190 - PARTIAL = 191 - ALWAYS = 192 - INNER_JOIN = 193 - LEFT_JOIN = 194 - CROSS_JOIN = 195 - FULL_JOIN = 196 - MAPS_FROM = 197 - MAPS_TO = 198 - MAP_TO = 199 - MAP_FROM = 200 - RETURNS = 201 - PIVOT = 202 - CUSTOMPIVOT = 203 - UNPIVOT = 204 - SUBSPACE = 205 - APPLY = 206 - CONDITIONED = 207 - PERIOD_INDICATOR = 208 - SINGLE = 209 - DURATION = 210 - TIME_AGG = 211 - UNIT = 212 - VALUE = 213 - VALUEDOMAINS = 214 - VARIABLES = 215 - INPUT = 216 - OUTPUT = 217 - CAST = 218 - RULE_PRIORITY = 219 - DATASET_PRIORITY = 220 - DEFAULT = 221 - CHECK_DATAPOINT = 222 - CHECK_HIERARCHY = 223 - COMPUTED = 224 - NON_NULL = 225 - NON_ZERO = 226 - PARTIAL_NULL = 227 - PARTIAL_ZERO = 228 - ALWAYS_NULL = 229 - ALWAYS_ZERO = 230 - COMPONENTS = 231 - ALL_MEASURES = 232 - SCALAR = 233 - COMPONENT = 234 - DATAPOINT_ON_VD = 235 - DATAPOINT_ON_VAR = 236 - HIERARCHICAL_ON_VD = 237 - HIERARCHICAL_ON_VAR = 238 - SET = 239 - LANGUAGE = 240 - INTEGER_CONSTANT = 241 - NUMBER_CONSTANT = 242 - BOOLEAN_CONSTANT = 243 - STRING_CONSTANT = 244 - IDENTIFIER = 245 - WS = 246 - EOL = 247 - ML_COMMENT = 248 - SL_COMMENT = 249 + PROPAGATION = 111 + CHARSET_MATCH = 112 + TYPE = 113 + NVL = 114 + HIERARCHY = 115 + OPTIONAL = 116 + INVALID = 117 + VALUE_DOMAIN = 118 + VARIABLE = 119 + DATA = 120 + STRUCTURE = 121 + DATASET = 122 + OPERATOR = 123 + DEFINE = 124 + PUT_SYMBOL = 125 + DATAPOINT = 126 + HIERARCHICAL = 127 + RULESET = 128 + RULE = 129 + END = 130 + ALTER_DATASET = 131 + LTRIM = 132 + RTRIM = 133 + INSTR = 134 + REPLACE = 135 + CEIL = 136 + FLOOR = 137 + SQRT = 138 + ANY = 139 + SETDIFF = 140 + STDDEV_POP = 141 + STDDEV_SAMP = 142 + VAR_POP = 143 + VAR_SAMP = 144 + GROUP = 145 + EXCEPT = 146 + HAVING = 147 + FIRST_VALUE = 148 + LAST_VALUE = 149 + LAG = 150 + LEAD = 151 + RATIO_TO_REPORT = 152 + OVER = 153 + PRECEDING = 154 + FOLLOWING = 155 + UNBOUNDED = 156 + PARTITION = 157 + ROWS = 158 + RANGE = 159 + CURRENT = 160 + VALID = 161 + FILL_TIME_SERIES = 162 + FLOW_TO_STOCK = 163 + STOCK_TO_FLOW = 164 + TIMESHIFT = 165 + MEASURES = 166 + NO_MEASURES = 167 + CONDITION = 168 + BOOLEAN = 169 + DATE = 170 + TIME_PERIOD = 171 + NUMBER = 172 + STRING = 173 + TIME = 174 + INTEGER = 175 + FLOAT = 176 + LIST = 177 + RECORD = 178 + RESTRICT = 179 + YYYY = 180 + MM = 181 + DD = 182 + MAX_LENGTH = 183 + REGEXP = 184 + IS = 185 + WHEN = 186 + FROM = 187 + AGGREGATES = 188 + POINTS = 189 + POINT = 190 + TOTAL = 191 + PARTIAL = 192 + ALWAYS = 193 + INNER_JOIN = 194 + LEFT_JOIN = 195 + CROSS_JOIN = 196 + FULL_JOIN = 197 + MAPS_FROM = 198 + MAPS_TO = 199 + MAP_TO = 200 + MAP_FROM = 201 + RETURNS = 202 + PIVOT = 203 + CUSTOMPIVOT = 204 + UNPIVOT = 205 + SUBSPACE = 206 + APPLY = 207 + CONDITIONED = 208 + PERIOD_INDICATOR = 209 + SINGLE = 210 + DURATION = 211 + TIME_AGG = 212 + UNIT = 213 + VALUE = 214 + VALUEDOMAINS = 215 + VARIABLES = 216 + INPUT = 217 + OUTPUT = 218 + CAST = 219 + RULE_PRIORITY = 220 + DATASET_PRIORITY = 221 + DEFAULT = 222 + CHECK_DATAPOINT = 223 + CHECK_HIERARCHY = 224 + COMPUTED = 225 + NON_NULL = 226 + NON_ZERO = 227 + PARTIAL_NULL = 228 + PARTIAL_ZERO = 229 + ALWAYS_NULL = 230 + ALWAYS_ZERO = 231 + COMPONENTS = 232 + ALL_MEASURES = 233 + SCALAR = 234 + COMPONENT = 235 + DATAPOINT_ON_VD = 236 + DATAPOINT_ON_VAR = 237 + HIERARCHICAL_ON_VD = 238 + HIERARCHICAL_ON_VAR = 239 + SET = 240 + LANGUAGE = 241 + INTEGER_CONSTANT = 242 + NUMBER_CONSTANT = 243 + BOOLEAN_CONSTANT = 244 + STRING_CONSTANT = 245 + IDENTIFIER = 246 + WS = 247 + EOL = 248 + ML_COMMENT = 249 + SL_COMMENT = 250 def __init__(self, input: TokenStream, output: TextIO = sys.stdout): super().__init__(input, output) @@ -2029,19 +2060,19 @@ def start(self) -> Any: self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 227 + self.state = 235 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.DEFINE or _la == Parser.IDENTIFIER: - self.state = 222 + self.state = 230 self.statement() - self.state = 223 + self.state = 231 self.match(Parser.EOL) - self.state = 229 + self.state = 237 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 230 + self.state = 238 self.match(Parser.EOF) except RecognitionException as re: localctx.exception = re @@ -2123,35 +2154,35 @@ def statement(self): localctx = Parser.StatementContext(self, self._ctx, self.state) self.enterRule(localctx, 2, self.RULE_statement) try: - self.state = 241 + self.state = 249 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input, 1, self._ctx) if la_ == 1: localctx = Parser.TemporaryAssignmentContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 232 + self.state = 240 self.varID() - self.state = 233 + self.state = 241 self.match(Parser.ASSIGN) - self.state = 234 + self.state = 242 self.expr(0) pass elif la_ == 2: localctx = Parser.PersistAssignmentContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 236 + self.state = 244 self.varID() - self.state = 237 + self.state = 245 self.match(Parser.PUT_SYMBOL) - self.state = 238 + self.state = 246 self.expr(0) pass elif la_ == 3: localctx = Parser.DefineExpressionContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 240 + self.state = 248 self.defOperators() pass @@ -2387,8 +2418,8 @@ class CaseExprContext(ExprContext): def __init__(self, parser, ctx: ParserRuleContext): # actually a Parser.ExprContext super().__init__(parser) self._expr = None # ExprContext - self.condExpr = [] # of ExprContexts - self.thenExpr = [] # of ExprContexts + self.condExpr = list() # of ExprContexts + self.thenExpr = list() # of ExprContexts self.elseExpr = None # ExprContext self.copyFrom(ctx) @@ -2521,7 +2552,7 @@ def expr(self, _p: int = 0): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 273 + self.state = 281 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input, 3, self._ctx) if la_ == 1: @@ -2529,11 +2560,11 @@ def expr(self, _p: int = 0): self._ctx = localctx _prevctx = localctx - self.state = 244 + self.state = 252 self.match(Parser.LPAREN) - self.state = 245 + self.state = 253 self.expr(0) - self.state = 246 + self.state = 254 self.match(Parser.RPAREN) pass @@ -2541,7 +2572,7 @@ def expr(self, _p: int = 0): localctx = Parser.FunctionsExpressionContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 248 + self.state = 256 self.functions() pass @@ -2549,7 +2580,7 @@ def expr(self, _p: int = 0): localctx = Parser.UnaryExprContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 249 + self.state = 257 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not ( @@ -2563,7 +2594,7 @@ def expr(self, _p: int = 0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 250 + self.state = 258 localctx.right = self.expr(11) pass @@ -2571,17 +2602,17 @@ def expr(self, _p: int = 0): localctx = Parser.IfExprContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 251 + self.state = 259 self.match(Parser.IF) - self.state = 252 + self.state = 260 localctx.conditionalExpr = self.expr(0) - self.state = 253 + self.state = 261 self.match(Parser.THEN) - self.state = 254 + self.state = 262 localctx.thenExpr = self.expr(0) - self.state = 255 + self.state = 263 self.match(Parser.ELSE) - self.state = 256 + self.state = 264 localctx.elseExpr = self.expr(4) pass @@ -2589,31 +2620,31 @@ def expr(self, _p: int = 0): localctx = Parser.CaseExprContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 258 + self.state = 266 self.match(Parser.CASE) - self.state = 264 + self.state = 272 self._errHandler.sync(self) _la = self._input.LA(1) while True: - self.state = 259 + self.state = 267 self.match(Parser.WHEN) - self.state = 260 + self.state = 268 localctx._expr = self.expr(0) localctx.condExpr.append(localctx._expr) - self.state = 261 + self.state = 269 self.match(Parser.THEN) - self.state = 262 + self.state = 270 localctx._expr = self.expr(0) localctx.thenExpr.append(localctx._expr) - self.state = 266 + self.state = 274 self._errHandler.sync(self) _la = self._input.LA(1) - if _la != Parser.WHEN: + if not (_la == Parser.WHEN): break - self.state = 268 + self.state = 276 self.match(Parser.ELSE) - self.state = 269 + self.state = 277 localctx.elseExpr = self.expr(3) pass @@ -2621,7 +2652,7 @@ def expr(self, _p: int = 0): localctx = Parser.ConstantExprContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 271 + self.state = 279 self.constant() pass @@ -2629,12 +2660,12 @@ def expr(self, _p: int = 0): localctx = Parser.VarIdExprContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 272 + self.state = 280 self.varID() pass self._ctx.stop = self._input.LT(-1) - self.state = 307 + self.state = 315 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input, 6, self._ctx) while _alt != 2 and _alt != ATN.INVALID_ALT_NUMBER: @@ -2642,7 +2673,7 @@ def expr(self, _p: int = 0): if self._parseListeners is not None: self.triggerExitRuleEvent() _prevctx = localctx - self.state = 305 + self.state = 313 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input, 5, self._ctx) if la_ == 1: @@ -2651,12 +2682,12 @@ def expr(self, _p: int = 0): ) localctx.left = _prevctx self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 275 + self.state = 283 if not self.precpred(self._ctx, 10): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 10)") - self.state = 276 + self.state = 284 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.MUL or _la == Parser.DIV): @@ -2664,7 +2695,7 @@ def expr(self, _p: int = 0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 277 + self.state = 285 localctx.right = self.expr(11) pass @@ -2674,12 +2705,12 @@ def expr(self, _p: int = 0): ) localctx.left = _prevctx self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 278 + self.state = 286 if not self.precpred(self._ctx, 9): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 9)") - self.state = 279 + self.state = 287 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.PLUS or _la == Parser.MINUS or _la == Parser.CONCAT): @@ -2687,7 +2718,7 @@ def expr(self, _p: int = 0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 280 + self.state = 288 localctx.right = self.expr(10) pass @@ -2697,14 +2728,14 @@ def expr(self, _p: int = 0): ) localctx.left = _prevctx self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 281 + self.state = 289 if not self.precpred(self._ctx, 8): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 8)") - self.state = 282 + self.state = 290 localctx.op = self.comparisonOperand() - self.state = 283 + self.state = 291 localctx.right = self.expr(9) pass @@ -2714,14 +2745,14 @@ def expr(self, _p: int = 0): ) localctx.left = _prevctx self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 285 + self.state = 293 if not self.precpred(self._ctx, 6): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 6)") - self.state = 286 + self.state = 294 localctx.op = self.match(Parser.AND) - self.state = 287 + self.state = 295 localctx.right = self.expr(7) pass @@ -2731,12 +2762,12 @@ def expr(self, _p: int = 0): ) localctx.left = _prevctx self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 288 + self.state = 296 if not self.precpred(self._ctx, 5): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 5)") - self.state = 289 + self.state = 297 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.OR or _la == Parser.XOR): @@ -2744,7 +2775,7 @@ def expr(self, _p: int = 0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 290 + self.state = 298 localctx.right = self.expr(6) pass @@ -2754,16 +2785,16 @@ def expr(self, _p: int = 0): ) localctx.dataset = _prevctx self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 291 + self.state = 299 if not self.precpred(self._ctx, 13): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 13)") - self.state = 292 + self.state = 300 self.match(Parser.QLPAREN) - self.state = 293 + self.state = 301 localctx.clause = self.datasetClause() - self.state = 294 + self.state = 302 self.match(Parser.QRPAREN) pass @@ -2772,14 +2803,14 @@ def expr(self, _p: int = 0): self, Parser.ExprContext(self, _parentctx, _parentState) ) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 296 + self.state = 304 if not self.precpred(self._ctx, 12): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 12)") - self.state = 297 + self.state = 305 self.match(Parser.MEMBERSHIP) - self.state = 298 + self.state = 306 self.simpleComponentId() pass @@ -2789,12 +2820,12 @@ def expr(self, _p: int = 0): ) localctx.left = _prevctx self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) - self.state = 299 + self.state = 307 if not self.precpred(self._ctx, 7): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 7)") - self.state = 300 + self.state = 308 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.IN or _la == Parser.NOT_IN): @@ -2802,15 +2833,15 @@ def expr(self, _p: int = 0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 303 + self.state = 311 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.GLPAREN]: - self.state = 301 + self.state = 309 self.lists() pass elif token in [Parser.IDENTIFIER]: - self.state = 302 + self.state = 310 self.valueDomainID() pass else: @@ -2818,7 +2849,7 @@ def expr(self, _p: int = 0): pass - self.state = 309 + self.state = 317 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input, 6, self._ctx) @@ -3090,8 +3121,8 @@ def __init__( ): # actually a Parser.ExprComponentContext super().__init__(parser) self._exprComponent = None # ExprComponentContext - self.condExpr = [] # of ExprComponentContexts - self.thenExpr = [] # of ExprComponentContexts + self.condExpr = list() # of ExprComponentContexts + self.thenExpr = list() # of ExprComponentContexts self.elseExpr = None # ExprComponentContext self.copyFrom(ctx) @@ -3166,7 +3197,7 @@ def exprComponent(self, _p: int = 0): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 340 + self.state = 348 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input, 8, self._ctx) if la_ == 1: @@ -3174,11 +3205,11 @@ def exprComponent(self, _p: int = 0): self._ctx = localctx _prevctx = localctx - self.state = 311 + self.state = 319 self.match(Parser.LPAREN) - self.state = 312 + self.state = 320 self.exprComponent(0) - self.state = 313 + self.state = 321 self.match(Parser.RPAREN) pass @@ -3186,7 +3217,7 @@ def exprComponent(self, _p: int = 0): localctx = Parser.FunctionsExpressionCompContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 315 + self.state = 323 self.functionsComponents() pass @@ -3194,7 +3225,7 @@ def exprComponent(self, _p: int = 0): localctx = Parser.UnaryExprCompContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 316 + self.state = 324 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not ( @@ -3208,7 +3239,7 @@ def exprComponent(self, _p: int = 0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 317 + self.state = 325 localctx.right = self.exprComponent(11) pass @@ -3216,17 +3247,17 @@ def exprComponent(self, _p: int = 0): localctx = Parser.IfExprCompContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 318 + self.state = 326 self.match(Parser.IF) - self.state = 319 + self.state = 327 localctx.conditionalExpr = self.exprComponent(0) - self.state = 320 + self.state = 328 self.match(Parser.THEN) - self.state = 321 + self.state = 329 localctx.thenExpr = self.exprComponent(0) - self.state = 322 + self.state = 330 self.match(Parser.ELSE) - self.state = 323 + self.state = 331 localctx.elseExpr = self.exprComponent(4) pass @@ -3234,31 +3265,31 @@ def exprComponent(self, _p: int = 0): localctx = Parser.CaseExprCompContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 325 + self.state = 333 self.match(Parser.CASE) - self.state = 331 + self.state = 339 self._errHandler.sync(self) _la = self._input.LA(1) while True: - self.state = 326 + self.state = 334 self.match(Parser.WHEN) - self.state = 327 + self.state = 335 localctx._exprComponent = self.exprComponent(0) localctx.condExpr.append(localctx._exprComponent) - self.state = 328 + self.state = 336 self.match(Parser.THEN) - self.state = 329 + self.state = 337 localctx._exprComponent = self.exprComponent(0) localctx.thenExpr.append(localctx._exprComponent) - self.state = 333 + self.state = 341 self._errHandler.sync(self) _la = self._input.LA(1) - if _la != Parser.WHEN: + if not (_la == Parser.WHEN): break - self.state = 335 + self.state = 343 self.match(Parser.ELSE) - self.state = 336 + self.state = 344 localctx.elseExpr = self.exprComponent(3) pass @@ -3266,7 +3297,7 @@ def exprComponent(self, _p: int = 0): localctx = Parser.ConstantExprCompContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 338 + self.state = 346 self.constant() pass @@ -3274,12 +3305,12 @@ def exprComponent(self, _p: int = 0): localctx = Parser.CompIdContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 339 + self.state = 347 self.componentID() pass self._ctx.stop = self._input.LT(-1) - self.state = 366 + self.state = 374 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input, 11, self._ctx) while _alt != 2 and _alt != ATN.INVALID_ALT_NUMBER: @@ -3287,7 +3318,7 @@ def exprComponent(self, _p: int = 0): if self._parseListeners is not None: self.triggerExitRuleEvent() _prevctx = localctx - self.state = 364 + self.state = 372 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input, 10, self._ctx) if la_ == 1: @@ -3296,12 +3327,12 @@ def exprComponent(self, _p: int = 0): ) localctx.left = _prevctx self.pushNewRecursionContext(localctx, _startState, self.RULE_exprComponent) - self.state = 342 + self.state = 350 if not self.precpred(self._ctx, 10): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 10)") - self.state = 343 + self.state = 351 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.MUL or _la == Parser.DIV): @@ -3309,7 +3340,7 @@ def exprComponent(self, _p: int = 0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 344 + self.state = 352 localctx.right = self.exprComponent(11) pass @@ -3319,12 +3350,12 @@ def exprComponent(self, _p: int = 0): ) localctx.left = _prevctx self.pushNewRecursionContext(localctx, _startState, self.RULE_exprComponent) - self.state = 345 + self.state = 353 if not self.precpred(self._ctx, 9): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 9)") - self.state = 346 + self.state = 354 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.PLUS or _la == Parser.MINUS or _la == Parser.CONCAT): @@ -3332,7 +3363,7 @@ def exprComponent(self, _p: int = 0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 347 + self.state = 355 localctx.right = self.exprComponent(10) pass @@ -3342,14 +3373,14 @@ def exprComponent(self, _p: int = 0): ) localctx.left = _prevctx self.pushNewRecursionContext(localctx, _startState, self.RULE_exprComponent) - self.state = 348 + self.state = 356 if not self.precpred(self._ctx, 8): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 8)") - self.state = 349 + self.state = 357 self.comparisonOperand() - self.state = 350 + self.state = 358 localctx.right = self.exprComponent(9) pass @@ -3359,14 +3390,14 @@ def exprComponent(self, _p: int = 0): ) localctx.left = _prevctx self.pushNewRecursionContext(localctx, _startState, self.RULE_exprComponent) - self.state = 352 + self.state = 360 if not self.precpred(self._ctx, 6): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 6)") - self.state = 353 + self.state = 361 localctx.op = self.match(Parser.AND) - self.state = 354 + self.state = 362 localctx.right = self.exprComponent(7) pass @@ -3376,12 +3407,12 @@ def exprComponent(self, _p: int = 0): ) localctx.left = _prevctx self.pushNewRecursionContext(localctx, _startState, self.RULE_exprComponent) - self.state = 355 + self.state = 363 if not self.precpred(self._ctx, 5): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 5)") - self.state = 356 + self.state = 364 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.OR or _la == Parser.XOR): @@ -3389,7 +3420,7 @@ def exprComponent(self, _p: int = 0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 357 + self.state = 365 localctx.right = self.exprComponent(6) pass @@ -3399,12 +3430,12 @@ def exprComponent(self, _p: int = 0): ) localctx.left = _prevctx self.pushNewRecursionContext(localctx, _startState, self.RULE_exprComponent) - self.state = 358 + self.state = 366 if not self.precpred(self._ctx, 7): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 7)") - self.state = 359 + self.state = 367 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.IN or _la == Parser.NOT_IN): @@ -3412,15 +3443,15 @@ def exprComponent(self, _p: int = 0): else: self._errHandler.reportMatch(self) self.consume() - self.state = 362 + self.state = 370 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.GLPAREN]: - self.state = 360 + self.state = 368 self.lists() pass elif token in [Parser.IDENTIFIER]: - self.state = 361 + self.state = 369 self.valueDomainID() pass else: @@ -3428,7 +3459,7 @@ def exprComponent(self, _p: int = 0): pass - self.state = 368 + self.state = 376 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input, 11, self._ctx) @@ -3586,62 +3617,62 @@ def functionsComponents(self): localctx = Parser.FunctionsComponentsContext(self, self._ctx, self.state) self.enterRule(localctx, 8, self.RULE_functionsComponents) try: - self.state = 377 + self.state = 385 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input, 12, self._ctx) if la_ == 1: localctx = Parser.GenericFunctionsComponentsContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 369 + self.state = 377 self.genericOperatorsComponent() pass elif la_ == 2: localctx = Parser.StringFunctionsComponentsContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 370 + self.state = 378 self.stringOperatorsComponent() pass elif la_ == 3: localctx = Parser.NumericFunctionsComponentsContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 371 + self.state = 379 self.numericOperatorsComponent() pass elif la_ == 4: localctx = Parser.ComparisonFunctionsComponentsContext(self, localctx) self.enterOuterAlt(localctx, 4) - self.state = 372 + self.state = 380 self.comparisonOperatorsComponent() pass elif la_ == 5: localctx = Parser.TimeFunctionsComponentsContext(self, localctx) self.enterOuterAlt(localctx, 5) - self.state = 373 + self.state = 381 self.timeOperatorsComponent() pass elif la_ == 6: localctx = Parser.ConditionalFunctionsComponentsContext(self, localctx) self.enterOuterAlt(localctx, 6) - self.state = 374 + self.state = 382 self.conditionalOperatorsComponent() pass elif la_ == 7: localctx = Parser.AggregateFunctionsComponentsContext(self, localctx) self.enterOuterAlt(localctx, 7) - self.state = 375 + self.state = 383 self.aggrOperators() pass elif la_ == 8: localctx = Parser.AnalyticFunctionsComponentsContext(self, localctx) self.enterOuterAlt(localctx, 8) - self.state = 376 + self.state = 384 self.anFunctionComponent() pass @@ -3839,90 +3870,90 @@ def functions(self): localctx = Parser.FunctionsContext(self, self._ctx, self.state) self.enterRule(localctx, 10, self.RULE_functions) try: - self.state = 391 + self.state = 399 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input, 13, self._ctx) if la_ == 1: localctx = Parser.JoinFunctionsContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 379 + self.state = 387 self.joinOperators() pass elif la_ == 2: localctx = Parser.GenericFunctionsContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 380 + self.state = 388 self.genericOperators() pass elif la_ == 3: localctx = Parser.StringFunctionsContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 381 + self.state = 389 self.stringOperators() pass elif la_ == 4: localctx = Parser.NumericFunctionsContext(self, localctx) self.enterOuterAlt(localctx, 4) - self.state = 382 + self.state = 390 self.numericOperators() pass elif la_ == 5: localctx = Parser.ComparisonFunctionsContext(self, localctx) self.enterOuterAlt(localctx, 5) - self.state = 383 + self.state = 391 self.comparisonOperators() pass elif la_ == 6: localctx = Parser.TimeFunctionsContext(self, localctx) self.enterOuterAlt(localctx, 6) - self.state = 384 + self.state = 392 self.timeOperators() pass elif la_ == 7: localctx = Parser.SetFunctionsContext(self, localctx) self.enterOuterAlt(localctx, 7) - self.state = 385 + self.state = 393 self.setOperators() pass elif la_ == 8: localctx = Parser.HierarchyFunctionsContext(self, localctx) self.enterOuterAlt(localctx, 8) - self.state = 386 + self.state = 394 self.hierarchyOperators() pass elif la_ == 9: localctx = Parser.ValidationFunctionsContext(self, localctx) self.enterOuterAlt(localctx, 9) - self.state = 387 + self.state = 395 self.validationOperators() pass elif la_ == 10: localctx = Parser.ConditionalFunctionsContext(self, localctx) self.enterOuterAlt(localctx, 10) - self.state = 388 + self.state = 396 self.conditionalOperators() pass elif la_ == 11: localctx = Parser.AggregateFunctionsContext(self, localctx) self.enterOuterAlt(localctx, 11) - self.state = 389 + self.state = 397 self.aggrOperatorsGrouping() pass elif la_ == 12: localctx = Parser.AnalyticFunctionsContext(self, localctx) self.enterOuterAlt(localctx, 12) - self.state = 390 + self.state = 398 self.anFunction() pass @@ -3976,42 +4007,42 @@ def datasetClause(self): localctx = Parser.DatasetClauseContext(self, self._ctx, self.state) self.enterRule(localctx, 12, self.RULE_datasetClause) try: - self.state = 400 + self.state = 408 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.RENAME]: self.enterOuterAlt(localctx, 1) - self.state = 393 + self.state = 401 self.renameClause() pass elif token in [Parser.AGGREGATE]: self.enterOuterAlt(localctx, 2) - self.state = 394 + self.state = 402 self.aggrClause() pass elif token in [Parser.FILTER]: self.enterOuterAlt(localctx, 3) - self.state = 395 + self.state = 403 self.filterClause() pass elif token in [Parser.CALC]: self.enterOuterAlt(localctx, 4) - self.state = 396 + self.state = 404 self.calcClause() pass elif token in [Parser.DROP, Parser.KEEP]: self.enterOuterAlt(localctx, 5) - self.state = 397 + self.state = 405 self.keepOrDropClause() pass elif token in [Parser.PIVOT, Parser.UNPIVOT]: self.enterOuterAlt(localctx, 6) - self.state = 398 + self.state = 406 self.pivotOrUnpivotClause() pass elif token in [Parser.SUBSPACE]: self.enterOuterAlt(localctx, 7) - self.state = 399 + self.state = 407 self.subspaceClause() pass else: @@ -4063,19 +4094,19 @@ def renameClause(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 402 + self.state = 410 self.match(Parser.RENAME) - self.state = 403 + self.state = 411 self.renameClauseItem() - self.state = 408 + self.state = 416 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 404 + self.state = 412 self.match(Parser.COMMA) - self.state = 405 + self.state = 413 self.renameClauseItem() - self.state = 410 + self.state = 418 self._errHandler.sync(self) _la = self._input.LA(1) @@ -4122,21 +4153,21 @@ def aggrClause(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 411 + self.state = 419 self.match(Parser.AGGREGATE) - self.state = 412 + self.state = 420 self.aggregateClause() - self.state = 417 + self.state = 425 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.GROUP: - self.state = 413 + self.state = 421 self.groupingClause() - self.state = 415 + self.state = 423 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.HAVING: - self.state = 414 + self.state = 422 self.havingClause() except RecognitionException as re: @@ -4175,9 +4206,9 @@ def filterClause(self): self.enterRule(localctx, 18, self.RULE_filterClause) try: self.enterOuterAlt(localctx, 1) - self.state = 419 + self.state = 427 self.match(Parser.FILTER) - self.state = 420 + self.state = 428 self.exprComponent(0) except RecognitionException as re: localctx.exception = re @@ -4225,19 +4256,19 @@ def calcClause(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 422 + self.state = 430 self.match(Parser.CALC) - self.state = 423 + self.state = 431 self.calcClauseItem() - self.state = 428 + self.state = 436 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 424 + self.state = 432 self.match(Parser.COMMA) - self.state = 425 + self.state = 433 self.calcClauseItem() - self.state = 430 + self.state = 438 self._errHandler.sync(self) _la = self._input.LA(1) @@ -4291,7 +4322,7 @@ def keepOrDropClause(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 431 + self.state = 439 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.DROP or _la == Parser.KEEP): @@ -4299,17 +4330,17 @@ def keepOrDropClause(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 432 + self.state = 440 self.componentID() - self.state = 437 + self.state = 445 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 433 + self.state = 441 self.match(Parser.COMMA) - self.state = 434 + self.state = 442 self.componentID() - self.state = 439 + self.state = 447 self._errHandler.sync(self) _la = self._input.LA(1) @@ -4362,7 +4393,7 @@ def pivotOrUnpivotClause(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 440 + self.state = 448 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.PIVOT or _la == Parser.UNPIVOT): @@ -4370,11 +4401,11 @@ def pivotOrUnpivotClause(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 441 + self.state = 449 localctx.id_ = self.componentID() - self.state = 442 + self.state = 450 self.match(Parser.COMMA) - self.state = 443 + self.state = 451 localctx.mea = self.componentID() except RecognitionException as re: localctx.exception = re @@ -4433,27 +4464,27 @@ def customPivotClause(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 445 + self.state = 453 self.match(Parser.CUSTOMPIVOT) - self.state = 446 + self.state = 454 localctx.id_ = self.componentID() - self.state = 447 + self.state = 455 self.match(Parser.COMMA) - self.state = 448 + self.state = 456 localctx.mea = self.componentID() - self.state = 449 + self.state = 457 self.match(Parser.IN) - self.state = 450 + self.state = 458 self.constant() - self.state = 455 + self.state = 463 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 451 + self.state = 459 self.match(Parser.COMMA) - self.state = 452 + self.state = 460 self.constant() - self.state = 457 + self.state = 465 self._errHandler.sync(self) _la = self._input.LA(1) @@ -4503,19 +4534,19 @@ def subspaceClause(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 458 + self.state = 466 self.match(Parser.SUBSPACE) - self.state = 459 + self.state = 467 self.subspaceClauseItem() - self.state = 464 + self.state = 472 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 460 + self.state = 468 self.match(Parser.COMMA) - self.state = 461 + self.state = 469 self.subspaceClauseItem() - self.state = 466 + self.state = 474 self._errHandler.sync(self) _la = self._input.LA(1) @@ -4587,13 +4618,13 @@ def joinOperators(self): self.enterRule(localctx, 30, self.RULE_joinOperators) self._la = 0 # Token type try: - self.state = 479 + self.state = 487 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.INNER_JOIN, Parser.LEFT_JOIN]: localctx = Parser.JoinExprContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 467 + self.state = 475 localctx.joinKeyword = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.INNER_JOIN or _la == Parser.LEFT_JOIN): @@ -4601,19 +4632,19 @@ def joinOperators(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 468 + self.state = 476 self.match(Parser.LPAREN) - self.state = 469 + self.state = 477 self.joinClause() - self.state = 470 + self.state = 478 self.joinBody() - self.state = 471 + self.state = 479 self.match(Parser.RPAREN) pass elif token in [Parser.CROSS_JOIN, Parser.FULL_JOIN]: localctx = Parser.JoinExprContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 473 + self.state = 481 localctx.joinKeyword = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.CROSS_JOIN or _la == Parser.FULL_JOIN): @@ -4621,13 +4652,13 @@ def joinOperators(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 474 + self.state = 482 self.match(Parser.LPAREN) - self.state = 475 + self.state = 483 self.joinClauseWithoutUsing() - self.state = 476 + self.state = 484 self.joinBody() - self.state = 477 + self.state = 485 self.match(Parser.RPAREN) pass else: @@ -4757,6 +4788,53 @@ def accept(self, visitor: ParseTreeVisitor): else: return visitor.visitChildren(self) + class DefViralPropagationContext(DefOperatorsContext): + def __init__(self, parser, ctx: ParserRuleContext): # actually a Parser.DefOperatorsContext + super().__init__(parser) + self.copyFrom(ctx) + + def DEFINE(self): + return self.getToken(Parser.DEFINE, 0) + + def VIRAL(self, i: int = None): + if i is None: + return self.getTokens(Parser.VIRAL) + else: + return self.getToken(Parser.VIRAL, i) + + def PROPAGATION(self, i: int = None): + if i is None: + return self.getTokens(Parser.PROPAGATION) + else: + return self.getToken(Parser.PROPAGATION, i) + + def varID(self): + return self.getTypedRuleContext(Parser.VarIDContext, 0) + + def LPAREN(self): + return self.getToken(Parser.LPAREN, 0) + + def vpSignature(self): + return self.getTypedRuleContext(Parser.VpSignatureContext, 0) + + def RPAREN(self): + return self.getToken(Parser.RPAREN, 0) + + def IS(self): + return self.getToken(Parser.IS, 0) + + def vpBody(self): + return self.getTypedRuleContext(Parser.VpBodyContext, 0) + + def END(self): + return self.getToken(Parser.END, 0) + + def accept(self, visitor: ParseTreeVisitor): + if hasattr(visitor, "visitDefViralPropagation"): + return visitor.visitDefViralPropagation(self) + else: + return visitor.visitChildren(self) + class DefDatapointRulesetContext(DefOperatorsContext): def __init__(self, parser, ctx: ParserRuleContext): # actually a Parser.DefOperatorsContext super().__init__(parser) @@ -4810,118 +4888,472 @@ def defOperators(self): self.enterRule(localctx, 32, self.RULE_defOperators) self._la = 0 # Token type try: - self.state = 531 + self.state = 552 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input, 26, self._ctx) if la_ == 1: localctx = Parser.DefOperatorContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 481 + self.state = 489 self.match(Parser.DEFINE) - self.state = 482 + self.state = 490 self.match(Parser.OPERATOR) - self.state = 483 + self.state = 491 self.operatorID() - self.state = 484 + self.state = 492 self.match(Parser.LPAREN) - self.state = 493 + self.state = 501 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.IDENTIFIER: - self.state = 485 + self.state = 493 self.parameterItem() - self.state = 490 + self.state = 498 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 486 + self.state = 494 self.match(Parser.COMMA) - self.state = 487 + self.state = 495 self.parameterItem() - self.state = 492 + self.state = 500 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 495 + self.state = 503 self.match(Parser.RPAREN) - self.state = 498 + self.state = 506 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.RETURNS: - self.state = 496 + self.state = 504 self.match(Parser.RETURNS) - self.state = 497 + self.state = 505 self.outputParameterType() - self.state = 500 + self.state = 508 self.match(Parser.IS) - self.state = 501 + self.state = 509 self.expr(0) - self.state = 502 + self.state = 510 self.match(Parser.END) - self.state = 503 + self.state = 511 self.match(Parser.OPERATOR) pass elif la_ == 2: localctx = Parser.DefDatapointRulesetContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 505 + self.state = 513 self.match(Parser.DEFINE) - self.state = 506 + self.state = 514 self.match(Parser.DATAPOINT) - self.state = 507 + self.state = 515 self.match(Parser.RULESET) - self.state = 508 + self.state = 516 self.rulesetID() - self.state = 509 + self.state = 517 self.match(Parser.LPAREN) - self.state = 510 + self.state = 518 self.rulesetSignature() - self.state = 511 + self.state = 519 self.match(Parser.RPAREN) - self.state = 512 + self.state = 520 self.match(Parser.IS) - self.state = 513 + self.state = 521 self.ruleClauseDatapoint() - self.state = 514 + self.state = 522 self.match(Parser.END) - self.state = 515 + self.state = 523 self.match(Parser.DATAPOINT) - self.state = 516 + self.state = 524 self.match(Parser.RULESET) pass elif la_ == 3: localctx = Parser.DefHierarchicalContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 518 + self.state = 526 self.match(Parser.DEFINE) - self.state = 519 + self.state = 527 self.match(Parser.HIERARCHICAL) - self.state = 520 + self.state = 528 self.match(Parser.RULESET) - self.state = 521 + self.state = 529 self.rulesetID() - self.state = 522 + self.state = 530 self.match(Parser.LPAREN) - self.state = 523 + self.state = 531 self.hierRuleSignature() - self.state = 524 + self.state = 532 self.match(Parser.RPAREN) - self.state = 525 + self.state = 533 self.match(Parser.IS) - self.state = 526 + self.state = 534 self.ruleClauseHierarchical() - self.state = 527 + self.state = 535 self.match(Parser.END) - self.state = 528 + self.state = 536 self.match(Parser.HIERARCHICAL) - self.state = 529 + self.state = 537 self.match(Parser.RULESET) pass + elif la_ == 4: + localctx = Parser.DefViralPropagationContext(self, localctx) + self.enterOuterAlt(localctx, 4) + self.state = 539 + self.match(Parser.DEFINE) + self.state = 540 + self.match(Parser.VIRAL) + self.state = 541 + self.match(Parser.PROPAGATION) + self.state = 542 + self.varID() + self.state = 543 + self.match(Parser.LPAREN) + self.state = 544 + self.vpSignature() + self.state = 545 + self.match(Parser.RPAREN) + self.state = 546 + self.match(Parser.IS) + self.state = 547 + self.vpBody() + self.state = 548 + self.match(Parser.END) + self.state = 549 + self.match(Parser.VIRAL) + self.state = 550 + self.match(Parser.PROPAGATION) + pass + + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + class VpSignatureContext(ParserRuleContext): + __slots__ = "parser" + + def __init__(self, parser, parent: ParserRuleContext = None, invokingState: int = -1): + super().__init__(parent, invokingState) + self.parser = parser + + def VALUE_DOMAIN(self): + return self.getToken(Parser.VALUE_DOMAIN, 0) + + def varID(self): + return self.getTypedRuleContext(Parser.VarIDContext, 0) + + def VARIABLE(self): + return self.getToken(Parser.VARIABLE, 0) + + def getRuleIndex(self): + return Parser.RULE_vpSignature + + def accept(self, visitor: ParseTreeVisitor): + if hasattr(visitor, "visitVpSignature"): + return visitor.visitVpSignature(self) + else: + return visitor.visitChildren(self) + + def vpSignature(self): + + localctx = Parser.VpSignatureContext(self, self._ctx, self.state) + self.enterRule(localctx, 34, self.RULE_vpSignature) + try: + self.state = 558 + self._errHandler.sync(self) + token = self._input.LA(1) + if token in [Parser.VALUE_DOMAIN]: + self.enterOuterAlt(localctx, 1) + self.state = 554 + self.match(Parser.VALUE_DOMAIN) + self.state = 555 + self.varID() + pass + elif token in [Parser.VARIABLE]: + self.enterOuterAlt(localctx, 2) + self.state = 556 + self.match(Parser.VARIABLE) + self.state = 557 + self.varID() + pass + else: + raise NoViableAltException(self) + + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + class VpBodyContext(ParserRuleContext): + __slots__ = "parser" + + def __init__(self, parser, parent: ParserRuleContext = None, invokingState: int = -1): + super().__init__(parent, invokingState) + self.parser = parser + + def vpClause(self, i: int = None): + if i is None: + return self.getTypedRuleContexts(Parser.VpClauseContext) + else: + return self.getTypedRuleContext(Parser.VpClauseContext, i) + + def EOL(self, i: int = None): + if i is None: + return self.getTokens(Parser.EOL) + else: + return self.getToken(Parser.EOL, i) + + def getRuleIndex(self): + return Parser.RULE_vpBody + + def accept(self, visitor: ParseTreeVisitor): + if hasattr(visitor, "visitVpBody"): + return visitor.visitVpBody(self) + else: + return visitor.visitChildren(self) + + def vpBody(self): + + localctx = Parser.VpBodyContext(self, self._ctx, self.state) + self.enterRule(localctx, 36, self.RULE_vpBody) + self._la = 0 # Token type + try: + self.enterOuterAlt(localctx, 1) + self.state = 560 + self.vpClause() + self.state = 565 + self._errHandler.sync(self) + _la = self._input.LA(1) + while _la == Parser.EOL: + self.state = 561 + self.match(Parser.EOL) + self.state = 562 + self.vpClause() + self.state = 567 + self._errHandler.sync(self) + _la = self._input.LA(1) + + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + class VpClauseContext(ParserRuleContext): + __slots__ = "parser" + + def __init__(self, parser, parent: ParserRuleContext = None, invokingState: int = -1): + super().__init__(parent, invokingState) + self.parser = parser + + def getRuleIndex(self): + return Parser.RULE_vpClause + + def copyFrom(self, ctx: ParserRuleContext): + super().copyFrom(ctx) + + class AggregationVpClauseContext(VpClauseContext): + def __init__(self, parser, ctx: ParserRuleContext): # actually a Parser.VpClauseContext + super().__init__(parser) + self.copyFrom(ctx) + + def AGGREGATE(self): + return self.getToken(Parser.AGGREGATE, 0) + + def MIN(self): + return self.getToken(Parser.MIN, 0) + + def MAX(self): + return self.getToken(Parser.MAX, 0) + + def SUM(self): + return self.getToken(Parser.SUM, 0) + + def AVG(self): + return self.getToken(Parser.AVG, 0) + + def accept(self, visitor: ParseTreeVisitor): + if hasattr(visitor, "visitAggregationVpClause"): + return visitor.visitAggregationVpClause(self) + else: + return visitor.visitChildren(self) + + class DefaultVpClauseContext(VpClauseContext): + def __init__(self, parser, ctx: ParserRuleContext): # actually a Parser.VpClauseContext + super().__init__(parser) + self.copyFrom(ctx) + + def ELSE(self): + return self.getToken(Parser.ELSE, 0) + + def constant(self): + return self.getTypedRuleContext(Parser.ConstantContext, 0) + + def accept(self, visitor: ParseTreeVisitor): + if hasattr(visitor, "visitDefaultVpClause"): + return visitor.visitDefaultVpClause(self) + else: + return visitor.visitChildren(self) + + class EnumeratedVpClauseContext(VpClauseContext): + def __init__(self, parser, ctx: ParserRuleContext): # actually a Parser.VpClauseContext + super().__init__(parser) + self.copyFrom(ctx) + + def WHEN(self): + return self.getToken(Parser.WHEN, 0) + + def vpCondition(self): + return self.getTypedRuleContext(Parser.VpConditionContext, 0) + + def THEN(self): + return self.getToken(Parser.THEN, 0) + + def constant(self): + return self.getTypedRuleContext(Parser.ConstantContext, 0) + + def IDENTIFIER(self): + return self.getToken(Parser.IDENTIFIER, 0) + + def COLON(self): + return self.getToken(Parser.COLON, 0) + + def accept(self, visitor: ParseTreeVisitor): + if hasattr(visitor, "visitEnumeratedVpClause"): + return visitor.visitEnumeratedVpClause(self) + else: + return visitor.visitChildren(self) + + def vpClause(self): + + localctx = Parser.VpClauseContext(self, self._ctx, self.state) + self.enterRule(localctx, 38, self.RULE_vpClause) + self._la = 0 # Token type + try: + self.state = 581 + self._errHandler.sync(self) + token = self._input.LA(1) + if token in [Parser.WHEN, Parser.IDENTIFIER]: + localctx = Parser.EnumeratedVpClauseContext(self, localctx) + self.enterOuterAlt(localctx, 1) + self.state = 570 + self._errHandler.sync(self) + _la = self._input.LA(1) + if _la == Parser.IDENTIFIER: + self.state = 568 + self.match(Parser.IDENTIFIER) + self.state = 569 + self.match(Parser.COLON) + + self.state = 572 + self.match(Parser.WHEN) + self.state = 573 + self.vpCondition() + self.state = 574 + self.match(Parser.THEN) + self.state = 575 + self.constant() + pass + elif token in [Parser.AGGREGATE]: + localctx = Parser.AggregationVpClauseContext(self, localctx) + self.enterOuterAlt(localctx, 2) + self.state = 577 + self.match(Parser.AGGREGATE) + self.state = 578 + _la = self._input.LA(1) + if not ( + ((_la - 80) & ~0x3F) == 0 + and ( + (1 << (_la - 80)) + & ( + (1 << (Parser.MIN - 80)) + | (1 << (Parser.MAX - 80)) + | (1 << (Parser.SUM - 80)) + | (1 << (Parser.AVG - 80)) + ) + ) + != 0 + ): + self._errHandler.recoverInline(self) + else: + self._errHandler.reportMatch(self) + self.consume() + pass + elif token in [Parser.ELSE]: + localctx = Parser.DefaultVpClauseContext(self, localctx) + self.enterOuterAlt(localctx, 3) + self.state = 579 + self.match(Parser.ELSE) + self.state = 580 + self.constant() + pass + else: + raise NoViableAltException(self) + + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + class VpConditionContext(ParserRuleContext): + __slots__ = "parser" + + def __init__(self, parser, parent: ParserRuleContext = None, invokingState: int = -1): + super().__init__(parent, invokingState) + self.parser = parser + + def constant(self, i: int = None): + if i is None: + return self.getTypedRuleContexts(Parser.ConstantContext) + else: + return self.getTypedRuleContext(Parser.ConstantContext, i) + + def AND(self): + return self.getToken(Parser.AND, 0) + + def getRuleIndex(self): + return Parser.RULE_vpCondition + + def accept(self, visitor: ParseTreeVisitor): + if hasattr(visitor, "visitVpCondition"): + return visitor.visitVpCondition(self) + else: + return visitor.visitChildren(self) + + def vpCondition(self): + + localctx = Parser.VpConditionContext(self, self._ctx, self.state) + self.enterRule(localctx, 40, self.RULE_vpCondition) + self._la = 0 # Token type + try: + self.enterOuterAlt(localctx, 1) + self.state = 583 + self.constant() + self.state = 586 + self._errHandler.sync(self) + _la = self._input.LA(1) + if _la == Parser.AND: + self.state = 584 + self.match(Parser.AND) + self.state = 585 + self.constant() + except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) @@ -5081,20 +5513,20 @@ def accept(self, visitor: ParseTreeVisitor): def genericOperators(self): localctx = Parser.GenericOperatorsContext(self, self._ctx, self.state) - self.enterRule(localctx, 34, self.RULE_genericOperators) + self.enterRule(localctx, 42, self.RULE_genericOperators) self._la = 0 # Token type try: - self.state = 590 + self.state = 645 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.IDENTIFIER]: localctx = Parser.CallDatasetContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 533 + self.state = 588 self.operatorID() - self.state = 534 + self.state = 589 self.match(Parser.LPAREN) - self.state = 543 + self.state = 598 self._errHandler.sync(self) _la = self._input.LA(1) if ( @@ -5167,92 +5599,92 @@ def genericOperators(self): != 0 ) or ( - ((_la - 131) & ~0x3F) == 0 + ((_la - 132) & ~0x3F) == 0 and ( - (1 << (_la - 131)) + (1 << (_la - 132)) & ( - (1 << (Parser.LTRIM - 131)) - | (1 << (Parser.RTRIM - 131)) - | (1 << (Parser.INSTR - 131)) - | (1 << (Parser.REPLACE - 131)) - | (1 << (Parser.CEIL - 131)) - | (1 << (Parser.FLOOR - 131)) - | (1 << (Parser.SQRT - 131)) - | (1 << (Parser.SETDIFF - 131)) - | (1 << (Parser.STDDEV_POP - 131)) - | (1 << (Parser.STDDEV_SAMP - 131)) - | (1 << (Parser.VAR_POP - 131)) - | (1 << (Parser.VAR_SAMP - 131)) - | (1 << (Parser.FIRST_VALUE - 131)) - | (1 << (Parser.LAST_VALUE - 131)) - | (1 << (Parser.LAG - 131)) - | (1 << (Parser.LEAD - 131)) - | (1 << (Parser.RATIO_TO_REPORT - 131)) - | (1 << (Parser.FILL_TIME_SERIES - 131)) - | (1 << (Parser.FLOW_TO_STOCK - 131)) - | (1 << (Parser.STOCK_TO_FLOW - 131)) - | (1 << (Parser.TIMESHIFT - 131)) - | (1 << (Parser.INNER_JOIN - 131)) - | (1 << (Parser.LEFT_JOIN - 131)) + (1 << (Parser.LTRIM - 132)) + | (1 << (Parser.RTRIM - 132)) + | (1 << (Parser.INSTR - 132)) + | (1 << (Parser.REPLACE - 132)) + | (1 << (Parser.CEIL - 132)) + | (1 << (Parser.FLOOR - 132)) + | (1 << (Parser.SQRT - 132)) + | (1 << (Parser.SETDIFF - 132)) + | (1 << (Parser.STDDEV_POP - 132)) + | (1 << (Parser.STDDEV_SAMP - 132)) + | (1 << (Parser.VAR_POP - 132)) + | (1 << (Parser.VAR_SAMP - 132)) + | (1 << (Parser.FIRST_VALUE - 132)) + | (1 << (Parser.LAST_VALUE - 132)) + | (1 << (Parser.LAG - 132)) + | (1 << (Parser.LEAD - 132)) + | (1 << (Parser.RATIO_TO_REPORT - 132)) + | (1 << (Parser.FILL_TIME_SERIES - 132)) + | (1 << (Parser.FLOW_TO_STOCK - 132)) + | (1 << (Parser.STOCK_TO_FLOW - 132)) + | (1 << (Parser.TIMESHIFT - 132)) + | (1 << (Parser.INNER_JOIN - 132)) + | (1 << (Parser.LEFT_JOIN - 132)) ) ) != 0 ) or ( - ((_la - 195) & ~0x3F) == 0 + ((_la - 196) & ~0x3F) == 0 and ( - (1 << (_la - 195)) + (1 << (_la - 196)) & ( - (1 << (Parser.CROSS_JOIN - 195)) - | (1 << (Parser.FULL_JOIN - 195)) - | (1 << (Parser.PERIOD_INDICATOR - 195)) - | (1 << (Parser.TIME_AGG - 195)) - | (1 << (Parser.CAST - 195)) - | (1 << (Parser.CHECK_DATAPOINT - 195)) - | (1 << (Parser.CHECK_HIERARCHY - 195)) - | (1 << (Parser.INTEGER_CONSTANT - 195)) - | (1 << (Parser.NUMBER_CONSTANT - 195)) - | (1 << (Parser.BOOLEAN_CONSTANT - 195)) - | (1 << (Parser.STRING_CONSTANT - 195)) - | (1 << (Parser.IDENTIFIER - 195)) + (1 << (Parser.CROSS_JOIN - 196)) + | (1 << (Parser.FULL_JOIN - 196)) + | (1 << (Parser.PERIOD_INDICATOR - 196)) + | (1 << (Parser.TIME_AGG - 196)) + | (1 << (Parser.CAST - 196)) + | (1 << (Parser.CHECK_DATAPOINT - 196)) + | (1 << (Parser.CHECK_HIERARCHY - 196)) + | (1 << (Parser.INTEGER_CONSTANT - 196)) + | (1 << (Parser.NUMBER_CONSTANT - 196)) + | (1 << (Parser.BOOLEAN_CONSTANT - 196)) + | (1 << (Parser.STRING_CONSTANT - 196)) + | (1 << (Parser.IDENTIFIER - 196)) ) ) != 0 ) ): - self.state = 535 + self.state = 590 self.parameter() - self.state = 540 + self.state = 595 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 536 + self.state = 591 self.match(Parser.COMMA) - self.state = 537 + self.state = 592 self.parameter() - self.state = 542 + self.state = 597 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 545 + self.state = 600 self.match(Parser.RPAREN) pass elif token in [Parser.EVAL]: localctx = Parser.EvalAtomContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 547 + self.state = 602 self.match(Parser.EVAL) - self.state = 548 + self.state = 603 self.match(Parser.LPAREN) - self.state = 549 + self.state = 604 self.routineName() - self.state = 550 + self.state = 605 self.match(Parser.LPAREN) - self.state = 553 + self.state = 608 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.IDENTIFIER]: - self.state = 551 + self.state = 606 self.varID() pass elif token in [ @@ -5265,24 +5697,24 @@ def genericOperators(self): Parser.BOOLEAN_CONSTANT, Parser.STRING_CONSTANT, ]: - self.state = 552 + self.state = 607 self.scalarItem() pass elif token in [Parser.RPAREN, Parser.COMMA]: pass else: pass - self.state = 562 + self.state = 617 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 555 + self.state = 610 self.match(Parser.COMMA) - self.state = 558 + self.state = 613 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.IDENTIFIER]: - self.state = 556 + self.state = 611 self.varID() pass elif token in [ @@ -5295,51 +5727,51 @@ def genericOperators(self): Parser.BOOLEAN_CONSTANT, Parser.STRING_CONSTANT, ]: - self.state = 557 + self.state = 612 self.scalarItem() pass else: raise NoViableAltException(self) - self.state = 564 + self.state = 619 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 565 + self.state = 620 self.match(Parser.RPAREN) - self.state = 568 + self.state = 623 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.LANGUAGE: - self.state = 566 + self.state = 621 self.match(Parser.LANGUAGE) - self.state = 567 + self.state = 622 self.match(Parser.STRING_CONSTANT) - self.state = 572 + self.state = 627 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.RETURNS: - self.state = 570 + self.state = 625 self.match(Parser.RETURNS) - self.state = 571 + self.state = 626 self.evalDatasetType() - self.state = 574 + self.state = 629 self.match(Parser.RPAREN) pass elif token in [Parser.CAST]: localctx = Parser.CastExprDatasetContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 576 + self.state = 631 self.match(Parser.CAST) - self.state = 577 + self.state = 632 self.match(Parser.LPAREN) - self.state = 578 + self.state = 633 self.expr(0) - self.state = 579 + self.state = 634 self.match(Parser.COMMA) - self.state = 582 + self.state = 637 self._errHandler.sync(self) token = self._input.LA(1) if token in [ @@ -5353,26 +5785,26 @@ def genericOperators(self): Parser.DURATION, Parser.SCALAR, ]: - self.state = 580 + self.state = 635 self.basicScalarType() pass elif token in [Parser.IDENTIFIER]: - self.state = 581 + self.state = 636 self.valueDomainName() pass else: raise NoViableAltException(self) - self.state = 586 + self.state = 641 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 584 + self.state = 639 self.match(Parser.COMMA) - self.state = 585 + self.state = 640 self.match(Parser.STRING_CONSTANT) - self.state = 588 + self.state = 643 self.match(Parser.RPAREN) pass else: @@ -5537,20 +5969,20 @@ def accept(self, visitor: ParseTreeVisitor): def genericOperatorsComponent(self): localctx = Parser.GenericOperatorsComponentContext(self, self._ctx, self.state) - self.enterRule(localctx, 36, self.RULE_genericOperatorsComponent) + self.enterRule(localctx, 44, self.RULE_genericOperatorsComponent) self._la = 0 # Token type try: - self.state = 649 + self.state = 704 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.IDENTIFIER]: localctx = Parser.CallComponentContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 592 + self.state = 647 self.operatorID() - self.state = 593 + self.state = 648 self.match(Parser.LPAREN) - self.state = 602 + self.state = 657 self._errHandler.sync(self) _la = self._input.LA(1) if ( @@ -5620,7 +6052,6 @@ def genericOperatorsComponent(self): | (1 << (Parser.CEIL - 77)) | (1 << (Parser.FLOOR - 77)) | (1 << (Parser.SQRT - 77)) - | (1 << (Parser.STDDEV_POP - 77)) ) ) != 0 @@ -5630,7 +6061,8 @@ def genericOperatorsComponent(self): and ( (1 << (_la - 141)) & ( - (1 << (Parser.STDDEV_SAMP - 141)) + (1 << (Parser.STDDEV_POP - 141)) + | (1 << (Parser.STDDEV_SAMP - 141)) | (1 << (Parser.VAR_POP - 141)) | (1 << (Parser.VAR_SAMP - 141)) | (1 << (Parser.FIRST_VALUE - 141)) @@ -5647,52 +6079,52 @@ def genericOperatorsComponent(self): != 0 ) or ( - ((_la - 208) & ~0x3F) == 0 + ((_la - 209) & ~0x3F) == 0 and ( - (1 << (_la - 208)) + (1 << (_la - 209)) & ( - (1 << (Parser.PERIOD_INDICATOR - 208)) - | (1 << (Parser.TIME_AGG - 208)) - | (1 << (Parser.CAST - 208)) - | (1 << (Parser.INTEGER_CONSTANT - 208)) - | (1 << (Parser.NUMBER_CONSTANT - 208)) - | (1 << (Parser.BOOLEAN_CONSTANT - 208)) - | (1 << (Parser.STRING_CONSTANT - 208)) - | (1 << (Parser.IDENTIFIER - 208)) + (1 << (Parser.PERIOD_INDICATOR - 209)) + | (1 << (Parser.TIME_AGG - 209)) + | (1 << (Parser.CAST - 209)) + | (1 << (Parser.INTEGER_CONSTANT - 209)) + | (1 << (Parser.NUMBER_CONSTANT - 209)) + | (1 << (Parser.BOOLEAN_CONSTANT - 209)) + | (1 << (Parser.STRING_CONSTANT - 209)) + | (1 << (Parser.IDENTIFIER - 209)) ) ) != 0 ) ): - self.state = 594 + self.state = 649 self.parameterComponent() - self.state = 599 + self.state = 654 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 595 + self.state = 650 self.match(Parser.COMMA) - self.state = 596 + self.state = 651 self.parameterComponent() - self.state = 601 + self.state = 656 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 604 + self.state = 659 self.match(Parser.RPAREN) pass elif token in [Parser.CAST]: localctx = Parser.CastExprComponentContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 606 + self.state = 661 self.match(Parser.CAST) - self.state = 607 + self.state = 662 self.match(Parser.LPAREN) - self.state = 608 + self.state = 663 self.exprComponent(0) - self.state = 609 + self.state = 664 self.match(Parser.COMMA) - self.state = 612 + self.state = 667 self._errHandler.sync(self) token = self._input.LA(1) if token in [ @@ -5706,44 +6138,44 @@ def genericOperatorsComponent(self): Parser.DURATION, Parser.SCALAR, ]: - self.state = 610 + self.state = 665 self.basicScalarType() pass elif token in [Parser.IDENTIFIER]: - self.state = 611 + self.state = 666 self.valueDomainName() pass else: raise NoViableAltException(self) - self.state = 616 + self.state = 671 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 614 + self.state = 669 self.match(Parser.COMMA) - self.state = 615 + self.state = 670 self.match(Parser.STRING_CONSTANT) - self.state = 618 + self.state = 673 self.match(Parser.RPAREN) pass elif token in [Parser.EVAL]: localctx = Parser.EvalAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 620 + self.state = 675 self.match(Parser.EVAL) - self.state = 621 + self.state = 676 self.match(Parser.LPAREN) - self.state = 622 + self.state = 677 self.routineName() - self.state = 623 + self.state = 678 self.match(Parser.LPAREN) - self.state = 626 + self.state = 681 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.IDENTIFIER]: - self.state = 624 + self.state = 679 self.componentID() pass elif token in [ @@ -5756,24 +6188,24 @@ def genericOperatorsComponent(self): Parser.BOOLEAN_CONSTANT, Parser.STRING_CONSTANT, ]: - self.state = 625 + self.state = 680 self.scalarItem() pass elif token in [Parser.RPAREN, Parser.COMMA]: pass else: pass - self.state = 635 + self.state = 690 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 628 + self.state = 683 self.match(Parser.COMMA) - self.state = 631 + self.state = 686 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.IDENTIFIER]: - self.state = 629 + self.state = 684 self.componentID() pass elif token in [ @@ -5786,37 +6218,37 @@ def genericOperatorsComponent(self): Parser.BOOLEAN_CONSTANT, Parser.STRING_CONSTANT, ]: - self.state = 630 + self.state = 685 self.scalarItem() pass else: raise NoViableAltException(self) - self.state = 637 + self.state = 692 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 638 + self.state = 693 self.match(Parser.RPAREN) - self.state = 641 + self.state = 696 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.LANGUAGE: - self.state = 639 + self.state = 694 self.match(Parser.LANGUAGE) - self.state = 640 + self.state = 695 self.match(Parser.STRING_CONSTANT) - self.state = 645 + self.state = 700 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.RETURNS: - self.state = 643 + self.state = 698 self.match(Parser.RETURNS) - self.state = 644 + self.state = 699 self.outputParameterTypeComponent() - self.state = 647 + self.state = 702 self.match(Parser.RPAREN) pass else: @@ -5855,9 +6287,9 @@ def accept(self, visitor: ParseTreeVisitor): def parameterComponent(self): localctx = Parser.ParameterComponentContext(self, self._ctx, self.state) - self.enterRule(localctx, 38, self.RULE_parameterComponent) + self.enterRule(localctx, 46, self.RULE_parameterComponent) try: - self.state = 653 + self.state = 708 self._errHandler.sync(self) token = self._input.LA(1) if token in [ @@ -5935,12 +6367,12 @@ def parameterComponent(self): Parser.IDENTIFIER, ]: self.enterOuterAlt(localctx, 1) - self.state = 651 + self.state = 706 self.exprComponent(0) pass elif token in [Parser.OPTIONAL]: self.enterOuterAlt(localctx, 2) - self.state = 652 + self.state = 707 self.match(Parser.OPTIONAL) pass else: @@ -5979,9 +6411,9 @@ def accept(self, visitor: ParseTreeVisitor): def parameter(self): localctx = Parser.ParameterContext(self, self._ctx, self.state) - self.enterRule(localctx, 40, self.RULE_parameter) + self.enterRule(localctx, 48, self.RULE_parameter) try: - self.state = 657 + self.state = 712 self._errHandler.sync(self) token = self._input.LA(1) if token in [ @@ -6071,12 +6503,12 @@ def parameter(self): Parser.IDENTIFIER, ]: self.enterOuterAlt(localctx, 1) - self.state = 655 + self.state = 710 self.expr(0) pass elif token in [Parser.OPTIONAL]: self.enterOuterAlt(localctx, 2) - self.state = 656 + self.state = 711 self.match(Parser.OPTIONAL) pass else: @@ -6267,10 +6699,10 @@ def accept(self, visitor: ParseTreeVisitor): def stringOperators(self): localctx = Parser.StringOperatorsContext(self, self._ctx, self.state) - self.enterRule(localctx, 42, self.RULE_stringOperators) + self.enterRule(localctx, 50, self.RULE_stringOperators) self._la = 0 # Token type try: - self.state = 707 + self.state = 762 self._errHandler.sync(self) token = self._input.LA(1) if token in [ @@ -6283,7 +6715,7 @@ def stringOperators(self): ]: localctx = Parser.UnaryStringFunctionContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 659 + self.state = 714 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not ( @@ -6305,109 +6737,109 @@ def stringOperators(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 660 + self.state = 715 self.match(Parser.LPAREN) - self.state = 661 + self.state = 716 self.expr(0) - self.state = 662 + self.state = 717 self.match(Parser.RPAREN) pass elif token in [Parser.SUBSTR]: localctx = Parser.SubstrAtomContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 664 + self.state = 719 self.match(Parser.SUBSTR) - self.state = 665 + self.state = 720 self.match(Parser.LPAREN) - self.state = 666 + self.state = 721 self.expr(0) - self.state = 677 + self.state = 732 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 50, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 55, self._ctx) if la_ == 1: - self.state = 673 + self.state = 728 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 667 + self.state = 722 self.match(Parser.COMMA) - self.state = 668 + self.state = 723 localctx.startParameter = self.optionalExpr() - self.state = 670 + self.state = 725 self.match(Parser.COMMA) - self.state = 671 + self.state = 726 localctx.endParameter = self.optionalExpr() pass elif la_ == 2: - self.state = 675 + self.state = 730 self.match(Parser.COMMA) - self.state = 676 + self.state = 731 localctx.startParameter = self.optionalExpr() pass - self.state = 679 + self.state = 734 self.match(Parser.RPAREN) pass elif token in [Parser.REPLACE]: localctx = Parser.ReplaceAtomContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 681 + self.state = 736 self.match(Parser.REPLACE) - self.state = 682 + self.state = 737 self.match(Parser.LPAREN) - self.state = 683 + self.state = 738 self.expr(0) - self.state = 684 + self.state = 739 self.match(Parser.COMMA) - self.state = 685 + self.state = 740 localctx.param = self.expr(0) - self.state = 688 + self.state = 743 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 686 + self.state = 741 self.match(Parser.COMMA) - self.state = 687 + self.state = 742 self.optionalExpr() - self.state = 690 + self.state = 745 self.match(Parser.RPAREN) pass elif token in [Parser.INSTR]: localctx = Parser.InstrAtomContext(self, localctx) self.enterOuterAlt(localctx, 4) - self.state = 692 + self.state = 747 self.match(Parser.INSTR) - self.state = 693 + self.state = 748 self.match(Parser.LPAREN) - self.state = 694 + self.state = 749 self.expr(0) - self.state = 695 + self.state = 750 self.match(Parser.COMMA) - self.state = 696 + self.state = 751 localctx.pattern = self.expr(0) - self.state = 699 + self.state = 754 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 52, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 57, self._ctx) if la_ == 1: - self.state = 697 + self.state = 752 self.match(Parser.COMMA) - self.state = 698 + self.state = 753 localctx.startParameter = self.optionalExpr() - self.state = 703 + self.state = 758 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 701 + self.state = 756 self.match(Parser.COMMA) - self.state = 702 + self.state = 757 localctx.occurrenceParameter = self.optionalExpr() - self.state = 705 + self.state = 760 self.match(Parser.RPAREN) pass else: @@ -6598,10 +7030,10 @@ def accept(self, visitor: ParseTreeVisitor): def stringOperatorsComponent(self): localctx = Parser.StringOperatorsComponentContext(self, self._ctx, self.state) - self.enterRule(localctx, 44, self.RULE_stringOperatorsComponent) + self.enterRule(localctx, 52, self.RULE_stringOperatorsComponent) self._la = 0 # Token type try: - self.state = 757 + self.state = 812 self._errHandler.sync(self) token = self._input.LA(1) if token in [ @@ -6614,7 +7046,7 @@ def stringOperatorsComponent(self): ]: localctx = Parser.UnaryStringFunctionComponentContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 709 + self.state = 764 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not ( @@ -6636,109 +7068,109 @@ def stringOperatorsComponent(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 710 + self.state = 765 self.match(Parser.LPAREN) - self.state = 711 + self.state = 766 self.exprComponent(0) - self.state = 712 + self.state = 767 self.match(Parser.RPAREN) pass elif token in [Parser.SUBSTR]: localctx = Parser.SubstrAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 714 + self.state = 769 self.match(Parser.SUBSTR) - self.state = 715 + self.state = 770 self.match(Parser.LPAREN) - self.state = 716 + self.state = 771 self.exprComponent(0) - self.state = 727 + self.state = 782 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 56, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 61, self._ctx) if la_ == 1: - self.state = 723 + self.state = 778 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 717 + self.state = 772 self.match(Parser.COMMA) - self.state = 718 + self.state = 773 localctx.startParameter = self.optionalExprComponent() - self.state = 720 + self.state = 775 self.match(Parser.COMMA) - self.state = 721 + self.state = 776 localctx.endParameter = self.optionalExprComponent() pass elif la_ == 2: - self.state = 725 + self.state = 780 self.match(Parser.COMMA) - self.state = 726 + self.state = 781 localctx.startParameter = self.optionalExprComponent() pass - self.state = 729 + self.state = 784 self.match(Parser.RPAREN) pass elif token in [Parser.REPLACE]: localctx = Parser.ReplaceAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 731 + self.state = 786 self.match(Parser.REPLACE) - self.state = 732 + self.state = 787 self.match(Parser.LPAREN) - self.state = 733 + self.state = 788 self.exprComponent(0) - self.state = 734 + self.state = 789 self.match(Parser.COMMA) - self.state = 735 + self.state = 790 localctx.param = self.exprComponent(0) - self.state = 738 + self.state = 793 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 736 + self.state = 791 self.match(Parser.COMMA) - self.state = 737 + self.state = 792 self.optionalExprComponent() - self.state = 740 + self.state = 795 self.match(Parser.RPAREN) pass elif token in [Parser.INSTR]: localctx = Parser.InstrAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 4) - self.state = 742 + self.state = 797 self.match(Parser.INSTR) - self.state = 743 + self.state = 798 self.match(Parser.LPAREN) - self.state = 744 + self.state = 799 self.exprComponent(0) - self.state = 745 + self.state = 800 self.match(Parser.COMMA) - self.state = 746 + self.state = 801 localctx.pattern = self.exprComponent(0) - self.state = 749 + self.state = 804 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 58, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 63, self._ctx) if la_ == 1: - self.state = 747 + self.state = 802 self.match(Parser.COMMA) - self.state = 748 + self.state = 803 localctx.startParameter = self.optionalExprComponent() - self.state = 753 + self.state = 808 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 751 + self.state = 806 self.match(Parser.COMMA) - self.state = 752 + self.state = 807 localctx.occurrenceParameter = self.optionalExprComponent() - self.state = 755 + self.state = 810 self.match(Parser.RPAREN) pass else: @@ -6887,16 +7319,16 @@ def accept(self, visitor: ParseTreeVisitor): def numericOperators(self): localctx = Parser.NumericOperatorsContext(self, self._ctx, self.state) - self.enterRule(localctx, 46, self.RULE_numericOperators) + self.enterRule(localctx, 54, self.RULE_numericOperators) self._la = 0 # Token type try: - self.state = 780 + self.state = 835 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.ABS, Parser.LN, Parser.EXP, Parser.CEIL, Parser.FLOOR, Parser.SQRT]: localctx = Parser.UnaryNumericContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 759 + self.state = 814 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not ( @@ -6918,17 +7350,17 @@ def numericOperators(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 760 + self.state = 815 self.match(Parser.LPAREN) - self.state = 761 + self.state = 816 self.expr(0) - self.state = 762 + self.state = 817 self.match(Parser.RPAREN) pass elif token in [Parser.TRUNC, Parser.ROUND]: localctx = Parser.UnaryWithOptionalNumericContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 764 + self.state = 819 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.TRUNC or _la == Parser.ROUND): @@ -6936,26 +7368,26 @@ def numericOperators(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 765 + self.state = 820 self.match(Parser.LPAREN) - self.state = 766 + self.state = 821 self.expr(0) - self.state = 769 + self.state = 824 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 767 + self.state = 822 self.match(Parser.COMMA) - self.state = 768 + self.state = 823 self.optionalExpr() - self.state = 771 + self.state = 826 self.match(Parser.RPAREN) pass elif token in [Parser.RANDOM, Parser.LOG, Parser.POWER, Parser.MOD]: localctx = Parser.BinaryNumericContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 773 + self.state = 828 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not ( @@ -6975,15 +7407,15 @@ def numericOperators(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 774 + self.state = 829 self.match(Parser.LPAREN) - self.state = 775 + self.state = 830 localctx.left = self.expr(0) - self.state = 776 + self.state = 831 self.match(Parser.COMMA) - self.state = 777 + self.state = 832 localctx.right = self.expr(0) - self.state = 778 + self.state = 833 self.match(Parser.RPAREN) pass else: @@ -7132,16 +7564,16 @@ def accept(self, visitor: ParseTreeVisitor): def numericOperatorsComponent(self): localctx = Parser.NumericOperatorsComponentContext(self, self._ctx, self.state) - self.enterRule(localctx, 48, self.RULE_numericOperatorsComponent) + self.enterRule(localctx, 56, self.RULE_numericOperatorsComponent) self._la = 0 # Token type try: - self.state = 803 + self.state = 858 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.ABS, Parser.LN, Parser.EXP, Parser.CEIL, Parser.FLOOR, Parser.SQRT]: localctx = Parser.UnaryNumericComponentContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 782 + self.state = 837 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not ( @@ -7163,17 +7595,17 @@ def numericOperatorsComponent(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 783 + self.state = 838 self.match(Parser.LPAREN) - self.state = 784 + self.state = 839 self.exprComponent(0) - self.state = 785 + self.state = 840 self.match(Parser.RPAREN) pass elif token in [Parser.TRUNC, Parser.ROUND]: localctx = Parser.UnaryWithOptionalNumericComponentContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 787 + self.state = 842 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.TRUNC or _la == Parser.ROUND): @@ -7181,26 +7613,26 @@ def numericOperatorsComponent(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 788 + self.state = 843 self.match(Parser.LPAREN) - self.state = 789 + self.state = 844 self.exprComponent(0) - self.state = 792 + self.state = 847 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 790 + self.state = 845 self.match(Parser.COMMA) - self.state = 791 + self.state = 846 self.optionalExprComponent() - self.state = 794 + self.state = 849 self.match(Parser.RPAREN) pass elif token in [Parser.RANDOM, Parser.LOG, Parser.POWER, Parser.MOD]: localctx = Parser.BinaryNumericComponentContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 796 + self.state = 851 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not ( @@ -7220,15 +7652,15 @@ def numericOperatorsComponent(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 797 + self.state = 852 self.match(Parser.LPAREN) - self.state = 798 + self.state = 853 localctx.left = self.exprComponent(0) - self.state = 799 + self.state = 854 self.match(Parser.COMMA) - self.state = 800 + self.state = 855 localctx.right = self.exprComponent(0) - self.state = 801 + self.state = 856 self.match(Parser.RPAREN) pass else: @@ -7392,83 +7824,83 @@ def accept(self, visitor: ParseTreeVisitor): def comparisonOperators(self): localctx = Parser.ComparisonOperatorsContext(self, self._ctx, self.state) - self.enterRule(localctx, 50, self.RULE_comparisonOperators) + self.enterRule(localctx, 58, self.RULE_comparisonOperators) self._la = 0 # Token type try: - self.state = 837 + self.state = 892 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.BETWEEN]: localctx = Parser.BetweenAtomContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 805 + self.state = 860 self.match(Parser.BETWEEN) - self.state = 806 + self.state = 861 self.match(Parser.LPAREN) - self.state = 807 + self.state = 862 localctx.op = self.expr(0) - self.state = 808 + self.state = 863 self.match(Parser.COMMA) - self.state = 809 + self.state = 864 localctx.from_ = self.expr(0) - self.state = 810 + self.state = 865 self.match(Parser.COMMA) - self.state = 811 + self.state = 866 localctx.to_ = self.expr(0) - self.state = 812 + self.state = 867 self.match(Parser.RPAREN) pass elif token in [Parser.CHARSET_MATCH]: localctx = Parser.CharsetMatchAtomContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 814 + self.state = 869 self.match(Parser.CHARSET_MATCH) - self.state = 815 + self.state = 870 self.match(Parser.LPAREN) - self.state = 816 + self.state = 871 localctx.op = self.expr(0) - self.state = 817 + self.state = 872 self.match(Parser.COMMA) - self.state = 818 + self.state = 873 localctx.pattern = self.expr(0) - self.state = 819 + self.state = 874 self.match(Parser.RPAREN) pass elif token in [Parser.ISNULL]: localctx = Parser.IsNullAtomContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 821 + self.state = 876 self.match(Parser.ISNULL) - self.state = 822 + self.state = 877 self.match(Parser.LPAREN) - self.state = 823 + self.state = 878 self.expr(0) - self.state = 824 + self.state = 879 self.match(Parser.RPAREN) pass elif token in [Parser.EXISTS_IN]: localctx = Parser.ExistInAtomContext(self, localctx) self.enterOuterAlt(localctx, 4) - self.state = 826 + self.state = 881 self.match(Parser.EXISTS_IN) - self.state = 827 + self.state = 882 self.match(Parser.LPAREN) - self.state = 828 + self.state = 883 localctx.left = self.expr(0) - self.state = 829 + self.state = 884 self.match(Parser.COMMA) - self.state = 830 + self.state = 885 localctx.right = self.expr(0) - self.state = 833 + self.state = 888 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 831 + self.state = 886 self.match(Parser.COMMA) - self.state = 832 + self.state = 887 self.retainType() - self.state = 835 + self.state = 890 self.match(Parser.RPAREN) pass else: @@ -7593,57 +8025,57 @@ def accept(self, visitor: ParseTreeVisitor): def comparisonOperatorsComponent(self): localctx = Parser.ComparisonOperatorsComponentContext(self, self._ctx, self.state) - self.enterRule(localctx, 52, self.RULE_comparisonOperatorsComponent) + self.enterRule(localctx, 60, self.RULE_comparisonOperatorsComponent) try: - self.state = 860 + self.state = 915 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.BETWEEN]: localctx = Parser.BetweenAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 839 + self.state = 894 self.match(Parser.BETWEEN) - self.state = 840 + self.state = 895 self.match(Parser.LPAREN) - self.state = 841 + self.state = 896 localctx.op = self.exprComponent(0) - self.state = 842 + self.state = 897 self.match(Parser.COMMA) - self.state = 843 + self.state = 898 localctx.from_ = self.exprComponent(0) - self.state = 844 + self.state = 899 self.match(Parser.COMMA) - self.state = 845 + self.state = 900 localctx.to_ = self.exprComponent(0) - self.state = 846 + self.state = 901 self.match(Parser.RPAREN) pass elif token in [Parser.CHARSET_MATCH]: localctx = Parser.CharsetMatchAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 848 + self.state = 903 self.match(Parser.CHARSET_MATCH) - self.state = 849 + self.state = 904 self.match(Parser.LPAREN) - self.state = 850 + self.state = 905 localctx.op = self.exprComponent(0) - self.state = 851 + self.state = 906 self.match(Parser.COMMA) - self.state = 852 + self.state = 907 localctx.pattern = self.exprComponent(0) - self.state = 853 + self.state = 908 self.match(Parser.RPAREN) pass elif token in [Parser.ISNULL]: localctx = Parser.IsNullAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 855 + self.state = 910 self.match(Parser.ISNULL) - self.state = 856 + self.state = 911 self.match(Parser.LPAREN) - self.state = 857 + self.state = 912 self.exprComponent(0) - self.state = 858 + self.state = 913 self.match(Parser.RPAREN) pass else: @@ -8135,20 +8567,20 @@ def accept(self, visitor: ParseTreeVisitor): def timeOperators(self): localctx = Parser.TimeOperatorsContext(self, self._ctx, self.state) - self.enterRule(localctx, 54, self.RULE_timeOperators) + self.enterRule(localctx, 62, self.RULE_timeOperators) self._la = 0 # Token type try: - self.state = 964 + self.state = 1019 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.PERIOD_INDICATOR]: localctx = Parser.PeriodAtomContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 862 + self.state = 917 self.match(Parser.PERIOD_INDICATOR) - self.state = 863 + self.state = 918 self.match(Parser.LPAREN) - self.state = 865 + self.state = 920 self._errHandler.sync(self) _la = self._input.LA(1) if ( @@ -8220,81 +8652,81 @@ def timeOperators(self): != 0 ) or ( - ((_la - 131) & ~0x3F) == 0 + ((_la - 132) & ~0x3F) == 0 and ( - (1 << (_la - 131)) + (1 << (_la - 132)) & ( - (1 << (Parser.LTRIM - 131)) - | (1 << (Parser.RTRIM - 131)) - | (1 << (Parser.INSTR - 131)) - | (1 << (Parser.REPLACE - 131)) - | (1 << (Parser.CEIL - 131)) - | (1 << (Parser.FLOOR - 131)) - | (1 << (Parser.SQRT - 131)) - | (1 << (Parser.SETDIFF - 131)) - | (1 << (Parser.STDDEV_POP - 131)) - | (1 << (Parser.STDDEV_SAMP - 131)) - | (1 << (Parser.VAR_POP - 131)) - | (1 << (Parser.VAR_SAMP - 131)) - | (1 << (Parser.FIRST_VALUE - 131)) - | (1 << (Parser.LAST_VALUE - 131)) - | (1 << (Parser.LAG - 131)) - | (1 << (Parser.LEAD - 131)) - | (1 << (Parser.RATIO_TO_REPORT - 131)) - | (1 << (Parser.FILL_TIME_SERIES - 131)) - | (1 << (Parser.FLOW_TO_STOCK - 131)) - | (1 << (Parser.STOCK_TO_FLOW - 131)) - | (1 << (Parser.TIMESHIFT - 131)) - | (1 << (Parser.INNER_JOIN - 131)) - | (1 << (Parser.LEFT_JOIN - 131)) + (1 << (Parser.LTRIM - 132)) + | (1 << (Parser.RTRIM - 132)) + | (1 << (Parser.INSTR - 132)) + | (1 << (Parser.REPLACE - 132)) + | (1 << (Parser.CEIL - 132)) + | (1 << (Parser.FLOOR - 132)) + | (1 << (Parser.SQRT - 132)) + | (1 << (Parser.SETDIFF - 132)) + | (1 << (Parser.STDDEV_POP - 132)) + | (1 << (Parser.STDDEV_SAMP - 132)) + | (1 << (Parser.VAR_POP - 132)) + | (1 << (Parser.VAR_SAMP - 132)) + | (1 << (Parser.FIRST_VALUE - 132)) + | (1 << (Parser.LAST_VALUE - 132)) + | (1 << (Parser.LAG - 132)) + | (1 << (Parser.LEAD - 132)) + | (1 << (Parser.RATIO_TO_REPORT - 132)) + | (1 << (Parser.FILL_TIME_SERIES - 132)) + | (1 << (Parser.FLOW_TO_STOCK - 132)) + | (1 << (Parser.STOCK_TO_FLOW - 132)) + | (1 << (Parser.TIMESHIFT - 132)) + | (1 << (Parser.INNER_JOIN - 132)) + | (1 << (Parser.LEFT_JOIN - 132)) ) ) != 0 ) or ( - ((_la - 195) & ~0x3F) == 0 + ((_la - 196) & ~0x3F) == 0 and ( - (1 << (_la - 195)) + (1 << (_la - 196)) & ( - (1 << (Parser.CROSS_JOIN - 195)) - | (1 << (Parser.FULL_JOIN - 195)) - | (1 << (Parser.PERIOD_INDICATOR - 195)) - | (1 << (Parser.TIME_AGG - 195)) - | (1 << (Parser.CAST - 195)) - | (1 << (Parser.CHECK_DATAPOINT - 195)) - | (1 << (Parser.CHECK_HIERARCHY - 195)) - | (1 << (Parser.INTEGER_CONSTANT - 195)) - | (1 << (Parser.NUMBER_CONSTANT - 195)) - | (1 << (Parser.BOOLEAN_CONSTANT - 195)) - | (1 << (Parser.STRING_CONSTANT - 195)) - | (1 << (Parser.IDENTIFIER - 195)) + (1 << (Parser.CROSS_JOIN - 196)) + | (1 << (Parser.FULL_JOIN - 196)) + | (1 << (Parser.PERIOD_INDICATOR - 196)) + | (1 << (Parser.TIME_AGG - 196)) + | (1 << (Parser.CAST - 196)) + | (1 << (Parser.CHECK_DATAPOINT - 196)) + | (1 << (Parser.CHECK_HIERARCHY - 196)) + | (1 << (Parser.INTEGER_CONSTANT - 196)) + | (1 << (Parser.NUMBER_CONSTANT - 196)) + | (1 << (Parser.BOOLEAN_CONSTANT - 196)) + | (1 << (Parser.STRING_CONSTANT - 196)) + | (1 << (Parser.IDENTIFIER - 196)) ) ) != 0 ) ): - self.state = 864 + self.state = 919 self.expr(0) - self.state = 867 + self.state = 922 self.match(Parser.RPAREN) pass elif token in [Parser.FILL_TIME_SERIES]: localctx = Parser.FillTimeAtomContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 868 + self.state = 923 self.match(Parser.FILL_TIME_SERIES) - self.state = 869 + self.state = 924 self.match(Parser.LPAREN) - self.state = 870 + self.state = 925 self.expr(0) - self.state = 873 + self.state = 928 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 871 + self.state = 926 self.match(Parser.COMMA) - self.state = 872 + self.state = 927 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.ALL or _la == Parser.SINGLE): @@ -8303,13 +8735,13 @@ def timeOperators(self): self._errHandler.reportMatch(self) self.consume() - self.state = 875 + self.state = 930 self.match(Parser.RPAREN) pass elif token in [Parser.FLOW_TO_STOCK, Parser.STOCK_TO_FLOW]: localctx = Parser.FlowAtomContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 877 + self.state = 932 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.FLOW_TO_STOCK or _la == Parser.STOCK_TO_FLOW): @@ -8317,45 +8749,45 @@ def timeOperators(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 878 + self.state = 933 self.match(Parser.LPAREN) - self.state = 879 + self.state = 934 self.expr(0) - self.state = 880 + self.state = 935 self.match(Parser.RPAREN) pass elif token in [Parser.TIMESHIFT]: localctx = Parser.TimeShiftAtomContext(self, localctx) self.enterOuterAlt(localctx, 4) - self.state = 882 + self.state = 937 self.match(Parser.TIMESHIFT) - self.state = 883 + self.state = 938 self.match(Parser.LPAREN) - self.state = 884 + self.state = 939 self.expr(0) - self.state = 885 + self.state = 940 self.match(Parser.COMMA) - self.state = 886 + self.state = 941 self.signedInteger() - self.state = 887 + self.state = 942 self.match(Parser.RPAREN) pass elif token in [Parser.TIME_AGG]: localctx = Parser.TimeAggAtomContext(self, localctx) self.enterOuterAlt(localctx, 5) - self.state = 889 + self.state = 944 self.match(Parser.TIME_AGG) - self.state = 890 + self.state = 945 self.match(Parser.LPAREN) - self.state = 891 + self.state = 946 localctx.periodIndTo = self.match(Parser.STRING_CONSTANT) - self.state = 894 + self.state = 949 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 70, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 75, self._ctx) if la_ == 1: - self.state = 892 + self.state = 947 self.match(Parser.COMMA) - self.state = 893 + self.state = 948 localctx.periodIndFrom = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.OPTIONAL or _la == Parser.STRING_CONSTANT): @@ -8364,22 +8796,22 @@ def timeOperators(self): self._errHandler.reportMatch(self) self.consume() - self.state = 898 + self.state = 953 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 71, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 76, self._ctx) if la_ == 1: - self.state = 896 + self.state = 951 self.match(Parser.COMMA) - self.state = 897 + self.state = 952 localctx.op = self.optionalExpr() - self.state = 902 + self.state = 957 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 900 + self.state = 955 self.match(Parser.COMMA) - self.state = 901 + self.state = 956 localctx.delim = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.FIRST or _la == Parser.LAST): @@ -8388,149 +8820,149 @@ def timeOperators(self): self._errHandler.reportMatch(self) self.consume() - self.state = 904 + self.state = 959 self.match(Parser.RPAREN) pass elif token in [Parser.CURRENT_DATE]: localctx = Parser.CurrentDateAtomContext(self, localctx) self.enterOuterAlt(localctx, 6) - self.state = 905 + self.state = 960 self.match(Parser.CURRENT_DATE) - self.state = 906 + self.state = 961 self.match(Parser.LPAREN) - self.state = 907 + self.state = 962 self.match(Parser.RPAREN) pass elif token in [Parser.DATEDIFF]: localctx = Parser.DateDiffAtomContext(self, localctx) self.enterOuterAlt(localctx, 7) - self.state = 908 + self.state = 963 self.match(Parser.DATEDIFF) - self.state = 909 + self.state = 964 self.match(Parser.LPAREN) - self.state = 910 + self.state = 965 localctx.dateFrom = self.expr(0) - self.state = 911 + self.state = 966 self.match(Parser.COMMA) - self.state = 912 + self.state = 967 localctx.dateTo = self.expr(0) - self.state = 913 + self.state = 968 self.match(Parser.RPAREN) pass elif token in [Parser.DATEADD]: localctx = Parser.DateAddAtomContext(self, localctx) self.enterOuterAlt(localctx, 8) - self.state = 915 + self.state = 970 self.match(Parser.DATEADD) - self.state = 916 + self.state = 971 self.match(Parser.LPAREN) - self.state = 917 + self.state = 972 localctx.op = self.expr(0) - self.state = 918 + self.state = 973 self.match(Parser.COMMA) - self.state = 919 + self.state = 974 localctx.shiftNumber = self.expr(0) - self.state = 920 + self.state = 975 self.match(Parser.COMMA) - self.state = 921 + self.state = 976 localctx.periodInd = self.expr(0) - self.state = 922 + self.state = 977 self.match(Parser.RPAREN) pass elif token in [Parser.YEAR_OP]: localctx = Parser.YearAtomContext(self, localctx) self.enterOuterAlt(localctx, 9) - self.state = 924 + self.state = 979 self.match(Parser.YEAR_OP) - self.state = 925 + self.state = 980 self.match(Parser.LPAREN) - self.state = 926 + self.state = 981 self.expr(0) - self.state = 927 + self.state = 982 self.match(Parser.RPAREN) pass elif token in [Parser.MONTH_OP]: localctx = Parser.MonthAtomContext(self, localctx) self.enterOuterAlt(localctx, 10) - self.state = 929 + self.state = 984 self.match(Parser.MONTH_OP) - self.state = 930 + self.state = 985 self.match(Parser.LPAREN) - self.state = 931 + self.state = 986 self.expr(0) - self.state = 932 + self.state = 987 self.match(Parser.RPAREN) pass elif token in [Parser.DAYOFMONTH]: localctx = Parser.DayOfMonthAtomContext(self, localctx) self.enterOuterAlt(localctx, 11) - self.state = 934 + self.state = 989 self.match(Parser.DAYOFMONTH) - self.state = 935 + self.state = 990 self.match(Parser.LPAREN) - self.state = 936 + self.state = 991 self.expr(0) - self.state = 937 + self.state = 992 self.match(Parser.RPAREN) pass elif token in [Parser.DAYOFYEAR]: localctx = Parser.DayOfYearAtomContext(self, localctx) self.enterOuterAlt(localctx, 12) - self.state = 939 + self.state = 994 self.match(Parser.DAYOFYEAR) - self.state = 940 + self.state = 995 self.match(Parser.LPAREN) - self.state = 941 + self.state = 996 self.expr(0) - self.state = 942 + self.state = 997 self.match(Parser.RPAREN) pass elif token in [Parser.DAYTOYEAR]: localctx = Parser.DayToYearAtomContext(self, localctx) self.enterOuterAlt(localctx, 13) - self.state = 944 + self.state = 999 self.match(Parser.DAYTOYEAR) - self.state = 945 + self.state = 1000 self.match(Parser.LPAREN) - self.state = 946 + self.state = 1001 self.expr(0) - self.state = 947 + self.state = 1002 self.match(Parser.RPAREN) pass elif token in [Parser.DAYTOMONTH]: localctx = Parser.DayToMonthAtomContext(self, localctx) self.enterOuterAlt(localctx, 14) - self.state = 949 + self.state = 1004 self.match(Parser.DAYTOMONTH) - self.state = 950 + self.state = 1005 self.match(Parser.LPAREN) - self.state = 951 + self.state = 1006 self.expr(0) - self.state = 952 + self.state = 1007 self.match(Parser.RPAREN) pass elif token in [Parser.YEARTODAY]: localctx = Parser.YearTodayAtomContext(self, localctx) self.enterOuterAlt(localctx, 15) - self.state = 954 + self.state = 1009 self.match(Parser.YEARTODAY) - self.state = 955 + self.state = 1010 self.match(Parser.LPAREN) - self.state = 956 + self.state = 1011 self.expr(0) - self.state = 957 + self.state = 1012 self.match(Parser.RPAREN) pass elif token in [Parser.MONTHTODAY]: localctx = Parser.MonthTodayAtomContext(self, localctx) self.enterOuterAlt(localctx, 16) - self.state = 959 + self.state = 1014 self.match(Parser.MONTHTODAY) - self.state = 960 + self.state = 1015 self.match(Parser.LPAREN) - self.state = 961 + self.state = 1016 self.expr(0) - self.state = 962 + self.state = 1017 self.match(Parser.RPAREN) pass else: @@ -9022,20 +9454,20 @@ def accept(self, visitor: ParseTreeVisitor): def timeOperatorsComponent(self): localctx = Parser.TimeOperatorsComponentContext(self, self._ctx, self.state) - self.enterRule(localctx, 56, self.RULE_timeOperatorsComponent) + self.enterRule(localctx, 64, self.RULE_timeOperatorsComponent) self._la = 0 # Token type try: - self.state = 1068 + self.state = 1123 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.PERIOD_INDICATOR]: localctx = Parser.PeriodAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 966 + self.state = 1021 self.match(Parser.PERIOD_INDICATOR) - self.state = 967 + self.state = 1022 self.match(Parser.LPAREN) - self.state = 969 + self.state = 1024 self._errHandler.sync(self) _la = self._input.LA(1) if ( @@ -9104,7 +9536,6 @@ def timeOperatorsComponent(self): | (1 << (Parser.CEIL - 77)) | (1 << (Parser.FLOOR - 77)) | (1 << (Parser.SQRT - 77)) - | (1 << (Parser.STDDEV_POP - 77)) ) ) != 0 @@ -9114,7 +9545,8 @@ def timeOperatorsComponent(self): and ( (1 << (_la - 141)) & ( - (1 << (Parser.STDDEV_SAMP - 141)) + (1 << (Parser.STDDEV_POP - 141)) + | (1 << (Parser.STDDEV_SAMP - 141)) | (1 << (Parser.VAR_POP - 141)) | (1 << (Parser.VAR_SAMP - 141)) | (1 << (Parser.FIRST_VALUE - 141)) @@ -9131,45 +9563,45 @@ def timeOperatorsComponent(self): != 0 ) or ( - ((_la - 208) & ~0x3F) == 0 + ((_la - 209) & ~0x3F) == 0 and ( - (1 << (_la - 208)) + (1 << (_la - 209)) & ( - (1 << (Parser.PERIOD_INDICATOR - 208)) - | (1 << (Parser.TIME_AGG - 208)) - | (1 << (Parser.CAST - 208)) - | (1 << (Parser.INTEGER_CONSTANT - 208)) - | (1 << (Parser.NUMBER_CONSTANT - 208)) - | (1 << (Parser.BOOLEAN_CONSTANT - 208)) - | (1 << (Parser.STRING_CONSTANT - 208)) - | (1 << (Parser.IDENTIFIER - 208)) + (1 << (Parser.PERIOD_INDICATOR - 209)) + | (1 << (Parser.TIME_AGG - 209)) + | (1 << (Parser.CAST - 209)) + | (1 << (Parser.INTEGER_CONSTANT - 209)) + | (1 << (Parser.NUMBER_CONSTANT - 209)) + | (1 << (Parser.BOOLEAN_CONSTANT - 209)) + | (1 << (Parser.STRING_CONSTANT - 209)) + | (1 << (Parser.IDENTIFIER - 209)) ) ) != 0 ) ): - self.state = 968 + self.state = 1023 self.exprComponent(0) - self.state = 971 + self.state = 1026 self.match(Parser.RPAREN) pass elif token in [Parser.FILL_TIME_SERIES]: localctx = Parser.FillTimeAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 972 + self.state = 1027 self.match(Parser.FILL_TIME_SERIES) - self.state = 973 + self.state = 1028 self.match(Parser.LPAREN) - self.state = 974 + self.state = 1029 self.exprComponent(0) - self.state = 977 + self.state = 1032 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 975 + self.state = 1030 self.match(Parser.COMMA) - self.state = 976 + self.state = 1031 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.ALL or _la == Parser.SINGLE): @@ -9178,13 +9610,13 @@ def timeOperatorsComponent(self): self._errHandler.reportMatch(self) self.consume() - self.state = 979 + self.state = 1034 self.match(Parser.RPAREN) pass elif token in [Parser.FLOW_TO_STOCK, Parser.STOCK_TO_FLOW]: localctx = Parser.FlowAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 981 + self.state = 1036 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.FLOW_TO_STOCK or _la == Parser.STOCK_TO_FLOW): @@ -9192,45 +9624,45 @@ def timeOperatorsComponent(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 982 + self.state = 1037 self.match(Parser.LPAREN) - self.state = 983 + self.state = 1038 self.exprComponent(0) - self.state = 984 + self.state = 1039 self.match(Parser.RPAREN) pass elif token in [Parser.TIMESHIFT]: localctx = Parser.TimeShiftAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 4) - self.state = 986 + self.state = 1041 self.match(Parser.TIMESHIFT) - self.state = 987 + self.state = 1042 self.match(Parser.LPAREN) - self.state = 988 + self.state = 1043 self.exprComponent(0) - self.state = 989 + self.state = 1044 self.match(Parser.COMMA) - self.state = 990 + self.state = 1045 self.signedInteger() - self.state = 991 + self.state = 1046 self.match(Parser.RPAREN) pass elif token in [Parser.TIME_AGG]: localctx = Parser.TimeAggAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 5) - self.state = 993 + self.state = 1048 self.match(Parser.TIME_AGG) - self.state = 994 + self.state = 1049 self.match(Parser.LPAREN) - self.state = 995 + self.state = 1050 localctx.periodIndTo = self.match(Parser.STRING_CONSTANT) - self.state = 998 + self.state = 1053 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 76, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 81, self._ctx) if la_ == 1: - self.state = 996 + self.state = 1051 self.match(Parser.COMMA) - self.state = 997 + self.state = 1052 localctx.periodIndFrom = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.OPTIONAL or _la == Parser.STRING_CONSTANT): @@ -9239,22 +9671,22 @@ def timeOperatorsComponent(self): self._errHandler.reportMatch(self) self.consume() - self.state = 1002 + self.state = 1057 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 77, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 82, self._ctx) if la_ == 1: - self.state = 1000 + self.state = 1055 self.match(Parser.COMMA) - self.state = 1001 + self.state = 1056 localctx.op = self.optionalExprComponent() - self.state = 1006 + self.state = 1061 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 1004 + self.state = 1059 self.match(Parser.COMMA) - self.state = 1005 + self.state = 1060 localctx.delim = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.FIRST or _la == Parser.LAST): @@ -9263,149 +9695,149 @@ def timeOperatorsComponent(self): self._errHandler.reportMatch(self) self.consume() - self.state = 1008 + self.state = 1063 self.match(Parser.RPAREN) pass elif token in [Parser.CURRENT_DATE]: localctx = Parser.CurrentDateAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 6) - self.state = 1009 + self.state = 1064 self.match(Parser.CURRENT_DATE) - self.state = 1010 + self.state = 1065 self.match(Parser.LPAREN) - self.state = 1011 + self.state = 1066 self.match(Parser.RPAREN) pass elif token in [Parser.DATEDIFF]: localctx = Parser.DateDiffAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 7) - self.state = 1012 + self.state = 1067 self.match(Parser.DATEDIFF) - self.state = 1013 + self.state = 1068 self.match(Parser.LPAREN) - self.state = 1014 + self.state = 1069 localctx.dateFrom = self.exprComponent(0) - self.state = 1015 + self.state = 1070 self.match(Parser.COMMA) - self.state = 1016 + self.state = 1071 localctx.dateTo = self.expr(0) - self.state = 1017 + self.state = 1072 self.match(Parser.RPAREN) pass elif token in [Parser.DATEADD]: localctx = Parser.DateAddAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 8) - self.state = 1019 + self.state = 1074 self.match(Parser.DATEADD) - self.state = 1020 + self.state = 1075 self.match(Parser.LPAREN) - self.state = 1021 + self.state = 1076 localctx.op = self.exprComponent(0) - self.state = 1022 + self.state = 1077 self.match(Parser.COMMA) - self.state = 1023 + self.state = 1078 localctx.shiftNumber = self.exprComponent(0) - self.state = 1024 + self.state = 1079 self.match(Parser.COMMA) - self.state = 1025 + self.state = 1080 localctx.periodInd = self.exprComponent(0) - self.state = 1026 + self.state = 1081 self.match(Parser.RPAREN) pass elif token in [Parser.YEAR_OP]: localctx = Parser.YearAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 9) - self.state = 1028 + self.state = 1083 self.match(Parser.YEAR_OP) - self.state = 1029 + self.state = 1084 self.match(Parser.LPAREN) - self.state = 1030 + self.state = 1085 self.exprComponent(0) - self.state = 1031 + self.state = 1086 self.match(Parser.RPAREN) pass elif token in [Parser.MONTH_OP]: localctx = Parser.MonthAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 10) - self.state = 1033 + self.state = 1088 self.match(Parser.MONTH_OP) - self.state = 1034 + self.state = 1089 self.match(Parser.LPAREN) - self.state = 1035 + self.state = 1090 self.exprComponent(0) - self.state = 1036 + self.state = 1091 self.match(Parser.RPAREN) pass elif token in [Parser.DAYOFMONTH]: localctx = Parser.DayOfMonthAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 11) - self.state = 1038 + self.state = 1093 self.match(Parser.DAYOFMONTH) - self.state = 1039 + self.state = 1094 self.match(Parser.LPAREN) - self.state = 1040 + self.state = 1095 self.exprComponent(0) - self.state = 1041 + self.state = 1096 self.match(Parser.RPAREN) pass elif token in [Parser.DAYOFYEAR]: localctx = Parser.DatOfYearAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 12) - self.state = 1043 + self.state = 1098 self.match(Parser.DAYOFYEAR) - self.state = 1044 + self.state = 1099 self.match(Parser.LPAREN) - self.state = 1045 + self.state = 1100 self.exprComponent(0) - self.state = 1046 + self.state = 1101 self.match(Parser.RPAREN) pass elif token in [Parser.DAYTOYEAR]: localctx = Parser.DayToYearAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 13) - self.state = 1048 + self.state = 1103 self.match(Parser.DAYTOYEAR) - self.state = 1049 + self.state = 1104 self.match(Parser.LPAREN) - self.state = 1050 + self.state = 1105 self.exprComponent(0) - self.state = 1051 + self.state = 1106 self.match(Parser.RPAREN) pass elif token in [Parser.DAYTOMONTH]: localctx = Parser.DayToMonthAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 14) - self.state = 1053 + self.state = 1108 self.match(Parser.DAYTOMONTH) - self.state = 1054 + self.state = 1109 self.match(Parser.LPAREN) - self.state = 1055 + self.state = 1110 self.exprComponent(0) - self.state = 1056 + self.state = 1111 self.match(Parser.RPAREN) pass elif token in [Parser.YEARTODAY]: localctx = Parser.YearTodayAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 15) - self.state = 1058 + self.state = 1113 self.match(Parser.YEARTODAY) - self.state = 1059 + self.state = 1114 self.match(Parser.LPAREN) - self.state = 1060 + self.state = 1115 self.exprComponent(0) - self.state = 1061 + self.state = 1116 self.match(Parser.RPAREN) pass elif token in [Parser.MONTHTODAY]: localctx = Parser.MonthTodayAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 16) - self.state = 1063 + self.state = 1118 self.match(Parser.MONTHTODAY) - self.state = 1064 + self.state = 1119 self.match(Parser.LPAREN) - self.state = 1065 + self.state = 1120 self.exprComponent(0) - self.state = 1066 + self.state = 1121 self.match(Parser.RPAREN) pass else: @@ -9536,68 +9968,68 @@ def accept(self, visitor: ParseTreeVisitor): def setOperators(self): localctx = Parser.SetOperatorsContext(self, self._ctx, self.state) - self.enterRule(localctx, 58, self.RULE_setOperators) + self.enterRule(localctx, 66, self.RULE_setOperators) self._la = 0 # Token type try: - self.state = 1099 + self.state = 1154 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.UNION]: localctx = Parser.UnionAtomContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 1070 + self.state = 1125 self.match(Parser.UNION) - self.state = 1071 + self.state = 1126 self.match(Parser.LPAREN) - self.state = 1072 + self.state = 1127 localctx.left = self.expr(0) - self.state = 1075 + self.state = 1130 self._errHandler.sync(self) _la = self._input.LA(1) while True: - self.state = 1073 + self.state = 1128 self.match(Parser.COMMA) - self.state = 1074 + self.state = 1129 self.expr(0) - self.state = 1077 + self.state = 1132 self._errHandler.sync(self) _la = self._input.LA(1) - if _la != Parser.COMMA: + if not (_la == Parser.COMMA): break - self.state = 1079 + self.state = 1134 self.match(Parser.RPAREN) pass elif token in [Parser.INTERSECT]: localctx = Parser.IntersectAtomContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 1081 + self.state = 1136 self.match(Parser.INTERSECT) - self.state = 1082 + self.state = 1137 self.match(Parser.LPAREN) - self.state = 1083 + self.state = 1138 localctx.left = self.expr(0) - self.state = 1086 + self.state = 1141 self._errHandler.sync(self) _la = self._input.LA(1) while True: - self.state = 1084 + self.state = 1139 self.match(Parser.COMMA) - self.state = 1085 + self.state = 1140 self.expr(0) - self.state = 1088 + self.state = 1143 self._errHandler.sync(self) _la = self._input.LA(1) - if _la != Parser.COMMA: + if not (_la == Parser.COMMA): break - self.state = 1090 + self.state = 1145 self.match(Parser.RPAREN) pass elif token in [Parser.SYMDIFF, Parser.SETDIFF]: localctx = Parser.SetOrSYmDiffAtomContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 1092 + self.state = 1147 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.SYMDIFF or _la == Parser.SETDIFF): @@ -9605,15 +10037,15 @@ def setOperators(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 1093 + self.state = 1148 self.match(Parser.LPAREN) - self.state = 1094 + self.state = 1149 localctx.left = self.expr(0) - self.state = 1095 + self.state = 1150 self.match(Parser.COMMA) - self.state = 1096 + self.state = 1151 localctx.right = self.expr(0) - self.state = 1097 + self.state = 1152 self.match(Parser.RPAREN) pass else: @@ -9685,68 +10117,68 @@ def accept(self, visitor: ParseTreeVisitor): def hierarchyOperators(self): localctx = Parser.HierarchyOperatorsContext(self, self._ctx, self.state) - self.enterRule(localctx, 60, self.RULE_hierarchyOperators) + self.enterRule(localctx, 68, self.RULE_hierarchyOperators) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1101 + self.state = 1156 self.match(Parser.HIERARCHY) - self.state = 1102 + self.state = 1157 self.match(Parser.LPAREN) - self.state = 1103 + self.state = 1158 localctx.op = self.expr(0) - self.state = 1104 + self.state = 1159 self.match(Parser.COMMA) - self.state = 1105 + self.state = 1160 localctx.hrName = self.match(Parser.IDENTIFIER) - self.state = 1107 + self.state = 1162 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.CONDITION: - self.state = 1106 + self.state = 1161 self.conditionClause() - self.state = 1111 + self.state = 1166 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 84, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 89, self._ctx) if la_ == 1: - self.state = 1109 + self.state = 1164 self.match(Parser.RULE) - self.state = 1110 + self.state = 1165 localctx.ruleComponent = self.componentID() - self.state = 1114 + self.state = 1169 self._errHandler.sync(self) _la = self._input.LA(1) - if ((_la - 225) & ~0x3F) == 0 and ( - (1 << (_la - 225)) + if ((_la - 226) & ~0x3F) == 0 and ( + (1 << (_la - 226)) & ( - (1 << (Parser.NON_NULL - 225)) - | (1 << (Parser.NON_ZERO - 225)) - | (1 << (Parser.PARTIAL_NULL - 225)) - | (1 << (Parser.PARTIAL_ZERO - 225)) - | (1 << (Parser.ALWAYS_NULL - 225)) - | (1 << (Parser.ALWAYS_ZERO - 225)) + (1 << (Parser.NON_NULL - 226)) + | (1 << (Parser.NON_ZERO - 226)) + | (1 << (Parser.PARTIAL_NULL - 226)) + | (1 << (Parser.PARTIAL_ZERO - 226)) + | (1 << (Parser.ALWAYS_NULL - 226)) + | (1 << (Parser.ALWAYS_ZERO - 226)) ) ) != 0: - self.state = 1113 + self.state = 1168 self.validationMode() - self.state = 1117 + self.state = 1172 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.DATASET or _la == Parser.RULE or _la == Parser.RULE_PRIORITY: - self.state = 1116 + self.state = 1171 self.inputModeHierarchy() - self.state = 1120 + self.state = 1175 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.ALL or _la == Parser.COMPUTED: - self.state = 1119 + self.state = 1174 self.outputModeHierarchy() - self.state = 1122 + self.state = 1177 self.match(Parser.RPAREN) except RecognitionException as re: localctx.exception = re @@ -9915,153 +10347,153 @@ def accept(self, visitor: ParseTreeVisitor): def validationOperators(self): localctx = Parser.ValidationOperatorsContext(self, self._ctx, self.state) - self.enterRule(localctx, 62, self.RULE_validationOperators) + self.enterRule(localctx, 70, self.RULE_validationOperators) self._la = 0 # Token type try: - self.state = 1185 + self.state = 1240 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.CHECK_DATAPOINT]: localctx = Parser.ValidateDPrulesetContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 1124 + self.state = 1179 self.match(Parser.CHECK_DATAPOINT) - self.state = 1125 + self.state = 1180 self.match(Parser.LPAREN) - self.state = 1126 + self.state = 1181 localctx.op = self.expr(0) - self.state = 1127 + self.state = 1182 self.match(Parser.COMMA) - self.state = 1128 + self.state = 1183 localctx.dpName = self.match(Parser.IDENTIFIER) - self.state = 1138 + self.state = 1193 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMPONENTS: - self.state = 1129 + self.state = 1184 self.match(Parser.COMPONENTS) - self.state = 1130 + self.state = 1185 self.componentID() - self.state = 1135 + self.state = 1190 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 1131 + self.state = 1186 self.match(Parser.COMMA) - self.state = 1132 + self.state = 1187 self.componentID() - self.state = 1137 + self.state = 1192 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 1141 + self.state = 1196 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.ALL or _la == Parser.INVALID or _la == Parser.ALL_MEASURES: - self.state = 1140 + self.state = 1195 self.validationOutput() - self.state = 1143 + self.state = 1198 self.match(Parser.RPAREN) pass elif token in [Parser.CHECK_HIERARCHY]: localctx = Parser.ValidateHRrulesetContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 1145 + self.state = 1200 self.match(Parser.CHECK_HIERARCHY) - self.state = 1146 + self.state = 1201 self.match(Parser.LPAREN) - self.state = 1147 + self.state = 1202 localctx.op = self.expr(0) - self.state = 1148 + self.state = 1203 self.match(Parser.COMMA) - self.state = 1149 + self.state = 1204 localctx.hrName = self.match(Parser.IDENTIFIER) - self.state = 1151 + self.state = 1206 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.CONDITION: - self.state = 1150 + self.state = 1205 self.conditionClause() - self.state = 1155 + self.state = 1210 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.RULE: - self.state = 1153 + self.state = 1208 self.match(Parser.RULE) - self.state = 1154 + self.state = 1209 self.componentID() - self.state = 1158 + self.state = 1213 self._errHandler.sync(self) _la = self._input.LA(1) - if ((_la - 225) & ~0x3F) == 0 and ( - (1 << (_la - 225)) + if ((_la - 226) & ~0x3F) == 0 and ( + (1 << (_la - 226)) & ( - (1 << (Parser.NON_NULL - 225)) - | (1 << (Parser.NON_ZERO - 225)) - | (1 << (Parser.PARTIAL_NULL - 225)) - | (1 << (Parser.PARTIAL_ZERO - 225)) - | (1 << (Parser.ALWAYS_NULL - 225)) - | (1 << (Parser.ALWAYS_ZERO - 225)) + (1 << (Parser.NON_NULL - 226)) + | (1 << (Parser.NON_ZERO - 226)) + | (1 << (Parser.PARTIAL_NULL - 226)) + | (1 << (Parser.PARTIAL_ZERO - 226)) + | (1 << (Parser.ALWAYS_NULL - 226)) + | (1 << (Parser.ALWAYS_ZERO - 226)) ) ) != 0: - self.state = 1157 + self.state = 1212 self.validationMode() - self.state = 1161 + self.state = 1216 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.DATASET or _la == Parser.DATASET_PRIORITY: - self.state = 1160 + self.state = 1215 self.inputMode() - self.state = 1164 + self.state = 1219 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.ALL or _la == Parser.INVALID or _la == Parser.ALL_MEASURES: - self.state = 1163 + self.state = 1218 self.validationOutput() - self.state = 1166 + self.state = 1221 self.match(Parser.RPAREN) pass elif token in [Parser.CHECK]: localctx = Parser.ValidationSimpleContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 1168 + self.state = 1223 self.match(Parser.CHECK) - self.state = 1169 + self.state = 1224 self.match(Parser.LPAREN) - self.state = 1170 + self.state = 1225 localctx.op = self.expr(0) - self.state = 1172 + self.state = 1227 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.ERRORCODE: - self.state = 1171 + self.state = 1226 localctx.codeErr = self.erCode() - self.state = 1175 + self.state = 1230 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.ERRORLEVEL: - self.state = 1174 + self.state = 1229 localctx.levelCode = self.erLevel() - self.state = 1178 + self.state = 1233 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.IMBALANCE: - self.state = 1177 + self.state = 1232 self.imbalanceExpr() - self.state = 1181 + self.state = 1236 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.ALL or _la == Parser.INVALID: - self.state = 1180 + self.state = 1235 localctx.output = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.ALL or _la == Parser.INVALID): @@ -10070,7 +10502,7 @@ def validationOperators(self): self._errHandler.reportMatch(self) self.consume() - self.state = 1183 + self.state = 1238 self.match(Parser.RPAREN) pass else: @@ -10133,21 +10565,21 @@ def accept(self, visitor: ParseTreeVisitor): def conditionalOperators(self): localctx = Parser.ConditionalOperatorsContext(self, self._ctx, self.state) - self.enterRule(localctx, 64, self.RULE_conditionalOperators) + self.enterRule(localctx, 72, self.RULE_conditionalOperators) try: localctx = Parser.NvlAtomContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 1187 + self.state = 1242 self.match(Parser.NVL) - self.state = 1188 + self.state = 1243 self.match(Parser.LPAREN) - self.state = 1189 + self.state = 1244 localctx.left = self.expr(0) - self.state = 1190 + self.state = 1245 self.match(Parser.COMMA) - self.state = 1191 + self.state = 1246 localctx.right = self.expr(0) - self.state = 1192 + self.state = 1247 self.match(Parser.RPAREN) except RecognitionException as re: localctx.exception = re @@ -10206,21 +10638,21 @@ def accept(self, visitor: ParseTreeVisitor): def conditionalOperatorsComponent(self): localctx = Parser.ConditionalOperatorsComponentContext(self, self._ctx, self.state) - self.enterRule(localctx, 66, self.RULE_conditionalOperatorsComponent) + self.enterRule(localctx, 74, self.RULE_conditionalOperatorsComponent) try: localctx = Parser.NvlAtomComponentContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 1194 + self.state = 1249 self.match(Parser.NVL) - self.state = 1195 + self.state = 1250 self.match(Parser.LPAREN) - self.state = 1196 + self.state = 1251 localctx.left = self.exprComponent(0) - self.state = 1197 + self.state = 1252 self.match(Parser.COMMA) - self.state = 1198 + self.state = 1253 localctx.right = self.exprComponent(0) - self.state = 1199 + self.state = 1254 self.match(Parser.RPAREN) except RecognitionException as re: localctx.exception = re @@ -10321,57 +10753,59 @@ def accept(self, visitor: ParseTreeVisitor): def aggrOperators(self): localctx = Parser.AggrOperatorsContext(self, self._ctx, self.state) - self.enterRule(localctx, 68, self.RULE_aggrOperators) + self.enterRule(localctx, 76, self.RULE_aggrOperators) self._la = 0 # Token type try: - self.state = 1209 + self.state = 1264 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 101, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 106, self._ctx) if la_ == 1: localctx = Parser.AggrCompContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 1201 + self.state = 1256 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not ( - ((_la - 80) & ~0x3F) == 0 - and ( - (1 << (_la - 80)) - & ( - (1 << (Parser.MIN - 80)) - | (1 << (Parser.MAX - 80)) - | (1 << (Parser.SUM - 80)) - | (1 << (Parser.AVG - 80)) - | (1 << (Parser.MEDIAN - 80)) - | (1 << (Parser.COUNT - 80)) - | (1 << (Parser.STDDEV_POP - 80)) - | (1 << (Parser.STDDEV_SAMP - 80)) - | (1 << (Parser.VAR_POP - 80)) - | (1 << (Parser.VAR_SAMP - 80)) + ( + ((_la - 80) & ~0x3F) == 0 + and ( + (1 << (_la - 80)) + & ( + (1 << (Parser.MIN - 80)) + | (1 << (Parser.MAX - 80)) + | (1 << (Parser.SUM - 80)) + | (1 << (Parser.AVG - 80)) + | (1 << (Parser.MEDIAN - 80)) + | (1 << (Parser.COUNT - 80)) + | (1 << (Parser.STDDEV_POP - 80)) + | (1 << (Parser.STDDEV_SAMP - 80)) + | (1 << (Parser.VAR_POP - 80)) + ) ) + != 0 ) - != 0 + or _la == Parser.VAR_SAMP ): localctx.op = self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) self.consume() - self.state = 1202 + self.state = 1257 self.match(Parser.LPAREN) - self.state = 1203 + self.state = 1258 self.exprComponent(0) - self.state = 1204 + self.state = 1259 self.match(Parser.RPAREN) pass elif la_ == 2: localctx = Parser.CountAggrCompContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 1206 + self.state = 1261 self.match(Parser.COUNT) - self.state = 1207 + self.state = 1262 self.match(Parser.LPAREN) - self.state = 1208 + self.state = 1263 self.match(Parser.RPAREN) pass @@ -10458,55 +10892,57 @@ def accept(self, visitor: ParseTreeVisitor): def aggrOperatorsGrouping(self): localctx = Parser.AggrOperatorsGroupingContext(self, self._ctx, self.state) - self.enterRule(localctx, 70, self.RULE_aggrOperatorsGrouping) + self.enterRule(localctx, 78, self.RULE_aggrOperatorsGrouping) self._la = 0 # Token type try: localctx = Parser.AggrDatasetContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 1211 + self.state = 1266 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not ( - ((_la - 80) & ~0x3F) == 0 - and ( - (1 << (_la - 80)) - & ( - (1 << (Parser.MIN - 80)) - | (1 << (Parser.MAX - 80)) - | (1 << (Parser.SUM - 80)) - | (1 << (Parser.AVG - 80)) - | (1 << (Parser.MEDIAN - 80)) - | (1 << (Parser.COUNT - 80)) - | (1 << (Parser.STDDEV_POP - 80)) - | (1 << (Parser.STDDEV_SAMP - 80)) - | (1 << (Parser.VAR_POP - 80)) - | (1 << (Parser.VAR_SAMP - 80)) + ( + ((_la - 80) & ~0x3F) == 0 + and ( + (1 << (_la - 80)) + & ( + (1 << (Parser.MIN - 80)) + | (1 << (Parser.MAX - 80)) + | (1 << (Parser.SUM - 80)) + | (1 << (Parser.AVG - 80)) + | (1 << (Parser.MEDIAN - 80)) + | (1 << (Parser.COUNT - 80)) + | (1 << (Parser.STDDEV_POP - 80)) + | (1 << (Parser.STDDEV_SAMP - 80)) + | (1 << (Parser.VAR_POP - 80)) + ) ) + != 0 ) - != 0 + or _la == Parser.VAR_SAMP ): localctx.op = self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) self.consume() - self.state = 1212 + self.state = 1267 self.match(Parser.LPAREN) - self.state = 1213 + self.state = 1268 self.expr(0) - self.state = 1218 + self.state = 1273 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.GROUP: - self.state = 1214 + self.state = 1269 self.groupingClause() - self.state = 1216 + self.state = 1271 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.HAVING: - self.state = 1215 + self.state = 1270 self.havingClause() - self.state = 1220 + self.state = 1275 self.match(Parser.RPAREN) except RecognitionException as re: localctx.exception = re @@ -10705,10 +11141,10 @@ def accept(self, visitor: ParseTreeVisitor): def anFunction(self): localctx = Parser.AnFunctionContext(self, self._ctx, self.state) - self.enterRule(localctx, 72, self.RULE_anFunction) + self.enterRule(localctx, 80, self.RULE_anFunction) self._la = 0 # Token type try: - self.state = 1269 + self.state = 1324 self._errHandler.sync(self) token = self._input.LA(1) if token in [ @@ -10727,7 +11163,7 @@ def anFunction(self): ]: localctx = Parser.AnSimpleFunctionContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 1222 + self.state = 1277 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not ( @@ -10745,57 +11181,66 @@ def anFunction(self): | (1 << (Parser.STDDEV_POP - 80)) | (1 << (Parser.STDDEV_SAMP - 80)) | (1 << (Parser.VAR_POP - 80)) - | (1 << (Parser.VAR_SAMP - 80)) ) ) != 0 ) - or _la == Parser.FIRST_VALUE - or _la == Parser.LAST_VALUE + or ( + ((_la - 144) & ~0x3F) == 0 + and ( + (1 << (_la - 144)) + & ( + (1 << (Parser.VAR_SAMP - 144)) + | (1 << (Parser.FIRST_VALUE - 144)) + | (1 << (Parser.LAST_VALUE - 144)) + ) + ) + != 0 + ) ): localctx.op = self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) self.consume() - self.state = 1223 + self.state = 1278 self.match(Parser.LPAREN) - self.state = 1224 + self.state = 1279 self.expr(0) - self.state = 1225 + self.state = 1280 self.match(Parser.OVER) - self.state = 1226 + self.state = 1281 self.match(Parser.LPAREN) - self.state = 1228 + self.state = 1283 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.PARTITION: - self.state = 1227 + self.state = 1282 localctx.partition = self.partitionByClause() - self.state = 1231 + self.state = 1286 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.ORDER: - self.state = 1230 + self.state = 1285 localctx.orderBy = self.orderByClause() - self.state = 1234 + self.state = 1289 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.DATA or _la == Parser.RANGE: - self.state = 1233 + self.state = 1288 localctx.windowing = self.windowingClause() - self.state = 1236 + self.state = 1291 self.match(Parser.RPAREN) - self.state = 1237 + self.state = 1292 self.match(Parser.RPAREN) pass elif token in [Parser.LAG, Parser.LEAD]: localctx = Parser.LagOrLeadAnContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 1239 + self.state = 1294 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.LAG or _la == Parser.LEAD): @@ -10803,65 +11248,65 @@ def anFunction(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 1240 + self.state = 1295 self.match(Parser.LPAREN) - self.state = 1241 + self.state = 1296 self.expr(0) - self.state = 1248 + self.state = 1303 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 1242 + self.state = 1297 self.match(Parser.COMMA) - self.state = 1243 + self.state = 1298 localctx.offset = self.signedInteger() - self.state = 1246 + self.state = 1301 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 1244 + self.state = 1299 self.match(Parser.COMMA) - self.state = 1245 + self.state = 1300 localctx.defaultValue = self.scalarItem() - self.state = 1250 + self.state = 1305 self.match(Parser.OVER) - self.state = 1251 + self.state = 1306 self.match(Parser.LPAREN) - self.state = 1253 + self.state = 1308 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.PARTITION: - self.state = 1252 + self.state = 1307 localctx.partition = self.partitionByClause() - self.state = 1255 + self.state = 1310 localctx.orderBy = self.orderByClause() - self.state = 1257 + self.state = 1312 self.match(Parser.RPAREN) - self.state = 1258 + self.state = 1313 self.match(Parser.RPAREN) pass elif token in [Parser.RATIO_TO_REPORT]: localctx = Parser.RatioToReportAnContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 1260 + self.state = 1315 localctx.op = self.match(Parser.RATIO_TO_REPORT) - self.state = 1261 + self.state = 1316 self.match(Parser.LPAREN) - self.state = 1262 + self.state = 1317 self.expr(0) - self.state = 1263 + self.state = 1318 self.match(Parser.OVER) - self.state = 1264 + self.state = 1319 self.match(Parser.LPAREN) - self.state = 1265 + self.state = 1320 localctx.partition = self.partitionByClause() - self.state = 1266 + self.state = 1321 self.match(Parser.RPAREN) - self.state = 1267 + self.state = 1322 self.match(Parser.RPAREN) pass else: @@ -11107,10 +11552,10 @@ def accept(self, visitor: ParseTreeVisitor): def anFunctionComponent(self): localctx = Parser.AnFunctionComponentContext(self, self._ctx, self.state) - self.enterRule(localctx, 74, self.RULE_anFunctionComponent) + self.enterRule(localctx, 82, self.RULE_anFunctionComponent) self._la = 0 # Token type try: - self.state = 1329 + self.state = 1384 self._errHandler.sync(self) token = self._input.LA(1) if token in [ @@ -11129,7 +11574,7 @@ def anFunctionComponent(self): ]: localctx = Parser.AnSimpleFunctionComponentContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 1271 + self.state = 1326 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not ( @@ -11147,57 +11592,66 @@ def anFunctionComponent(self): | (1 << (Parser.STDDEV_POP - 80)) | (1 << (Parser.STDDEV_SAMP - 80)) | (1 << (Parser.VAR_POP - 80)) - | (1 << (Parser.VAR_SAMP - 80)) ) ) != 0 ) - or _la == Parser.FIRST_VALUE - or _la == Parser.LAST_VALUE + or ( + ((_la - 144) & ~0x3F) == 0 + and ( + (1 << (_la - 144)) + & ( + (1 << (Parser.VAR_SAMP - 144)) + | (1 << (Parser.FIRST_VALUE - 144)) + | (1 << (Parser.LAST_VALUE - 144)) + ) + ) + != 0 + ) ): localctx.op = self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) self.consume() - self.state = 1272 + self.state = 1327 self.match(Parser.LPAREN) - self.state = 1273 + self.state = 1328 self.exprComponent(0) - self.state = 1274 + self.state = 1329 self.match(Parser.OVER) - self.state = 1275 + self.state = 1330 self.match(Parser.LPAREN) - self.state = 1277 + self.state = 1332 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.PARTITION: - self.state = 1276 + self.state = 1331 localctx.partition = self.partitionByClause() - self.state = 1280 + self.state = 1335 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.ORDER: - self.state = 1279 + self.state = 1334 localctx.orderBy = self.orderByClause() - self.state = 1283 + self.state = 1338 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.DATA or _la == Parser.RANGE: - self.state = 1282 + self.state = 1337 localctx.windowing = self.windowingClause() - self.state = 1285 + self.state = 1340 self.match(Parser.RPAREN) - self.state = 1286 + self.state = 1341 self.match(Parser.RPAREN) pass elif token in [Parser.LAG, Parser.LEAD]: localctx = Parser.LagOrLeadAnComponentContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 1288 + self.state = 1343 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.LAG or _la == Parser.LEAD): @@ -11205,19 +11659,19 @@ def anFunctionComponent(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 1289 + self.state = 1344 self.match(Parser.LPAREN) - self.state = 1290 + self.state = 1345 self.exprComponent(0) - self.state = 1296 + self.state = 1351 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 1291 + self.state = 1346 self.match(Parser.COMMA) - self.state = 1292 + self.state = 1347 localctx.offset = self.signedInteger() - self.state = 1294 + self.state = 1349 self._errHandler.sync(self) _la = self._input.LA(1) if ( @@ -11232,86 +11686,86 @@ def anFunctionComponent(self): ) != 0 ) or ( - ((_la - 218) & ~0x3F) == 0 + ((_la - 219) & ~0x3F) == 0 and ( - (1 << (_la - 218)) + (1 << (_la - 219)) & ( - (1 << (Parser.CAST - 218)) - | (1 << (Parser.INTEGER_CONSTANT - 218)) - | (1 << (Parser.NUMBER_CONSTANT - 218)) - | (1 << (Parser.BOOLEAN_CONSTANT - 218)) - | (1 << (Parser.STRING_CONSTANT - 218)) + (1 << (Parser.CAST - 219)) + | (1 << (Parser.INTEGER_CONSTANT - 219)) + | (1 << (Parser.NUMBER_CONSTANT - 219)) + | (1 << (Parser.BOOLEAN_CONSTANT - 219)) + | (1 << (Parser.STRING_CONSTANT - 219)) ) ) != 0 ): - self.state = 1293 + self.state = 1348 localctx.defaultValue = self.scalarItem() - self.state = 1298 + self.state = 1353 self.match(Parser.OVER) - self.state = 1299 + self.state = 1354 self.match(Parser.LPAREN) - self.state = 1301 + self.state = 1356 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.PARTITION: - self.state = 1300 + self.state = 1355 localctx.partition = self.partitionByClause() - self.state = 1303 + self.state = 1358 localctx.orderBy = self.orderByClause() - self.state = 1305 + self.state = 1360 self.match(Parser.RPAREN) - self.state = 1306 + self.state = 1361 self.match(Parser.RPAREN) pass elif token in [Parser.RANK]: localctx = Parser.RankAnComponentContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 1308 + self.state = 1363 localctx.op = self.match(Parser.RANK) - self.state = 1309 + self.state = 1364 self.match(Parser.LPAREN) - self.state = 1310 + self.state = 1365 self.match(Parser.OVER) - self.state = 1311 + self.state = 1366 self.match(Parser.LPAREN) - self.state = 1313 + self.state = 1368 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.PARTITION: - self.state = 1312 + self.state = 1367 localctx.partition = self.partitionByClause() - self.state = 1315 + self.state = 1370 localctx.orderBy = self.orderByClause() - self.state = 1317 + self.state = 1372 self.match(Parser.RPAREN) - self.state = 1318 + self.state = 1373 self.match(Parser.RPAREN) pass elif token in [Parser.RATIO_TO_REPORT]: localctx = Parser.RatioToReportAnComponentContext(self, localctx) self.enterOuterAlt(localctx, 4) - self.state = 1320 + self.state = 1375 localctx.op = self.match(Parser.RATIO_TO_REPORT) - self.state = 1321 + self.state = 1376 self.match(Parser.LPAREN) - self.state = 1322 + self.state = 1377 self.exprComponent(0) - self.state = 1323 + self.state = 1378 self.match(Parser.OVER) - self.state = 1324 + self.state = 1379 self.match(Parser.LPAREN) - self.state = 1325 + self.state = 1380 localctx.partition = self.partitionByClause() - self.state = 1326 + self.state = 1381 self.match(Parser.RPAREN) - self.state = 1327 + self.state = 1382 self.match(Parser.RPAREN) pass else: @@ -11355,14 +11809,14 @@ def accept(self, visitor: ParseTreeVisitor): def renameClauseItem(self): localctx = Parser.RenameClauseItemContext(self, self._ctx, self.state) - self.enterRule(localctx, 76, self.RULE_renameClauseItem) + self.enterRule(localctx, 84, self.RULE_renameClauseItem) try: self.enterOuterAlt(localctx, 1) - self.state = 1331 + self.state = 1386 localctx.fromName = self.componentID() - self.state = 1332 + self.state = 1387 self.match(Parser.TO) - self.state = 1333 + self.state = 1388 localctx.toName = self.componentID() except RecognitionException as re: localctx.exception = re @@ -11403,21 +11857,21 @@ def accept(self, visitor: ParseTreeVisitor): def aggregateClause(self): localctx = Parser.AggregateClauseContext(self, self._ctx, self.state) - self.enterRule(localctx, 78, self.RULE_aggregateClause) + self.enterRule(localctx, 86, self.RULE_aggregateClause) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1335 + self.state = 1390 self.aggrFunctionClause() - self.state = 1340 + self.state = 1395 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 1336 + self.state = 1391 self.match(Parser.COMMA) - self.state = 1337 + self.state = 1392 self.aggrFunctionClause() - self.state = 1342 + self.state = 1397 self._errHandler.sync(self) _la = self._input.LA(1) @@ -11460,11 +11914,11 @@ def accept(self, visitor: ParseTreeVisitor): def aggrFunctionClause(self): localctx = Parser.AggrFunctionClauseContext(self, self._ctx, self.state) - self.enterRule(localctx, 80, self.RULE_aggrFunctionClause) + self.enterRule(localctx, 88, self.RULE_aggrFunctionClause) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1344 + self.state = 1399 self._errHandler.sync(self) _la = self._input.LA(1) if ( @@ -11480,14 +11934,14 @@ def aggrFunctionClause(self): ) != 0 ) or _la == Parser.COMPONENT: - self.state = 1343 + self.state = 1398 self.componentRole() - self.state = 1346 + self.state = 1401 self.componentID() - self.state = 1347 + self.state = 1402 self.match(Parser.ASSIGN) - self.state = 1348 + self.state = 1403 self.aggrOperators() except RecognitionException as re: localctx.exception = re @@ -11528,11 +11982,11 @@ def accept(self, visitor: ParseTreeVisitor): def calcClauseItem(self): localctx = Parser.CalcClauseItemContext(self, self._ctx, self.state) - self.enterRule(localctx, 82, self.RULE_calcClauseItem) + self.enterRule(localctx, 90, self.RULE_calcClauseItem) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1351 + self.state = 1406 self._errHandler.sync(self) _la = self._input.LA(1) if ( @@ -11548,14 +12002,14 @@ def calcClauseItem(self): ) != 0 ) or _la == Parser.COMPONENT: - self.state = 1350 + self.state = 1405 self.componentRole() - self.state = 1353 + self.state = 1408 self.componentID() - self.state = 1354 + self.state = 1409 self.match(Parser.ASSIGN) - self.state = 1355 + self.state = 1410 self.exprComponent(0) except RecognitionException as re: localctx.exception = re @@ -11593,14 +12047,14 @@ def accept(self, visitor: ParseTreeVisitor): def subspaceClauseItem(self): localctx = Parser.SubspaceClauseItemContext(self, self._ctx, self.state) - self.enterRule(localctx, 84, self.RULE_subspaceClauseItem) + self.enterRule(localctx, 92, self.RULE_subspaceClauseItem) try: self.enterOuterAlt(localctx, 1) - self.state = 1357 + self.state = 1412 self.componentID() - self.state = 1358 + self.state = 1413 self.match(Parser.EQ) - self.state = 1359 + self.state = 1414 self.scalarItem() except RecognitionException as re: localctx.exception = re @@ -11675,10 +12129,10 @@ def accept(self, visitor: ParseTreeVisitor): def scalarItem(self): localctx = Parser.ScalarItemContext(self, self._ctx, self.state) - self.enterRule(localctx, 86, self.RULE_scalarItem) + self.enterRule(localctx, 94, self.RULE_scalarItem) self._la = 0 # Token type try: - self.state = 1373 + self.state = 1428 self._errHandler.sync(self) token = self._input.LA(1) if token in [ @@ -11692,33 +12146,33 @@ def scalarItem(self): ]: localctx = Parser.SimpleScalarContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 1361 + self.state = 1416 self.constant() pass elif token in [Parser.CAST]: localctx = Parser.ScalarWithCastContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 1362 + self.state = 1417 self.match(Parser.CAST) - self.state = 1363 + self.state = 1418 self.match(Parser.LPAREN) - self.state = 1364 + self.state = 1419 self.constant() - self.state = 1365 + self.state = 1420 self.match(Parser.COMMA) - self.state = 1366 + self.state = 1421 self.basicScalarType() - self.state = 1369 + self.state = 1424 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 1367 + self.state = 1422 self.match(Parser.COMMA) - self.state = 1368 + self.state = 1423 self.match(Parser.STRING_CONSTANT) - self.state = 1371 + self.state = 1426 self.match(Parser.RPAREN) pass else: @@ -11763,21 +12217,21 @@ def accept(self, visitor: ParseTreeVisitor): def joinClauseWithoutUsing(self): localctx = Parser.JoinClauseWithoutUsingContext(self, self._ctx, self.state) - self.enterRule(localctx, 88, self.RULE_joinClauseWithoutUsing) + self.enterRule(localctx, 96, self.RULE_joinClauseWithoutUsing) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1375 + self.state = 1430 self.joinClauseItem() - self.state = 1380 + self.state = 1435 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 1376 + self.state = 1431 self.match(Parser.COMMA) - self.state = 1377 + self.state = 1432 self.joinClauseItem() - self.state = 1382 + self.state = 1437 self._errHandler.sync(self) _la = self._input.LA(1) @@ -11829,41 +12283,41 @@ def accept(self, visitor: ParseTreeVisitor): def joinClause(self): localctx = Parser.JoinClauseContext(self, self._ctx, self.state) - self.enterRule(localctx, 90, self.RULE_joinClause) + self.enterRule(localctx, 98, self.RULE_joinClause) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1383 + self.state = 1438 self.joinClauseItem() - self.state = 1388 + self.state = 1443 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 1384 + self.state = 1439 self.match(Parser.COMMA) - self.state = 1385 + self.state = 1440 self.joinClauseItem() - self.state = 1390 + self.state = 1445 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 1400 + self.state = 1455 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.USING: - self.state = 1391 + self.state = 1446 self.match(Parser.USING) - self.state = 1392 + self.state = 1447 self.componentID() - self.state = 1397 + self.state = 1452 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 1393 + self.state = 1448 self.match(Parser.COMMA) - self.state = 1394 + self.state = 1449 self.componentID() - self.state = 1399 + self.state = 1454 self._errHandler.sync(self) _la = self._input.LA(1) @@ -11903,19 +12357,19 @@ def accept(self, visitor: ParseTreeVisitor): def joinClauseItem(self): localctx = Parser.JoinClauseItemContext(self, self._ctx, self.state) - self.enterRule(localctx, 92, self.RULE_joinClauseItem) + self.enterRule(localctx, 100, self.RULE_joinClauseItem) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1402 + self.state = 1457 self.expr(0) - self.state = 1405 + self.state = 1460 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.AS: - self.state = 1403 + self.state = 1458 self.match(Parser.AS) - self.state = 1404 + self.state = 1459 self.alias() except RecognitionException as re: @@ -11963,48 +12417,48 @@ def accept(self, visitor: ParseTreeVisitor): def joinBody(self): localctx = Parser.JoinBodyContext(self, self._ctx, self.state) - self.enterRule(localctx, 94, self.RULE_joinBody) + self.enterRule(localctx, 102, self.RULE_joinBody) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1408 + self.state = 1463 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.FILTER: - self.state = 1407 + self.state = 1462 self.filterClause() - self.state = 1413 + self.state = 1468 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.CALC]: - self.state = 1410 + self.state = 1465 self.calcClause() pass elif token in [Parser.APPLY]: - self.state = 1411 + self.state = 1466 self.joinApplyClause() pass elif token in [Parser.AGGREGATE]: - self.state = 1412 + self.state = 1467 self.aggrClause() pass elif token in [Parser.RPAREN, Parser.DROP, Parser.KEEP, Parser.RENAME]: pass else: pass - self.state = 1416 + self.state = 1471 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.DROP or _la == Parser.KEEP: - self.state = 1415 + self.state = 1470 self.keepOrDropClause() - self.state = 1419 + self.state = 1474 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.RENAME: - self.state = 1418 + self.state = 1473 self.renameClause() except RecognitionException as re: @@ -12040,12 +12494,12 @@ def accept(self, visitor: ParseTreeVisitor): def joinApplyClause(self): localctx = Parser.JoinApplyClauseContext(self, self._ctx, self.state) - self.enterRule(localctx, 96, self.RULE_joinApplyClause) + self.enterRule(localctx, 104, self.RULE_joinApplyClause) try: self.enterOuterAlt(localctx, 1) - self.state = 1421 + self.state = 1476 self.match(Parser.APPLY) - self.state = 1422 + self.state = 1477 self.expr(0) except RecognitionException as re: localctx.exception = re @@ -12092,25 +12546,25 @@ def accept(self, visitor: ParseTreeVisitor): def partitionByClause(self): localctx = Parser.PartitionByClauseContext(self, self._ctx, self.state) - self.enterRule(localctx, 98, self.RULE_partitionByClause) + self.enterRule(localctx, 106, self.RULE_partitionByClause) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1424 + self.state = 1479 self.match(Parser.PARTITION) - self.state = 1425 + self.state = 1480 self.match(Parser.BY) - self.state = 1426 + self.state = 1481 self.componentID() - self.state = 1431 + self.state = 1486 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 1427 + self.state = 1482 self.match(Parser.COMMA) - self.state = 1428 + self.state = 1483 self.componentID() - self.state = 1433 + self.state = 1488 self._errHandler.sync(self) _la = self._input.LA(1) @@ -12159,25 +12613,25 @@ def accept(self, visitor: ParseTreeVisitor): def orderByClause(self): localctx = Parser.OrderByClauseContext(self, self._ctx, self.state) - self.enterRule(localctx, 100, self.RULE_orderByClause) + self.enterRule(localctx, 108, self.RULE_orderByClause) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1434 + self.state = 1489 self.match(Parser.ORDER) - self.state = 1435 + self.state = 1490 self.match(Parser.BY) - self.state = 1436 + self.state = 1491 self.orderByItem() - self.state = 1441 + self.state = 1496 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 1437 + self.state = 1492 self.match(Parser.COMMA) - self.state = 1438 + self.state = 1493 self.orderByItem() - self.state = 1443 + self.state = 1498 self._errHandler.sync(self) _la = self._input.LA(1) @@ -12217,17 +12671,17 @@ def accept(self, visitor: ParseTreeVisitor): def orderByItem(self): localctx = Parser.OrderByItemContext(self, self._ctx, self.state) - self.enterRule(localctx, 102, self.RULE_orderByItem) + self.enterRule(localctx, 110, self.RULE_orderByItem) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1444 + self.state = 1499 self.componentID() - self.state = 1446 + self.state = 1501 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.ASC or _la == Parser.DESC: - self.state = 1445 + self.state = 1500 _la = self._input.LA(1) if not (_la == Parser.ASC or _la == Parser.DESC): self._errHandler.recoverInline(self) @@ -12285,32 +12739,32 @@ def accept(self, visitor: ParseTreeVisitor): def windowingClause(self): localctx = Parser.WindowingClauseContext(self, self._ctx, self.state) - self.enterRule(localctx, 104, self.RULE_windowingClause) + self.enterRule(localctx, 112, self.RULE_windowingClause) try: self.enterOuterAlt(localctx, 1) - self.state = 1451 + self.state = 1506 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.DATA]: - self.state = 1448 + self.state = 1503 self.match(Parser.DATA) - self.state = 1449 + self.state = 1504 self.match(Parser.POINTS) pass elif token in [Parser.RANGE]: - self.state = 1450 + self.state = 1505 self.match(Parser.RANGE) pass else: raise NoViableAltException(self) - self.state = 1453 + self.state = 1508 self.match(Parser.BETWEEN) - self.state = 1454 + self.state = 1509 localctx.from_ = self.limitClauseItem() - self.state = 1455 + self.state = 1510 self.match(Parser.AND) - self.state = 1456 + self.state = 1511 localctx.to_ = self.limitClauseItem() except RecognitionException as re: localctx.exception = re @@ -12348,15 +12802,15 @@ def accept(self, visitor: ParseTreeVisitor): def signedInteger(self): localctx = Parser.SignedIntegerContext(self, self._ctx, self.state) - self.enterRule(localctx, 106, self.RULE_signedInteger) + self.enterRule(localctx, 114, self.RULE_signedInteger) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1459 + self.state = 1514 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.PLUS or _la == Parser.MINUS: - self.state = 1458 + self.state = 1513 _la = self._input.LA(1) if not (_la == Parser.PLUS or _la == Parser.MINUS): self._errHandler.recoverInline(self) @@ -12364,7 +12818,7 @@ def signedInteger(self): self._errHandler.reportMatch(self) self.consume() - self.state = 1461 + self.state = 1516 self.match(Parser.INTEGER_CONSTANT) except RecognitionException as re: localctx.exception = re @@ -12402,15 +12856,15 @@ def accept(self, visitor: ParseTreeVisitor): def signedNumber(self): localctx = Parser.SignedNumberContext(self, self._ctx, self.state) - self.enterRule(localctx, 108, self.RULE_signedNumber) + self.enterRule(localctx, 116, self.RULE_signedNumber) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1464 + self.state = 1519 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.PLUS or _la == Parser.MINUS: - self.state = 1463 + self.state = 1518 _la = self._input.LA(1) if not (_la == Parser.PLUS or _la == Parser.MINUS): self._errHandler.recoverInline(self) @@ -12418,7 +12872,7 @@ def signedNumber(self): self._errHandler.reportMatch(self) self.consume() - self.state = 1466 + self.state = 1521 self.match(Parser.NUMBER_CONSTANT) except RecognitionException as re: localctx.exception = re @@ -12469,50 +12923,50 @@ def accept(self, visitor: ParseTreeVisitor): def limitClauseItem(self): localctx = Parser.LimitClauseItemContext(self, self._ctx, self.state) - self.enterRule(localctx, 110, self.RULE_limitClauseItem) + self.enterRule(localctx, 118, self.RULE_limitClauseItem) try: - self.state = 1481 + self.state = 1536 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 139, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 144, self._ctx) if la_ == 1: self.enterOuterAlt(localctx, 1) - self.state = 1468 + self.state = 1523 self.signedInteger() - self.state = 1469 + self.state = 1524 localctx.limitDir = self.match(Parser.PRECEDING) pass elif la_ == 2: self.enterOuterAlt(localctx, 2) - self.state = 1471 + self.state = 1526 self.signedInteger() - self.state = 1472 + self.state = 1527 localctx.limitDir = self.match(Parser.FOLLOWING) pass elif la_ == 3: self.enterOuterAlt(localctx, 3) - self.state = 1474 + self.state = 1529 self.match(Parser.CURRENT) - self.state = 1475 + self.state = 1530 self.match(Parser.DATA) - self.state = 1476 + self.state = 1531 self.match(Parser.POINT) pass elif la_ == 4: self.enterOuterAlt(localctx, 4) - self.state = 1477 + self.state = 1532 self.match(Parser.UNBOUNDED) - self.state = 1478 + self.state = 1533 localctx.limitDir = self.match(Parser.PRECEDING) pass elif la_ == 5: self.enterOuterAlt(localctx, 5) - self.state = 1479 + self.state = 1534 self.match(Parser.UNBOUNDED) - self.state = 1480 + self.state = 1535 localctx.limitDir = self.match(Parser.FOLLOWING) pass @@ -12635,18 +13089,18 @@ def accept(self, visitor: ParseTreeVisitor): def groupingClause(self): localctx = Parser.GroupingClauseContext(self, self._ctx, self.state) - self.enterRule(localctx, 112, self.RULE_groupingClause) + self.enterRule(localctx, 120, self.RULE_groupingClause) self._la = 0 # Token type try: - self.state = 1515 + self.state = 1570 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 145, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 150, self._ctx) if la_ == 1: localctx = Parser.GroupByOrExceptContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 1483 + self.state = 1538 self.match(Parser.GROUP) - self.state = 1484 + self.state = 1539 localctx.op = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.BY or _la == Parser.EXCEPT): @@ -12654,37 +13108,37 @@ def groupingClause(self): else: self._errHandler.reportMatch(self) self.consume() - self.state = 1485 + self.state = 1540 self.componentID() - self.state = 1490 + self.state = 1545 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 1486 + self.state = 1541 self.match(Parser.COMMA) - self.state = 1487 + self.state = 1542 self.componentID() - self.state = 1492 + self.state = 1547 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 1501 + self.state = 1556 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.TIME_AGG: - self.state = 1493 + self.state = 1548 self.match(Parser.TIME_AGG) - self.state = 1494 + self.state = 1549 self.match(Parser.LPAREN) - self.state = 1495 + self.state = 1550 self.match(Parser.STRING_CONSTANT) - self.state = 1498 + self.state = 1553 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 1496 + self.state = 1551 self.match(Parser.COMMA) - self.state = 1497 + self.state = 1552 localctx.delim = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.FIRST or _la == Parser.LAST): @@ -12693,7 +13147,7 @@ def groupingClause(self): self._errHandler.reportMatch(self) self.consume() - self.state = 1500 + self.state = 1555 self.match(Parser.RPAREN) pass @@ -12701,27 +13155,27 @@ def groupingClause(self): elif la_ == 2: localctx = Parser.GroupAllContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 1503 + self.state = 1558 self.match(Parser.GROUP) - self.state = 1504 + self.state = 1559 self.match(Parser.ALL) - self.state = 1513 + self.state = 1568 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.TIME_AGG: - self.state = 1505 + self.state = 1560 self.match(Parser.TIME_AGG) - self.state = 1506 + self.state = 1561 self.match(Parser.LPAREN) - self.state = 1507 + self.state = 1562 self.match(Parser.STRING_CONSTANT) - self.state = 1510 + self.state = 1565 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.COMMA: - self.state = 1508 + self.state = 1563 self.match(Parser.COMMA) - self.state = 1509 + self.state = 1564 localctx.delim = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.FIRST or _la == Parser.LAST): @@ -12730,7 +13184,7 @@ def groupingClause(self): self._errHandler.reportMatch(self) self.consume() - self.state = 1512 + self.state = 1567 self.match(Parser.RPAREN) pass @@ -12768,12 +13222,12 @@ def accept(self, visitor: ParseTreeVisitor): def havingClause(self): localctx = Parser.HavingClauseContext(self, self._ctx, self.state) - self.enterRule(localctx, 114, self.RULE_havingClause) + self.enterRule(localctx, 122, self.RULE_havingClause) try: self.enterOuterAlt(localctx, 1) - self.state = 1517 + self.state = 1572 self.match(Parser.HAVING) - self.state = 1518 + self.state = 1573 self.exprComponent(0) except RecognitionException as re: localctx.exception = re @@ -12814,21 +13268,21 @@ def accept(self, visitor: ParseTreeVisitor): def parameterItem(self): localctx = Parser.ParameterItemContext(self, self._ctx, self.state) - self.enterRule(localctx, 116, self.RULE_parameterItem) + self.enterRule(localctx, 124, self.RULE_parameterItem) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1520 + self.state = 1575 self.varID() - self.state = 1521 + self.state = 1576 self.inputParameterType() - self.state = 1524 + self.state = 1579 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.DEFAULT: - self.state = 1522 + self.state = 1577 self.match(Parser.DEFAULT) - self.state = 1523 + self.state = 1578 self.scalarItem() except RecognitionException as re: @@ -12867,9 +13321,9 @@ def accept(self, visitor: ParseTreeVisitor): def outputParameterType(self): localctx = Parser.OutputParameterTypeContext(self, self._ctx, self.state) - self.enterRule(localctx, 118, self.RULE_outputParameterType) + self.enterRule(localctx, 126, self.RULE_outputParameterType) try: - self.state = 1529 + self.state = 1584 self._errHandler.sync(self) token = self._input.LA(1) if token in [ @@ -12885,12 +13339,12 @@ def outputParameterType(self): Parser.IDENTIFIER, ]: self.enterOuterAlt(localctx, 1) - self.state = 1526 + self.state = 1581 self.scalarType() pass elif token in [Parser.DATASET]: self.enterOuterAlt(localctx, 2) - self.state = 1527 + self.state = 1582 self.datasetType() pass elif token in [ @@ -12901,7 +13355,7 @@ def outputParameterType(self): Parser.COMPONENT, ]: self.enterOuterAlt(localctx, 3) - self.state = 1528 + self.state = 1583 self.componentType() pass else: @@ -12940,9 +13394,9 @@ def accept(self, visitor: ParseTreeVisitor): def outputParameterTypeComponent(self): localctx = Parser.OutputParameterTypeComponentContext(self, self._ctx, self.state) - self.enterRule(localctx, 120, self.RULE_outputParameterTypeComponent) + self.enterRule(localctx, 128, self.RULE_outputParameterTypeComponent) try: - self.state = 1533 + self.state = 1588 self._errHandler.sync(self) token = self._input.LA(1) if token in [ @@ -12953,7 +13407,7 @@ def outputParameterTypeComponent(self): Parser.COMPONENT, ]: self.enterOuterAlt(localctx, 1) - self.state = 1531 + self.state = 1586 self.componentType() pass elif token in [ @@ -12969,7 +13423,7 @@ def outputParameterTypeComponent(self): Parser.IDENTIFIER, ]: self.enterOuterAlt(localctx, 2) - self.state = 1532 + self.state = 1587 self.scalarType() pass else: @@ -13017,9 +13471,9 @@ def accept(self, visitor: ParseTreeVisitor): def inputParameterType(self): localctx = Parser.InputParameterTypeContext(self, self._ctx, self.state) - self.enterRule(localctx, 122, self.RULE_inputParameterType) + self.enterRule(localctx, 130, self.RULE_inputParameterType) try: - self.state = 1540 + self.state = 1595 self._errHandler.sync(self) token = self._input.LA(1) if token in [ @@ -13035,17 +13489,17 @@ def inputParameterType(self): Parser.IDENTIFIER, ]: self.enterOuterAlt(localctx, 1) - self.state = 1535 + self.state = 1590 self.scalarType() pass elif token in [Parser.DATASET]: self.enterOuterAlt(localctx, 2) - self.state = 1536 + self.state = 1591 self.datasetType() pass elif token in [Parser.SET]: self.enterOuterAlt(localctx, 3) - self.state = 1537 + self.state = 1592 self.scalarSetType() pass elif token in [ @@ -13058,7 +13512,7 @@ def inputParameterType(self): Parser.HIERARCHICAL_ON_VAR, ]: self.enterOuterAlt(localctx, 4) - self.state = 1538 + self.state = 1593 self.rulesetType() pass elif token in [ @@ -13069,7 +13523,7 @@ def inputParameterType(self): Parser.COMPONENT, ]: self.enterOuterAlt(localctx, 5) - self.state = 1539 + self.state = 1594 self.componentType() pass else: @@ -13111,19 +13565,19 @@ def accept(self, visitor: ParseTreeVisitor): def rulesetType(self): localctx = Parser.RulesetTypeContext(self, self._ctx, self.state) - self.enterRule(localctx, 124, self.RULE_rulesetType) + self.enterRule(localctx, 132, self.RULE_rulesetType) try: - self.state = 1545 + self.state = 1600 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.RULESET]: self.enterOuterAlt(localctx, 1) - self.state = 1542 + self.state = 1597 self.match(Parser.RULESET) pass elif token in [Parser.DATAPOINT, Parser.DATAPOINT_ON_VD, Parser.DATAPOINT_ON_VAR]: self.enterOuterAlt(localctx, 2) - self.state = 1543 + self.state = 1598 self.dpRuleset() pass elif token in [ @@ -13132,7 +13586,7 @@ def rulesetType(self): Parser.HIERARCHICAL_ON_VAR, ]: self.enterOuterAlt(localctx, 3) - self.state = 1544 + self.state = 1599 self.hrRuleset() pass else: @@ -13180,11 +13634,11 @@ def accept(self, visitor: ParseTreeVisitor): def scalarType(self): localctx = Parser.ScalarTypeContext(self, self._ctx, self.state) - self.enterRule(localctx, 126, self.RULE_scalarType) + self.enterRule(localctx, 134, self.RULE_scalarType) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1549 + self.state = 1604 self._errHandler.sync(self) token = self._input.LA(1) if token in [ @@ -13198,35 +13652,35 @@ def scalarType(self): Parser.DURATION, Parser.SCALAR, ]: - self.state = 1547 + self.state = 1602 self.basicScalarType() pass elif token in [Parser.IDENTIFIER]: - self.state = 1548 + self.state = 1603 self.valueDomainName() pass else: raise NoViableAltException(self) - self.state = 1552 + self.state = 1607 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.QLPAREN or _la == Parser.GLPAREN: - self.state = 1551 + self.state = 1606 self.scalarTypeConstraint() - self.state = 1558 + self.state = 1613 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.NOT or _la == Parser.NULL_CONSTANT: - self.state = 1555 + self.state = 1610 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.NOT: - self.state = 1554 + self.state = 1609 self.match(Parser.NOT) - self.state = 1557 + self.state = 1612 self.match(Parser.NULL_CONSTANT) except RecognitionException as re: @@ -13268,21 +13722,21 @@ def accept(self, visitor: ParseTreeVisitor): def componentType(self): localctx = Parser.ComponentTypeContext(self, self._ctx, self.state) - self.enterRule(localctx, 128, self.RULE_componentType) + self.enterRule(localctx, 136, self.RULE_componentType) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1560 + self.state = 1615 self.componentRole() - self.state = 1565 + self.state = 1620 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.LT: - self.state = 1561 + self.state = 1616 self.match(Parser.LT) - self.state = 1562 + self.state = 1617 self.scalarType() - self.state = 1563 + self.state = 1618 self.match(Parser.MT) except RecognitionException as re: @@ -13333,33 +13787,33 @@ def accept(self, visitor: ParseTreeVisitor): def datasetType(self): localctx = Parser.DatasetTypeContext(self, self._ctx, self.state) - self.enterRule(localctx, 130, self.RULE_datasetType) + self.enterRule(localctx, 138, self.RULE_datasetType) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1567 + self.state = 1622 self.match(Parser.DATASET) - self.state = 1579 + self.state = 1634 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.GLPAREN: - self.state = 1568 + self.state = 1623 self.match(Parser.GLPAREN) - self.state = 1569 + self.state = 1624 self.compConstraint() - self.state = 1574 + self.state = 1629 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 1570 + self.state = 1625 self.match(Parser.COMMA) - self.state = 1571 + self.state = 1626 self.compConstraint() - self.state = 1576 + self.state = 1631 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 1577 + self.state = 1632 self.match(Parser.GRPAREN) except RecognitionException as re: @@ -13395,14 +13849,14 @@ def accept(self, visitor: ParseTreeVisitor): def evalDatasetType(self): localctx = Parser.EvalDatasetTypeContext(self, self._ctx, self.state) - self.enterRule(localctx, 132, self.RULE_evalDatasetType) + self.enterRule(localctx, 140, self.RULE_evalDatasetType) try: - self.state = 1583 + self.state = 1638 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.DATASET]: self.enterOuterAlt(localctx, 1) - self.state = 1581 + self.state = 1636 self.datasetType() pass elif token in [ @@ -13418,7 +13872,7 @@ def evalDatasetType(self): Parser.IDENTIFIER, ]: self.enterOuterAlt(localctx, 2) - self.state = 1582 + self.state = 1637 self.scalarType() pass else: @@ -13463,21 +13917,21 @@ def accept(self, visitor: ParseTreeVisitor): def scalarSetType(self): localctx = Parser.ScalarSetTypeContext(self, self._ctx, self.state) - self.enterRule(localctx, 134, self.RULE_scalarSetType) + self.enterRule(localctx, 142, self.RULE_scalarSetType) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1585 + self.state = 1640 self.match(Parser.SET) - self.state = 1590 + self.state = 1645 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.LT: - self.state = 1586 + self.state = 1641 self.match(Parser.LT) - self.state = 1587 + self.state = 1642 self.scalarType() - self.state = 1588 + self.state = 1643 self.match(Parser.MT) except RecognitionException as re: @@ -13582,73 +14036,73 @@ def accept(self, visitor: ParseTreeVisitor): def dpRuleset(self): localctx = Parser.DpRulesetContext(self, self._ctx, self.state) - self.enterRule(localctx, 136, self.RULE_dpRuleset) + self.enterRule(localctx, 144, self.RULE_dpRuleset) self._la = 0 # Token type try: - self.state = 1621 + self.state = 1676 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.DATAPOINT]: localctx = Parser.DataPointContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 1592 + self.state = 1647 self.match(Parser.DATAPOINT) pass elif token in [Parser.DATAPOINT_ON_VD]: localctx = Parser.DataPointVdContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 1593 + self.state = 1648 self.match(Parser.DATAPOINT_ON_VD) - self.state = 1605 + self.state = 1660 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.GLPAREN: - self.state = 1594 + self.state = 1649 self.match(Parser.GLPAREN) - self.state = 1595 + self.state = 1650 self.valueDomainName() - self.state = 1600 + self.state = 1655 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.MUL: - self.state = 1596 + self.state = 1651 self.match(Parser.MUL) - self.state = 1597 + self.state = 1652 self.valueDomainName() - self.state = 1602 + self.state = 1657 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 1603 + self.state = 1658 self.match(Parser.GRPAREN) pass elif token in [Parser.DATAPOINT_ON_VAR]: localctx = Parser.DataPointVarContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 1607 + self.state = 1662 self.match(Parser.DATAPOINT_ON_VAR) - self.state = 1619 + self.state = 1674 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.GLPAREN: - self.state = 1608 + self.state = 1663 self.match(Parser.GLPAREN) - self.state = 1609 + self.state = 1664 self.varID() - self.state = 1614 + self.state = 1669 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.MUL: - self.state = 1610 + self.state = 1665 self.match(Parser.MUL) - self.state = 1611 + self.state = 1666 self.varID() - self.state = 1616 + self.state = 1671 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 1617 + self.state = 1672 self.match(Parser.GRPAREN) pass @@ -13774,95 +14228,95 @@ def accept(self, visitor: ParseTreeVisitor): def hrRuleset(self): localctx = Parser.HrRulesetContext(self, self._ctx, self.state) - self.enterRule(localctx, 138, self.RULE_hrRuleset) + self.enterRule(localctx, 146, self.RULE_hrRuleset) self._la = 0 # Token type try: - self.state = 1663 + self.state = 1718 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.HIERARCHICAL]: localctx = Parser.HrRulesetTypeContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 1623 + self.state = 1678 self.match(Parser.HIERARCHICAL) pass elif token in [Parser.HIERARCHICAL_ON_VD]: localctx = Parser.HrRulesetVdTypeContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 1624 + self.state = 1679 self.match(Parser.HIERARCHICAL_ON_VD) - self.state = 1641 + self.state = 1696 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.GLPAREN: - self.state = 1625 + self.state = 1680 self.match(Parser.GLPAREN) - self.state = 1626 + self.state = 1681 localctx.vdName = self.match(Parser.IDENTIFIER) - self.state = 1638 + self.state = 1693 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.LPAREN: - self.state = 1627 + self.state = 1682 self.match(Parser.LPAREN) - self.state = 1628 + self.state = 1683 self.valueDomainName() - self.state = 1633 + self.state = 1688 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.MUL: - self.state = 1629 + self.state = 1684 self.match(Parser.MUL) - self.state = 1630 + self.state = 1685 self.valueDomainName() - self.state = 1635 + self.state = 1690 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 1636 + self.state = 1691 self.match(Parser.RPAREN) - self.state = 1640 + self.state = 1695 self.match(Parser.GRPAREN) pass elif token in [Parser.HIERARCHICAL_ON_VAR]: localctx = Parser.HrRulesetVarTypeContext(self, localctx) self.enterOuterAlt(localctx, 3) - self.state = 1643 + self.state = 1698 self.match(Parser.HIERARCHICAL_ON_VAR) - self.state = 1661 + self.state = 1716 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.GLPAREN: - self.state = 1644 + self.state = 1699 self.match(Parser.GLPAREN) - self.state = 1645 + self.state = 1700 localctx.varName = self.varID() - self.state = 1657 + self.state = 1712 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.LPAREN: - self.state = 1646 + self.state = 1701 self.match(Parser.LPAREN) - self.state = 1647 + self.state = 1702 self.varID() - self.state = 1652 + self.state = 1707 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.MUL: - self.state = 1648 + self.state = 1703 self.match(Parser.MUL) - self.state = 1649 + self.state = 1704 self.varID() - self.state = 1654 + self.state = 1709 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 1655 + self.state = 1710 self.match(Parser.RPAREN) - self.state = 1659 + self.state = 1714 self.match(Parser.GRPAREN) pass @@ -13899,10 +14353,10 @@ def accept(self, visitor: ParseTreeVisitor): def valueDomainName(self): localctx = Parser.ValueDomainNameContext(self, self._ctx, self.state) - self.enterRule(localctx, 140, self.RULE_valueDomainName) + self.enterRule(localctx, 148, self.RULE_valueDomainName) try: self.enterOuterAlt(localctx, 1) - self.state = 1665 + self.state = 1720 self.match(Parser.IDENTIFIER) except RecognitionException as re: localctx.exception = re @@ -13934,10 +14388,10 @@ def accept(self, visitor: ParseTreeVisitor): def rulesetID(self): localctx = Parser.RulesetIDContext(self, self._ctx, self.state) - self.enterRule(localctx, 142, self.RULE_rulesetID) + self.enterRule(localctx, 150, self.RULE_rulesetID) try: self.enterOuterAlt(localctx, 1) - self.state = 1667 + self.state = 1722 self.match(Parser.IDENTIFIER) except RecognitionException as re: localctx.exception = re @@ -13984,28 +14438,28 @@ def accept(self, visitor: ParseTreeVisitor): def rulesetSignature(self): localctx = Parser.RulesetSignatureContext(self, self._ctx, self.state) - self.enterRule(localctx, 144, self.RULE_rulesetSignature) + self.enterRule(localctx, 152, self.RULE_rulesetSignature) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1669 + self.state = 1724 _la = self._input.LA(1) if not (_la == Parser.VALUE_DOMAIN or _la == Parser.VARIABLE): self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) self.consume() - self.state = 1670 + self.state = 1725 self.signature() - self.state = 1675 + self.state = 1730 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 1671 + self.state = 1726 self.match(Parser.COMMA) - self.state = 1672 + self.state = 1727 self.signature() - self.state = 1677 + self.state = 1732 self._errHandler.sync(self) _la = self._input.LA(1) @@ -14045,19 +14499,19 @@ def accept(self, visitor: ParseTreeVisitor): def signature(self): localctx = Parser.SignatureContext(self, self._ctx, self.state) - self.enterRule(localctx, 146, self.RULE_signature) + self.enterRule(localctx, 154, self.RULE_signature) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1678 + self.state = 1733 self.varID() - self.state = 1681 + self.state = 1736 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.AS: - self.state = 1679 + self.state = 1734 self.match(Parser.AS) - self.state = 1680 + self.state = 1735 self.alias() except RecognitionException as re: @@ -14099,21 +14553,21 @@ def accept(self, visitor: ParseTreeVisitor): def ruleClauseDatapoint(self): localctx = Parser.RuleClauseDatapointContext(self, self._ctx, self.state) - self.enterRule(localctx, 148, self.RULE_ruleClauseDatapoint) + self.enterRule(localctx, 156, self.RULE_ruleClauseDatapoint) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1683 + self.state = 1738 self.ruleItemDatapoint() - self.state = 1688 + self.state = 1743 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.EOL: - self.state = 1684 + self.state = 1739 self.match(Parser.EOL) - self.state = 1685 + self.state = 1740 self.ruleItemDatapoint() - self.state = 1690 + self.state = 1745 self._errHandler.sync(self) _la = self._input.LA(1) @@ -14171,44 +14625,44 @@ def accept(self, visitor: ParseTreeVisitor): def ruleItemDatapoint(self): localctx = Parser.RuleItemDatapointContext(self, self._ctx, self.state) - self.enterRule(localctx, 150, self.RULE_ruleItemDatapoint) + self.enterRule(localctx, 158, self.RULE_ruleItemDatapoint) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1693 + self.state = 1748 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 175, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 180, self._ctx) if la_ == 1: - self.state = 1691 + self.state = 1746 localctx.ruleName = self.match(Parser.IDENTIFIER) - self.state = 1692 + self.state = 1747 self.match(Parser.COLON) - self.state = 1699 + self.state = 1754 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.WHEN: - self.state = 1695 + self.state = 1750 self.match(Parser.WHEN) - self.state = 1696 + self.state = 1751 localctx.antecedentContiditon = self.exprComponent(0) - self.state = 1697 + self.state = 1752 self.match(Parser.THEN) - self.state = 1701 + self.state = 1756 localctx.consequentCondition = self.exprComponent(0) - self.state = 1703 + self.state = 1758 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.ERRORCODE: - self.state = 1702 + self.state = 1757 self.erCode() - self.state = 1706 + self.state = 1761 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.ERRORLEVEL: - self.state = 1705 + self.state = 1760 self.erLevel() except RecognitionException as re: @@ -14250,21 +14704,21 @@ def accept(self, visitor: ParseTreeVisitor): def ruleClauseHierarchical(self): localctx = Parser.RuleClauseHierarchicalContext(self, self._ctx, self.state) - self.enterRule(localctx, 152, self.RULE_ruleClauseHierarchical) + self.enterRule(localctx, 160, self.RULE_ruleClauseHierarchical) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1708 + self.state = 1763 self.ruleItemHierarchical() - self.state = 1713 + self.state = 1768 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.EOL: - self.state = 1709 + self.state = 1764 self.match(Parser.EOL) - self.state = 1710 + self.state = 1765 self.ruleItemHierarchical() - self.state = 1715 + self.state = 1770 self._errHandler.sync(self) _la = self._input.LA(1) @@ -14311,33 +14765,33 @@ def accept(self, visitor: ParseTreeVisitor): def ruleItemHierarchical(self): localctx = Parser.RuleItemHierarchicalContext(self, self._ctx, self.state) - self.enterRule(localctx, 154, self.RULE_ruleItemHierarchical) + self.enterRule(localctx, 162, self.RULE_ruleItemHierarchical) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1718 + self.state = 1773 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 180, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 185, self._ctx) if la_ == 1: - self.state = 1716 + self.state = 1771 localctx.ruleName = self.match(Parser.IDENTIFIER) - self.state = 1717 + self.state = 1772 self.match(Parser.COLON) - self.state = 1720 + self.state = 1775 self.codeItemRelation() - self.state = 1722 + self.state = 1777 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.ERRORCODE: - self.state = 1721 + self.state = 1776 self.erCode() - self.state = 1725 + self.state = 1780 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.ERRORLEVEL: - self.state = 1724 + self.state = 1779 self.erLevel() except RecognitionException as re: @@ -14385,29 +14839,29 @@ def accept(self, visitor: ParseTreeVisitor): def hierRuleSignature(self): localctx = Parser.HierRuleSignatureContext(self, self._ctx, self.state) - self.enterRule(localctx, 156, self.RULE_hierRuleSignature) + self.enterRule(localctx, 164, self.RULE_hierRuleSignature) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1727 + self.state = 1782 _la = self._input.LA(1) if not (_la == Parser.VALUE_DOMAIN or _la == Parser.VARIABLE): self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) self.consume() - self.state = 1730 + self.state = 1785 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.CONDITION: - self.state = 1728 + self.state = 1783 self.match(Parser.CONDITION) - self.state = 1729 + self.state = 1784 self.valueDomainSignature() - self.state = 1732 + self.state = 1787 self.match(Parser.RULE) - self.state = 1733 + self.state = 1788 self.match(Parser.IDENTIFIER) except RecognitionException as re: localctx.exception = re @@ -14448,21 +14902,21 @@ def accept(self, visitor: ParseTreeVisitor): def valueDomainSignature(self): localctx = Parser.ValueDomainSignatureContext(self, self._ctx, self.state) - self.enterRule(localctx, 158, self.RULE_valueDomainSignature) + self.enterRule(localctx, 166, self.RULE_valueDomainSignature) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1735 + self.state = 1790 self.signature() - self.state = 1740 + self.state = 1795 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 1736 + self.state = 1791 self.match(Parser.COMMA) - self.state = 1737 + self.state = 1792 self.signature() - self.state = 1742 + self.state = 1797 self._errHandler.sync(self) _la = self._input.LA(1) @@ -14515,24 +14969,24 @@ def accept(self, visitor: ParseTreeVisitor): def codeItemRelation(self): localctx = Parser.CodeItemRelationContext(self, self._ctx, self.state) - self.enterRule(localctx, 160, self.RULE_codeItemRelation) + self.enterRule(localctx, 168, self.RULE_codeItemRelation) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1747 + self.state = 1802 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.WHEN: - self.state = 1743 + self.state = 1798 self.match(Parser.WHEN) - self.state = 1744 + self.state = 1799 self.exprComponent(0) - self.state = 1745 + self.state = 1800 self.match(Parser.THEN) - self.state = 1749 + self.state = 1804 localctx.codetemRef = self.valueDomainValue() - self.state = 1751 + self.state = 1806 self._errHandler.sync(self) _la = self._input.LA(1) if ((_la) & ~0x3F) == 0 and ( @@ -14546,33 +15000,33 @@ def codeItemRelation(self): | (1 << Parser.LE) ) ) != 0: - self.state = 1750 + self.state = 1805 self.comparisonOperand() - self.state = 1753 + self.state = 1808 self.codeItemRelationClause() - self.state = 1757 + self.state = 1812 self._errHandler.sync(self) _la = self._input.LA(1) while ( _la == Parser.PLUS or _la == Parser.MINUS or ( - ((_la - 241) & ~0x3F) == 0 + ((_la - 242) & ~0x3F) == 0 and ( - (1 << (_la - 241)) + (1 << (_la - 242)) & ( - (1 << (Parser.INTEGER_CONSTANT - 241)) - | (1 << (Parser.NUMBER_CONSTANT - 241)) - | (1 << (Parser.IDENTIFIER - 241)) + (1 << (Parser.INTEGER_CONSTANT - 242)) + | (1 << (Parser.NUMBER_CONSTANT - 242)) + | (1 << (Parser.IDENTIFIER - 242)) ) ) != 0 ) ): - self.state = 1754 + self.state = 1809 self.codeItemRelationClause() - self.state = 1759 + self.state = 1814 self._errHandler.sync(self) _la = self._input.LA(1) @@ -14624,15 +15078,15 @@ def accept(self, visitor: ParseTreeVisitor): def codeItemRelationClause(self): localctx = Parser.CodeItemRelationClauseContext(self, self._ctx, self.state) - self.enterRule(localctx, 162, self.RULE_codeItemRelationClause) + self.enterRule(localctx, 170, self.RULE_codeItemRelationClause) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1761 + self.state = 1816 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 188, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 193, self._ctx) if la_ == 1: - self.state = 1760 + self.state = 1815 localctx.opAdd = self._input.LT(1) _la = self._input.LA(1) if not (_la == Parser.PLUS or _la == Parser.MINUS): @@ -14641,17 +15095,17 @@ def codeItemRelationClause(self): self._errHandler.reportMatch(self) self.consume() - self.state = 1763 + self.state = 1818 localctx.rightCodeItem = self.valueDomainValue() - self.state = 1768 + self.state = 1823 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.QLPAREN: - self.state = 1764 + self.state = 1819 self.match(Parser.QLPAREN) - self.state = 1765 + self.state = 1820 localctx.rightCondition = self.exprComponent(0) - self.state = 1766 + self.state = 1821 self.match(Parser.QRPAREN) except RecognitionException as re: @@ -14690,26 +15144,26 @@ def accept(self, visitor: ParseTreeVisitor): def valueDomainValue(self): localctx = Parser.ValueDomainValueContext(self, self._ctx, self.state) - self.enterRule(localctx, 164, self.RULE_valueDomainValue) + self.enterRule(localctx, 172, self.RULE_valueDomainValue) try: - self.state = 1773 + self.state = 1828 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 190, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 195, self._ctx) if la_ == 1: self.enterOuterAlt(localctx, 1) - self.state = 1770 + self.state = 1825 self.match(Parser.IDENTIFIER) pass elif la_ == 2: self.enterOuterAlt(localctx, 2) - self.state = 1771 + self.state = 1826 self.signedInteger() pass elif la_ == 3: self.enterOuterAlt(localctx, 3) - self.state = 1772 + self.state = 1827 self.signedNumber() pass @@ -14790,42 +15244,42 @@ def accept(self, visitor: ParseTreeVisitor): def scalarTypeConstraint(self): localctx = Parser.ScalarTypeConstraintContext(self, self._ctx, self.state) - self.enterRule(localctx, 166, self.RULE_scalarTypeConstraint) + self.enterRule(localctx, 174, self.RULE_scalarTypeConstraint) self._la = 0 # Token type try: - self.state = 1790 + self.state = 1845 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.QLPAREN]: localctx = Parser.ConditionConstraintContext(self, localctx) self.enterOuterAlt(localctx, 1) - self.state = 1775 + self.state = 1830 self.match(Parser.QLPAREN) - self.state = 1776 + self.state = 1831 self.exprComponent(0) - self.state = 1777 + self.state = 1832 self.match(Parser.QRPAREN) pass elif token in [Parser.GLPAREN]: localctx = Parser.RangeConstraintContext(self, localctx) self.enterOuterAlt(localctx, 2) - self.state = 1779 + self.state = 1834 self.match(Parser.GLPAREN) - self.state = 1780 + self.state = 1835 self.scalarItem() - self.state = 1785 + self.state = 1840 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 1781 + self.state = 1836 self.match(Parser.COMMA) - self.state = 1782 + self.state = 1837 self.scalarItem() - self.state = 1787 + self.state = 1842 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 1788 + self.state = 1843 self.match(Parser.GRPAREN) pass else: @@ -14867,20 +15321,20 @@ def accept(self, visitor: ParseTreeVisitor): def compConstraint(self): localctx = Parser.CompConstraintContext(self, self._ctx, self.state) - self.enterRule(localctx, 168, self.RULE_compConstraint) + self.enterRule(localctx, 176, self.RULE_compConstraint) try: self.enterOuterAlt(localctx, 1) - self.state = 1792 + self.state = 1847 self.componentType() - self.state = 1795 + self.state = 1850 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.IDENTIFIER]: - self.state = 1793 + self.state = 1848 self.componentID() pass elif token in [Parser.OPTIONAL]: - self.state = 1794 + self.state = 1849 self.multModifier() pass else: @@ -14922,17 +15376,17 @@ def accept(self, visitor: ParseTreeVisitor): def multModifier(self): localctx = Parser.MultModifierContext(self, self._ctx, self.state) - self.enterRule(localctx, 170, self.RULE_multModifier) + self.enterRule(localctx, 178, self.RULE_multModifier) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1797 + self.state = 1852 self.match(Parser.OPTIONAL) - self.state = 1799 + self.state = 1854 self._errHandler.sync(self) _la = self._input.LA(1) if _la == Parser.PLUS or _la == Parser.MUL: - self.state = 1798 + self.state = 1853 _la = self._input.LA(1) if not (_la == Parser.PLUS or _la == Parser.MUL): self._errHandler.recoverInline(self) @@ -14976,11 +15430,11 @@ def accept(self, visitor: ParseTreeVisitor): def validationOutput(self): localctx = Parser.ValidationOutputContext(self, self._ctx, self.state) - self.enterRule(localctx, 172, self.RULE_validationOutput) + self.enterRule(localctx, 180, self.RULE_validationOutput) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1801 + self.state = 1856 _la = self._input.LA(1) if not (_la == Parser.ALL or _la == Parser.INVALID or _la == Parser.ALL_MEASURES): self._errHandler.recoverInline(self) @@ -15032,23 +15486,23 @@ def accept(self, visitor: ParseTreeVisitor): def validationMode(self): localctx = Parser.ValidationModeContext(self, self._ctx, self.state) - self.enterRule(localctx, 174, self.RULE_validationMode) + self.enterRule(localctx, 182, self.RULE_validationMode) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1803 + self.state = 1858 _la = self._input.LA(1) if not ( - ((_la - 225) & ~0x3F) == 0 + ((_la - 226) & ~0x3F) == 0 and ( - (1 << (_la - 225)) + (1 << (_la - 226)) & ( - (1 << (Parser.NON_NULL - 225)) - | (1 << (Parser.NON_ZERO - 225)) - | (1 << (Parser.PARTIAL_NULL - 225)) - | (1 << (Parser.PARTIAL_ZERO - 225)) - | (1 << (Parser.ALWAYS_NULL - 225)) - | (1 << (Parser.ALWAYS_ZERO - 225)) + (1 << (Parser.NON_NULL - 226)) + | (1 << (Parser.NON_ZERO - 226)) + | (1 << (Parser.PARTIAL_NULL - 226)) + | (1 << (Parser.PARTIAL_ZERO - 226)) + | (1 << (Parser.ALWAYS_NULL - 226)) + | (1 << (Parser.ALWAYS_ZERO - 226)) ) ) != 0 @@ -15099,23 +15553,23 @@ def accept(self, visitor: ParseTreeVisitor): def conditionClause(self): localctx = Parser.ConditionClauseContext(self, self._ctx, self.state) - self.enterRule(localctx, 176, self.RULE_conditionClause) + self.enterRule(localctx, 184, self.RULE_conditionClause) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1805 + self.state = 1860 self.match(Parser.CONDITION) - self.state = 1806 + self.state = 1861 self.componentID() - self.state = 1811 + self.state = 1866 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 1807 + self.state = 1862 self.match(Parser.COMMA) - self.state = 1808 + self.state = 1863 self.componentID() - self.state = 1813 + self.state = 1868 self._errHandler.sync(self) _la = self._input.LA(1) @@ -15152,11 +15606,11 @@ def accept(self, visitor: ParseTreeVisitor): def inputMode(self): localctx = Parser.InputModeContext(self, self._ctx, self.state) - self.enterRule(localctx, 178, self.RULE_inputMode) + self.enterRule(localctx, 186, self.RULE_inputMode) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1814 + self.state = 1869 _la = self._input.LA(1) if not (_la == Parser.DATASET or _la == Parser.DATASET_PRIORITY): self._errHandler.recoverInline(self) @@ -15196,12 +15650,12 @@ def accept(self, visitor: ParseTreeVisitor): def imbalanceExpr(self): localctx = Parser.ImbalanceExprContext(self, self._ctx, self.state) - self.enterRule(localctx, 180, self.RULE_imbalanceExpr) + self.enterRule(localctx, 188, self.RULE_imbalanceExpr) try: self.enterOuterAlt(localctx, 1) - self.state = 1816 + self.state = 1871 self.match(Parser.IMBALANCE) - self.state = 1817 + self.state = 1872 self.expr(0) except RecognitionException as re: localctx.exception = re @@ -15239,11 +15693,11 @@ def accept(self, visitor: ParseTreeVisitor): def inputModeHierarchy(self): localctx = Parser.InputModeHierarchyContext(self, self._ctx, self.state) - self.enterRule(localctx, 182, self.RULE_inputModeHierarchy) + self.enterRule(localctx, 190, self.RULE_inputModeHierarchy) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1819 + self.state = 1874 _la = self._input.LA(1) if not (_la == Parser.DATASET or _la == Parser.RULE or _la == Parser.RULE_PRIORITY): self._errHandler.recoverInline(self) @@ -15283,11 +15737,11 @@ def accept(self, visitor: ParseTreeVisitor): def outputModeHierarchy(self): localctx = Parser.OutputModeHierarchyContext(self, self._ctx, self.state) - self.enterRule(localctx, 184, self.RULE_outputModeHierarchy) + self.enterRule(localctx, 192, self.RULE_outputModeHierarchy) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1821 + self.state = 1876 _la = self._input.LA(1) if not (_la == Parser.ALL or _la == Parser.COMPUTED): self._errHandler.recoverInline(self) @@ -15324,10 +15778,10 @@ def accept(self, visitor: ParseTreeVisitor): def alias(self): localctx = Parser.AliasContext(self, self._ctx, self.state) - self.enterRule(localctx, 186, self.RULE_alias) + self.enterRule(localctx, 194, self.RULE_alias) try: self.enterOuterAlt(localctx, 1) - self.state = 1823 + self.state = 1878 self.match(Parser.IDENTIFIER) except RecognitionException as re: localctx.exception = re @@ -15359,10 +15813,10 @@ def accept(self, visitor: ParseTreeVisitor): def varID(self): localctx = Parser.VarIDContext(self, self._ctx, self.state) - self.enterRule(localctx, 188, self.RULE_varID) + self.enterRule(localctx, 196, self.RULE_varID) try: self.enterOuterAlt(localctx, 1) - self.state = 1825 + self.state = 1880 self.match(Parser.IDENTIFIER) except RecognitionException as re: localctx.exception = re @@ -15394,10 +15848,10 @@ def accept(self, visitor: ParseTreeVisitor): def simpleComponentId(self): localctx = Parser.SimpleComponentIdContext(self, self._ctx, self.state) - self.enterRule(localctx, 190, self.RULE_simpleComponentId) + self.enterRule(localctx, 198, self.RULE_simpleComponentId) try: self.enterOuterAlt(localctx, 1) - self.state = 1827 + self.state = 1882 self.match(Parser.IDENTIFIER) except RecognitionException as re: localctx.exception = re @@ -15435,18 +15889,18 @@ def accept(self, visitor: ParseTreeVisitor): def componentID(self): localctx = Parser.ComponentIDContext(self, self._ctx, self.state) - self.enterRule(localctx, 192, self.RULE_componentID) + self.enterRule(localctx, 200, self.RULE_componentID) try: self.enterOuterAlt(localctx, 1) - self.state = 1829 + self.state = 1884 self.match(Parser.IDENTIFIER) - self.state = 1832 + self.state = 1887 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 196, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 201, self._ctx) if la_ == 1: - self.state = 1830 + self.state = 1885 self.match(Parser.MEMBERSHIP) - self.state = 1831 + self.state = 1886 self.match(Parser.IDENTIFIER) except RecognitionException as re: @@ -15494,27 +15948,27 @@ def accept(self, visitor: ParseTreeVisitor): def lists(self): localctx = Parser.ListsContext(self, self._ctx, self.state) - self.enterRule(localctx, 194, self.RULE_lists) + self.enterRule(localctx, 202, self.RULE_lists) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1834 + self.state = 1889 self.match(Parser.GLPAREN) - self.state = 1835 + self.state = 1890 self.scalarItem() - self.state = 1840 + self.state = 1895 self._errHandler.sync(self) _la = self._input.LA(1) while _la == Parser.COMMA: - self.state = 1836 + self.state = 1891 self.match(Parser.COMMA) - self.state = 1837 + self.state = 1892 self.scalarItem() - self.state = 1842 + self.state = 1897 self._errHandler.sync(self) _la = self._input.LA(1) - self.state = 1843 + self.state = 1898 self.match(Parser.GRPAREN) except RecognitionException as re: localctx.exception = re @@ -15549,12 +16003,12 @@ def accept(self, visitor: ParseTreeVisitor): def erCode(self): localctx = Parser.ErCodeContext(self, self._ctx, self.state) - self.enterRule(localctx, 196, self.RULE_erCode) + self.enterRule(localctx, 204, self.RULE_erCode) try: self.enterOuterAlt(localctx, 1) - self.state = 1845 + self.state = 1900 self.match(Parser.ERRORCODE) - self.state = 1846 + self.state = 1901 self.constant() except RecognitionException as re: localctx.exception = re @@ -15589,12 +16043,12 @@ def accept(self, visitor: ParseTreeVisitor): def erLevel(self): localctx = Parser.ErLevelContext(self, self._ctx, self.state) - self.enterRule(localctx, 198, self.RULE_erLevel) + self.enterRule(localctx, 206, self.RULE_erLevel) try: self.enterOuterAlt(localctx, 1) - self.state = 1848 + self.state = 1903 self.match(Parser.ERRORLEVEL) - self.state = 1849 + self.state = 1904 self.constant() except RecognitionException as re: localctx.exception = re @@ -15641,11 +16095,11 @@ def accept(self, visitor: ParseTreeVisitor): def comparisonOperand(self): localctx = Parser.ComparisonOperandContext(self, self._ctx, self.state) - self.enterRule(localctx, 200, self.RULE_comparisonOperand) + self.enterRule(localctx, 208, self.RULE_comparisonOperand) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1851 + self.state = 1906 _la = self._input.LA(1) if not ( ((_la) & ~0x3F) == 0 @@ -15699,9 +16153,9 @@ def accept(self, visitor: ParseTreeVisitor): def optionalExpr(self): localctx = Parser.OptionalExprContext(self, self._ctx, self.state) - self.enterRule(localctx, 202, self.RULE_optionalExpr) + self.enterRule(localctx, 210, self.RULE_optionalExpr) try: - self.state = 1855 + self.state = 1910 self._errHandler.sync(self) token = self._input.LA(1) if token in [ @@ -15791,12 +16245,12 @@ def optionalExpr(self): Parser.IDENTIFIER, ]: self.enterOuterAlt(localctx, 1) - self.state = 1853 + self.state = 1908 self.expr(0) pass elif token in [Parser.OPTIONAL]: self.enterOuterAlt(localctx, 2) - self.state = 1854 + self.state = 1909 self.match(Parser.OPTIONAL) pass else: @@ -15835,9 +16289,9 @@ def accept(self, visitor: ParseTreeVisitor): def optionalExprComponent(self): localctx = Parser.OptionalExprComponentContext(self, self._ctx, self.state) - self.enterRule(localctx, 204, self.RULE_optionalExprComponent) + self.enterRule(localctx, 212, self.RULE_optionalExprComponent) try: - self.state = 1859 + self.state = 1914 self._errHandler.sync(self) token = self._input.LA(1) if token in [ @@ -15915,12 +16369,12 @@ def optionalExprComponent(self): Parser.IDENTIFIER, ]: self.enterOuterAlt(localctx, 1) - self.state = 1857 + self.state = 1912 self.exprComponent(0) pass elif token in [Parser.OPTIONAL]: self.enterOuterAlt(localctx, 2) - self.state = 1858 + self.state = 1913 self.match(Parser.OPTIONAL) pass else: @@ -15968,34 +16422,34 @@ def accept(self, visitor: ParseTreeVisitor): def componentRole(self): localctx = Parser.ComponentRoleContext(self, self._ctx, self.state) - self.enterRule(localctx, 206, self.RULE_componentRole) + self.enterRule(localctx, 214, self.RULE_componentRole) try: - self.state = 1866 + self.state = 1921 self._errHandler.sync(self) token = self._input.LA(1) if token in [Parser.MEASURE]: self.enterOuterAlt(localctx, 1) - self.state = 1861 + self.state = 1916 self.match(Parser.MEASURE) pass elif token in [Parser.COMPONENT]: self.enterOuterAlt(localctx, 2) - self.state = 1862 + self.state = 1917 self.match(Parser.COMPONENT) pass elif token in [Parser.DIMENSION]: self.enterOuterAlt(localctx, 3) - self.state = 1863 + self.state = 1918 self.match(Parser.DIMENSION) pass elif token in [Parser.ATTRIBUTE]: self.enterOuterAlt(localctx, 4) - self.state = 1864 + self.state = 1919 self.match(Parser.ATTRIBUTE) pass elif token in [Parser.VIRAL]: self.enterOuterAlt(localctx, 5) - self.state = 1865 + self.state = 1920 self.viralAttribute() pass else: @@ -16034,12 +16488,12 @@ def accept(self, visitor: ParseTreeVisitor): def viralAttribute(self): localctx = Parser.ViralAttributeContext(self, self._ctx, self.state) - self.enterRule(localctx, 208, self.RULE_viralAttribute) + self.enterRule(localctx, 216, self.RULE_viralAttribute) try: self.enterOuterAlt(localctx, 1) - self.state = 1868 + self.state = 1923 self.match(Parser.VIRAL) - self.state = 1869 + self.state = 1924 self.match(Parser.ATTRIBUTE) except RecognitionException as re: localctx.exception = re @@ -16071,10 +16525,10 @@ def accept(self, visitor: ParseTreeVisitor): def valueDomainID(self): localctx = Parser.ValueDomainIDContext(self, self._ctx, self.state) - self.enterRule(localctx, 210, self.RULE_valueDomainID) + self.enterRule(localctx, 218, self.RULE_valueDomainID) try: self.enterOuterAlt(localctx, 1) - self.state = 1871 + self.state = 1926 self.match(Parser.IDENTIFIER) except RecognitionException as re: localctx.exception = re @@ -16106,10 +16560,10 @@ def accept(self, visitor: ParseTreeVisitor): def operatorID(self): localctx = Parser.OperatorIDContext(self, self._ctx, self.state) - self.enterRule(localctx, 212, self.RULE_operatorID) + self.enterRule(localctx, 220, self.RULE_operatorID) try: self.enterOuterAlt(localctx, 1) - self.state = 1873 + self.state = 1928 self.match(Parser.IDENTIFIER) except RecognitionException as re: localctx.exception = re @@ -16141,10 +16595,10 @@ def accept(self, visitor: ParseTreeVisitor): def routineName(self): localctx = Parser.RoutineNameContext(self, self._ctx, self.state) - self.enterRule(localctx, 214, self.RULE_routineName) + self.enterRule(localctx, 222, self.RULE_routineName) try: self.enterOuterAlt(localctx, 1) - self.state = 1875 + self.state = 1930 self.match(Parser.IDENTIFIER) except RecognitionException as re: localctx.exception = re @@ -16188,38 +16642,38 @@ def accept(self, visitor: ParseTreeVisitor): def constant(self): localctx = Parser.ConstantContext(self, self._ctx, self.state) - self.enterRule(localctx, 216, self.RULE_constant) + self.enterRule(localctx, 224, self.RULE_constant) try: - self.state = 1882 + self.state = 1937 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input, 201, self._ctx) + la_ = self._interp.adaptivePredict(self._input, 206, self._ctx) if la_ == 1: self.enterOuterAlt(localctx, 1) - self.state = 1877 + self.state = 1932 self.signedInteger() pass elif la_ == 2: self.enterOuterAlt(localctx, 2) - self.state = 1878 + self.state = 1933 self.signedNumber() pass elif la_ == 3: self.enterOuterAlt(localctx, 3) - self.state = 1879 + self.state = 1934 self.match(Parser.BOOLEAN_CONSTANT) pass elif la_ == 4: self.enterOuterAlt(localctx, 4) - self.state = 1880 + self.state = 1935 self.match(Parser.STRING_CONSTANT) pass elif la_ == 5: self.enterOuterAlt(localctx, 5) - self.state = 1881 + self.state = 1936 self.match(Parser.NULL_CONSTANT) pass @@ -16277,26 +16731,26 @@ def accept(self, visitor: ParseTreeVisitor): def basicScalarType(self): localctx = Parser.BasicScalarTypeContext(self, self._ctx, self.state) - self.enterRule(localctx, 218, self.RULE_basicScalarType) + self.enterRule(localctx, 226, self.RULE_basicScalarType) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1884 + self.state = 1939 _la = self._input.LA(1) if not ( ( - ((_la - 168) & ~0x3F) == 0 + ((_la - 169) & ~0x3F) == 0 and ( - (1 << (_la - 168)) + (1 << (_la - 169)) & ( - (1 << (Parser.BOOLEAN - 168)) - | (1 << (Parser.DATE - 168)) - | (1 << (Parser.TIME_PERIOD - 168)) - | (1 << (Parser.NUMBER - 168)) - | (1 << (Parser.STRING - 168)) - | (1 << (Parser.TIME - 168)) - | (1 << (Parser.INTEGER - 168)) - | (1 << (Parser.DURATION - 168)) + (1 << (Parser.BOOLEAN - 169)) + | (1 << (Parser.DATE - 169)) + | (1 << (Parser.TIME_PERIOD - 169)) + | (1 << (Parser.NUMBER - 169)) + | (1 << (Parser.STRING - 169)) + | (1 << (Parser.TIME - 169)) + | (1 << (Parser.INTEGER - 169)) + | (1 << (Parser.DURATION - 169)) ) ) != 0 @@ -16340,11 +16794,11 @@ def accept(self, visitor: ParseTreeVisitor): def retainType(self): localctx = Parser.RetainTypeContext(self, self._ctx, self.state) - self.enterRule(localctx, 220, self.RULE_retainType) + self.enterRule(localctx, 228, self.RULE_retainType) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 1886 + self.state = 1941 _la = self._input.LA(1) if not (_la == Parser.ALL or _la == Parser.BOOLEAN_CONSTANT): self._errHandler.recoverInline(self) @@ -16360,8 +16814,8 @@ def retainType(self): return localctx def sempred(self, localctx: RuleContext, ruleIndex: int, predIndex: int): - if self._predicates is None: - self._predicates = {} + if self._predicates == None: + self._predicates = dict() self._predicates[2] = self.expr_sempred self._predicates[3] = self.exprComponent_sempred pred = self._predicates.get(ruleIndex, None) diff --git a/src/vtlengine/AST/Grammar/tokens.py b/src/vtlengine/AST/Grammar/tokens.py index c7a2e8a3b..a9bc917e5 100644 --- a/src/vtlengine/AST/Grammar/tokens.py +++ b/src/vtlengine/AST/Grammar/tokens.py @@ -134,6 +134,7 @@ MEASURE = "measure" ATTRIBUTE = "attribute" VIRAL_ATTRIBUTE = "viral attribute" +PROPAGATION = "propagation" # Other Operators. TO = "to" AS = "as" diff --git a/src/vtlengine/AST/VtlVisitor.py b/src/vtlengine/AST/VtlVisitor.py index f2d65f7d4..23eb1bf0a 100644 --- a/src/vtlengine/AST/VtlVisitor.py +++ b/src/vtlengine/AST/VtlVisitor.py @@ -902,5 +902,33 @@ def visitBasicScalarType(self, ctx: Parser.BasicScalarTypeContext): def visitRetainType(self, ctx: Parser.RetainTypeContext): return self.visitChildren(ctx) + # Visit a parse tree produced by Parser#defViralPropagation. + def visitDefViralPropagation(self, ctx: Parser.DefViralPropagationContext): + return self.visitChildren(ctx) + + # Visit a parse tree produced by Parser#vpSignature. + def visitVpSignature(self, ctx: Parser.VpSignatureContext): + return self.visitChildren(ctx) + + # Visit a parse tree produced by Parser#vpBody. + def visitVpBody(self, ctx: Parser.VpBodyContext): + return self.visitChildren(ctx) + + # Visit a parse tree produced by Parser#enumeratedVpClause. + def visitEnumeratedVpClause(self, ctx: Parser.EnumeratedVpClauseContext): + return self.visitChildren(ctx) + + # Visit a parse tree produced by Parser#aggregationVpClause. + def visitAggregationVpClause(self, ctx: Parser.AggregationVpClauseContext): + return self.visitChildren(ctx) + + # Visit a parse tree produced by Parser#defaultVpClause. + def visitDefaultVpClause(self, ctx: Parser.DefaultVpClauseContext): + return self.visitChildren(ctx) + + # Visit a parse tree produced by Parser#vpCondition. + def visitVpCondition(self, ctx: Parser.VpConditionContext): + return self.visitChildren(ctx) + del Parser diff --git a/src/vtlengine/AST/__init__.py b/src/vtlengine/AST/__init__.py index 36600c2ac..dd3215ddf 100644 --- a/src/vtlengine/AST/__init__.py +++ b/src/vtlengine/AST/__init__.py @@ -732,6 +732,44 @@ class DPRuleset(AST): __eq__ = AST.ast_equality +@dataclass +class EnumeratedVpClause(AST): + """A single enumerated clause: when "A" [and "B"] then "C".""" + + name: Optional[str] + values: List[str] + result: str + + __eq__ = AST.ast_equality + + +@dataclass +class AggregateVpClause(AST): + """An aggregate clause: aggregate min|max|sum|avg""" + + function: str + + __eq__ = AST.ast_equality + + +@dataclass +class ViralPropagationDef(AST): + """ + define viral propagation name (valuedomain|variable target) is + clauses + end viral propagation + """ + + name: str + signature_type: str + target: str + enumerated_clauses: List[EnumeratedVpClause] + aggregate_clause: Optional[AggregateVpClause] + default_value: Optional[str] + + __eq__ = AST.ast_equality + + @dataclass class EvalOp(AST): """ diff --git a/src/vtlengine/Interpreter/__init__.py b/src/vtlengine/Interpreter/__init__.py index 664cb5139..a7801bec2 100644 --- a/src/vtlengine/Interpreter/__init__.py +++ b/src/vtlengine/Interpreter/__init__.py @@ -245,7 +245,8 @@ def visit_Start(self, node: AST.Start) -> Any: vtlengine.Exceptions.dataset_output = child.left.value # type: ignore[attr-defined] self._load_datapoints_efficient(statement_num) if not isinstance( - child, (AST.HRuleset, AST.DPRuleset, AST.Operator) + child, + (AST.HRuleset, AST.DPRuleset, AST.Operator, AST.ViralPropagationDef), ) and not isinstance(child, (AST.Assignment, AST.PersistentAssignment)): raise SemanticError("1-2-5") result = self.visit(child) @@ -412,6 +413,11 @@ def visit_HRuleset(self, node: AST.HRuleset) -> None: self.hrs[node.name] = ruleset_data + def visit_ViralPropagationDef(self, node: AST.ViralPropagationDef) -> None: + """Store the viral propagation definition for later use by operators.""" + # Storage will be wired in Task 7 (ViralPropagationRegistry) + pass + # Execution Language def visit_Assignment(self, node: AST.Assignment) -> Any: if ( diff --git a/tests/ViralAttributes/test_viral_parsing.py b/tests/ViralAttributes/test_viral_parsing.py new file mode 100644 index 000000000..caab7d29d --- /dev/null +++ b/tests/ViralAttributes/test_viral_parsing.py @@ -0,0 +1,157 @@ +import pandas as pd + +from vtlengine import run +from vtlengine.Model import Role + + +class TestViralPropagationParsing: + def test_parse_enumerated_propagation(self): + """Enumerated viral propagation definition parses and runs without error.""" + script = """ + define viral propagation CONF_priority (variable At_1) is + when "C" then "C"; + when "N" then "N"; + else "F" + end viral propagation; + + DS_r <- DS_1; + """ + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + }, + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE + + def test_parse_aggregate_propagation(self): + """Aggregate viral propagation definition parses and runs without error.""" + script = """ + define viral propagation TIME_prop (variable At_1) is + aggr max + end viral propagation; + + DS_r <- DS_1; + """ + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + { + "name": "At_1", + "type": "Integer", + "role": "Viral Attribute", + "nullable": True, + }, + ], + }, + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": [5]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + + def test_parse_binary_clause_propagation(self): + """Binary clause (when "A" and "B" then "C") parses correctly.""" + script = """ + define viral propagation COMP_mix (variable At_1) is + when "C" and "M" then "N"; + when "M" then "M"; + else " " + end viral propagation; + + DS_r <- DS_1; + """ + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + }, + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["C"]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + assert "DS_r" in result + + def test_parse_valuedomain_propagation(self): + """Value domain signature parses correctly.""" + script = """ + define viral propagation OBS_default (valuedomain CL_OBS_STATUS) is + when "M" then "M"; + when "L" then "L"; + else "A" + end viral propagation; + + DS_r <- DS_1; + """ + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + ], + }, + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + assert "DS_r" in result From f1bc27578895bec0696c88024016d8c402fb5153 Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Wed, 25 Mar 2026 17:13:24 +0100 Subject: [PATCH 07/14] feat(#510): implement viral propagation registry and wire into operators - Create ViralPropagation package with ViralPropagationRule and ViralPropagationRegistry - Registry supports resolve_pair (binary) and resolve_group (aggregation) - Wire registry into Interpreter: initialize per run, register rules from AST nodes - Wire into Binary._cleanup_attributes_after_merge: use resolve_pair for dual-viral attrs - Wire into Aggregation.evaluate: propagate viral attrs using resolve_group after grouping - Move imports to top of files per project convention --- src/vtlengine/Interpreter/__init__.py | 29 ++- src/vtlengine/Operators/Aggregation.py | 19 ++ src/vtlengine/Operators/__init__.py | 9 +- src/vtlengine/ViralPropagation/__init__.py | 125 +++++++++ tests/ViralAttributes/test_viral_binary.py | 8 +- .../test_viral_propagation_e2e.py | 246 ++++++++++++++++++ 6 files changed, 427 insertions(+), 9 deletions(-) create mode 100644 src/vtlengine/ViralPropagation/__init__.py create mode 100644 tests/ViralAttributes/test_viral_propagation_e2e.py diff --git a/src/vtlengine/Interpreter/__init__.py b/src/vtlengine/Interpreter/__init__.py index a7801bec2..62b6c591c 100644 --- a/src/vtlengine/Interpreter/__init__.py +++ b/src/vtlengine/Interpreter/__init__.py @@ -102,6 +102,12 @@ UNARY_MAPPING, ) from vtlengine.Utils.__Virtual_Assets import VirtualCounter +from vtlengine.ViralPropagation import ( + ViralPropagationRegistry, + ViralPropagationRule, + get_current_registry, + set_current_registry, +) # noinspection PyTypeChecker @@ -231,6 +237,9 @@ def _save_scalars_efficient(self, scalars: Dict[str, Scalar]) -> None: # ********************************** def visit_Start(self, node: AST.Start) -> Any: + # Initialize fresh viral propagation registry for this run + set_current_registry(ViralPropagationRegistry()) + statement_num = 1 if self.only_semantic: Operators.only_semantic = True @@ -414,9 +423,23 @@ def visit_HRuleset(self, node: AST.HRuleset) -> None: self.hrs[node.name] = ruleset_data def visit_ViralPropagationDef(self, node: AST.ViralPropagationDef) -> None: - """Store the viral propagation definition for later use by operators.""" - # Storage will be wired in Task 7 (ViralPropagationRegistry) - pass + """Store the viral propagation definition in the registry.""" + registry = get_current_registry() + + enumerated_clauses = [ + {"values": clause.values, "result": clause.result} for clause in node.enumerated_clauses + ] + aggregate_function = node.aggregate_clause.function if node.aggregate_clause else None + + rule = ViralPropagationRule( + name=node.name, + signature_type=node.signature_type, + target=node.target, + enumerated_clauses=enumerated_clauses, + aggregate_function=aggregate_function, + default_value=node.default_value, + ) + registry.register(rule) # Execution Language def visit_Assignment(self, node: AST.Assignment) -> Any: diff --git a/src/vtlengine/Operators/Aggregation.py b/src/vtlengine/Operators/Aggregation.py index 37e942ce9..9feeb4fa3 100644 --- a/src/vtlengine/Operators/Aggregation.py +++ b/src/vtlengine/Operators/Aggregation.py @@ -35,6 +35,7 @@ ) from vtlengine.Exceptions import RunTimeError, SemanticError from vtlengine.Model import Component, Dataset, Role +from vtlengine.ViralPropagation import get_current_registry def extract_grouping_identifiers( @@ -257,6 +258,9 @@ def evaluate( # type: ignore[override] grouping_keys = result.get_identifiers_names() result_df = operand.data.copy() if operand.data is not None else pd.DataFrame() measure_names = operand.get_measures_names() + viral_attr_names = operand.get_viral_attributes_names() + # Keep a copy of viral attrs for post-aggregation propagation + viral_df = result_df[grouping_keys + viral_attr_names].copy() if viral_attr_names else None result_df = result_df[grouping_keys + measure_names] if cls.op == COUNT: result_df = result_df.dropna(subset=measure_names, how="any") @@ -285,6 +289,21 @@ def evaluate( # type: ignore[override] aux_df = pd.merge(aux_df, result_df, how="left", on=grouping_keys) if having_expr is not None: aux_df.dropna(subset=result.get_measures_names(), how="any", inplace=True) + # Propagate viral attributes using the registry + if viral_df is not None and viral_attr_names: + registry = get_current_registry() + if grouping_keys: + grouped = viral_df.groupby(grouping_keys, sort=False) + for va_name in viral_attr_names: + aux_df[va_name] = ( + grouped[va_name] + .agg(lambda vals: registry.resolve_group(va_name, list(vals))) + .values + ) + else: + for va_name in viral_attr_names: + aux_df[va_name] = registry.resolve_group(va_name, list(viral_df[va_name])) + for comp_name, comp in result.components.items(): if comp_name in aux_df.columns: aux_df[comp_name] = aux_df[comp_name].astype(comp.data_type.dtype()) # type: ignore[call-overload] diff --git a/src/vtlengine/Operators/__init__.py b/src/vtlengine/Operators/__init__.py index 921f7b74e..2ab6739e2 100644 --- a/src/vtlengine/Operators/__init__.py +++ b/src/vtlengine/Operators/__init__.py @@ -34,6 +34,7 @@ from vtlengine.Exceptions import SemanticError from vtlengine.Model import Component, DataComponent, Dataset, Role, Scalar, ScalarSet from vtlengine.Utils.__Virtual_Assets import VirtualCounter +from vtlengine.ViralPropagation import get_current_registry ALL_MODEL_DATA_TYPES = Union[Dataset, Scalar, DataComponent] @@ -540,6 +541,7 @@ def _cleanup_attributes_after_merge( result_data = result_data.drop(att + "_y", axis=1) # Handle viral attribute merge suffixes + registry = get_current_registry() left_viral = set(left_operand.get_viral_attributes_names()) right_viral = set(right_operand.get_viral_attributes_names()) all_viral = left_viral | right_viral @@ -547,8 +549,11 @@ def _cleanup_attributes_after_merge( has_x = va + "_x" in result_data.columns has_y = va + "_y" in result_data.columns if has_x and has_y: - # Both operands have this viral attr; keep left value - result_data[va] = result_data[va + "_x"] + # Both operands have this viral attr — apply propagation rule + result_data[va] = result_data[[va + "_x", va + "_y"]].apply( + lambda row: registry.resolve_pair(va, row.iloc[0], row.iloc[1]), + axis=1, + ) result_data = result_data.drop([va + "_x", va + "_y"], axis=1) elif has_x: result_data = result_data.rename(columns={va + "_x": va}) diff --git a/src/vtlengine/ViralPropagation/__init__.py b/src/vtlengine/ViralPropagation/__init__.py new file mode 100644 index 000000000..4ace0f151 --- /dev/null +++ b/src/vtlengine/ViralPropagation/__init__.py @@ -0,0 +1,125 @@ +""" +ViralPropagation +================ + +Registry and resolution logic for viral attribute propagation rules +as defined by VTL 2.2 ``define viral propagation`` construct. +""" + +from dataclasses import dataclass, field +from functools import reduce +from typing import Any, Dict, List, Optional + + +@dataclass +class ViralPropagationRule: + """A single viral propagation rule definition.""" + + name: str + signature_type: str # "valuedomain" or "variable" + target: str + enumerated_clauses: List[Dict[str, Any]] = field(default_factory=list) + aggregate_function: Optional[str] = None # "min", "max", "sum", "avg" + default_value: Optional[str] = None + + +class ViralPropagationRegistry: + """Registry that stores viral propagation rules and resolves attribute values.""" + + def __init__(self) -> None: + self._variable_rules: Dict[str, ViralPropagationRule] = {} + self._valuedomain_rules: Dict[str, ViralPropagationRule] = {} + + def register(self, rule: ViralPropagationRule) -> None: + """Register a viral propagation rule.""" + if rule.signature_type == "variable": + self._variable_rules[rule.target] = rule + else: + self._valuedomain_rules[rule.target] = rule + + def get_rule_for_variable(self, variable_name: str) -> Optional[ViralPropagationRule]: + """Get the propagation rule for a variable (variable-level overrides value domain).""" + if variable_name in self._variable_rules: + return self._variable_rules[variable_name] + # Value domain lookup would require knowing which VD the variable uses. + # For v1, only variable-level rules are supported. + return None + + def resolve_pair(self, variable_name: str, value_a: Any, value_b: Any) -> Any: + """Resolve two viral attribute values into one (for binary operators).""" + rule = self.get_rule_for_variable(variable_name) + if rule is None: + return None + + if rule.aggregate_function is not None: + if rule.aggregate_function == "avg": + return (value_a + value_b) / 2 + elif rule.aggregate_function == "min": + return min(value_a, value_b) + elif rule.aggregate_function == "max": + return max(value_a, value_b) + elif rule.aggregate_function == "sum": + return value_a + value_b + return None + + # Enumerated: binary clauses first, then unary (per spec) + binary_clauses = [c for c in rule.enumerated_clauses if len(c["values"]) == 2] + unary_clauses = [c for c in rule.enumerated_clauses if len(c["values"]) == 1] + + pair = {value_a, value_b} + for clause in binary_clauses: + if set(clause["values"]) == pair: + return clause["result"] + + for clause in unary_clauses: + if clause["values"][0] in pair: + return clause["result"] + + return rule.default_value + + def resolve_group(self, variable_name: str, values: List[Any]) -> Any: + """Resolve N values (for aggregation/analytic operators).""" + rule = self.get_rule_for_variable(variable_name) + if rule is None: + return None + + if len(values) == 0: + return None + if len(values) == 1: + return values[0] + + if rule.aggregate_function is not None: + funcs: Dict[str, Any] = { + "min": min, + "max": max, + "sum": sum, + "avg": lambda v: sum(v) / len(v), + } + return funcs[rule.aggregate_function](values) + + # Enumerated: reduce pairwise (associative + commutative guarantees correctness) + return reduce(lambda a, b: self.resolve_pair(variable_name, a, b), values) + + def clear(self) -> None: + """Clear all registered rules.""" + self._variable_rules.clear() + self._valuedomain_rules.clear() + + +# Module-level accessor for operators to use. +# The Interpreter sets this at the start of each run() call. +_current_registry: Optional[ViralPropagationRegistry] = None + + +def get_current_registry() -> ViralPropagationRegistry: + """Get the current viral propagation registry.""" + global _current_registry # noqa: PLW0603 + if _current_registry is None: + _current_registry = ViralPropagationRegistry() + return _current_registry + + +def set_current_registry(registry: ViralPropagationRegistry) -> None: + """Set the current viral propagation registry (called by Interpreter).""" + global _current_registry # noqa: PLW0603 + _current_registry = registry diff --git a/tests/ViralAttributes/test_viral_binary.py b/tests/ViralAttributes/test_viral_binary.py index b56e0047f..6330831db 100644 --- a/tests/ViralAttributes/test_viral_binary.py +++ b/tests/ViralAttributes/test_viral_binary.py @@ -156,8 +156,8 @@ def test_binary_dataset_scalar_keeps_viral_attr(self): assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE assert list(ds_r.data["At_1"]) == ["A", "B"] - def test_binary_both_operands_viral_keeps_left(self): - """When both operands have the same viral attr, keep left value.""" + def test_binary_both_operands_viral_no_rule_gives_null(self): + """When both operands have same viral attr but no rule, result is null.""" script = "DS_r <- DS_1 + DS_2;" data_structures = { "datasets": [ @@ -216,5 +216,5 @@ def test_binary_both_operands_viral_keeps_left(self): result = run(script=script, data_structures=data_structures, datapoints=datapoints) ds_r = result["DS_r"] assert "At_1" in ds_r.components - # Left operand values kept when no propagation rule - assert list(ds_r.data["At_1"]) == ["A", "B"] + # No propagation rule → null values + assert all(pd.isna(v) for v in ds_r.data["At_1"]) diff --git a/tests/ViralAttributes/test_viral_propagation_e2e.py b/tests/ViralAttributes/test_viral_propagation_e2e.py new file mode 100644 index 000000000..05330e6b7 --- /dev/null +++ b/tests/ViralAttributes/test_viral_propagation_e2e.py @@ -0,0 +1,246 @@ +import pandas as pd + +from vtlengine import run +from vtlengine.Model import Role + + +class TestViralPropagationEndToEnd: + def test_binary_with_enumerated_propagation(self): + """End-to-end: define viral propagation + binary operator.""" + script = """ + define viral propagation CONF_priority (variable At_1) is + when "C" then "C"; + when "N" then "N"; + else "F" + end viral propagation; + + DS_r <- DS_1 + DS_2; + """ + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + }, + { + "name": "DS_2", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + }, + ] + } + datapoints = { + "DS_1": pd.DataFrame( + {"Id_1": [1, 2, 3], "Me_1": [10.0, 20.0, 30.0], "At_1": ["C", "N", "F"]} + ), + "DS_2": pd.DataFrame( + {"Id_1": [1, 2, 3], "Me_1": [5.0, 15.0, 25.0], "At_1": ["N", "F", "F"]} + ), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE + # C+N → C (unary "C" matches); N+F → N (unary "N" matches); F+F → F (else) + assert list(ds_r.data["At_1"]) == ["C", "N", "F"] + + def test_binary_with_binary_clause_precedence(self): + """Binary clauses take precedence over unary clauses.""" + script = """ + define viral propagation COMP_mix (variable At_1) is + when "C" and "M" then "N"; + when "M" then "M"; + else " " + end viral propagation; + + DS_r <- DS_1 + DS_2; + """ + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + }, + { + "name": "DS_2", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + }, + ] + } + datapoints = { + "DS_1": pd.DataFrame( + {"Id_1": [1, 2, 3], "Me_1": [10.0, 20.0, 30.0], "At_1": ["C", "M", "X"]} + ), + "DS_2": pd.DataFrame( + {"Id_1": [1, 2, 3], "Me_1": [5.0, 15.0, 25.0], "At_1": ["M", "F", "Y"]} + ), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + # C+M → N (binary clause); M+F → M (unary "M"); X+Y → " " (else/default) + assert list(ds_r.data["At_1"]) == ["N", "M", " "] + + def test_no_rule_gives_null(self): + """When both operands have same viral attr but no propagation rule, result is null.""" + script = """ + DS_r <- DS_1 + DS_2; + """ + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + }, + { + "name": "DS_2", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + { + "name": "At_1", + "type": "String", + "role": "Viral Attribute", + "nullable": True, + }, + ], + }, + ] + } + datapoints = { + "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]}), + "DS_2": pd.DataFrame({"Id_1": [1], "Me_1": [5.0], "At_1": ["B"]}), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + # No propagation rule → null + assert pd.isna(ds_r.data["At_1"].iloc[0]) + + def test_aggregate_propagation_with_max(self): + """End-to-end: aggregate max propagation in aggregation.""" + script = """ + define viral propagation SCORE_prop (variable At_1) is + aggr max + end viral propagation; + + DS_r <- sum(DS_1 group by Id_1); + """ + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + { + "name": "Id_2", + "type": "Integer", + "role": "Identifier", + "nullable": False, + }, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + { + "name": "At_1", + "type": "Integer", + "role": "Viral Attribute", + "nullable": True, + }, + ], + } + ] + } + datapoints = { + "DS_1": pd.DataFrame( + { + "Id_1": [1, 1, 2], + "Id_2": [1, 2, 1], + "Me_1": [10.0, 20.0, 30.0], + "At_1": [3, 7, 5], + } + ), + } + result = run(script=script, data_structures=data_structures, datapoints=datapoints) + ds_r = result["DS_r"] + assert "At_1" in ds_r.components + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE + # Group Id_1=1: max(3,7)=7; Group Id_1=2: max(5)=5 + sorted_data = ds_r.data.sort_values("Id_1").reset_index(drop=True) + assert list(sorted_data["At_1"]) == [7, 5] From 829a97399c7fd22777e549700855aa7ad14970c7 Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Wed, 25 Mar 2026 17:14:03 +0100 Subject: [PATCH 08/14] feat(#510): add visitor stubs for viral propagation AST nodes in ASTTemplate --- src/vtlengine/AST/ASTTemplate.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/vtlengine/AST/ASTTemplate.py b/src/vtlengine/AST/ASTTemplate.py index 871712dbe..7ee4be76e 100644 --- a/src/vtlengine/AST/ASTTemplate.py +++ b/src/vtlengine/AST/ASTTemplate.py @@ -613,3 +613,12 @@ def visit_Comment(self, node: AST.Comment) -> None: """ Comment: (value) """ + + def visit_ViralPropagationDef(self, node: AST.ViralPropagationDef) -> None: + pass + + def visit_EnumeratedVpClause(self, node: AST.EnumeratedVpClause) -> None: + pass + + def visit_AggregateVpClause(self, node: AST.AggregateVpClause) -> None: + pass From 0f97732718213fc9e66fd3d216588ec76e542de5 Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Wed, 25 Mar 2026 17:14:48 +0100 Subject: [PATCH 09/14] feat(#510): add prettify support for define viral propagation --- src/vtlengine/AST/ASTString.py | 35 +++++++++++++++ tests/ViralAttributes/test_viral_prettify.py | 47 ++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 tests/ViralAttributes/test_viral_prettify.py diff --git a/src/vtlengine/AST/ASTString.py b/src/vtlengine/AST/ASTString.py index e70b68e96..f5a16eb3b 100644 --- a/src/vtlengine/AST/ASTString.py +++ b/src/vtlengine/AST/ASTString.py @@ -239,6 +239,41 @@ def visit_DPRuleset(self, node: AST.DPRuleset) -> None: f"({signature}) is {rules} end datapoint ruleset;" ) + # ---------------------- Viral Propagation ---------------------- + def visit_ViralPropagationDef(self, node: AST.ViralPropagationDef) -> None: + clauses_strs: list[str] = [] + for clause in node.enumerated_clauses: + clause_str = "" + if clause.name is not None: + clause_str += f"{clause.name} : " + values_str = " and ".join([f'"{v}"' for v in clause.values]) + clause_str += f'when {values_str} then "{clause.result}"' + clauses_strs.append(clause_str) + if node.aggregate_clause is not None: + clauses_strs.append(f"aggr {node.aggregate_clause.function}") + if node.default_value is not None: + clauses_strs.append(f'else "{node.default_value}"') + + if self.pretty: + self.vtl_script += ( + f"define viral propagation {node.name}({node.signature_type} {node.target}) is{nl}" + ) + for i, c in enumerate(clauses_strs): + self.vtl_script += f"{tab}{c}" + if i != len(clauses_strs) - 1: + self.vtl_script += f";{nl}" + else: + self.vtl_script += nl + self.vtl_script += f"end viral propagation;{nl}" + else: + clauses_joined = ";".join(clauses_strs) + self.vtl_script += ( + f"define viral propagation {node.name} " + f"({node.signature_type} {node.target}) is " + f"{clauses_joined} " + f"end viral propagation;" + ) + # ---------------------- User Defined Operators ---------------------- def visit_Argument(self, node: AST.Argument) -> str: diff --git a/tests/ViralAttributes/test_viral_prettify.py b/tests/ViralAttributes/test_viral_prettify.py new file mode 100644 index 000000000..103a1e9e9 --- /dev/null +++ b/tests/ViralAttributes/test_viral_prettify.py @@ -0,0 +1,47 @@ +from vtlengine import prettify + + +class TestViralPropagationPrettify: + def test_prettify_enumerated(self): + script = ( + "define viral propagation CONF_priority(variable At_1) is " + 'when "C" then "C";when "N" then "N";else "F" ' + "end viral propagation;" + "DS_r<-DS_1+DS_2;" + ) + result = prettify(script=script) + assert "define viral propagation" in result + assert 'when "C" then "C"' in result + assert 'else "F"' in result + assert "end viral propagation" in result + + def test_prettify_aggregate(self): + script = ( + "define viral propagation TIME_prop(variable At_1)" + "is aggr max end viral propagation;" + "DS_r<-DS_1;" + ) + result = prettify(script=script) + assert "define viral propagation" in result + assert "aggr max" in result + assert "end viral propagation" in result + + def test_prettify_binary_clause(self): + script = ( + "define viral propagation MIX(variable At_1) is " + 'when "C" and "M" then "N";when "M" then "M";else " " ' + "end viral propagation;" + "DS_r<-DS_1;" + ) + result = prettify(script=script) + assert 'when "C" and "M" then "N"' in result + + def test_prettify_valuedomain(self): + script = ( + "define viral propagation OBS(valuedomain CL_OBS)" + 'is when "M" then "M";else "A" ' + "end viral propagation;" + "DS_r<-DS_1;" + ) + result = prettify(script=script) + assert "valuedomain CL_OBS" in result From 27fb07dfbc9af57850e2e515bafeb680d804cbc3 Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Wed, 25 Mar 2026 17:18:11 +0100 Subject: [PATCH 10/14] feat(#510): add semantic validation for viral propagation rules - Add error codes 1-3-3-1 through 1-3-3-4 to messages.py - Validate: no duplicate rules for same variable/valuedomain - Validate: no duplicate enumeration combinations - Validate: no mixing enumerated and aggregate clauses --- src/vtlengine/Exceptions/messages.py | 23 ++++++++++ src/vtlengine/Interpreter/__init__.py | 20 ++++++++- .../ViralAttributes/test_viral_validation.py | 44 +++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 tests/ViralAttributes/test_viral_validation.py diff --git a/src/vtlengine/Exceptions/messages.py b/src/vtlengine/Exceptions/messages.py index 7cd45abe5..edb7b42a2 100644 --- a/src/vtlengine/Exceptions/messages.py +++ b/src/vtlengine/Exceptions/messages.py @@ -979,6 +979,29 @@ "description": "Raised when a Time aggregation operator is missing the operand " "definition outside an aggregation context.", }, + # ---------- Viral Propagation ---------- + "1-3-3-1": { + "message": "Duplicate viral propagation rule for variable {name}.", + "description": "Raised when two define viral propagation statements " + "target the same variable.", + }, + "1-3-3-2": { + "message": "Duplicate viral propagation rule for value domain {name}.", + "description": "Raised when two define viral propagation statements " + "target the same value domain.", + }, + "1-3-3-3": { + "message": "Cannot mix enumerated and aggregate clauses in viral " + "propagation definition {name}.", + "description": "Raised when a viral propagation definition contains both " + "enumerated (when/then) and aggregate clauses.", + }, + "1-3-3-4": { + "message": "Duplicate enumeration combination {values} in viral " + "propagation definition {name}.", + "description": "Raised when the same value pair is described more than " + "once in an enumerated viral propagation.", + }, # ---------- Interpreter ---------- "1-3-5": { "message": "{node_op} not found or not valid for {op_type}.", diff --git a/src/vtlengine/Interpreter/__init__.py b/src/vtlengine/Interpreter/__init__.py index 62b6c591c..daca745f6 100644 --- a/src/vtlengine/Interpreter/__init__.py +++ b/src/vtlengine/Interpreter/__init__.py @@ -423,9 +423,27 @@ def visit_HRuleset(self, node: AST.HRuleset) -> None: self.hrs[node.name] = ruleset_data def visit_ViralPropagationDef(self, node: AST.ViralPropagationDef) -> None: - """Store the viral propagation definition in the registry.""" + """Validate and store the viral propagation definition in the registry.""" registry = get_current_registry() + # Validate: cannot mix enumerated and aggregate clauses + if node.enumerated_clauses and node.aggregate_clause: + raise SemanticError("1-3-3-3", name=node.name) + + # Validate: no duplicate enumeration combinations + seen_values: Set[frozenset[str]] = set() + for clause in node.enumerated_clauses: + key = frozenset(clause.values) + if key in seen_values: + raise SemanticError("1-3-3-4", values=clause.values, name=node.name) + seen_values.add(key) + + # Validate: no duplicate rules for the same target + existing = registry.get_rule_for_variable(node.target) + if existing is not None and node.signature_type == existing.signature_type: + code = "1-3-3-1" if node.signature_type == "variable" else "1-3-3-2" + raise SemanticError(code, name=node.target) + enumerated_clauses = [ {"values": clause.values, "result": clause.result} for clause in node.enumerated_clauses ] diff --git a/tests/ViralAttributes/test_viral_validation.py b/tests/ViralAttributes/test_viral_validation.py new file mode 100644 index 000000000..b3d547aa6 --- /dev/null +++ b/tests/ViralAttributes/test_viral_validation.py @@ -0,0 +1,44 @@ +import pandas as pd +import pytest + +from vtlengine import run +from vtlengine.Exceptions import SemanticError + +DATA_STRUCTURES = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + ], + } + ] +} +DATAPOINTS = {"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0]})} + + +class TestViralPropagationSemanticErrors: + def test_duplicate_variable_rule_raises_error(self): + script = """ + define viral propagation rule1 (variable At_1) is + when "C" then "C" + end viral propagation; + define viral propagation rule2 (variable At_1) is + when "N" then "N" + end viral propagation; + DS_r <- DS_1; + """ + with pytest.raises(SemanticError, match="1-3-3-1"): + run(script=script, data_structures=DATA_STRUCTURES, datapoints=DATAPOINTS) + + def test_duplicate_enumeration_raises_error(self): + script = """ + define viral propagation dup (variable At_1) is + when "C" then "C"; + when "C" then "N" + end viral propagation; + DS_r <- DS_1; + """ + with pytest.raises(SemanticError, match="1-3-3-4"): + run(script=script, data_structures=DATA_STRUCTURES, datapoints=DATAPOINTS) From 687c923d6145888001181b7eb25ad830e4dd475d Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Wed, 25 Mar 2026 17:26:17 +0100 Subject: [PATCH 11/14] refactor(#510): consolidate viral attribute tests into 4 focused files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merged 9 test files into 4 well-organized files with shared fixtures: - test_viral_role.py: data model unit tests (6 tests) - test_viral_operators.py: operator propagation — binary, unary, other ops (24 tests) - test_viral_propagation.py: define viral propagation — parsing, e2e, validation (10 tests) - test_viral_prettify.py: prettify support (4 tests) Extracted shared data structure builders (_ds, _id, _me, _va, _at, _run) to eliminate boilerplate duplication across tests. --- tests/ViralAttributes/test_viral_binary.py | 220 ---------------- tests/ViralAttributes/test_viral_calc.py | 104 -------- tests/ViralAttributes/test_viral_operators.py | 232 +++++++++++++++++ tests/ViralAttributes/test_viral_parsing.py | 157 ----------- .../ViralAttributes/test_viral_propagation.py | 226 ++++++++++++++++ .../test_viral_propagation_e2e.py | 246 ------------------ .../test_viral_remaining_ops.py | 158 ----------- tests/ViralAttributes/test_viral_unary.py | 189 -------------- .../ViralAttributes/test_viral_validation.py | 44 ---- 9 files changed, 458 insertions(+), 1118 deletions(-) delete mode 100644 tests/ViralAttributes/test_viral_binary.py delete mode 100644 tests/ViralAttributes/test_viral_calc.py create mode 100644 tests/ViralAttributes/test_viral_operators.py delete mode 100644 tests/ViralAttributes/test_viral_parsing.py create mode 100644 tests/ViralAttributes/test_viral_propagation.py delete mode 100644 tests/ViralAttributes/test_viral_propagation_e2e.py delete mode 100644 tests/ViralAttributes/test_viral_remaining_ops.py delete mode 100644 tests/ViralAttributes/test_viral_unary.py delete mode 100644 tests/ViralAttributes/test_viral_validation.py diff --git a/tests/ViralAttributes/test_viral_binary.py b/tests/ViralAttributes/test_viral_binary.py deleted file mode 100644 index 6330831db..000000000 --- a/tests/ViralAttributes/test_viral_binary.py +++ /dev/null @@ -1,220 +0,0 @@ -import pandas as pd - -from vtlengine import run -from vtlengine.Model import Role - - -class TestViralAttributeBinaryOps: - def test_binary_propagation_single_viral_attribute(self): - """Viral attribute from one operand is kept in result with same values.""" - script = "DS_r <- DS_1 + DS_2;" - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Me_1", - "type": "Number", - "role": "Measure", - "nullable": True, - }, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - }, - { - "name": "DS_2", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Me_1", - "type": "Number", - "role": "Measure", - "nullable": True, - }, - ], - }, - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), - "DS_2": pd.DataFrame({"Id_1": [1, 2], "Me_1": [5.0, 15.0]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE - assert list(ds_r.data["At_1"]) == ["A", "B"] - - def test_binary_non_viral_attribute_still_dropped(self): - """Non-viral (regular) attributes are still dropped as before.""" - script = "DS_r <- DS_1 + DS_2;" - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Me_1", - "type": "Number", - "role": "Measure", - "nullable": True, - }, - { - "name": "At_1", - "type": "String", - "role": "Attribute", - "nullable": True, - }, - ], - }, - { - "name": "DS_2", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Me_1", - "type": "Number", - "role": "Measure", - "nullable": True, - }, - ], - }, - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), - "DS_2": pd.DataFrame({"Id_1": [1, 2], "Me_1": [5.0, 15.0]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" not in ds_r.components - - def test_binary_dataset_scalar_keeps_viral_attr(self): - """DS_r <- DS_1 + 5 where DS_1 has a viral attribute.""" - script = "DS_r <- DS_1 + 5;" - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Me_1", - "type": "Number", - "role": "Measure", - "nullable": True, - }, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - }, - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE - assert list(ds_r.data["At_1"]) == ["A", "B"] - - def test_binary_both_operands_viral_no_rule_gives_null(self): - """When both operands have same viral attr but no rule, result is null.""" - script = "DS_r <- DS_1 + DS_2;" - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Me_1", - "type": "Number", - "role": "Measure", - "nullable": True, - }, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - }, - { - "name": "DS_2", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Me_1", - "type": "Number", - "role": "Measure", - "nullable": True, - }, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - }, - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), - "DS_2": pd.DataFrame({"Id_1": [1, 2], "Me_1": [5.0, 15.0], "At_1": ["X", "Y"]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - # No propagation rule → null values - assert all(pd.isna(v) for v in ds_r.data["At_1"]) diff --git a/tests/ViralAttributes/test_viral_calc.py b/tests/ViralAttributes/test_viral_calc.py deleted file mode 100644 index bb6714d2f..000000000 --- a/tests/ViralAttributes/test_viral_calc.py +++ /dev/null @@ -1,104 +0,0 @@ -import pandas as pd - -from vtlengine import run -from vtlengine.Model import Role - - -class TestViralAttributeCalc: - def test_calc_viral_attribute(self): - """Test that 'viral attribute' role setter works in calc clause.""" - script = """ - DS_r <- DS_1 [calc viral attribute At_1 := "X"]; - """ - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - ], - } - ] - } - datapoints = {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0]})} - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE - assert list(ds_r.data["At_1"]) == ["X", "X"] - - def test_input_viral_attribute_loaded(self): - """Test that a viral attribute in input data structure is correctly loaded.""" - script = """ - DS_r <- DS_1; - """ - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - } - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE - assert list(ds_r.data["At_1"]) == ["A", "B"] - - def test_input_viral_attribute_legacy_format(self): - """Test that 'ViralAttribute' (legacy format) is correctly loaded.""" - script = """ - DS_r <- DS_1; - """ - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - { - "name": "At_1", - "type": "String", - "role": "ViralAttribute", - "nullable": True, - }, - ], - } - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE diff --git a/tests/ViralAttributes/test_viral_operators.py b/tests/ViralAttributes/test_viral_operators.py new file mode 100644 index 000000000..4818d87af --- /dev/null +++ b/tests/ViralAttributes/test_viral_operators.py @@ -0,0 +1,232 @@ +"""Tests for viral attribute propagation through all operator categories.""" + +import pandas as pd +import pytest + +from vtlengine import run +from vtlengine.Model import Role + +# -- Shared data structure builders -- + + +def _ds(name: str, components: list) -> dict: + return {"name": name, "DataStructure": components} + + +def _id(name: str = "Id_1") -> dict: + return {"name": name, "type": "Integer", "role": "Identifier", "nullable": False} + + +def _me(name: str = "Me_1", type_: str = "Number") -> dict: + return {"name": name, "type": type_, "role": "Measure", "nullable": True} + + +def _va(name: str = "At_1", type_: str = "String") -> dict: + return {"name": name, "type": type_, "role": "Viral Attribute", "nullable": True} + + +def _at(name: str = "At_1", type_: str = "String") -> dict: + return {"name": name, "type": type_, "role": "Attribute", "nullable": True} + + +def _run(script: str, datasets: list, datapoints: dict) -> dict: + return run( + script=script, + data_structures={"datasets": datasets}, + datapoints=datapoints, + ) + + +# -- Calc / Input loading -- + + +class TestViralAttributeInputAndCalc: + def test_calc_viral_attribute(self): + result = _run( + 'DS_r <- DS_1 [calc viral attribute At_1 := "X"];', + [_ds("DS_1", [_id(), _me()])], + {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0]})}, + ) + assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE + + def test_input_viral_attribute_loaded(self): + result = _run( + "DS_r <- DS_1;", + [_ds("DS_1", [_id(), _me(), _va()])], + {"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]})}, + ) + assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE + assert list(result["DS_r"].data["At_1"]) == ["A"] + + def test_input_viral_attribute_legacy_format(self): + ds = { + "name": "DS_1", + "DataStructure": [ + _id(), + _me(), + {"name": "At_1", "type": "String", "role": "ViralAttribute", "nullable": True}, + ], + } + result = _run( + "DS_r <- DS_1;", + [ds], + {"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]})}, + ) + assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE + + +# -- Binary operators -- + + +class TestViralAttributeBinaryOps: + def test_single_viral_attribute_propagated(self): + result = _run( + "DS_r <- DS_1 + DS_2;", + [_ds("DS_1", [_id(), _me(), _va()]), _ds("DS_2", [_id(), _me()])], + { + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), + "DS_2": pd.DataFrame({"Id_1": [1, 2], "Me_1": [5.0, 15.0]}), + }, + ) + ds_r = result["DS_r"] + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE + assert list(ds_r.data["At_1"]) == ["A", "B"] + + def test_non_viral_attribute_still_dropped(self): + result = _run( + "DS_r <- DS_1 + DS_2;", + [_ds("DS_1", [_id(), _me(), _at()]), _ds("DS_2", [_id(), _me()])], + { + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), + "DS_2": pd.DataFrame({"Id_1": [1, 2], "Me_1": [5.0, 15.0]}), + }, + ) + assert "At_1" not in result["DS_r"].components + + def test_dataset_scalar_keeps_viral_attr(self): + result = _run( + "DS_r <- DS_1 + 5;", + [_ds("DS_1", [_id(), _me(), _va()])], + {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]})}, + ) + ds_r = result["DS_r"] + assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE + assert list(ds_r.data["At_1"]) == ["A", "B"] + + def test_both_operands_viral_no_rule_gives_null(self): + result = _run( + "DS_r <- DS_1 + DS_2;", + [_ds("DS_1", [_id(), _me(), _va()]), _ds("DS_2", [_id(), _me(), _va()])], + { + "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]}), + "DS_2": pd.DataFrame({"Id_1": [1], "Me_1": [5.0], "At_1": ["B"]}), + }, + ) + assert all(pd.isna(v) for v in result["DS_r"].data["At_1"]) + + +# -- Unary operators -- + +NUMERIC_UNARY_OPS = [ + ("abs", "Number", [10.0, -20.0]), + ("ceil", "Number", [1.1, 2.9]), + ("floor", "Number", [1.1, 2.9]), + ("ln", "Number", [1.0, 2.718]), + ("exp", "Number", [0.0, 1.0]), + ("sqrt", "Number", [4.0, 9.0]), +] + +STRING_UNARY_OPS = [ + ("upper", "String", ["abc", "def"]), + ("lower", "String", ["ABC", "DEF"]), + ("trim", "String", [" abc ", " def "]), + ("ltrim", "String", [" abc", " def"]), + ("rtrim", "String", ["abc ", "def "]), + ("length", "String", ["abc", "defgh"]), +] + + +class TestViralAttributeUnaryOps: + @pytest.mark.parametrize( + "op,me_type,me_values", + NUMERIC_UNARY_OPS, + ids=[x[0] for x in NUMERIC_UNARY_OPS], + ) + def test_numeric_unary_preserves_viral_attr(self, op, me_type, me_values): + result = _run( + f"DS_r <- {op}(DS_1);", + [_ds("DS_1", [_id(), _me(type_=me_type), _va()])], + {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": me_values, "At_1": ["A", "B"]})}, + ) + assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE + assert list(result["DS_r"].data["At_1"]) == ["A", "B"] + + @pytest.mark.parametrize( + "op,me_type,me_values", + STRING_UNARY_OPS, + ids=[x[0] for x in STRING_UNARY_OPS], + ) + def test_string_unary_preserves_viral_attr(self, op, me_type, me_values): + result = _run( + f"DS_r <- {op}(DS_1);", + [_ds("DS_1", [_id(), _me(type_=me_type), _va()])], + {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": me_values, "At_1": ["A", "B"]})}, + ) + assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE + + def test_not_preserves_viral_attr(self): + result = _run( + "DS_r <- not DS_1;", + [_ds("DS_1", [_id(), _me(type_="Boolean"), _va()])], + {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [True, False], "At_1": ["A", "B"]})}, + ) + assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE + + def test_isnull_preserves_viral_attr(self): + result = _run( + "DS_r <- isnull(DS_1);", + [_ds("DS_1", [_id(), _me(), _va()])], + {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, None], "At_1": ["A", "B"]})}, + ) + assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE + + +# -- Other operators -- + + +class TestViralAttributeOtherOps: + def test_aggregation_keeps_viral_attribute(self): + result = _run( + "DS_r <- sum(DS_1 group by Id_1);", + [_ds("DS_1", [_id(), _id("Id_2"), _me(), _va()])], + { + "DS_1": pd.DataFrame( + { + "Id_1": [1, 1, 2], + "Id_2": [1, 2, 1], + "Me_1": [10.0, 20.0, 30.0], + "At_1": ["A", "A", "B"], + } + ) + }, + ) + assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE + + def test_between_keeps_viral_attribute(self): + result = _run( + "DS_r <- between(DS_1, 5, 25);", + [_ds("DS_1", [_id(), _me(), _va()])], + {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 30.0], "At_1": ["A", "B"]})}, + ) + assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE + + def test_intersect_preserves_viral_attribute(self): + result = _run( + "DS_r <- intersect(DS_1, DS_2);", + [_ds("DS_1", [_id(), _me(), _va()]), _ds("DS_2", [_id(), _me(), _va()])], + { + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), + "DS_2": pd.DataFrame({"Id_1": [1, 3], "Me_1": [10.0, 30.0], "At_1": ["A", "C"]}), + }, + ) + assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE diff --git a/tests/ViralAttributes/test_viral_parsing.py b/tests/ViralAttributes/test_viral_parsing.py deleted file mode 100644 index caab7d29d..000000000 --- a/tests/ViralAttributes/test_viral_parsing.py +++ /dev/null @@ -1,157 +0,0 @@ -import pandas as pd - -from vtlengine import run -from vtlengine.Model import Role - - -class TestViralPropagationParsing: - def test_parse_enumerated_propagation(self): - """Enumerated viral propagation definition parses and runs without error.""" - script = """ - define viral propagation CONF_priority (variable At_1) is - when "C" then "C"; - when "N" then "N"; - else "F" - end viral propagation; - - DS_r <- DS_1; - """ - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - }, - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE - - def test_parse_aggregate_propagation(self): - """Aggregate viral propagation definition parses and runs without error.""" - script = """ - define viral propagation TIME_prop (variable At_1) is - aggr max - end viral propagation; - - DS_r <- DS_1; - """ - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - { - "name": "At_1", - "type": "Integer", - "role": "Viral Attribute", - "nullable": True, - }, - ], - }, - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": [5]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - - def test_parse_binary_clause_propagation(self): - """Binary clause (when "A" and "B" then "C") parses correctly.""" - script = """ - define viral propagation COMP_mix (variable At_1) is - when "C" and "M" then "N"; - when "M" then "M"; - else " " - end viral propagation; - - DS_r <- DS_1; - """ - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - }, - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["C"]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - assert "DS_r" in result - - def test_parse_valuedomain_propagation(self): - """Value domain signature parses correctly.""" - script = """ - define viral propagation OBS_default (valuedomain CL_OBS_STATUS) is - when "M" then "M"; - when "L" then "L"; - else "A" - end viral propagation; - - DS_r <- DS_1; - """ - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - ], - }, - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - assert "DS_r" in result diff --git a/tests/ViralAttributes/test_viral_propagation.py b/tests/ViralAttributes/test_viral_propagation.py new file mode 100644 index 000000000..b230dbe8d --- /dev/null +++ b/tests/ViralAttributes/test_viral_propagation.py @@ -0,0 +1,226 @@ +"""Tests for define viral propagation: parsing, end-to-end execution, and semantic validation.""" + +import pandas as pd +import pytest + +from vtlengine import run +from vtlengine.Exceptions import SemanticError +from vtlengine.Model import Role + +# -- Shared fixtures -- + +SIMPLE_DS = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + ], + } + ] +} +SIMPLE_DP = {"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0]})} + + +def _ds_with_viral(name: str, va_type: str = "String") -> dict: + return { + "name": name, + "DataStructure": [ + {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + {"name": "At_1", "type": va_type, "role": "Viral Attribute", "nullable": True}, + ], + } + + +# -- Parsing tests -- + + +class TestViralPropagationParsing: + def test_parse_enumerated(self): + script = """ + define viral propagation CONF (variable At_1) is + when "C" then "C"; + when "N" then "N"; + else "F" + end viral propagation; + DS_r <- DS_1; + """ + result = run( + script=script, + data_structures={"datasets": [_ds_with_viral("DS_1")]}, + datapoints={"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]})}, + ) + assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE + + def test_parse_aggregate(self): + script = """ + define viral propagation T (variable At_1) is + aggr max + end viral propagation; + DS_r <- DS_1; + """ + result = run( + script=script, + data_structures={"datasets": [_ds_with_viral("DS_1", "Integer")]}, + datapoints={"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": [5]})}, + ) + assert "At_1" in result["DS_r"].components + + def test_parse_binary_clause(self): + script = """ + define viral propagation MIX (variable At_1) is + when "C" and "M" then "N"; + when "M" then "M"; + else " " + end viral propagation; + DS_r <- DS_1; + """ + result = run( + script=script, + data_structures={"datasets": [_ds_with_viral("DS_1")]}, + datapoints={"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["C"]})}, + ) + assert "DS_r" in result + + def test_parse_valuedomain(self): + script = """ + define viral propagation OBS (valuedomain CL_OBS) is + when "M" then "M"; + else "A" + end viral propagation; + DS_r <- DS_1; + """ + result = run(script=script, data_structures=SIMPLE_DS, datapoints=SIMPLE_DP) + assert "DS_r" in result + + +# -- End-to-end propagation tests -- + + +class TestViralPropagationEndToEnd: + def test_enumerated_binary_propagation(self): + """Unary clauses resolve viral attr values in binary operations.""" + script = """ + define viral propagation CONF (variable At_1) is + when "C" then "C"; + when "N" then "N"; + else "F" + end viral propagation; + DS_r <- DS_1 + DS_2; + """ + result = run( + script=script, + data_structures={"datasets": [_ds_with_viral("DS_1"), _ds_with_viral("DS_2")]}, + datapoints={ + "DS_1": pd.DataFrame( + {"Id_1": [1, 2, 3], "Me_1": [10.0, 20.0, 30.0], "At_1": ["C", "N", "F"]} + ), + "DS_2": pd.DataFrame( + {"Id_1": [1, 2, 3], "Me_1": [5.0, 15.0, 25.0], "At_1": ["N", "F", "F"]} + ), + }, + ) + # C+N→C (unary "C"); N+F→N (unary "N"); F+F→F (else) + assert list(result["DS_r"].data["At_1"]) == ["C", "N", "F"] + + def test_binary_clause_precedence(self): + """Binary clauses take precedence over unary clauses.""" + script = """ + define viral propagation MIX (variable At_1) is + when "C" and "M" then "N"; + when "M" then "M"; + else " " + end viral propagation; + DS_r <- DS_1 + DS_2; + """ + result = run( + script=script, + data_structures={"datasets": [_ds_with_viral("DS_1"), _ds_with_viral("DS_2")]}, + datapoints={ + "DS_1": pd.DataFrame( + {"Id_1": [1, 2, 3], "Me_1": [10.0, 20.0, 30.0], "At_1": ["C", "M", "X"]} + ), + "DS_2": pd.DataFrame( + {"Id_1": [1, 2, 3], "Me_1": [5.0, 15.0, 25.0], "At_1": ["M", "F", "Y"]} + ), + }, + ) + # C+M→N (binary); M+F→M (unary "M"); X+Y→" " (else) + assert list(result["DS_r"].data["At_1"]) == ["N", "M", " "] + + def test_no_rule_gives_null(self): + """Both operands viral but no rule defined → null.""" + result = run( + script="DS_r <- DS_1 + DS_2;", + data_structures={"datasets": [_ds_with_viral("DS_1"), _ds_with_viral("DS_2")]}, + datapoints={ + "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]}), + "DS_2": pd.DataFrame({"Id_1": [1], "Me_1": [5.0], "At_1": ["B"]}), + }, + ) + assert pd.isna(result["DS_r"].data["At_1"].iloc[0]) + + def test_aggregate_max_in_aggregation(self): + """Aggregate max propagation in group by.""" + script = """ + define viral propagation S (variable At_1) is + aggr max + end viral propagation; + DS_r <- sum(DS_1 group by Id_1); + """ + ds = { + "name": "DS_1", + "DataStructure": [ + {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, + {"name": "Id_2", "type": "Integer", "role": "Identifier", "nullable": False}, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + {"name": "At_1", "type": "Integer", "role": "Viral Attribute", "nullable": True}, + ], + } + result = run( + script=script, + data_structures={"datasets": [ds]}, + datapoints={ + "DS_1": pd.DataFrame( + { + "Id_1": [1, 1, 2], + "Id_2": [1, 2, 1], + "Me_1": [10.0, 20.0, 30.0], + "At_1": [3, 7, 5], + } + ) + }, + ) + sorted_data = result["DS_r"].data.sort_values("Id_1").reset_index(drop=True) + assert list(sorted_data["At_1"]) == [7, 5] + + +# -- Semantic validation tests -- + + +class TestViralPropagationValidation: + def test_duplicate_variable_rule_raises_error(self): + script = """ + define viral propagation r1 (variable At_1) is + when "C" then "C" + end viral propagation; + define viral propagation r2 (variable At_1) is + when "N" then "N" + end viral propagation; + DS_r <- DS_1; + """ + with pytest.raises(SemanticError, match="1-3-3-1"): + run(script=script, data_structures=SIMPLE_DS, datapoints=SIMPLE_DP) + + def test_duplicate_enumeration_raises_error(self): + script = """ + define viral propagation dup (variable At_1) is + when "C" then "C"; + when "C" then "N" + end viral propagation; + DS_r <- DS_1; + """ + with pytest.raises(SemanticError, match="1-3-3-4"): + run(script=script, data_structures=SIMPLE_DS, datapoints=SIMPLE_DP) diff --git a/tests/ViralAttributes/test_viral_propagation_e2e.py b/tests/ViralAttributes/test_viral_propagation_e2e.py deleted file mode 100644 index 05330e6b7..000000000 --- a/tests/ViralAttributes/test_viral_propagation_e2e.py +++ /dev/null @@ -1,246 +0,0 @@ -import pandas as pd - -from vtlengine import run -from vtlengine.Model import Role - - -class TestViralPropagationEndToEnd: - def test_binary_with_enumerated_propagation(self): - """End-to-end: define viral propagation + binary operator.""" - script = """ - define viral propagation CONF_priority (variable At_1) is - when "C" then "C"; - when "N" then "N"; - else "F" - end viral propagation; - - DS_r <- DS_1 + DS_2; - """ - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - }, - { - "name": "DS_2", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - }, - ] - } - datapoints = { - "DS_1": pd.DataFrame( - {"Id_1": [1, 2, 3], "Me_1": [10.0, 20.0, 30.0], "At_1": ["C", "N", "F"]} - ), - "DS_2": pd.DataFrame( - {"Id_1": [1, 2, 3], "Me_1": [5.0, 15.0, 25.0], "At_1": ["N", "F", "F"]} - ), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE - # C+N → C (unary "C" matches); N+F → N (unary "N" matches); F+F → F (else) - assert list(ds_r.data["At_1"]) == ["C", "N", "F"] - - def test_binary_with_binary_clause_precedence(self): - """Binary clauses take precedence over unary clauses.""" - script = """ - define viral propagation COMP_mix (variable At_1) is - when "C" and "M" then "N"; - when "M" then "M"; - else " " - end viral propagation; - - DS_r <- DS_1 + DS_2; - """ - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - }, - { - "name": "DS_2", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - }, - ] - } - datapoints = { - "DS_1": pd.DataFrame( - {"Id_1": [1, 2, 3], "Me_1": [10.0, 20.0, 30.0], "At_1": ["C", "M", "X"]} - ), - "DS_2": pd.DataFrame( - {"Id_1": [1, 2, 3], "Me_1": [5.0, 15.0, 25.0], "At_1": ["M", "F", "Y"]} - ), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - # C+M → N (binary clause); M+F → M (unary "M"); X+Y → " " (else/default) - assert list(ds_r.data["At_1"]) == ["N", "M", " "] - - def test_no_rule_gives_null(self): - """When both operands have same viral attr but no propagation rule, result is null.""" - script = """ - DS_r <- DS_1 + DS_2; - """ - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - }, - { - "name": "DS_2", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - }, - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]}), - "DS_2": pd.DataFrame({"Id_1": [1], "Me_1": [5.0], "At_1": ["B"]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - # No propagation rule → null - assert pd.isna(ds_r.data["At_1"].iloc[0]) - - def test_aggregate_propagation_with_max(self): - """End-to-end: aggregate max propagation in aggregation.""" - script = """ - define viral propagation SCORE_prop (variable At_1) is - aggr max - end viral propagation; - - DS_r <- sum(DS_1 group by Id_1); - """ - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Id_2", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - { - "name": "At_1", - "type": "Integer", - "role": "Viral Attribute", - "nullable": True, - }, - ], - } - ] - } - datapoints = { - "DS_1": pd.DataFrame( - { - "Id_1": [1, 1, 2], - "Id_2": [1, 2, 1], - "Me_1": [10.0, 20.0, 30.0], - "At_1": [3, 7, 5], - } - ), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE - # Group Id_1=1: max(3,7)=7; Group Id_1=2: max(5)=5 - sorted_data = ds_r.data.sort_values("Id_1").reset_index(drop=True) - assert list(sorted_data["At_1"]) == [7, 5] diff --git a/tests/ViralAttributes/test_viral_remaining_ops.py b/tests/ViralAttributes/test_viral_remaining_ops.py deleted file mode 100644 index 1674b882d..000000000 --- a/tests/ViralAttributes/test_viral_remaining_ops.py +++ /dev/null @@ -1,158 +0,0 @@ -import pandas as pd - -from vtlengine import run -from vtlengine.Model import Role - - -class TestViralAttributeAggregation: - def test_aggregation_keeps_viral_attribute(self): - script = "DS_r <- sum(DS_1 group by Id_1);" - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Id_2", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Me_1", - "type": "Number", - "role": "Measure", - "nullable": True, - }, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - } - ] - } - datapoints = { - "DS_1": pd.DataFrame( - { - "Id_1": [1, 1, 2], - "Id_2": [1, 2, 1], - "Me_1": [10.0, 20.0, 30.0], - "At_1": ["A", "A", "B"], - } - ), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE - - -class TestViralAttributeBetween: - def test_between_keeps_viral_attribute(self): - script = "DS_r <- between(DS_1, 5, 25);" - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Me_1", - "type": "Number", - "role": "Measure", - "nullable": True, - }, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - } - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 30.0], "At_1": ["A", "B"]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE - - -class TestViralAttributeSetOps: - def test_intersect_preserves_viral_attribute(self): - script = "DS_r <- intersect(DS_1, DS_2);" - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Me_1", - "type": "Number", - "role": "Measure", - "nullable": True, - }, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - }, - { - "name": "DS_2", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Me_1", - "type": "Number", - "role": "Measure", - "nullable": True, - }, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - }, - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), - "DS_2": pd.DataFrame({"Id_1": [1, 3], "Me_1": [10.0, 30.0], "At_1": ["A", "C"]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE diff --git a/tests/ViralAttributes/test_viral_unary.py b/tests/ViralAttributes/test_viral_unary.py deleted file mode 100644 index 6e239c1ec..000000000 --- a/tests/ViralAttributes/test_viral_unary.py +++ /dev/null @@ -1,189 +0,0 @@ -import pandas as pd -import pytest - -from vtlengine import run -from vtlengine.Model import Role - -NUMERIC_UNARY_OPS = [ - ("abs", "Number", [10.0, -20.0]), - ("ceil", "Number", [1.1, 2.9]), - ("floor", "Number", [1.1, 2.9]), - ("ln", "Number", [1.0, 2.718]), - ("exp", "Number", [0.0, 1.0]), - ("sqrt", "Number", [4.0, 9.0]), -] - -STRING_UNARY_OPS = [ - ("upper", "String", ["abc", "def"]), - ("lower", "String", ["ABC", "DEF"]), - ("trim", "String", [" abc ", " def "]), - ("ltrim", "String", [" abc", " def"]), - ("rtrim", "String", ["abc ", "def "]), - ("length", "String", ["abc", "defgh"]), -] - - -class TestViralAttributeUnaryOps: - @pytest.mark.parametrize( - "op,me_type,me_values", - NUMERIC_UNARY_OPS, - ids=[x[0] for x in NUMERIC_UNARY_OPS], - ) - def test_numeric_unary_preserves_viral_attr( - self, op: str, me_type: str, me_values: list - ) -> None: - script = f"DS_r <- {op}(DS_1);" - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Me_1", - "type": me_type, - "role": "Measure", - "nullable": True, - }, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - } - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": me_values, "At_1": ["A", "B"]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE - assert list(ds_r.data["At_1"]) == ["A", "B"] - - @pytest.mark.parametrize( - "op,me_type,me_values", - STRING_UNARY_OPS, - ids=[x[0] for x in STRING_UNARY_OPS], - ) - def test_string_unary_preserves_viral_attr( - self, op: str, me_type: str, me_values: list - ) -> None: - script = f"DS_r <- {op}(DS_1);" - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Me_1", - "type": me_type, - "role": "Measure", - "nullable": True, - }, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - } - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": me_values, "At_1": ["A", "B"]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE - assert list(ds_r.data["At_1"]) == ["A", "B"] - - def test_not_preserves_viral_attr(self) -> None: - script = "DS_r <- not DS_1;" - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Me_1", - "type": "Boolean", - "role": "Measure", - "nullable": True, - }, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - } - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [True, False], "At_1": ["A", "B"]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE - - def test_isnull_preserves_viral_attr(self) -> None: - script = "DS_r <- isnull(DS_1);" - data_structures = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - { - "name": "Id_1", - "type": "Integer", - "role": "Identifier", - "nullable": False, - }, - { - "name": "Me_1", - "type": "Number", - "role": "Measure", - "nullable": True, - }, - { - "name": "At_1", - "type": "String", - "role": "Viral Attribute", - "nullable": True, - }, - ], - } - ] - } - datapoints = { - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, None], "At_1": ["A", "B"]}), - } - result = run(script=script, data_structures=data_structures, datapoints=datapoints) - ds_r = result["DS_r"] - assert "At_1" in ds_r.components - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE diff --git a/tests/ViralAttributes/test_viral_validation.py b/tests/ViralAttributes/test_viral_validation.py deleted file mode 100644 index b3d547aa6..000000000 --- a/tests/ViralAttributes/test_viral_validation.py +++ /dev/null @@ -1,44 +0,0 @@ -import pandas as pd -import pytest - -from vtlengine import run -from vtlengine.Exceptions import SemanticError - -DATA_STRUCTURES = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - ], - } - ] -} -DATAPOINTS = {"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0]})} - - -class TestViralPropagationSemanticErrors: - def test_duplicate_variable_rule_raises_error(self): - script = """ - define viral propagation rule1 (variable At_1) is - when "C" then "C" - end viral propagation; - define viral propagation rule2 (variable At_1) is - when "N" then "N" - end viral propagation; - DS_r <- DS_1; - """ - with pytest.raises(SemanticError, match="1-3-3-1"): - run(script=script, data_structures=DATA_STRUCTURES, datapoints=DATAPOINTS) - - def test_duplicate_enumeration_raises_error(self): - script = """ - define viral propagation dup (variable At_1) is - when "C" then "C"; - when "C" then "N" - end viral propagation; - DS_r <- DS_1; - """ - with pytest.raises(SemanticError, match="1-3-3-4"): - run(script=script, data_structures=DATA_STRUCTURES, datapoints=DATAPOINTS) From dc05d7f68ed003b7e5002c0f86a2f1d206c62092 Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Wed, 25 Mar 2026 17:55:00 +0100 Subject: [PATCH 12/14] refactor(#510): move prettify tests to AST string test infrastructure - Add viral_propagation.vtl input files for ast_string and prettier tests - Add reference_viral_propagation.vtl expected output - Register in params and params_prettier lists in test_AST_String.py - Remove standalone test_viral_prettify.py --- .../prettier/reference_viral_propagation.vtl | 18 +++++++ tests/AST/data/prettier/viral_propagation.vtl | 1 + tests/AST/data/vtl/viral_propagation.vtl | 18 +++++++ tests/AST/test_AST_String.py | 2 + tests/ViralAttributes/test_viral_prettify.py | 47 ------------------- 5 files changed, 39 insertions(+), 47 deletions(-) create mode 100644 tests/AST/data/prettier/reference_viral_propagation.vtl create mode 100644 tests/AST/data/prettier/viral_propagation.vtl create mode 100644 tests/AST/data/vtl/viral_propagation.vtl delete mode 100644 tests/ViralAttributes/test_viral_prettify.py diff --git a/tests/AST/data/prettier/reference_viral_propagation.vtl b/tests/AST/data/prettier/reference_viral_propagation.vtl new file mode 100644 index 000000000..947e59786 --- /dev/null +++ b/tests/AST/data/prettier/reference_viral_propagation.vtl @@ -0,0 +1,18 @@ +define viral propagation CONF_priority(variable At_1) is + when "C" then "C"; + when "N" then "N"; + else "F" +end viral propagation; + +define viral propagation OBS_default(valuedomain CL_OBS_STATUS) is + when "M" then "M"; + when "Q" and "P" then "Q"; + else "A" +end viral propagation; + +define viral propagation EMBARGO_time(variable EMBARGO_TIME) is + aggr max +end viral propagation; + +DS_r <- + DS_1 + DS_2; diff --git a/tests/AST/data/prettier/viral_propagation.vtl b/tests/AST/data/prettier/viral_propagation.vtl new file mode 100644 index 000000000..fc1712b09 --- /dev/null +++ b/tests/AST/data/prettier/viral_propagation.vtl @@ -0,0 +1 @@ +define viral propagation CONF_priority(variable At_1) is when "C" then "C";when "N" then "N";else "F" end viral propagation;define viral propagation OBS_default(valuedomain CL_OBS_STATUS) is when "M" then "M";when "Q" and "P" then "Q";else "A" end viral propagation;define viral propagation EMBARGO_time(variable EMBARGO_TIME) is aggr max end viral propagation;DS_r<-DS_1+DS_2; diff --git a/tests/AST/data/vtl/viral_propagation.vtl b/tests/AST/data/vtl/viral_propagation.vtl new file mode 100644 index 000000000..704c11c77 --- /dev/null +++ b/tests/AST/data/vtl/viral_propagation.vtl @@ -0,0 +1,18 @@ +define viral propagation CONF_priority (variable At_1) is + when "C" then "C"; + when "N" then "N"; + else "F" +end viral propagation; + +define viral propagation OBS_default (valuedomain CL_OBS_STATUS) is + when "M" then "M"; + when "L" then "L"; + when "Q" and "P" then "Q"; + else "A" +end viral propagation; + +define viral propagation EMBARGO_time (variable EMBARGO_TIME) is + aggr max +end viral propagation; + +DS_r <- DS_1 + DS_2; diff --git a/tests/AST/test_AST_String.py b/tests/AST/test_AST_String.py index e7523171a..4ccf80bd8 100644 --- a/tests/AST/test_AST_String.py +++ b/tests/AST/test_AST_String.py @@ -26,6 +26,7 @@ "GH_358.vtl", "comments_end_line.vtl", "time_agg.vtl", + "viral_propagation.vtl", ] params_prettier = [ @@ -53,6 +54,7 @@ ("validation_str_errorlevel.vtl", "reference_validation_str_errorlevel.vtl"), ("unbounded.vtl", "reference_unbounded.vtl"), ("time_agg.vtl", "reference_time_agg.vtl"), + ("viral_propagation.vtl", "reference_viral_propagation.vtl"), ] diff --git a/tests/ViralAttributes/test_viral_prettify.py b/tests/ViralAttributes/test_viral_prettify.py deleted file mode 100644 index 103a1e9e9..000000000 --- a/tests/ViralAttributes/test_viral_prettify.py +++ /dev/null @@ -1,47 +0,0 @@ -from vtlengine import prettify - - -class TestViralPropagationPrettify: - def test_prettify_enumerated(self): - script = ( - "define viral propagation CONF_priority(variable At_1) is " - 'when "C" then "C";when "N" then "N";else "F" ' - "end viral propagation;" - "DS_r<-DS_1+DS_2;" - ) - result = prettify(script=script) - assert "define viral propagation" in result - assert 'when "C" then "C"' in result - assert 'else "F"' in result - assert "end viral propagation" in result - - def test_prettify_aggregate(self): - script = ( - "define viral propagation TIME_prop(variable At_1)" - "is aggr max end viral propagation;" - "DS_r<-DS_1;" - ) - result = prettify(script=script) - assert "define viral propagation" in result - assert "aggr max" in result - assert "end viral propagation" in result - - def test_prettify_binary_clause(self): - script = ( - "define viral propagation MIX(variable At_1) is " - 'when "C" and "M" then "N";when "M" then "M";else " " ' - "end viral propagation;" - "DS_r<-DS_1;" - ) - result = prettify(script=script) - assert 'when "C" and "M" then "N"' in result - - def test_prettify_valuedomain(self): - script = ( - "define viral propagation OBS(valuedomain CL_OBS)" - 'is when "M" then "M";else "A" ' - "end viral propagation;" - "DS_r<-DS_1;" - ) - result = prettify(script=script) - assert "valuedomain CL_OBS" in result From a98683add462f12cb264733c41b9156703ccf2c0 Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Wed, 25 Mar 2026 18:15:17 +0100 Subject: [PATCH 13/14] refactor(#510): restructure viral attribute tests for maintainability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Layered dataset approach: one base, progressively add 1/2/3 viral attrs - Parametrize operators × num_viral_attrs (unary, binary, scalar, other) - Shared propagation rules defined once, reused across parametrized ops - Multi-attribute test: enumerated (At_1) + aggregate max (At_2) in one script - 79 tests covering all operator categories with 1, 2, and 3 viral attrs --- tests/ViralAttributes/test_viral_operators.py | 340 +++++++++--------- .../ViralAttributes/test_viral_propagation.py | 231 +++++++----- 2 files changed, 306 insertions(+), 265 deletions(-) diff --git a/tests/ViralAttributes/test_viral_operators.py b/tests/ViralAttributes/test_viral_operators.py index 4818d87af..c0598281e 100644 --- a/tests/ViralAttributes/test_viral_operators.py +++ b/tests/ViralAttributes/test_viral_operators.py @@ -6,227 +6,215 @@ from vtlengine import run from vtlengine.Model import Role -# -- Shared data structure builders -- +# -- Layered dataset builders -- +BASE_COMPS = [ + {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, +] -def _ds(name: str, components: list) -> dict: - return {"name": name, "DataStructure": components} - +VA_1 = {"name": "At_1", "type": "String", "role": "Viral Attribute", "nullable": True} +VA_2 = {"name": "At_2", "type": "String", "role": "Viral Attribute", "nullable": True} +VA_3 = {"name": "At_3", "type": "String", "role": "Viral Attribute", "nullable": True} -def _id(name: str = "Id_1") -> dict: - return {"name": name, "type": "Integer", "role": "Identifier", "nullable": False} +VA_COMPONENTS = [VA_1, VA_2, VA_3] +VA_NAMES = ["At_1", "At_2", "At_3"] +VA_VALUES = [["A", "B"], ["X", "Y"], ["P", "Q"]] -def _me(name: str = "Me_1", type_: str = "Number") -> dict: - return {"name": name, "type": type_, "role": "Measure", "nullable": True} +def _make_ds(name: str, num_viral: int) -> dict: + """Build a dataset definition with 0..3 viral attributes.""" + comps = BASE_COMPS + VA_COMPONENTS[:num_viral] + return {"name": name, "DataStructure": comps} -def _va(name: str = "At_1", type_: str = "String") -> dict: - return {"name": name, "type": type_, "role": "Viral Attribute", "nullable": True} +def _make_dp(num_viral: int) -> pd.DataFrame: + """Build datapoints matching a dataset with num_viral viral attributes.""" + data: dict = {"Id_1": [1, 2], "Me_1": [10.0, 20.0]} + for i in range(num_viral): + data[VA_NAMES[i]] = VA_VALUES[i] + return pd.DataFrame(data) -def _at(name: str = "At_1", type_: str = "String") -> dict: - return {"name": name, "type": type_, "role": "Attribute", "nullable": True} +def _run_single(expr: str, num_viral: int) -> dict: + """Run an expression with a single dataset (DS_1).""" + return run( + script=f"DS_r <- {expr};", + data_structures={"datasets": [_make_ds("DS_1", num_viral)]}, + datapoints={"DS_1": _make_dp(num_viral)}, + ) -def _run(script: str, datasets: list, datapoints: dict) -> dict: +def _run_pair(expr: str, num_viral: int) -> dict: + """Run an expression with two datasets (DS_1, DS_2).""" return run( - script=script, - data_structures={"datasets": datasets}, - datapoints=datapoints, + script=f"DS_r <- {expr};", + data_structures={"datasets": [_make_ds("DS_1", num_viral), _make_ds("DS_2", num_viral)]}, + datapoints={"DS_1": _make_dp(num_viral), "DS_2": _make_dp(num_viral)}, ) -# -- Calc / Input loading -- +def _assert_viral_attrs(result: dict, num_viral: int) -> None: + """Assert that the expected viral attributes are present with correct role.""" + ds_r = result["DS_r"] + for va_name in VA_NAMES[:num_viral]: + assert va_name in ds_r.components, f"{va_name} missing from result components" + assert ds_r.components[va_name].role == Role.VIRAL_ATTRIBUTE -class TestViralAttributeInputAndCalc: - def test_calc_viral_attribute(self): - result = _run( - 'DS_r <- DS_1 [calc viral attribute At_1 := "X"];', - [_ds("DS_1", [_id(), _me()])], - {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0]})}, - ) - assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE +# -- Unary operators -- - def test_input_viral_attribute_loaded(self): - result = _run( - "DS_r <- DS_1;", - [_ds("DS_1", [_id(), _me(), _va()])], - {"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]})}, - ) - assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE - assert list(result["DS_r"].data["At_1"]) == ["A"] +unary_params = [ + "abs(DS_1)", + "ceil(DS_1)", + "floor(DS_1)", + "sqrt(DS_1)", + "ln(DS_1)", + "exp(DS_1)", + "isnull(DS_1)", +] - def test_input_viral_attribute_legacy_format(self): - ds = { - "name": "DS_1", - "DataStructure": [ - _id(), - _me(), - {"name": "At_1", "type": "String", "role": "ViralAttribute", "nullable": True}, - ], - } - result = _run( - "DS_r <- DS_1;", - [ds], - {"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]})}, - ) - assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE +class TestViralAttributeUnaryOps: + @pytest.mark.parametrize("expr", unary_params) + @pytest.mark.parametrize("num_viral", [1, 2, 3]) + def test_unary_preserves_viral_attrs(self, expr: str, num_viral: int) -> None: + result = _run_single(expr, num_viral) + _assert_viral_attrs(result, num_viral) -# -- Binary operators -- +# -- Binary operators (two datasets) -- -class TestViralAttributeBinaryOps: - def test_single_viral_attribute_propagated(self): - result = _run( - "DS_r <- DS_1 + DS_2;", - [_ds("DS_1", [_id(), _me(), _va()]), _ds("DS_2", [_id(), _me()])], - { - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), - "DS_2": pd.DataFrame({"Id_1": [1, 2], "Me_1": [5.0, 15.0]}), - }, - ) - ds_r = result["DS_r"] - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE - assert list(ds_r.data["At_1"]) == ["A", "B"] - - def test_non_viral_attribute_still_dropped(self): - result = _run( - "DS_r <- DS_1 + DS_2;", - [_ds("DS_1", [_id(), _me(), _at()]), _ds("DS_2", [_id(), _me()])], - { - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), - "DS_2": pd.DataFrame({"Id_1": [1, 2], "Me_1": [5.0, 15.0]}), - }, - ) - assert "At_1" not in result["DS_r"].components +binary_params = [ + "DS_1 + DS_2", + "DS_1 - DS_2", + "DS_1 * DS_2", + "DS_1 > DS_2", + "DS_1 = DS_2", +] - def test_dataset_scalar_keeps_viral_attr(self): - result = _run( - "DS_r <- DS_1 + 5;", - [_ds("DS_1", [_id(), _me(), _va()])], - {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]})}, - ) - ds_r = result["DS_r"] - assert ds_r.components["At_1"].role == Role.VIRAL_ATTRIBUTE - assert list(ds_r.data["At_1"]) == ["A", "B"] - - def test_both_operands_viral_no_rule_gives_null(self): - result = _run( - "DS_r <- DS_1 + DS_2;", - [_ds("DS_1", [_id(), _me(), _va()]), _ds("DS_2", [_id(), _me(), _va()])], - { - "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]}), - "DS_2": pd.DataFrame({"Id_1": [1], "Me_1": [5.0], "At_1": ["B"]}), - }, - ) - assert all(pd.isna(v) for v in result["DS_r"].data["At_1"]) +class TestViralAttributeBinaryOps: + @pytest.mark.parametrize("expr", binary_params) + @pytest.mark.parametrize("num_viral", [1, 2, 3]) + def test_binary_preserves_viral_attrs(self, expr: str, num_viral: int) -> None: + result = _run_pair(expr, num_viral) + _assert_viral_attrs(result, num_viral) -# -- Unary operators -- -NUMERIC_UNARY_OPS = [ - ("abs", "Number", [10.0, -20.0]), - ("ceil", "Number", [1.1, 2.9]), - ("floor", "Number", [1.1, 2.9]), - ("ln", "Number", [1.0, 2.718]), - ("exp", "Number", [0.0, 1.0]), - ("sqrt", "Number", [4.0, 9.0]), -] +# -- Binary operators (dataset + scalar) -- -STRING_UNARY_OPS = [ - ("upper", "String", ["abc", "def"]), - ("lower", "String", ["ABC", "DEF"]), - ("trim", "String", [" abc ", " def "]), - ("ltrim", "String", [" abc", " def"]), - ("rtrim", "String", ["abc ", "def "]), - ("length", "String", ["abc", "defgh"]), +binary_scalar_params = [ + "DS_1 + 5", + "DS_1 * 2", + "DS_1 - 1", ] -class TestViralAttributeUnaryOps: - @pytest.mark.parametrize( - "op,me_type,me_values", - NUMERIC_UNARY_OPS, - ids=[x[0] for x in NUMERIC_UNARY_OPS], - ) - def test_numeric_unary_preserves_viral_attr(self, op, me_type, me_values): - result = _run( - f"DS_r <- {op}(DS_1);", - [_ds("DS_1", [_id(), _me(type_=me_type), _va()])], - {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": me_values, "At_1": ["A", "B"]})}, - ) - assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE - assert list(result["DS_r"].data["At_1"]) == ["A", "B"] +class TestViralAttributeBinaryScalarOps: + @pytest.mark.parametrize("expr", binary_scalar_params) + @pytest.mark.parametrize("num_viral", [1, 2, 3]) + def test_binary_scalar_preserves_viral_attrs(self, expr: str, num_viral: int) -> None: + result = _run_single(expr, num_viral) + _assert_viral_attrs(result, num_viral) - @pytest.mark.parametrize( - "op,me_type,me_values", - STRING_UNARY_OPS, - ids=[x[0] for x in STRING_UNARY_OPS], - ) - def test_string_unary_preserves_viral_attr(self, op, me_type, me_values): - result = _run( - f"DS_r <- {op}(DS_1);", - [_ds("DS_1", [_id(), _me(type_=me_type), _va()])], - {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": me_values, "At_1": ["A", "B"]})}, - ) - assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE - def test_not_preserves_viral_attr(self): - result = _run( - "DS_r <- not DS_1;", - [_ds("DS_1", [_id(), _me(type_="Boolean"), _va()])], - {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [True, False], "At_1": ["A", "B"]})}, - ) - assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE +# -- Other operators -- - def test_isnull_preserves_viral_attr(self): - result = _run( - "DS_r <- isnull(DS_1);", - [_ds("DS_1", [_id(), _me(), _va()])], - {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, None], "At_1": ["A", "B"]})}, +other_single_params = [ + "between(DS_1, 5, 25)", +] + + +class TestViralAttributeOtherOps: + @pytest.mark.parametrize("expr", other_single_params) + @pytest.mark.parametrize("num_viral", [1, 2, 3]) + def test_other_single_preserves_viral_attrs(self, expr: str, num_viral: int) -> None: + result = _run_single(expr, num_viral) + _assert_viral_attrs(result, num_viral) + + @pytest.mark.parametrize("num_viral", [1, 2, 3]) + def test_intersect_preserves_viral_attrs(self, num_viral: int) -> None: + result = _run_pair("intersect(DS_1, DS_2)", num_viral) + _assert_viral_attrs(result, num_viral) + + @pytest.mark.parametrize("num_viral", [1, 2, 3]) + def test_aggregation_preserves_viral_attrs(self, num_viral: int) -> None: + comps = [ + {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, + {"name": "Id_2", "type": "Integer", "role": "Identifier", "nullable": False}, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + ] + VA_COMPONENTS[:num_viral] + data: dict = { + "Id_1": [1, 1, 2], + "Id_2": [1, 2, 1], + "Me_1": [10.0, 20.0, 30.0], + } + for i in range(num_viral): + data[VA_NAMES[i]] = [VA_VALUES[i][0], VA_VALUES[i][0], VA_VALUES[i][1]] + result = run( + script="DS_r <- sum(DS_1 group by Id_1);", + data_structures={"datasets": [{"name": "DS_1", "DataStructure": comps}]}, + datapoints={"DS_1": pd.DataFrame(data)}, ) - assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE + _assert_viral_attrs(result, num_viral) -# -- Other operators -- +# -- Special cases -- -class TestViralAttributeOtherOps: - def test_aggregation_keeps_viral_attribute(self): - result = _run( - "DS_r <- sum(DS_1 group by Id_1);", - [_ds("DS_1", [_id(), _id("Id_2"), _me(), _va()])], - { - "DS_1": pd.DataFrame( - { - "Id_1": [1, 1, 2], - "Id_2": [1, 2, 1], - "Me_1": [10.0, 20.0, 30.0], - "At_1": ["A", "A", "B"], - } - ) +class TestViralAttributeSpecialCases: + def test_non_viral_attribute_still_dropped(self) -> None: + ds = { + "name": "DS_1", + "DataStructure": [ + *BASE_COMPS, + {"name": "At_1", "type": "String", "role": "Attribute", "nullable": True}, + ], + } + result = run( + script="DS_r <- DS_1 + DS_2;", + data_structures={"datasets": [ds, {"name": "DS_2", "DataStructure": BASE_COMPS}]}, + datapoints={ + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), + "DS_2": pd.DataFrame({"Id_1": [1, 2], "Me_1": [5.0, 15.0]}), }, ) + assert "At_1" not in result["DS_r"].components + + def test_calc_viral_attribute(self) -> None: + result = run( + script='DS_r <- DS_1 [calc viral attribute At_1 := "X"];', + data_structures={"datasets": [{"name": "DS_1", "DataStructure": BASE_COMPS}]}, + datapoints={"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0]})}, + ) assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE - def test_between_keeps_viral_attribute(self): - result = _run( - "DS_r <- between(DS_1, 5, 25);", - [_ds("DS_1", [_id(), _me(), _va()])], - {"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 30.0], "At_1": ["A", "B"]})}, + def test_input_viral_attribute_legacy_format(self) -> None: + ds = { + "name": "DS_1", + "DataStructure": [ + *BASE_COMPS, + {"name": "At_1", "type": "String", "role": "ViralAttribute", "nullable": True}, + ], + } + result = run( + script="DS_r <- DS_1;", + data_structures={"datasets": [ds]}, + datapoints={"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]})}, ) assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE - def test_intersect_preserves_viral_attribute(self): - result = _run( - "DS_r <- intersect(DS_1, DS_2);", - [_ds("DS_1", [_id(), _me(), _va()]), _ds("DS_2", [_id(), _me(), _va()])], - { - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), - "DS_2": pd.DataFrame({"Id_1": [1, 3], "Me_1": [10.0, 30.0], "At_1": ["A", "C"]}), + def test_binary_one_operand_viral(self) -> None: + """Only DS_1 has viral attr, DS_2 doesn't — viral attr propagated from DS_1.""" + result = run( + script="DS_r <- DS_1 + DS_2;", + data_structures={"datasets": [_make_ds("DS_1", 2), _make_ds("DS_2", 0)]}, + datapoints={ + "DS_1": _make_dp(2), + "DS_2": pd.DataFrame({"Id_1": [1, 2], "Me_1": [5.0, 15.0]}), }, ) - assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE + _assert_viral_attrs(result, 2) + assert list(result["DS_r"].data["At_1"]) == ["A", "B"] + assert list(result["DS_r"].data["At_2"]) == ["X", "Y"] diff --git a/tests/ViralAttributes/test_viral_propagation.py b/tests/ViralAttributes/test_viral_propagation.py index b230dbe8d..a342137c6 100644 --- a/tests/ViralAttributes/test_viral_propagation.py +++ b/tests/ViralAttributes/test_viral_propagation.py @@ -7,84 +7,116 @@ from vtlengine.Exceptions import SemanticError from vtlengine.Model import Role -# -- Shared fixtures -- +# -- Shared propagation rules -- -SIMPLE_DS = { - "datasets": [ - { - "name": "DS_1", - "DataStructure": [ - {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - ], - } - ] +CONF_RULE = """ + define viral propagation CONF (variable At_1) is + when "C" then "C"; + when "N" then "N"; + else "F" + end viral propagation; +""" + +CONF_BINARY_RULE = """ + define viral propagation COMP_mix (variable At_1) is + when "C" and "M" then "N"; + when "M" then "M"; + else " " + end viral propagation; +""" + +TWO_RULES = """ + define viral propagation R1 (variable At_1) is + when "C" then "C"; + when "N" then "N"; + else "F" + end viral propagation; + define viral propagation R2 (variable At_2) is + aggr max + end viral propagation; +""" + +AGGR_MAX_RULE = """ + define viral propagation S (variable At_1) is + aggr max + end viral propagation; +""" + +# -- Shared datasets -- + +DS_1VA = { + "name": "DS_1", + "DataStructure": [ + {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + {"name": "At_1", "type": "String", "role": "Viral Attribute", "nullable": True}, + ], +} + +DS_2VA = { + "name": "DS_1", + "DataStructure": [ + {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + {"name": "At_1", "type": "String", "role": "Viral Attribute", "nullable": True}, + {"name": "At_2", "type": "Integer", "role": "Viral Attribute", "nullable": True}, + ], } + +DS_NO_VA = { + "name": "DS_1", + "DataStructure": [ + {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, + {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, + ], +} + +SIMPLE_DS = {"datasets": [DS_NO_VA]} SIMPLE_DP = {"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0]})} -def _ds_with_viral(name: str, va_type: str = "String") -> dict: - return { - "name": name, - "DataStructure": [ - {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, - {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - {"name": "At_1", "type": va_type, "role": "Viral Attribute", "nullable": True}, - ], - } +def _ds_pair(ds_def: dict) -> dict: + """Create a two-dataset structure from a single definition (DS_1, DS_2).""" + ds2 = {**ds_def, "name": "DS_2"} + return {"datasets": [ds_def, ds2]} # -- Parsing tests -- class TestViralPropagationParsing: - def test_parse_enumerated(self): - script = """ - define viral propagation CONF (variable At_1) is - when "C" then "C"; - when "N" then "N"; - else "F" - end viral propagation; - DS_r <- DS_1; - """ + def test_parse_enumerated(self) -> None: result = run( - script=script, - data_structures={"datasets": [_ds_with_viral("DS_1")]}, + script=CONF_RULE + "DS_r <- DS_1;", + data_structures={"datasets": [DS_1VA]}, datapoints={"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]})}, ) assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE - def test_parse_aggregate(self): - script = """ - define viral propagation T (variable At_1) is - aggr max - end viral propagation; - DS_r <- DS_1; - """ + def test_parse_aggregate(self) -> None: + ds = { + **DS_NO_VA, + "DataStructure": [ + *DS_NO_VA["DataStructure"], + {"name": "At_1", "type": "Integer", "role": "Viral Attribute", "nullable": True}, + ], + } result = run( - script=script, - data_structures={"datasets": [_ds_with_viral("DS_1", "Integer")]}, + script=AGGR_MAX_RULE + "DS_r <- DS_1;", + data_structures={"datasets": [ds]}, datapoints={"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": [5]})}, ) assert "At_1" in result["DS_r"].components - def test_parse_binary_clause(self): - script = """ - define viral propagation MIX (variable At_1) is - when "C" and "M" then "N"; - when "M" then "M"; - else " " - end viral propagation; - DS_r <- DS_1; - """ + def test_parse_binary_clause(self) -> None: result = run( - script=script, - data_structures={"datasets": [_ds_with_viral("DS_1")]}, + script=CONF_BINARY_RULE + "DS_r <- DS_1;", + data_structures={"datasets": [DS_1VA]}, datapoints={"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["C"]})}, ) assert "DS_r" in result - def test_parse_valuedomain(self): + def test_parse_valuedomain(self) -> None: script = """ define viral propagation OBS (valuedomain CL_OBS) is when "M" then "M"; @@ -96,23 +128,22 @@ def test_parse_valuedomain(self): assert "DS_r" in result -# -- End-to-end propagation tests -- +# -- End-to-end propagation (single viral attribute) -- + +propagation_binary_params = [ + "DS_1 + DS_2", + "DS_1 - DS_2", + "DS_1 * DS_2", +] class TestViralPropagationEndToEnd: - def test_enumerated_binary_propagation(self): - """Unary clauses resolve viral attr values in binary operations.""" - script = """ - define viral propagation CONF (variable At_1) is - when "C" then "C"; - when "N" then "N"; - else "F" - end viral propagation; - DS_r <- DS_1 + DS_2; - """ + @pytest.mark.parametrize("expr", propagation_binary_params) + def test_enumerated_propagation_binary(self, expr: str) -> None: + """Same CONF_RULE resolution regardless of binary operator.""" result = run( - script=script, - data_structures={"datasets": [_ds_with_viral("DS_1"), _ds_with_viral("DS_2")]}, + script=CONF_RULE + f"DS_r <- {expr};", + data_structures=_ds_pair(DS_1VA), datapoints={ "DS_1": pd.DataFrame( {"Id_1": [1, 2, 3], "Me_1": [10.0, 20.0, 30.0], "At_1": ["C", "N", "F"]} @@ -125,19 +156,11 @@ def test_enumerated_binary_propagation(self): # C+N→C (unary "C"); N+F→N (unary "N"); F+F→F (else) assert list(result["DS_r"].data["At_1"]) == ["C", "N", "F"] - def test_binary_clause_precedence(self): + def test_binary_clause_precedence(self) -> None: """Binary clauses take precedence over unary clauses.""" - script = """ - define viral propagation MIX (variable At_1) is - when "C" and "M" then "N"; - when "M" then "M"; - else " " - end viral propagation; - DS_r <- DS_1 + DS_2; - """ result = run( - script=script, - data_structures={"datasets": [_ds_with_viral("DS_1"), _ds_with_viral("DS_2")]}, + script=CONF_BINARY_RULE + "DS_r <- DS_1 + DS_2;", + data_structures=_ds_pair(DS_1VA), datapoints={ "DS_1": pd.DataFrame( {"Id_1": [1, 2, 3], "Me_1": [10.0, 20.0, 30.0], "At_1": ["C", "M", "X"]} @@ -150,11 +173,11 @@ def test_binary_clause_precedence(self): # C+M→N (binary); M+F→M (unary "M"); X+Y→" " (else) assert list(result["DS_r"].data["At_1"]) == ["N", "M", " "] - def test_no_rule_gives_null(self): + def test_no_rule_gives_null(self) -> None: """Both operands viral but no rule defined → null.""" result = run( script="DS_r <- DS_1 + DS_2;", - data_structures={"datasets": [_ds_with_viral("DS_1"), _ds_with_viral("DS_2")]}, + data_structures=_ds_pair(DS_1VA), datapoints={ "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]}), "DS_2": pd.DataFrame({"Id_1": [1], "Me_1": [5.0], "At_1": ["B"]}), @@ -162,14 +185,8 @@ def test_no_rule_gives_null(self): ) assert pd.isna(result["DS_r"].data["At_1"].iloc[0]) - def test_aggregate_max_in_aggregation(self): + def test_aggregate_max_in_aggregation(self) -> None: """Aggregate max propagation in group by.""" - script = """ - define viral propagation S (variable At_1) is - aggr max - end viral propagation; - DS_r <- sum(DS_1 group by Id_1); - """ ds = { "name": "DS_1", "DataStructure": [ @@ -180,7 +197,7 @@ def test_aggregate_max_in_aggregation(self): ], } result = run( - script=script, + script=AGGR_MAX_RULE + "DS_r <- sum(DS_1 group by Id_1);", data_structures={"datasets": [ds]}, datapoints={ "DS_1": pd.DataFrame( @@ -197,11 +214,47 @@ def test_aggregate_max_in_aggregation(self): assert list(sorted_data["At_1"]) == [7, 5] -# -- Semantic validation tests -- +# -- Multi-attribute propagation (enumerated + aggregate in one script) -- + + +class TestViralPropagationMultiAttribute: + @pytest.mark.parametrize("expr", propagation_binary_params) + def test_two_rules_two_attrs_binary(self, expr: str) -> None: + """TWO_RULES: At_1 enumerated + At_2 aggr max, applied to binary ops.""" + result = run( + script=TWO_RULES + f"DS_r <- {expr};", + data_structures=_ds_pair(DS_2VA), + datapoints={ + "DS_1": pd.DataFrame( + { + "Id_1": [1, 2, 3], + "Me_1": [10.0, 20.0, 30.0], + "At_1": ["C", "N", "F"], + "At_2": [3, 5, 1], + } + ), + "DS_2": pd.DataFrame( + { + "Id_1": [1, 2, 3], + "Me_1": [5.0, 15.0, 25.0], + "At_1": ["N", "F", "F"], + "At_2": [7, 2, 4], + } + ), + }, + ) + ds_r = result["DS_r"] + # At_1 enumerated: C+N→C, N+F→N, F+F→F + assert list(ds_r.data["At_1"]) == ["C", "N", "F"] + # At_2 aggr max: max(3,7)=7, max(5,2)=5, max(1,4)=4 + assert list(ds_r.data["At_2"]) == [7, 5, 4] + + +# -- Semantic validation -- class TestViralPropagationValidation: - def test_duplicate_variable_rule_raises_error(self): + def test_duplicate_variable_rule_raises_error(self) -> None: script = """ define viral propagation r1 (variable At_1) is when "C" then "C" @@ -214,7 +267,7 @@ def test_duplicate_variable_rule_raises_error(self): with pytest.raises(SemanticError, match="1-3-3-1"): run(script=script, data_structures=SIMPLE_DS, datapoints=SIMPLE_DP) - def test_duplicate_enumeration_raises_error(self): + def test_duplicate_enumeration_raises_error(self) -> None: script = """ define viral propagation dup (variable At_1) is when "C" then "C"; From 133ee8f6a06c80087698816d1a15edfe56f9a0bc Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Wed, 25 Mar 2026 18:16:52 +0100 Subject: [PATCH 14/14] refactor(#510): rename At_1/At_2/At_3 to VAt_1/VAt_2/VAt_3 in viral attribute tests --- tests/ViralAttributes/test_viral_operators.py | 28 +++---- .../ViralAttributes/test_viral_propagation.py | 76 +++++++++---------- tests/ViralAttributes/test_viral_role.py | 24 +++--- 3 files changed, 64 insertions(+), 64 deletions(-) diff --git a/tests/ViralAttributes/test_viral_operators.py b/tests/ViralAttributes/test_viral_operators.py index c0598281e..fd3645e13 100644 --- a/tests/ViralAttributes/test_viral_operators.py +++ b/tests/ViralAttributes/test_viral_operators.py @@ -13,12 +13,12 @@ {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, ] -VA_1 = {"name": "At_1", "type": "String", "role": "Viral Attribute", "nullable": True} -VA_2 = {"name": "At_2", "type": "String", "role": "Viral Attribute", "nullable": True} -VA_3 = {"name": "At_3", "type": "String", "role": "Viral Attribute", "nullable": True} +VA_1 = {"name": "VAt_1", "type": "String", "role": "Viral Attribute", "nullable": True} +VA_2 = {"name": "VAt_2", "type": "String", "role": "Viral Attribute", "nullable": True} +VA_3 = {"name": "VAt_3", "type": "String", "role": "Viral Attribute", "nullable": True} VA_COMPONENTS = [VA_1, VA_2, VA_3] -VA_NAMES = ["At_1", "At_2", "At_3"] +VA_NAMES = ["VAt_1", "VAt_2", "VAt_3"] VA_VALUES = [["A", "B"], ["X", "Y"], ["P", "Q"]] @@ -169,41 +169,41 @@ def test_non_viral_attribute_still_dropped(self) -> None: "name": "DS_1", "DataStructure": [ *BASE_COMPS, - {"name": "At_1", "type": "String", "role": "Attribute", "nullable": True}, + {"name": "VAt_1", "type": "String", "role": "Attribute", "nullable": True}, ], } result = run( script="DS_r <- DS_1 + DS_2;", data_structures={"datasets": [ds, {"name": "DS_2", "DataStructure": BASE_COMPS}]}, datapoints={ - "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "At_1": ["A", "B"]}), + "DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0], "VAt_1": ["A", "B"]}), "DS_2": pd.DataFrame({"Id_1": [1, 2], "Me_1": [5.0, 15.0]}), }, ) - assert "At_1" not in result["DS_r"].components + assert "VAt_1" not in result["DS_r"].components def test_calc_viral_attribute(self) -> None: result = run( - script='DS_r <- DS_1 [calc viral attribute At_1 := "X"];', + script='DS_r <- DS_1 [calc viral attribute VAt_1 := "X"];', data_structures={"datasets": [{"name": "DS_1", "DataStructure": BASE_COMPS}]}, datapoints={"DS_1": pd.DataFrame({"Id_1": [1, 2], "Me_1": [10.0, 20.0]})}, ) - assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE + assert result["DS_r"].components["VAt_1"].role == Role.VIRAL_ATTRIBUTE def test_input_viral_attribute_legacy_format(self) -> None: ds = { "name": "DS_1", "DataStructure": [ *BASE_COMPS, - {"name": "At_1", "type": "String", "role": "ViralAttribute", "nullable": True}, + {"name": "VAt_1", "type": "String", "role": "ViralAttribute", "nullable": True}, ], } result = run( script="DS_r <- DS_1;", data_structures={"datasets": [ds]}, - datapoints={"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]})}, + datapoints={"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "VAt_1": ["A"]})}, ) - assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE + assert result["DS_r"].components["VAt_1"].role == Role.VIRAL_ATTRIBUTE def test_binary_one_operand_viral(self) -> None: """Only DS_1 has viral attr, DS_2 doesn't — viral attr propagated from DS_1.""" @@ -216,5 +216,5 @@ def test_binary_one_operand_viral(self) -> None: }, ) _assert_viral_attrs(result, 2) - assert list(result["DS_r"].data["At_1"]) == ["A", "B"] - assert list(result["DS_r"].data["At_2"]) == ["X", "Y"] + assert list(result["DS_r"].data["VAt_1"]) == ["A", "B"] + assert list(result["DS_r"].data["VAt_2"]) == ["X", "Y"] diff --git a/tests/ViralAttributes/test_viral_propagation.py b/tests/ViralAttributes/test_viral_propagation.py index a342137c6..6da97c12e 100644 --- a/tests/ViralAttributes/test_viral_propagation.py +++ b/tests/ViralAttributes/test_viral_propagation.py @@ -10,7 +10,7 @@ # -- Shared propagation rules -- CONF_RULE = """ - define viral propagation CONF (variable At_1) is + define viral propagation CONF (variable VAt_1) is when "C" then "C"; when "N" then "N"; else "F" @@ -18,7 +18,7 @@ """ CONF_BINARY_RULE = """ - define viral propagation COMP_mix (variable At_1) is + define viral propagation COMP_mix (variable VAt_1) is when "C" and "M" then "N"; when "M" then "M"; else " " @@ -26,18 +26,18 @@ """ TWO_RULES = """ - define viral propagation R1 (variable At_1) is + define viral propagation R1 (variable VAt_1) is when "C" then "C"; when "N" then "N"; else "F" end viral propagation; - define viral propagation R2 (variable At_2) is + define viral propagation R2 (variable VAt_2) is aggr max end viral propagation; """ AGGR_MAX_RULE = """ - define viral propagation S (variable At_1) is + define viral propagation S (variable VAt_1) is aggr max end viral propagation; """ @@ -49,7 +49,7 @@ "DataStructure": [ {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - {"name": "At_1", "type": "String", "role": "Viral Attribute", "nullable": True}, + {"name": "VAt_1", "type": "String", "role": "Viral Attribute", "nullable": True}, ], } @@ -58,8 +58,8 @@ "DataStructure": [ {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - {"name": "At_1", "type": "String", "role": "Viral Attribute", "nullable": True}, - {"name": "At_2", "type": "Integer", "role": "Viral Attribute", "nullable": True}, + {"name": "VAt_1", "type": "String", "role": "Viral Attribute", "nullable": True}, + {"name": "VAt_2", "type": "Integer", "role": "Viral Attribute", "nullable": True}, ], } @@ -89,30 +89,30 @@ def test_parse_enumerated(self) -> None: result = run( script=CONF_RULE + "DS_r <- DS_1;", data_structures={"datasets": [DS_1VA]}, - datapoints={"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]})}, + datapoints={"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "VAt_1": ["A"]})}, ) - assert result["DS_r"].components["At_1"].role == Role.VIRAL_ATTRIBUTE + assert result["DS_r"].components["VAt_1"].role == Role.VIRAL_ATTRIBUTE def test_parse_aggregate(self) -> None: ds = { **DS_NO_VA, "DataStructure": [ *DS_NO_VA["DataStructure"], - {"name": "At_1", "type": "Integer", "role": "Viral Attribute", "nullable": True}, + {"name": "VAt_1", "type": "Integer", "role": "Viral Attribute", "nullable": True}, ], } result = run( script=AGGR_MAX_RULE + "DS_r <- DS_1;", data_structures={"datasets": [ds]}, - datapoints={"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": [5]})}, + datapoints={"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "VAt_1": [5]})}, ) - assert "At_1" in result["DS_r"].components + assert "VAt_1" in result["DS_r"].components def test_parse_binary_clause(self) -> None: result = run( script=CONF_BINARY_RULE + "DS_r <- DS_1;", data_structures={"datasets": [DS_1VA]}, - datapoints={"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["C"]})}, + datapoints={"DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "VAt_1": ["C"]})}, ) assert "DS_r" in result @@ -146,15 +146,15 @@ def test_enumerated_propagation_binary(self, expr: str) -> None: data_structures=_ds_pair(DS_1VA), datapoints={ "DS_1": pd.DataFrame( - {"Id_1": [1, 2, 3], "Me_1": [10.0, 20.0, 30.0], "At_1": ["C", "N", "F"]} + {"Id_1": [1, 2, 3], "Me_1": [10.0, 20.0, 30.0], "VAt_1": ["C", "N", "F"]} ), "DS_2": pd.DataFrame( - {"Id_1": [1, 2, 3], "Me_1": [5.0, 15.0, 25.0], "At_1": ["N", "F", "F"]} + {"Id_1": [1, 2, 3], "Me_1": [5.0, 15.0, 25.0], "VAt_1": ["N", "F", "F"]} ), }, ) # C+N→C (unary "C"); N+F→N (unary "N"); F+F→F (else) - assert list(result["DS_r"].data["At_1"]) == ["C", "N", "F"] + assert list(result["DS_r"].data["VAt_1"]) == ["C", "N", "F"] def test_binary_clause_precedence(self) -> None: """Binary clauses take precedence over unary clauses.""" @@ -163,15 +163,15 @@ def test_binary_clause_precedence(self) -> None: data_structures=_ds_pair(DS_1VA), datapoints={ "DS_1": pd.DataFrame( - {"Id_1": [1, 2, 3], "Me_1": [10.0, 20.0, 30.0], "At_1": ["C", "M", "X"]} + {"Id_1": [1, 2, 3], "Me_1": [10.0, 20.0, 30.0], "VAt_1": ["C", "M", "X"]} ), "DS_2": pd.DataFrame( - {"Id_1": [1, 2, 3], "Me_1": [5.0, 15.0, 25.0], "At_1": ["M", "F", "Y"]} + {"Id_1": [1, 2, 3], "Me_1": [5.0, 15.0, 25.0], "VAt_1": ["M", "F", "Y"]} ), }, ) # C+M→N (binary); M+F→M (unary "M"); X+Y→" " (else) - assert list(result["DS_r"].data["At_1"]) == ["N", "M", " "] + assert list(result["DS_r"].data["VAt_1"]) == ["N", "M", " "] def test_no_rule_gives_null(self) -> None: """Both operands viral but no rule defined → null.""" @@ -179,11 +179,11 @@ def test_no_rule_gives_null(self) -> None: script="DS_r <- DS_1 + DS_2;", data_structures=_ds_pair(DS_1VA), datapoints={ - "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]}), - "DS_2": pd.DataFrame({"Id_1": [1], "Me_1": [5.0], "At_1": ["B"]}), + "DS_1": pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "VAt_1": ["A"]}), + "DS_2": pd.DataFrame({"Id_1": [1], "Me_1": [5.0], "VAt_1": ["B"]}), }, ) - assert pd.isna(result["DS_r"].data["At_1"].iloc[0]) + assert pd.isna(result["DS_r"].data["VAt_1"].iloc[0]) def test_aggregate_max_in_aggregation(self) -> None: """Aggregate max propagation in group by.""" @@ -193,7 +193,7 @@ def test_aggregate_max_in_aggregation(self) -> None: {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, {"name": "Id_2", "type": "Integer", "role": "Identifier", "nullable": False}, {"name": "Me_1", "type": "Number", "role": "Measure", "nullable": True}, - {"name": "At_1", "type": "Integer", "role": "Viral Attribute", "nullable": True}, + {"name": "VAt_1", "type": "Integer", "role": "Viral Attribute", "nullable": True}, ], } result = run( @@ -205,13 +205,13 @@ def test_aggregate_max_in_aggregation(self) -> None: "Id_1": [1, 1, 2], "Id_2": [1, 2, 1], "Me_1": [10.0, 20.0, 30.0], - "At_1": [3, 7, 5], + "VAt_1": [3, 7, 5], } ) }, ) sorted_data = result["DS_r"].data.sort_values("Id_1").reset_index(drop=True) - assert list(sorted_data["At_1"]) == [7, 5] + assert list(sorted_data["VAt_1"]) == [7, 5] # -- Multi-attribute propagation (enumerated + aggregate in one script) -- @@ -220,7 +220,7 @@ def test_aggregate_max_in_aggregation(self) -> None: class TestViralPropagationMultiAttribute: @pytest.mark.parametrize("expr", propagation_binary_params) def test_two_rules_two_attrs_binary(self, expr: str) -> None: - """TWO_RULES: At_1 enumerated + At_2 aggr max, applied to binary ops.""" + """TWO_RULES: VAt_1 enumerated + VAt_2 aggr max, applied to binary ops.""" result = run( script=TWO_RULES + f"DS_r <- {expr};", data_structures=_ds_pair(DS_2VA), @@ -229,25 +229,25 @@ def test_two_rules_two_attrs_binary(self, expr: str) -> None: { "Id_1": [1, 2, 3], "Me_1": [10.0, 20.0, 30.0], - "At_1": ["C", "N", "F"], - "At_2": [3, 5, 1], + "VAt_1": ["C", "N", "F"], + "VAt_2": [3, 5, 1], } ), "DS_2": pd.DataFrame( { "Id_1": [1, 2, 3], "Me_1": [5.0, 15.0, 25.0], - "At_1": ["N", "F", "F"], - "At_2": [7, 2, 4], + "VAt_1": ["N", "F", "F"], + "VAt_2": [7, 2, 4], } ), }, ) ds_r = result["DS_r"] - # At_1 enumerated: C+N→C, N+F→N, F+F→F - assert list(ds_r.data["At_1"]) == ["C", "N", "F"] - # At_2 aggr max: max(3,7)=7, max(5,2)=5, max(1,4)=4 - assert list(ds_r.data["At_2"]) == [7, 5, 4] + # VAt_1 enumerated: C+N→C, N+F→N, F+F→F + assert list(ds_r.data["VAt_1"]) == ["C", "N", "F"] + # VAt_2 aggr max: max(3,7)=7, max(5,2)=5, max(1,4)=4 + assert list(ds_r.data["VAt_2"]) == [7, 5, 4] # -- Semantic validation -- @@ -256,10 +256,10 @@ def test_two_rules_two_attrs_binary(self, expr: str) -> None: class TestViralPropagationValidation: def test_duplicate_variable_rule_raises_error(self) -> None: script = """ - define viral propagation r1 (variable At_1) is + define viral propagation r1 (variable VAt_1) is when "C" then "C" end viral propagation; - define viral propagation r2 (variable At_1) is + define viral propagation r2 (variable VAt_1) is when "N" then "N" end viral propagation; DS_r <- DS_1; @@ -269,7 +269,7 @@ def test_duplicate_variable_rule_raises_error(self) -> None: def test_duplicate_enumeration_raises_error(self) -> None: script = """ - define viral propagation dup (variable At_1) is + define viral propagation dup (variable VAt_1) is when "C" then "C"; when "C" then "N" end viral propagation; diff --git a/tests/ViralAttributes/test_viral_role.py b/tests/ViralAttributes/test_viral_role.py index 693d23dfa..bc44bb162 100644 --- a/tests/ViralAttributes/test_viral_role.py +++ b/tests/ViralAttributes/test_viral_role.py @@ -13,7 +13,7 @@ def test_viral_attribute_in_role_keys(self): def test_component_with_viral_attribute_role(self): comp = Component( - name="At_1", + name="VAt_1", data_type=String, role=Role.VIRAL_ATTRIBUTE, nullable=True, @@ -26,24 +26,24 @@ def test_dataset_get_viral_attributes(self): components={ "Id_1": Component("Id_1", Integer, Role.IDENTIFIER, False), "Me_1": Component("Me_1", Number, Role.MEASURE, True), - "At_1": Component("At_1", String, Role.VIRAL_ATTRIBUTE, True), + "VAt_1": Component("VAt_1", String, Role.VIRAL_ATTRIBUTE, True), }, - data=pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "At_1": ["A"]}), + data=pd.DataFrame({"Id_1": [1], "Me_1": [10.0], "VAt_1": ["A"]}), ) viral_attrs = ds.get_viral_attributes() assert len(viral_attrs) == 1 - assert viral_attrs[0].name == "At_1" + assert viral_attrs[0].name == "VAt_1" def test_dataset_get_viral_attributes_names(self): ds = Dataset( name="DS_1", components={ "Id_1": Component("Id_1", Integer, Role.IDENTIFIER, False), - "At_1": Component("At_1", String, Role.VIRAL_ATTRIBUTE, True), + "VAt_1": Component("VAt_1", String, Role.VIRAL_ATTRIBUTE, True), }, - data=pd.DataFrame({"Id_1": [1], "At_1": ["A"]}), + data=pd.DataFrame({"Id_1": [1], "VAt_1": ["A"]}), ) - assert ds.get_viral_attributes_names() == ["At_1"] + assert ds.get_viral_attributes_names() == ["VAt_1"] def test_get_attributes_excludes_viral(self): """get_attributes() must NOT return VIRAL_ATTRIBUTE components.""" @@ -51,12 +51,12 @@ def test_get_attributes_excludes_viral(self): name="DS_1", components={ "Id_1": Component("Id_1", Integer, Role.IDENTIFIER, False), - "At_1": Component("At_1", String, Role.ATTRIBUTE, True), - "At_2": Component("At_2", String, Role.VIRAL_ATTRIBUTE, True), + "VAt_1": Component("VAt_1", String, Role.ATTRIBUTE, True), + "VAt_2": Component("VAt_2", String, Role.VIRAL_ATTRIBUTE, True), }, - data=pd.DataFrame({"Id_1": [1], "At_1": ["A"], "At_2": ["B"]}), + data=pd.DataFrame({"Id_1": [1], "VAt_1": ["A"], "VAt_2": ["B"]}), ) attrs = ds.get_attributes() assert len(attrs) == 1 - assert attrs[0].name == "At_1" - assert "At_2" not in ds.get_attributes_names() + assert attrs[0].name == "VAt_1" + assert "VAt_2" not in ds.get_attributes_names()