aas-core-codegen 0.0.16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aas_core_codegen/__init__.py +6 -0
- aas_core_codegen/__main__.py +8 -0
- aas_core_codegen/common.py +500 -0
- aas_core_codegen/cpp/__init__.py +1 -0
- aas_core_codegen/cpp/aas_common/__init__.py +6 -0
- aas_core_codegen/cpp/aas_common/_generate.py +713 -0
- aas_core_codegen/cpp/common.py +681 -0
- aas_core_codegen/cpp/constants/__init__.py +6 -0
- aas_core_codegen/cpp/constants/_generate.py +568 -0
- aas_core_codegen/cpp/description.py +654 -0
- aas_core_codegen/cpp/enhancing/__init__.py +4 -0
- aas_core_codegen/cpp/enhancing/_generate.py +993 -0
- aas_core_codegen/cpp/iteration/__init__.py +6 -0
- aas_core_codegen/cpp/iteration/_generate.py +2332 -0
- aas_core_codegen/cpp/jsonization/__init__.py +6 -0
- aas_core_codegen/cpp/jsonization/_generate.py +2619 -0
- aas_core_codegen/cpp/main.py +694 -0
- aas_core_codegen/cpp/naming.py +170 -0
- aas_core_codegen/cpp/optionaling.py +557 -0
- aas_core_codegen/cpp/pattern/__init__.py +6 -0
- aas_core_codegen/cpp/pattern/_generate.py +508 -0
- aas_core_codegen/cpp/revm/__init__.py +6 -0
- aas_core_codegen/cpp/revm/_generate.py +1149 -0
- aas_core_codegen/cpp/stringification/__init__.py +5 -0
- aas_core_codegen/cpp/stringification/_generate.py +955 -0
- aas_core_codegen/cpp/structure/__init__.py +7 -0
- aas_core_codegen/cpp/structure/_generate.py +1503 -0
- aas_core_codegen/cpp/transpilation.py +1383 -0
- aas_core_codegen/cpp/unrolling.py +159 -0
- aas_core_codegen/cpp/verification/__init__.py +6 -0
- aas_core_codegen/cpp/verification/_generate.py +3073 -0
- aas_core_codegen/cpp/visitation/__init__.py +6 -0
- aas_core_codegen/cpp/visitation/_generate.py +521 -0
- aas_core_codegen/cpp/wstringification/__init__.py +5 -0
- aas_core_codegen/cpp/wstringification/_generate.py +586 -0
- aas_core_codegen/cpp/xmlization/__init__.py +6 -0
- aas_core_codegen/cpp/xmlization/_generate.py +5373 -0
- aas_core_codegen/cpp/yielding.py +201 -0
- aas_core_codegen/csharp/__init__.py +1 -0
- aas_core_codegen/csharp/common.py +224 -0
- aas_core_codegen/csharp/constants/__init__.py +5 -0
- aas_core_codegen/csharp/constants/_generate.py +409 -0
- aas_core_codegen/csharp/copying/__init__.py +4 -0
- aas_core_codegen/csharp/copying/_generate.py +498 -0
- aas_core_codegen/csharp/description.py +1103 -0
- aas_core_codegen/csharp/enhancing/__init__.py +4 -0
- aas_core_codegen/csharp/enhancing/_generate.py +667 -0
- aas_core_codegen/csharp/jsonization/__init__.py +4 -0
- aas_core_codegen/csharp/jsonization/_generate.py +1630 -0
- aas_core_codegen/csharp/main.py +421 -0
- aas_core_codegen/csharp/naming.py +157 -0
- aas_core_codegen/csharp/reporting/__init__.py +4 -0
- aas_core_codegen/csharp/reporting/_generate.py +266 -0
- aas_core_codegen/csharp/stringification/__init__.py +4 -0
- aas_core_codegen/csharp/stringification/_generate.py +243 -0
- aas_core_codegen/csharp/structure/__init__.py +6 -0
- aas_core_codegen/csharp/structure/_generate.py +1341 -0
- aas_core_codegen/csharp/transpilation.py +990 -0
- aas_core_codegen/csharp/unrolling.py +211 -0
- aas_core_codegen/csharp/verification/__init__.py +6 -0
- aas_core_codegen/csharp/verification/_generate.py +1457 -0
- aas_core_codegen/csharp/visitation/__init__.py +5 -0
- aas_core_codegen/csharp/visitation/_generate.py +579 -0
- aas_core_codegen/csharp/xmlization/__init__.py +4 -0
- aas_core_codegen/csharp/xmlization/_generate.py +1980 -0
- aas_core_codegen/golang/__init__.py +1 -0
- aas_core_codegen/golang/aas_common/__init__.py +4 -0
- aas_core_codegen/golang/aas_common/_generate.py +152 -0
- aas_core_codegen/golang/common.py +303 -0
- aas_core_codegen/golang/constants/__init__.py +5 -0
- aas_core_codegen/golang/constants/_generate.py +339 -0
- aas_core_codegen/golang/description.py +501 -0
- aas_core_codegen/golang/enhancing/__init__.py +4 -0
- aas_core_codegen/golang/enhancing/_generate.py +527 -0
- aas_core_codegen/golang/jsonization/__init__.py +4 -0
- aas_core_codegen/golang/jsonization/_generate.py +1740 -0
- aas_core_codegen/golang/main.py +368 -0
- aas_core_codegen/golang/naming.py +412 -0
- aas_core_codegen/golang/pointering.py +631 -0
- aas_core_codegen/golang/reporting/__init__.py +4 -0
- aas_core_codegen/golang/reporting/_generate.py +218 -0
- aas_core_codegen/golang/stringification/__init__.py +4 -0
- aas_core_codegen/golang/stringification/_generate.py +394 -0
- aas_core_codegen/golang/structure/__init__.py +6 -0
- aas_core_codegen/golang/structure/_generate.py +1493 -0
- aas_core_codegen/golang/transpilation.py +1191 -0
- aas_core_codegen/golang/unrolling.py +159 -0
- aas_core_codegen/golang/verification/__init__.py +6 -0
- aas_core_codegen/golang/verification/_generate.py +1513 -0
- aas_core_codegen/golang/xmlization/__init__.py +4 -0
- aas_core_codegen/golang/xmlization/_generate.py +2507 -0
- aas_core_codegen/infer_for_schema/__init__.py +21 -0
- aas_core_codegen/infer_for_schema/_inline.py +693 -0
- aas_core_codegen/infer_for_schema/_len.py +527 -0
- aas_core_codegen/infer_for_schema/_pattern.py +311 -0
- aas_core_codegen/infer_for_schema/_set.py +394 -0
- aas_core_codegen/infer_for_schema/_stringify.py +201 -0
- aas_core_codegen/infer_for_schema/_types.py +135 -0
- aas_core_codegen/infer_for_schema/match.py +122 -0
- aas_core_codegen/intermediate/__init__.py +78 -0
- aas_core_codegen/intermediate/_hierarchy.py +397 -0
- aas_core_codegen/intermediate/_stringify.py +989 -0
- aas_core_codegen/intermediate/_translate.py +5128 -0
- aas_core_codegen/intermediate/_types.py +2901 -0
- aas_core_codegen/intermediate/construction.py +750 -0
- aas_core_codegen/intermediate/doc.py +344 -0
- aas_core_codegen/intermediate/pattern_verification.py +428 -0
- aas_core_codegen/intermediate/revm.py +985 -0
- aas_core_codegen/intermediate/type_inference.py +2266 -0
- aas_core_codegen/java/__init__.py +1 -0
- aas_core_codegen/java/common.py +197 -0
- aas_core_codegen/java/constants/__init__.py +5 -0
- aas_core_codegen/java/constants/_generate.py +334 -0
- aas_core_codegen/java/copying/__init__.py +4 -0
- aas_core_codegen/java/copying/_generate.py +502 -0
- aas_core_codegen/java/description.py +774 -0
- aas_core_codegen/java/enhancing/__init__.py +4 -0
- aas_core_codegen/java/enhancing/_generate.py +820 -0
- aas_core_codegen/java/generation/__init__.py +5 -0
- aas_core_codegen/java/generation/_generate.py +285 -0
- aas_core_codegen/java/jsonization/__init__.py +4 -0
- aas_core_codegen/java/jsonization/_generate.py +1472 -0
- aas_core_codegen/java/main.py +438 -0
- aas_core_codegen/java/naming.py +187 -0
- aas_core_codegen/java/optional.py +514 -0
- aas_core_codegen/java/reporting/__init__.py +4 -0
- aas_core_codegen/java/reporting/_generate.py +248 -0
- aas_core_codegen/java/stringification/__init__.py +4 -0
- aas_core_codegen/java/stringification/_generate.py +212 -0
- aas_core_codegen/java/structure/__init__.py +6 -0
- aas_core_codegen/java/structure/_generate.py +1767 -0
- aas_core_codegen/java/transpilation.py +1111 -0
- aas_core_codegen/java/verification/__init__.py +6 -0
- aas_core_codegen/java/verification/_generate.py +1536 -0
- aas_core_codegen/java/visitation/__init__.py +5 -0
- aas_core_codegen/java/visitation/_generate.py +689 -0
- aas_core_codegen/java/xmlization/__init__.py +4 -0
- aas_core_codegen/java/xmlization/_generate.py +2274 -0
- aas_core_codegen/jsonld/__init__.py +1 -0
- aas_core_codegen/jsonld/main.py +455 -0
- aas_core_codegen/jsonschema/__init__.py +1 -0
- aas_core_codegen/jsonschema/main.py +982 -0
- aas_core_codegen/main.py +245 -0
- aas_core_codegen/naming.py +133 -0
- aas_core_codegen/opcua/__init__.py +1 -0
- aas_core_codegen/opcua/main.py +1525 -0
- aas_core_codegen/opcua/naming.py +126 -0
- aas_core_codegen/parse/__init__.py +46 -0
- aas_core_codegen/parse/_rules.py +796 -0
- aas_core_codegen/parse/_stringify.py +532 -0
- aas_core_codegen/parse/_translate.py +3940 -0
- aas_core_codegen/parse/_types.py +973 -0
- aas_core_codegen/parse/retree/__init__.py +46 -0
- aas_core_codegen/parse/retree/_fix.py +434 -0
- aas_core_codegen/parse/retree/_parse.py +1143 -0
- aas_core_codegen/parse/retree/_render.py +298 -0
- aas_core_codegen/parse/retree/_stringify.py +199 -0
- aas_core_codegen/parse/retree/_types.py +362 -0
- aas_core_codegen/parse/retree/_visitor.py +70 -0
- aas_core_codegen/parse/tree.py +1303 -0
- aas_core_codegen/protobuf/__init__.py +1 -0
- aas_core_codegen/protobuf/common.py +225 -0
- aas_core_codegen/protobuf/description.py +1102 -0
- aas_core_codegen/protobuf/main.py +115 -0
- aas_core_codegen/protobuf/naming.py +143 -0
- aas_core_codegen/protobuf/structure/__init__.py +6 -0
- aas_core_codegen/protobuf/structure/_generate.py +502 -0
- aas_core_codegen/py.typed +1 -0
- aas_core_codegen/python/__init__.py +1 -0
- aas_core_codegen/python/aas_common/__init__.py +4 -0
- aas_core_codegen/python/aas_common/_generate.py +63 -0
- aas_core_codegen/python/common.py +406 -0
- aas_core_codegen/python/constants/__init__.py +5 -0
- aas_core_codegen/python/constants/_generate.py +377 -0
- aas_core_codegen/python/description.py +508 -0
- aas_core_codegen/python/jsonization/__init__.py +4 -0
- aas_core_codegen/python/jsonization/_generate.py +1391 -0
- aas_core_codegen/python/main.py +323 -0
- aas_core_codegen/python/naming.py +255 -0
- aas_core_codegen/python/stringification/__init__.py +4 -0
- aas_core_codegen/python/stringification/_generate.py +129 -0
- aas_core_codegen/python/structure/__init__.py +6 -0
- aas_core_codegen/python/structure/_generate.py +1801 -0
- aas_core_codegen/python/transpilation.py +958 -0
- aas_core_codegen/python/unrolling.py +156 -0
- aas_core_codegen/python/verification/__init__.py +6 -0
- aas_core_codegen/python/verification/_generate.py +1471 -0
- aas_core_codegen/python/xmlization/__init__.py +4 -0
- aas_core_codegen/python/xmlization/_generate.py +3003 -0
- aas_core_codegen/python_protobuf/__init__.py +1 -0
- aas_core_codegen/python_protobuf/main.py +1424 -0
- aas_core_codegen/python_protobuf/naming.py +85 -0
- aas_core_codegen/rdf_shacl/__init__.py +1 -0
- aas_core_codegen/rdf_shacl/_description.py +351 -0
- aas_core_codegen/rdf_shacl/common.py +206 -0
- aas_core_codegen/rdf_shacl/main.py +114 -0
- aas_core_codegen/rdf_shacl/naming.py +145 -0
- aas_core_codegen/rdf_shacl/rdf.py +435 -0
- aas_core_codegen/rdf_shacl/shacl.py +453 -0
- aas_core_codegen/run.py +124 -0
- aas_core_codegen/smoke/__init__.py +1 -0
- aas_core_codegen/smoke/main.py +219 -0
- aas_core_codegen/specific_implementations.py +72 -0
- aas_core_codegen/stringify.py +333 -0
- aas_core_codegen/typescript/__init__.py +1 -0
- aas_core_codegen/typescript/aas_common/__init__.py +4 -0
- aas_core_codegen/typescript/aas_common/_generate.py +472 -0
- aas_core_codegen/typescript/common.py +340 -0
- aas_core_codegen/typescript/constants/__init__.py +5 -0
- aas_core_codegen/typescript/constants/_generate.py +347 -0
- aas_core_codegen/typescript/description.py +530 -0
- aas_core_codegen/typescript/jsonization/__init__.py +4 -0
- aas_core_codegen/typescript/jsonization/_generate.py +1510 -0
- aas_core_codegen/typescript/main.py +258 -0
- aas_core_codegen/typescript/naming.py +189 -0
- aas_core_codegen/typescript/stringification/__init__.py +4 -0
- aas_core_codegen/typescript/stringification/_generate.py +367 -0
- aas_core_codegen/typescript/structure/__init__.py +6 -0
- aas_core_codegen/typescript/structure/_generate.py +2500 -0
- aas_core_codegen/typescript/transpilation.py +1051 -0
- aas_core_codegen/typescript/unrolling.py +159 -0
- aas_core_codegen/typescript/verification/__init__.py +6 -0
- aas_core_codegen/typescript/verification/_generate.py +1578 -0
- aas_core_codegen/xsd/__init__.py +1 -0
- aas_core_codegen/xsd/main.py +1187 -0
- aas_core_codegen/xsd/naming.py +83 -0
- aas_core_codegen/yielding/__init__.py +1 -0
- aas_core_codegen/yielding/flow.py +139 -0
- aas_core_codegen/yielding/linear.py +754 -0
- aas_core_codegen-0.0.16.dist-info/METADATA +211 -0
- aas_core_codegen-0.0.16.dist-info/RECORD +604 -0
- aas_core_codegen-0.0.16.dist-info/WHEEL +5 -0
- aas_core_codegen-0.0.16.dist-info/entry_points.txt +3 -0
- aas_core_codegen-0.0.16.dist-info/licenses/AUTHORS +9 -0
- aas_core_codegen-0.0.16.dist-info/licenses/LICENSE +23 -0
- aas_core_codegen-0.0.16.dist-info/top_level.txt +2 -0
- dev/continuous_integration/__init__.py +1 -0
- dev/continuous_integration/check_help_in_readme.py +208 -0
- dev/continuous_integration/check_init_and_pyproject_consistent.py +154 -0
- dev/continuous_integration/precommit.py +400 -0
- dev/dev_scripts/__init__.py +1 -0
- dev/dev_scripts/compare_rendered_regexes_against_source_py.py +42 -0
- dev/dev_scripts/copy_to_aas_core3_cpp.py +100 -0
- dev/dev_scripts/copy_to_aas_core3_java.py +90 -0
- dev/dev_scripts/download_latest_aas_core_meta_v3.py +114 -0
- dev/dev_scripts/draw_bipartite_graph_based_on_lines.py +37 -0
- dev/dev_scripts/run_tests_with_rerecord.py +69 -0
- dev/dev_scripts/update_to_aas_core_meta.py +174 -0
- dev/integration_tests/input/jsonschema/boilerplate/main.py +55 -0
- dev/integration_tests/input/meta_model.py +38 -0
- dev/integration_tests/input/python/boilerplate/main.py +153 -0
- dev/integration_tests/main.py +258 -0
- dev/test_data/csharp/test_structure/concrete_class_with_descendants/meta_model.py +15 -0
- dev/test_data/csharp/test_structure/constructor_without_arguments/all_properties_optional/meta_model.py +9 -0
- dev/test_data/csharp/test_structure/constructor_without_arguments/no_properties/meta_model.py +6 -0
- dev/test_data/csharp/test_verification/builtin_functions/len/on_list/meta_model.py +20 -0
- dev/test_data/csharp/test_verification/builtin_functions/len/on_str/meta_model.py +16 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/as_prefix/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/as_suffix/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_group_with_quantifier/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_the_middle/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_union/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/single_utf32_literal/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/with_quantifier_within_group/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/with_quantifier_without_group/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/at_the_beginning/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/at_the_end/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/in_the_middle/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/multiple/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/single/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/single_with_quantifier/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/mixed_with_non_utf32/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/more_than_two_high_surrogates/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/multiple_utf32_ranges/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/multiple_utf32_ranges_mixed_with_non_utf32/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/same_high_surrogate/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/same_high_surrogate_with_quantifier/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/two_high_surrogates/meta_model.py +8 -0
- dev/test_data/intermediate/expected/class/empty/meta_model.py +6 -0
- dev/test_data/intermediate/expected/class/implementation_specific_method/meta_model.py +8 -0
- dev/test_data/intermediate/expected/class/inheritance/meta_model.py +41 -0
- dev/test_data/intermediate/expected/class/methods_with_contracts/meta_model.py +15 -0
- dev/test_data/intermediate/expected/class/only_method_no_property/meta_model.py +7 -0
- dev/test_data/intermediate/expected/class/only_property_no_method/meta_model.py +9 -0
- dev/test_data/intermediate/expected/constant/constant_set/of_enum/meta_model.py +12 -0
- dev/test_data/intermediate/expected/constant/constant_set/of_str/meta_model.py +4 -0
- dev/test_data/intermediate/expected/constant/constant_set/with_description/meta_model.py +6 -0
- dev/test_data/intermediate/expected/constant/constant_set/with_superset_of/meta_model.py +14 -0
- dev/test_data/intermediate/expected/constant/constant_str/only_value/meta_model.py +7 -0
- dev/test_data/intermediate/expected/constant/constant_str/with_description/meta_model.py +5 -0
- dev/test_data/intermediate/expected/documentation/docstring_with_special_characters_in_literal/meta_model.py +20 -0
- dev/test_data/intermediate/expected/documentation/docstring_with_special_characters_outside_literal/meta_model.py +20 -0
- dev/test_data/intermediate/expected/empty/meta_model.py +2 -0
- dev/test_data/intermediate/expected/enumeration/meta_model.py +9 -0
- dev/test_data/intermediate/expected/interface/basic/meta_model.py +14 -0
- dev/test_data/intermediate/expected/interface/empty/meta_model.py +7 -0
- dev/test_data/intermediate/expected/interface/inheritance/meta_model.py +27 -0
- dev/test_data/intermediate/expected/interface/method_signature/meta_model.py +10 -0
- dev/test_data/intermediate/expected/interface/only_constructor/meta_model.py +11 -0
- dev/test_data/intermediate/expected/method/non_mutating/implementation_specific/meta_model.py +12 -0
- dev/test_data/intermediate/expected/method/non_mutating/understood/meta_model.py +11 -0
- dev/test_data/intermediate/expected/type_annotation/atomic/meta_model.py +9 -0
- dev/test_data/intermediate/expected/type_annotation/subscripted/class/meta_model.py +13 -0
- dev/test_data/intermediate/expected/type_annotation/subscripted/primitive/meta_model.py +9 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/enumeration_literals_in_subset_outside_of_superset/meta_model.py +20 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/invalid_literal/meta_model.py +11 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/mismatch_between_enumeration_and_literal/meta_model.py +30 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/mismatch_in_enumerations_between_subset_and_superset/meta_model.py +21 -0
- dev/test_data/intermediate/unexpected/constant_set/of_str/literals_in_subset_outside_of_superset/meta_model.py +18 -0
- dev/test_data/intermediate/unexpected/constant_set/of_str/mismatch_between_type_annotation_and_literals/meta_model.py +10 -0
- dev/test_data/intermediate/unexpected/constant_set/of_str/superset_and_subset_mismatch_in_type/meta_model.py +12 -0
- dev/test_data/intermediate/unexpected/constraints/dangling_constraintref/meta_model.py +18 -0
- dev/test_data/intermediate/unexpected/constraints/duplicate_constraints/meta_model.py +20 -0
- dev/test_data/intermediate/unexpected/documentation/unexpected_documentation_elements/meta_model.py +34 -0
- dev/test_data/intermediate/unexpected/invariant/class_invariant_uses_re/meta_model.py +10 -0
- dev/test_data/intermediate/unexpected/invariant/invariant_of_constrained_primitive_uses_re/meta_model.py +7 -0
- dev/test_data/intermediate/unexpected/invariant/unexpected_argument_count_to_len/meta_model.py +20 -0
- dev/test_data/intermediate/unexpected/invariant/unhandled_built_in_function/meta_model.py +16 -0
- dev/test_data/intermediate/unexpected/method_definitions/non_constant_default/meta_model.py +7 -0
- dev/test_data/intermediate/unexpected/optional_constructor_arguments_wo_default/default_non_none/meta_model.py +16 -0
- dev/test_data/intermediate/unexpected/optional_constructor_arguments_wo_default/no_default/meta_model.py +16 -0
- dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/after_inheritance/meta_model.py +58 -0
- dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/type_missmatch/meta_model.py +9 -0
- dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/within_class/meta_model.py +22 -0
- dev/test_data/jsonschema/test_main/regression_when_len_constraints_on_inherited_property/meta_model.py +28 -0
- dev/test_data/opcua/test_main/abstract_and_concrete_classes/meta_model.py +37 -0
- dev/test_data/opcua/test_main/classes_with_invariants/meta_model.py +21 -0
- dev/test_data/opcua/test_main/concrete_class_with_descendant/meta_model.py +27 -0
- dev/test_data/opcua/test_main/concrete_class_with_enum/meta_model.py +21 -0
- dev/test_data/opcua/test_main/concrete_class_with_list_of_instances/meta_model.py +21 -0
- dev/test_data/opcua/test_main/concrete_class_with_primitive_attributes/meta_model.py +41 -0
- dev/test_data/opcua/test_main/concrete_class_with_string/meta_model.py +13 -0
- dev/test_data/opcua/test_main/constrained_primitive/meta_model.py +20 -0
- dev/test_data/opcua/test_main/multiple_inheritance/meta_model.py +25 -0
- dev/test_data/parse/expected/constant/constant_set/of_enum/meta_model.py +12 -0
- dev/test_data/parse/expected/constant/constant_set/of_str/meta_model.py +4 -0
- dev/test_data/parse/expected/constant/constant_set/with_description/meta_model.py +6 -0
- dev/test_data/parse/expected/constant/constant_set/with_superset_of/meta_model.py +14 -0
- dev/test_data/parse/expected/constant/constant_str/only_value/meta_model.py +7 -0
- dev/test_data/parse/expected/constant/constant_str/with_description/meta_model.py +5 -0
- dev/test_data/parse/expected/enum/ok/meta_model.py +15 -0
- dev/test_data/parse/expected/implementation_specific_class/properties_and_methods_in_implementation_specific_class/meta_model.py +17 -0
- dev/test_data/parse/expected/inheritance/basic/meta_model.py +11 -0
- dev/test_data/parse/expected/inheritance/diamond/meta_model.py +26 -0
- dev/test_data/parse/expected/inheritance/inheritance_from_concrete_class/meta_model.py +10 -0
- dev/test_data/parse/expected/invariants/in_relation/meta_model.py +16 -0
- dev/test_data/parse/expected/method/arguments/meta_model.py +7 -0
- dev/test_data/parse/expected/method/basic/meta_model.py +7 -0
- dev/test_data/parse/expected/method/contracts/condition_as_keyword_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/condition_as_positional_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/description_as_keyword_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/description_as_positional_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/multiple_contracts_in_order/meta_model.py +17 -0
- dev/test_data/parse/expected/method/contracts/postcondition/basic/meta_model.py +10 -0
- dev/test_data/parse/expected/method/contracts/postcondition/snapshot/with_keyword_arguments/meta_model.py +9 -0
- dev/test_data/parse/expected/method/contracts/postcondition/snapshot/with_positional_arguments/meta_model.py +9 -0
- dev/test_data/parse/expected/method/default/meta_model.py +9 -0
- dev/test_data/parse/expected/method/description/meta_model.py +8 -0
- dev/test_data/parse/expected/method/is_implementation_specific/meta_model.py +8 -0
- dev/test_data/parse/expected/method/non_mutating/meta_model.py +11 -0
- dev/test_data/parse/expected/method/returns_none/meta_model.py +7 -0
- dev/test_data/parse/expected/method/returns_something/meta_model.py +7 -0
- dev/test_data/parse/expected/single_class/description/meta_model.py +12 -0
- dev/test_data/parse/expected/single_class/empty/meta_model.py +6 -0
- dev/test_data/parse/expected/single_class/property/description/meta_model.py +14 -0
- dev/test_data/parse/expected/single_class/property/mandatory/meta_model.py +6 -0
- dev/test_data/parse/expected/single_class/property/optional/meta_model.py +6 -0
- dev/test_data/parse/expected/single_class/property/recursion_to_entity/meta_model.py +6 -0
- dev/test_data/parse/unexpected/class_decorators/non_name_decorator/meta_model.py +7 -0
- dev/test_data/parse/unexpected/class_decorators/unknown_decorator/meta_model.py +7 -0
- dev/test_data/parse/unexpected/class_definitions/is_abstract_and_implementation_specific/meta_model.py +8 -0
- dev/test_data/parse/unexpected/class_definitions/unexpected_docstring_before_a_method/meta_model.py +11 -0
- dev/test_data/parse/unexpected/class_definitions/unexpected_docstring_for_a_pass/meta_model.py +9 -0
- dev/test_data/parse/unexpected/class_definitions/unexpected_double_description_for_a_property/meta_model.py +10 -0
- dev/test_data/parse/unexpected/class_inheritances/inheriting_from_implementation_specific_parent/meta_model.py +20 -0
- dev/test_data/parse/unexpected/class_inheritances/non_name_super_class/meta_model.py +6 -0
- dev/test_data/parse/unexpected/enum/expression_as_assignment_value/meta_model.py +6 -0
- dev/test_data/parse/unexpected/enum/non_assignment/meta_model.py +8 -0
- dev/test_data/parse/unexpected/enum/non_string_literal/meta_model.py +6 -0
- dev/test_data/parse/unexpected/enum/unexpected_inheritance/meta_model.py +6 -0
- dev/test_data/parse/unexpected/method_contracts/contract/non_lambda_condition/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/contract/non_string_literal_description/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/contract/without_any_arguments/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/contract/without_condition/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/postcondition/OLD_in_postcondition_without_snapshot/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/postcondition/argument_missing_in_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/precondition/argument_missing_in_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/argument_missing_in_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/capture_not_a_lambda/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/invalid_name/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/name_not_a_string_literal/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/without_a_capture/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/without_a_name/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/non_mutating/non_mutating_constructor/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/non_mutating/non_mutating_verification_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/non_name_decorator/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/unknown_call_decorator/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/unknown_name_decorator/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_definitions/argument_with_final/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/argument_without_a_type_annotation/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/default_for_self/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/dunder/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/init_with_return_type/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_keyword_only_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_positional_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_type_annotation_for_self/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_variable_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_variable_keyword_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/without_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/without_self/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/without_type_annotation_for_result/meta_model.py +7 -0
- dev/test_data/parse/unexpected/property_definitions/final_without_subscript/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/nested_final/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/non_simple/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/unexpected_assignment/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/unexpected_non_name_property/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/without_type_annotation/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/constant_set_with_a_non_set_subset/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_inheritance/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_a_property/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_an_argument/meta_model.py +7 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_constant_set/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_subset_in_constant_set/meta_model.py +4 -0
- dev/test_data/parse/unexpected/symbol_table/inheritance_from_non_class/meta_model.py +10 -0
- dev/test_data/parse_retree/expected/character_set/common_escaping/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/complementing/double_caret/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/complementing/multiple_ranges/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/complementing/suffix_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/escape_first_caret/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/literals_which_need_no_escaping_in_characters_set_but_need_escaping_outside/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/multiple_ranges/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/single_literal/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/single_range/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/unescaped_dash/only_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/unescaped_dash/prefix_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/unescaped_dash/suffix_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/dot/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/group/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/group_in_a_group/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/group_of_union_of_empty_concatenations/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/regex/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/union_of_empty_concatenations/source.py +1 -0
- dev/test_data/parse_retree/expected/escaped_literals/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/at_the_beginning/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/at_the_end/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/in_the_middle/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/single_formatted_value/source.py +1 -0
- dev/test_data/parse_retree/expected/literal/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/at_least_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/at_least_one/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/at_most_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/exactly_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/maybe/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/zero_or_more/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/at_least_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/at_least_one/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/at_most_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/exactly_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/maybe/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/zero_or_more/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_character_set/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_formatted_value/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_group/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_literal/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/double_end_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/double_start_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/end_symbol_in_the_middle/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/only_start_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/only_stop_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/start_symbol_at_the_beginning/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/start_symbol_in_the_middle/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/stop_symbol_at_the_end/source.py +1 -0
- dev/test_data/parse_retree/expected/union/of_character_sets/source.py +1 -0
- dev/test_data/parse_retree/expected/union/of_groups/source.py +1 -0
- dev/test_data/parse_retree/expected/union/of_string_literals/source.py +1 -0
- dev/test_data/parse_retree/expected/union/within_group/source.py +1 -0
- dev/test_data/parse_retree/expected/whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/Uxxxxxxxx_out_of_range/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/only_backslash/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_Uxxxxxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_uxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unexpected_escaping/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/Uxxxxxxxx_out_of_range/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/only_backslash/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_Uxxxxxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_uxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unexpected_escaping/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_character_range/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_quantifier/at_least_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_quantifier/between_3_and_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_quantifier/exactly_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unhandled_group_directives/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/character_set/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/group/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/group_of_union_of_empty_concatenations/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/quantifier/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/quantifier_with_comma/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/quantifier_with_number_and_comma/source.py +1 -0
- dev/test_data/proto/test_main/expected/abstract_and_concrete_classes/meta_model.py +37 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_descendants/meta_model.py +30 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_enum/meta_model.py +21 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_list_of_instances/meta_model.py +21 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_primitive_attributes/meta_model.py +41 -0
- dev/test_data/python_protobuf/test_main/abstract_and_concrete_classes/expected_output/pbization.py +532 -0
- dev/test_data/python_protobuf/test_main/abstract_and_concrete_classes/meta_model.py +37 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_descendant/expected_output/pbization.py +527 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_descendant/meta_model.py +27 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_enum/expected_output/pbization.py +290 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_enum/meta_model.py +21 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_list_of_instances/expected_output/pbization.py +328 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_list_of_instances/meta_model.py +23 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_primitive_attributes/expected_output/pbization.py +274 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_primitive_attributes/meta_model.py +41 -0
- dev/test_data/rdf_shacl/test_main/expected/regression_when_lang_string_class_is_missing/meta_model.py +29 -0
- dev/test_data/rdf_shacl/test_main/expected/regression_when_len_constraints_on_inherited_property/meta_model.py +27 -0
- dev/test_data/rdf_shacl/test_main/unexpected/regression_len_constraint_on_class_property/meta_model.py +61 -0
- dev/test_data/real_meta_models/aas_core_meta.v3.py +5721 -0
- dev/test_data/smoke/test_main/unexpected/infer_for_schema_error/meta_model.py +12 -0
- dev/test_data/smoke/test_main/unexpected/intermediate_error/meta_model.py +18 -0
- dev/test_data/smoke/test_main/unexpected/parse_error/meta_model.py +5 -0
- dev/test_data/smoke/test_main/unexpected/pattern_verification_unparsable_regex/direct_match/meta_model.py +8 -0
- dev/test_data/smoke/test_main/unexpected/type_error/meta_model.py +18 -0
- dev/tests/__init__.py +1 -0
- dev/tests/common.py +197 -0
- dev/tests/cpp/__init__.py +0 -0
- dev/tests/cpp/test_common.py +32 -0
- dev/tests/cpp/test_main.py +144 -0
- dev/tests/cpp/test_pattern.py +188 -0
- dev/tests/cpp/test_verification.py +189 -0
- dev/tests/cpp/test_yielding.py +225 -0
- dev/tests/csharp/__init__.py +0 -0
- dev/tests/csharp/live_test_main.py +109 -0
- dev/tests/csharp/test_common.py +28 -0
- dev/tests/csharp/test_description.py +684 -0
- dev/tests/csharp/test_main.py +129 -0
- dev/tests/csharp/test_structure.py +93 -0
- dev/tests/csharp/test_verification.py +82 -0
- dev/tests/description.py +29 -0
- dev/tests/golang/__init__.py +0 -0
- dev/tests/golang/test_common.py +78 -0
- dev/tests/golang/test_main.py +128 -0
- dev/tests/infer_for_schema/__init__.py +0 -0
- dev/tests/infer_for_schema/common.py +47 -0
- dev/tests/infer_for_schema/test_len_on_properties.py +955 -0
- dev/tests/infer_for_schema/test_len_on_self.py +580 -0
- dev/tests/infer_for_schema/test_patterns_on_properties.py +686 -0
- dev/tests/infer_for_schema/test_patterns_on_self.py +258 -0
- dev/tests/infer_for_schema/test_property_in_set_of_enumeration_literals.py +600 -0
- dev/tests/infer_for_schema/test_property_in_set_of_primitives.py +549 -0
- dev/tests/intermediate/__init__.py +0 -0
- dev/tests/intermediate/test_constructor.py +719 -0
- dev/tests/intermediate/test_hierarchy.py +221 -0
- dev/tests/intermediate/test_revm.py +134 -0
- dev/tests/intermediate/test_translate.py +337 -0
- dev/tests/intermediate/test_type_inference.py +333 -0
- dev/tests/intermediate/test_types.py +169 -0
- dev/tests/java/__init__.py +0 -0
- dev/tests/java/test_common.py +20 -0
- dev/tests/java/test_description.py +128 -0
- dev/tests/java/test_main.py +234 -0
- dev/tests/jsonld_context/test_main.py +79 -0
- dev/tests/opcua/__init__.py +3 -0
- dev/tests/opcua/test_main.py +110 -0
- dev/tests/our_jsonschema/__init__.py +3 -0
- dev/tests/our_jsonschema/test_main.py +232 -0
- dev/tests/parse/__init__.py +0 -0
- dev/tests/parse/test_parse.py +503 -0
- dev/tests/parse/test_retree.py +272 -0
- dev/tests/proto/__init__.py +0 -0
- dev/tests/proto/test_main.py +112 -0
- dev/tests/python/__init__.py +0 -0
- dev/tests/python/test_common.py +124 -0
- dev/tests/python/test_main.py +126 -0
- dev/tests/python/test_xml_playground.py +254 -0
- dev/tests/python_protobuf/__init__.py +0 -0
- dev/tests/python_protobuf/test_main.py +111 -0
- dev/tests/rdf_shacl/__init__.py +0 -0
- dev/tests/rdf_shacl/test_common.py +32 -0
- dev/tests/rdf_shacl/test_description.py +223 -0
- dev/tests/rdf_shacl/test_main.py +194 -0
- dev/tests/smoke/__init__.py +0 -0
- dev/tests/smoke/test_main.py +83 -0
- dev/tests/test_common.py +94 -0
- dev/tests/typescript/__init__.py +0 -0
- dev/tests/typescript/test_common.py +108 -0
- dev/tests/typescript/test_main.py +125 -0
- dev/tests/xsd/__init__.py +0 -0
- dev/tests/xsd/test_main.py +227 -0
- dev/tests/yielding/__init__.py +0 -0
- dev/tests/yielding/test_linear.py +558 -0
|
@@ -0,0 +1,1143 @@
|
|
|
1
|
+
"""Parse a regular expression defined over a possibly-formatted string."""
|
|
2
|
+
import collections.abc
|
|
3
|
+
import io
|
|
4
|
+
import math
|
|
5
|
+
import re
|
|
6
|
+
from typing import Tuple, Optional, List, Sequence, Union, MutableMapping
|
|
7
|
+
|
|
8
|
+
from icontract import invariant, require, ensure, snapshot
|
|
9
|
+
|
|
10
|
+
from aas_core_codegen.common import pairwise
|
|
11
|
+
from aas_core_codegen.parse.retree._types import (
|
|
12
|
+
Char,
|
|
13
|
+
Range,
|
|
14
|
+
Concatenation,
|
|
15
|
+
Symbol,
|
|
16
|
+
Group,
|
|
17
|
+
CharSet,
|
|
18
|
+
Quantifier,
|
|
19
|
+
Term,
|
|
20
|
+
UnionExpr,
|
|
21
|
+
Regex,
|
|
22
|
+
TermValueUnion,
|
|
23
|
+
SymbolKind,
|
|
24
|
+
)
|
|
25
|
+
from aas_core_codegen.parse.tree import FormattedValue
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# fmt: off
|
|
29
|
+
@invariant(
|
|
30
|
+
lambda self:
|
|
31
|
+
(
|
|
32
|
+
not self.done()
|
|
33
|
+
^ (
|
|
34
|
+
self.major_cursor == len(self.values)
|
|
35
|
+
or (
|
|
36
|
+
self.major_cursor == len(self.values) - 1
|
|
37
|
+
and isinstance(self.pointed_value(), str)
|
|
38
|
+
and self.minor_cursor == len(self.pointed_value())
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
),
|
|
42
|
+
"We are done iff we reached the end of values with the major cursor or "
|
|
43
|
+
"the end of the last pointed value as string"
|
|
44
|
+
)
|
|
45
|
+
@invariant(
|
|
46
|
+
lambda self:
|
|
47
|
+
not isinstance(self.pointed_value(), str)
|
|
48
|
+
or (0 <= self.minor_cursor <= len(self.pointed_value())),
|
|
49
|
+
"Minor cursor is within the expected range if the pointed value is a string"
|
|
50
|
+
)
|
|
51
|
+
@invariant(
|
|
52
|
+
lambda self:
|
|
53
|
+
not (not isinstance(self.pointed_value(), str))
|
|
54
|
+
or (self.minor_cursor is None),
|
|
55
|
+
"Minor cursor is invalidated if the pointed value is not a string"
|
|
56
|
+
)
|
|
57
|
+
@invariant(
|
|
58
|
+
lambda self:
|
|
59
|
+
(
|
|
60
|
+
not (self.major_cursor == len(self.values))
|
|
61
|
+
or self.pointed_value() is None
|
|
62
|
+
),
|
|
63
|
+
"No pointed value if we reached the end of the values"
|
|
64
|
+
)
|
|
65
|
+
@invariant(
|
|
66
|
+
lambda self:
|
|
67
|
+
(
|
|
68
|
+
not (0 <= self.major_cursor < len(self.values))
|
|
69
|
+
or self.pointed_value() is not None
|
|
70
|
+
),
|
|
71
|
+
"A value must be pointed at if we did not reach the end of the values"
|
|
72
|
+
)
|
|
73
|
+
@invariant(
|
|
74
|
+
lambda self:
|
|
75
|
+
0 <= self.major_cursor <= len(self.values),
|
|
76
|
+
"Major cursor is within the expected range"
|
|
77
|
+
)
|
|
78
|
+
# fmt: on
|
|
79
|
+
class Cursor:
|
|
80
|
+
"""Manage the iteration over the input stream."""
|
|
81
|
+
|
|
82
|
+
# fmt: off
|
|
83
|
+
@require(
|
|
84
|
+
lambda values:
|
|
85
|
+
not (len(values) > 1)
|
|
86
|
+
or not any(
|
|
87
|
+
(
|
|
88
|
+
isinstance(first, str)
|
|
89
|
+
and isinstance(second, str)
|
|
90
|
+
)
|
|
91
|
+
for first, second in zip(values, values[1:])
|
|
92
|
+
),
|
|
93
|
+
"No consecutive strings expected in the parsed sequence of an AST expression "
|
|
94
|
+
"representing a string interpolation"
|
|
95
|
+
)
|
|
96
|
+
# NOTE (mristin, 2024-05-08):
|
|
97
|
+
# We add a runtime test here since it already happened that we supplied ``values``
|
|
98
|
+
# as a string during development, causing an unnecessary long debugging session.
|
|
99
|
+
@require(
|
|
100
|
+
lambda values:
|
|
101
|
+
isinstance(values, collections.abc.Sequence),
|
|
102
|
+
"values must be a sequence"
|
|
103
|
+
)
|
|
104
|
+
# fmt: on
|
|
105
|
+
def __init__(self, values: Sequence[Union[str, FormattedValue]]) -> None:
|
|
106
|
+
"""Initialize with the given values."""
|
|
107
|
+
self.values = values
|
|
108
|
+
|
|
109
|
+
# Major cursor points within the values
|
|
110
|
+
self._major_cursor = 0
|
|
111
|
+
|
|
112
|
+
# Minor cursor points within a value
|
|
113
|
+
self._minor_cursor: Optional[int] = None
|
|
114
|
+
if isinstance(self.pointed_value(), str):
|
|
115
|
+
self._minor_cursor = 0
|
|
116
|
+
|
|
117
|
+
def copy(self) -> "Cursor":
|
|
118
|
+
"""Make a deep copy of the cursor."""
|
|
119
|
+
return Cursor(values=self.values)
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def major_cursor(self) -> int:
|
|
123
|
+
"""Return the current cursor in the :attr:`~values`."""
|
|
124
|
+
return self._major_cursor
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def minor_cursor(self) -> Optional[int]:
|
|
128
|
+
"""
|
|
129
|
+
Return the current cursor in the :attr:`~pointed_value`.
|
|
130
|
+
|
|
131
|
+
If the :attr:`~pointed_value` is not a string, return ``None``.
|
|
132
|
+
"""
|
|
133
|
+
if not isinstance(self.pointed_value(), str):
|
|
134
|
+
return None
|
|
135
|
+
|
|
136
|
+
return self._minor_cursor
|
|
137
|
+
|
|
138
|
+
def pointed_value(self) -> Optional[Union[str, FormattedValue]]:
|
|
139
|
+
"""Return the value pointed by the :attr:`~major_cursor`."""
|
|
140
|
+
if self._major_cursor >= len(self.values):
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
return self.values[self._major_cursor]
|
|
144
|
+
|
|
145
|
+
def _move_major_cursor(self) -> None:
|
|
146
|
+
"""
|
|
147
|
+
Move the major cursor to the next value.
|
|
148
|
+
|
|
149
|
+
The minor cursor is also updated accordingly, depending on the pointed value.
|
|
150
|
+
"""
|
|
151
|
+
if not self.done():
|
|
152
|
+
self._major_cursor += 1
|
|
153
|
+
|
|
154
|
+
self._minor_cursor = 0 if isinstance(self.pointed_value(), str) else None
|
|
155
|
+
|
|
156
|
+
@require(lambda jump_length: jump_length >= 0)
|
|
157
|
+
@require(
|
|
158
|
+
lambda self: not (not self.done())
|
|
159
|
+
or (self._minor_cursor is not None and isinstance(self.pointed_value(), str)),
|
|
160
|
+
"If we are not done, we should only move within a string value",
|
|
161
|
+
)
|
|
162
|
+
def _move_minor_cursor(self, jump_length: int) -> None:
|
|
163
|
+
"""
|
|
164
|
+
Move the minor cursor within a string value for ``jump_length`` positions.
|
|
165
|
+
|
|
166
|
+
If we reached the end of value, move to the next value.
|
|
167
|
+
"""
|
|
168
|
+
if self.done():
|
|
169
|
+
return
|
|
170
|
+
|
|
171
|
+
assert self._minor_cursor is not None
|
|
172
|
+
|
|
173
|
+
pointed_value = self.pointed_value()
|
|
174
|
+
assert pointed_value is not None
|
|
175
|
+
assert isinstance(pointed_value, str)
|
|
176
|
+
|
|
177
|
+
if self._minor_cursor + jump_length >= len(pointed_value):
|
|
178
|
+
self._move_major_cursor()
|
|
179
|
+
else:
|
|
180
|
+
self._minor_cursor += jump_length
|
|
181
|
+
|
|
182
|
+
def done(self) -> bool:
|
|
183
|
+
"""Signal that we reached the end of the :attr:`~values`."""
|
|
184
|
+
if self._major_cursor >= len(self.values):
|
|
185
|
+
return True
|
|
186
|
+
|
|
187
|
+
pointed_value = self.pointed_value()
|
|
188
|
+
if isinstance(pointed_value, str):
|
|
189
|
+
assert self._minor_cursor is not None
|
|
190
|
+
return self._minor_cursor >= len(pointed_value)
|
|
191
|
+
else:
|
|
192
|
+
assert self._minor_cursor is None
|
|
193
|
+
return False
|
|
194
|
+
|
|
195
|
+
def try_formatted_value(self) -> Optional[FormattedValue]:
|
|
196
|
+
"""
|
|
197
|
+
Try to read the formatted value at the current cursor and return it.
|
|
198
|
+
|
|
199
|
+
Otherwise, if no formatted value is present, return ``None``.
|
|
200
|
+
"""
|
|
201
|
+
value = self.pointed_value()
|
|
202
|
+
if isinstance(value, FormattedValue):
|
|
203
|
+
self._move_major_cursor()
|
|
204
|
+
return value
|
|
205
|
+
|
|
206
|
+
return None
|
|
207
|
+
|
|
208
|
+
def try_positive_integer_without_sign(self) -> Optional[int]:
|
|
209
|
+
"""
|
|
210
|
+
Try to read an integer and move the cursor accordingly.
|
|
211
|
+
|
|
212
|
+
An integer can be prefixed by a zero (*e.g.*, ``000123``). No sign is expected
|
|
213
|
+
as a prefix.
|
|
214
|
+
|
|
215
|
+
Otherwise, if there is no integer at the cursor, return ``None`` and do not
|
|
216
|
+
move the cursor.
|
|
217
|
+
"""
|
|
218
|
+
pointed_value = self.pointed_value()
|
|
219
|
+
if isinstance(pointed_value, FormattedValue):
|
|
220
|
+
return None
|
|
221
|
+
|
|
222
|
+
if self.minor_cursor is None:
|
|
223
|
+
return None
|
|
224
|
+
|
|
225
|
+
assert isinstance(pointed_value, str)
|
|
226
|
+
accumulator = [] # type: List[str]
|
|
227
|
+
for i in range(self.minor_cursor, len(pointed_value)):
|
|
228
|
+
if pointed_value[i].isdigit():
|
|
229
|
+
accumulator.append(pointed_value[i])
|
|
230
|
+
else:
|
|
231
|
+
break
|
|
232
|
+
|
|
233
|
+
if len(accumulator) > 0:
|
|
234
|
+
self._move_minor_cursor(jump_length=len(accumulator))
|
|
235
|
+
return int("".join(accumulator))
|
|
236
|
+
|
|
237
|
+
return None
|
|
238
|
+
|
|
239
|
+
@snapshot(lambda self, literal: self.peek_literal(literal), "peeked")
|
|
240
|
+
@ensure(
|
|
241
|
+
lambda result, OLD: (result and OLD.peeked) or (not result and not OLD.peeked),
|
|
242
|
+
"If we matched the literal, we should have been able to successfully peek it "
|
|
243
|
+
"before moving the cursor, and vice-versa.",
|
|
244
|
+
)
|
|
245
|
+
def try_literal(self, literal: str) -> bool:
|
|
246
|
+
"""
|
|
247
|
+
Try to match the ``literal``, return ``True`` and move the cursor accordingly.
|
|
248
|
+
|
|
249
|
+
If the ``literal`` could not be matched, return ``False`` and do not move the
|
|
250
|
+
cursor.
|
|
251
|
+
"""
|
|
252
|
+
result = self.peek_literal(literal=literal)
|
|
253
|
+
|
|
254
|
+
if result:
|
|
255
|
+
self._move_minor_cursor(jump_length=len(literal))
|
|
256
|
+
|
|
257
|
+
return result
|
|
258
|
+
|
|
259
|
+
def peek_literal(self, literal: str) -> bool:
|
|
260
|
+
"""
|
|
261
|
+
Try to match the ``literal``.
|
|
262
|
+
|
|
263
|
+
Do not move the cursor.
|
|
264
|
+
"""
|
|
265
|
+
pointed_value = self.pointed_value()
|
|
266
|
+
if not isinstance(pointed_value, str):
|
|
267
|
+
return False
|
|
268
|
+
|
|
269
|
+
assert self.minor_cursor is not None
|
|
270
|
+
if len(pointed_value) < self.minor_cursor + len(literal):
|
|
271
|
+
return False
|
|
272
|
+
|
|
273
|
+
result = (
|
|
274
|
+
pointed_value[self.minor_cursor : (self.minor_cursor + len(literal))]
|
|
275
|
+
== literal
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
return result
|
|
279
|
+
|
|
280
|
+
def peek_substring(self, length: int) -> Optional[str]:
|
|
281
|
+
"""
|
|
282
|
+
Try to read a substring of ``length`` characters.
|
|
283
|
+
|
|
284
|
+
If the remainder of the stream contains less than ``length`` characters,
|
|
285
|
+
return ``None``, or the pointed value is not a string, return ``None``.
|
|
286
|
+
|
|
287
|
+
Do not move the cursor.
|
|
288
|
+
"""
|
|
289
|
+
pointed_value = self.pointed_value()
|
|
290
|
+
if not isinstance(pointed_value, str):
|
|
291
|
+
return None
|
|
292
|
+
|
|
293
|
+
assert self.minor_cursor is not None
|
|
294
|
+
if len(pointed_value) < self.minor_cursor + length:
|
|
295
|
+
return None
|
|
296
|
+
|
|
297
|
+
return pointed_value[self.minor_cursor : (self.minor_cursor + length)]
|
|
298
|
+
|
|
299
|
+
def try_substring(self, length: int) -> Optional[str]:
|
|
300
|
+
"""
|
|
301
|
+
Try to read a substring of ``length`` characters and move the cursor.
|
|
302
|
+
|
|
303
|
+
If the remainder of the stream contains less than ``length`` characters,
|
|
304
|
+
or the pointed value is not a string, return ``None`` and
|
|
305
|
+
do not move the cursor.
|
|
306
|
+
"""
|
|
307
|
+
result = self.peek_substring(length=length)
|
|
308
|
+
if result is None:
|
|
309
|
+
return None
|
|
310
|
+
|
|
311
|
+
self._move_minor_cursor(jump_length=length)
|
|
312
|
+
|
|
313
|
+
return result
|
|
314
|
+
|
|
315
|
+
def try_spaces_or_tabs(self) -> bool:
|
|
316
|
+
"""
|
|
317
|
+
Try to read spaces (``" "``) and tabs (``"\t"``) from the stream.
|
|
318
|
+
|
|
319
|
+
If the spaces are found, move the cursor and return ``True``.
|
|
320
|
+
|
|
321
|
+
If no spaces are found at the cursor, return ``False`` and do not move
|
|
322
|
+
the cursor.
|
|
323
|
+
"""
|
|
324
|
+
found_tab_or_space = False
|
|
325
|
+
while True:
|
|
326
|
+
if self.try_literal(" "):
|
|
327
|
+
found_tab_or_space = True
|
|
328
|
+
elif self.try_literal("\t"):
|
|
329
|
+
found_tab_or_space = True
|
|
330
|
+
else:
|
|
331
|
+
break
|
|
332
|
+
|
|
333
|
+
return found_tab_or_space
|
|
334
|
+
|
|
335
|
+
# fmt: off
|
|
336
|
+
@require(
|
|
337
|
+
lambda other, self:
|
|
338
|
+
id(other.values) == id(self.values),
|
|
339
|
+
"This and the other cursor must point to the same values"
|
|
340
|
+
)
|
|
341
|
+
# fmt: on
|
|
342
|
+
def has_same_position(self, other: "Cursor") -> bool:
|
|
343
|
+
"""Check whether the ``other`` cursor points to the same position."""
|
|
344
|
+
return (self.done() and other.done()) or (
|
|
345
|
+
self.major_cursor == other.major_cursor
|
|
346
|
+
and self.minor_cursor == other.minor_cursor
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
# fmt: off
|
|
350
|
+
@require(
|
|
351
|
+
lambda other, self:
|
|
352
|
+
id(other.values) == id(self.values),
|
|
353
|
+
"This and the other cursor must point to the same values"
|
|
354
|
+
)
|
|
355
|
+
@ensure(
|
|
356
|
+
lambda other, self, result:
|
|
357
|
+
not (self.has_same_position(other))
|
|
358
|
+
or (not result)
|
|
359
|
+
)
|
|
360
|
+
# fmt: on
|
|
361
|
+
def is_before(self, other: "Cursor") -> bool:
|
|
362
|
+
"""Check whether this cursor is pointing before the ``other`` cursor."""
|
|
363
|
+
if self.done() and other.done():
|
|
364
|
+
return False
|
|
365
|
+
elif self.done() and not other.done():
|
|
366
|
+
return False
|
|
367
|
+
elif not self.done() and other.done():
|
|
368
|
+
return True
|
|
369
|
+
else:
|
|
370
|
+
assert self.major_cursor is not None
|
|
371
|
+
assert other.major_cursor is not None
|
|
372
|
+
|
|
373
|
+
if self.major_cursor < other.major_cursor:
|
|
374
|
+
return True
|
|
375
|
+
elif self.major_cursor > other.major_cursor:
|
|
376
|
+
return False
|
|
377
|
+
else:
|
|
378
|
+
if self.minor_cursor is None and other.minor_cursor is None:
|
|
379
|
+
# NOTE (mristin, 2022-06-02):
|
|
380
|
+
# Both major cursors point to the formatted value, so they
|
|
381
|
+
# point to the same position.
|
|
382
|
+
assert isinstance(self.pointed_value(), FormattedValue)
|
|
383
|
+
assert isinstance(other.pointed_value(), FormattedValue)
|
|
384
|
+
return False
|
|
385
|
+
else:
|
|
386
|
+
# NOTE (mristin, 2022-06-02):
|
|
387
|
+
# If one minor cursor is not None, it means the major cursors
|
|
388
|
+
# point to a string.
|
|
389
|
+
assert isinstance(self.pointed_value(), str)
|
|
390
|
+
assert isinstance(other.pointed_value(), str)
|
|
391
|
+
|
|
392
|
+
assert self.minor_cursor is not None
|
|
393
|
+
assert other.minor_cursor is not None
|
|
394
|
+
return self.minor_cursor < other.minor_cursor
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
class Error:
|
|
398
|
+
"""Represent an error occurring during the parsing of a regular expression."""
|
|
399
|
+
|
|
400
|
+
def __init__(self, message: str, cursor: Cursor) -> None:
|
|
401
|
+
"""Initialize with the given values."""
|
|
402
|
+
self.message = message
|
|
403
|
+
self.cursor = cursor
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
_UNEXPECTED_CHARACTERS_IN_REGEX_RE = re.compile("[\\n\\f\\v\\r]")
|
|
407
|
+
_WHITESPACE_RE = re.compile("\\s")
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
@require(lambda cursor: len(cursor.values) > 0)
|
|
411
|
+
@ensure(lambda result: len(result[0]) > 0 and len(result[1]) > 0)
|
|
412
|
+
@ensure(lambda result: result[1].endswith("^"))
|
|
413
|
+
def render_pointer(cursor: Cursor) -> Tuple[str, str]:
|
|
414
|
+
"""Render the regular expression and the pointer corresponding to the cursor."""
|
|
415
|
+
regex_writer = io.StringIO()
|
|
416
|
+
pointer_writer = io.StringIO()
|
|
417
|
+
|
|
418
|
+
@require(lambda text: not _UNEXPECTED_CHARACTERS_IN_REGEX_RE.search(text))
|
|
419
|
+
def write_text(text: str, draw_pointer: bool) -> None:
|
|
420
|
+
"""
|
|
421
|
+
Output the ``text``.
|
|
422
|
+
|
|
423
|
+
We write the ``text`` to the ``regex_writer``. Depending on ``draw_pointer``,
|
|
424
|
+
we either write the corresponding whitespace to ``pointer_writer``
|
|
425
|
+
(if ``False``) or draw a pointer (``^``).
|
|
426
|
+
"""
|
|
427
|
+
if not draw_pointer:
|
|
428
|
+
for character in text:
|
|
429
|
+
regex_writer.write(character)
|
|
430
|
+
|
|
431
|
+
if _WHITESPACE_RE.fullmatch(character):
|
|
432
|
+
pointer_writer.write(character)
|
|
433
|
+
else:
|
|
434
|
+
pointer_writer.write(" ")
|
|
435
|
+
else:
|
|
436
|
+
regex_writer.write(text)
|
|
437
|
+
pointer_writer.write("^")
|
|
438
|
+
|
|
439
|
+
a_cursor = Cursor(values=cursor.values)
|
|
440
|
+
while True:
|
|
441
|
+
if a_cursor.done():
|
|
442
|
+
assert a_cursor.has_same_position(cursor)
|
|
443
|
+
pointer_writer.write("^")
|
|
444
|
+
break
|
|
445
|
+
|
|
446
|
+
has_same_position = a_cursor.has_same_position(cursor)
|
|
447
|
+
|
|
448
|
+
formatted_value = a_cursor.try_formatted_value()
|
|
449
|
+
if formatted_value:
|
|
450
|
+
# NOTE (mristin, 2022-06-09):
|
|
451
|
+
# The asttokens can not get the text of the formatted values,
|
|
452
|
+
# see: https://github.com/gristlabs/asttokens/issues/6.
|
|
453
|
+
write_text(text="<formatted value>", draw_pointer=has_same_position)
|
|
454
|
+
else:
|
|
455
|
+
substring = a_cursor.try_substring(length=1)
|
|
456
|
+
assert substring is not None, (
|
|
457
|
+
f"We explicitly checked for a_cursor "
|
|
458
|
+
f"not done and not a formatted value, but got no substring: "
|
|
459
|
+
f"{a_cursor.pointed_value()=}, {a_cursor.major_cursor=}, "
|
|
460
|
+
f"{a_cursor.minor_cursor=}"
|
|
461
|
+
)
|
|
462
|
+
write_text(text=substring, draw_pointer=has_same_position)
|
|
463
|
+
|
|
464
|
+
if has_same_position:
|
|
465
|
+
break
|
|
466
|
+
|
|
467
|
+
# NOTE (mristin, 2022-06-09):
|
|
468
|
+
# Write the remainder of the regular expression
|
|
469
|
+
while not a_cursor.done():
|
|
470
|
+
formatted_value = a_cursor.try_formatted_value()
|
|
471
|
+
if formatted_value:
|
|
472
|
+
# NOTE (mristin, 2022-06-09):
|
|
473
|
+
# The asttokens can not get the text of the formatted values,
|
|
474
|
+
# see: https://github.com/gristlabs/asttokens/issues/6.
|
|
475
|
+
regex_writer.write("<formatted value>")
|
|
476
|
+
else:
|
|
477
|
+
substring = a_cursor.try_substring(length=1)
|
|
478
|
+
assert substring is not None, (
|
|
479
|
+
f"We explicitly checked for a_cursor "
|
|
480
|
+
f"not done and not a formatted value, but got no substring: "
|
|
481
|
+
f"{a_cursor.pointed_value()=}, {a_cursor.major_cursor=}, "
|
|
482
|
+
f"{a_cursor.minor_cursor=}"
|
|
483
|
+
)
|
|
484
|
+
regex_writer.write(substring)
|
|
485
|
+
|
|
486
|
+
return regex_writer.getvalue(), pointer_writer.getvalue()
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
# fmt: off
|
|
490
|
+
# noinspection RegExpSimplifiable
|
|
491
|
+
@require(
|
|
492
|
+
lambda cursor: not cursor.peek_literal("-"),
|
|
493
|
+
"The dash (``-``) handled before, outside of this function"
|
|
494
|
+
)
|
|
495
|
+
@require(
|
|
496
|
+
lambda cursor: not cursor.done(),
|
|
497
|
+
"End of input handled before, outside of this function"
|
|
498
|
+
)
|
|
499
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
500
|
+
# fmt: on
|
|
501
|
+
def _parse_range_char(cursor: Cursor) -> Tuple[Optional[Char], Optional[Error]]:
|
|
502
|
+
"""Try to parse a character in the range of a character set."""
|
|
503
|
+
if cursor.try_literal("\\x"):
|
|
504
|
+
substring = cursor.try_substring(length=2)
|
|
505
|
+
if substring is None:
|
|
506
|
+
return None, Error("Expected two hexadecimal digits after \\x", cursor)
|
|
507
|
+
|
|
508
|
+
# noinspection RegExpSimplifiable
|
|
509
|
+
if not re.fullmatch(r"[a-fA-F0-9]{2}", substring):
|
|
510
|
+
return None, Error(
|
|
511
|
+
f"Expected two hexadecimal digits after \\x, but got {substring!r}",
|
|
512
|
+
cursor,
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
result = Char(character=chr(int(substring, 16)), explicitly_encoded=True)
|
|
516
|
+
|
|
517
|
+
elif cursor.try_literal("\\u"):
|
|
518
|
+
substring = cursor.try_substring(length=4)
|
|
519
|
+
if substring is None:
|
|
520
|
+
return None, Error("Expected four hexadecimal digits after \\u", cursor)
|
|
521
|
+
|
|
522
|
+
if not re.fullmatch(r"[a-fA-F0-9]{4}", substring):
|
|
523
|
+
return None, Error(
|
|
524
|
+
f"Expected four hexadecimal digits after \\u, "
|
|
525
|
+
f"but got {substring!r}",
|
|
526
|
+
cursor,
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
result = Char(character=chr(int(substring, 16)), explicitly_encoded=True)
|
|
530
|
+
|
|
531
|
+
elif cursor.try_literal("\\U"):
|
|
532
|
+
substring = cursor.try_substring(length=8)
|
|
533
|
+
if substring is None:
|
|
534
|
+
return None, Error("Expected eight hexadecimal digits after \\U", cursor)
|
|
535
|
+
|
|
536
|
+
if not re.fullmatch(r"[a-fA-F0-9]{8}", substring):
|
|
537
|
+
return None, Error(
|
|
538
|
+
f"Expected eight hexadecimal digits after \\U, "
|
|
539
|
+
f"but got {substring!r}",
|
|
540
|
+
cursor,
|
|
541
|
+
)
|
|
542
|
+
|
|
543
|
+
code = int(substring, 16)
|
|
544
|
+
if code < 0x00010000 or code > 0x0010FFFF:
|
|
545
|
+
# noinspection SpellCheckingInspection
|
|
546
|
+
return None, Error(
|
|
547
|
+
f"Expected the character code in the range \\U00010000-\\U0010FFFF, "
|
|
548
|
+
f"but got \\U{code:08x}; "
|
|
549
|
+
f"the code can not be represented with high/low surrogates in UTF-16",
|
|
550
|
+
cursor,
|
|
551
|
+
)
|
|
552
|
+
|
|
553
|
+
result = Char(character=chr(code), explicitly_encoded=True)
|
|
554
|
+
elif cursor.try_literal("\\t"):
|
|
555
|
+
result = Char(character="\t")
|
|
556
|
+
|
|
557
|
+
elif cursor.try_literal("\\n"):
|
|
558
|
+
result = Char(character="\n")
|
|
559
|
+
|
|
560
|
+
elif cursor.try_literal("\\r"):
|
|
561
|
+
result = Char(character="\r")
|
|
562
|
+
|
|
563
|
+
elif cursor.try_literal("\\f"):
|
|
564
|
+
result = Char(character="\f")
|
|
565
|
+
|
|
566
|
+
elif cursor.try_literal("\\v"):
|
|
567
|
+
result = Char(character="\v")
|
|
568
|
+
|
|
569
|
+
elif cursor.try_literal("\\\\"):
|
|
570
|
+
result = Char(character="\\")
|
|
571
|
+
|
|
572
|
+
elif cursor.try_literal("\\["):
|
|
573
|
+
result = Char(character="[")
|
|
574
|
+
|
|
575
|
+
elif cursor.try_literal("\\]"):
|
|
576
|
+
result = Char(character="]")
|
|
577
|
+
|
|
578
|
+
elif cursor.try_literal("\\^"):
|
|
579
|
+
result = Char(character="^")
|
|
580
|
+
|
|
581
|
+
elif cursor.try_literal("\\-"):
|
|
582
|
+
result = Char(character="-")
|
|
583
|
+
|
|
584
|
+
elif cursor.try_literal("\\s") or cursor.try_literal("\\S"):
|
|
585
|
+
return None, Error(
|
|
586
|
+
"We do not handle whitespace escaping at the moment (2022-06-09), "
|
|
587
|
+
"as the notion of a whitespace depends on the regex engine",
|
|
588
|
+
cursor,
|
|
589
|
+
)
|
|
590
|
+
|
|
591
|
+
elif cursor.try_literal("\\d") or cursor.try_literal("\\D"):
|
|
592
|
+
return None, Error(
|
|
593
|
+
"We do not handle digit escaping at the moment (2022-06-09), "
|
|
594
|
+
"as the notion of a digit depends on the regex engine",
|
|
595
|
+
cursor,
|
|
596
|
+
)
|
|
597
|
+
|
|
598
|
+
elif cursor.try_literal("\\"):
|
|
599
|
+
return None, Error("Unexpected escaping", cursor)
|
|
600
|
+
|
|
601
|
+
else:
|
|
602
|
+
character = cursor.try_substring(length=1)
|
|
603
|
+
assert character is not None, (
|
|
604
|
+
"Expected to read at least one character since we explicitly checked "
|
|
605
|
+
"that the cursor is not done before"
|
|
606
|
+
)
|
|
607
|
+
result = Char(character=character)
|
|
608
|
+
|
|
609
|
+
assert result is not None
|
|
610
|
+
return result, None
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
614
|
+
def _parse_ranges_and_closing(
|
|
615
|
+
cursor: Cursor,
|
|
616
|
+
) -> Tuple[Optional[List[Range]], Optional[Error]]:
|
|
617
|
+
# noinspection GrazieInspection
|
|
618
|
+
"""Parse one or more ranges in a character set and the closing ``]``."""
|
|
619
|
+
ranges = [] # type: List[Range]
|
|
620
|
+
|
|
621
|
+
# Prefix dash is allowed and should be considered as a character.
|
|
622
|
+
if cursor.try_literal("-"):
|
|
623
|
+
ranges.append(Range(start=Char("-"), end=None))
|
|
624
|
+
|
|
625
|
+
cursor_by_range = dict() # type: MutableMapping[Range, Cursor]
|
|
626
|
+
|
|
627
|
+
while True:
|
|
628
|
+
if cursor.done():
|
|
629
|
+
return None, Error(
|
|
630
|
+
"Expected a closing bracket for the character set (``]``), "
|
|
631
|
+
"but reached the end of input.",
|
|
632
|
+
cursor,
|
|
633
|
+
)
|
|
634
|
+
|
|
635
|
+
cursor_at_start = cursor.copy()
|
|
636
|
+
|
|
637
|
+
# NOTE (mristin, 2022-06-08):
|
|
638
|
+
# A suffix dash is also allowed and should be considered a single character.
|
|
639
|
+
if cursor.try_literal("-]"):
|
|
640
|
+
the_range = Range(start=Char("-"), end=None)
|
|
641
|
+
cursor_by_range[the_range] = cursor_at_start
|
|
642
|
+
ranges.append(the_range)
|
|
643
|
+
break
|
|
644
|
+
elif cursor.try_literal("]"):
|
|
645
|
+
break
|
|
646
|
+
else:
|
|
647
|
+
start, error = _parse_range_char(cursor)
|
|
648
|
+
if error is not None:
|
|
649
|
+
return None, error
|
|
650
|
+
assert start is not None
|
|
651
|
+
|
|
652
|
+
end = None # type: Optional[Char]
|
|
653
|
+
if not cursor.peek_literal("-]"):
|
|
654
|
+
if cursor.try_literal("-"):
|
|
655
|
+
if cursor.try_literal("-"):
|
|
656
|
+
return None, Error(
|
|
657
|
+
"Unexpected double ``-`` in the character set", cursor
|
|
658
|
+
)
|
|
659
|
+
|
|
660
|
+
end, error = _parse_range_char(cursor)
|
|
661
|
+
if error is not None:
|
|
662
|
+
return None, error
|
|
663
|
+
assert end is not None
|
|
664
|
+
|
|
665
|
+
if end is not None and ord(start.character) > ord(end.character):
|
|
666
|
+
return None, Error(
|
|
667
|
+
"Invalid character range, start is smaller than end", cursor
|
|
668
|
+
)
|
|
669
|
+
|
|
670
|
+
the_range = Range(start=start, end=end)
|
|
671
|
+
cursor_by_range[the_range] = cursor_at_start
|
|
672
|
+
ranges.append(the_range)
|
|
673
|
+
|
|
674
|
+
for this_range, next_range in pairwise(
|
|
675
|
+
sorted(ranges, key=lambda rng: ord(rng.start.character))
|
|
676
|
+
):
|
|
677
|
+
this_end = this_range.end if this_range.end is not None else this_range.start
|
|
678
|
+
|
|
679
|
+
next_start = next_range.start
|
|
680
|
+
|
|
681
|
+
if ord(this_end.character) >= ord(next_start.character):
|
|
682
|
+
this_range_str = (
|
|
683
|
+
f"{this_range.start.character!r}"
|
|
684
|
+
if this_range.end is None
|
|
685
|
+
else f"{this_range.start.character!r}-{this_range.end.character!r}"
|
|
686
|
+
)
|
|
687
|
+
|
|
688
|
+
next_range_str = (
|
|
689
|
+
f"{next_range.start.character!r}"
|
|
690
|
+
if next_range.end is None
|
|
691
|
+
else f"{next_range.start.character!r}-{next_range.end.character!r}"
|
|
692
|
+
)
|
|
693
|
+
|
|
694
|
+
return None, Error(
|
|
695
|
+
f"The range {this_range_str} and the range {next_range_str} overlap",
|
|
696
|
+
cursor_by_range[this_range],
|
|
697
|
+
)
|
|
698
|
+
|
|
699
|
+
return ranges, None
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
# noinspection RegExpSimplifiable
|
|
703
|
+
def _parse_char_literal(cursor: Cursor) -> Tuple[Optional[Char], Optional[Error]]:
|
|
704
|
+
"""
|
|
705
|
+
Parse a character literal in a concatenation.
|
|
706
|
+
|
|
707
|
+
It might be that no character could be parsed, but that the stream is still valid.
|
|
708
|
+
For example, if there is a quantifier (such as ``*``, ``+`` or ``?``) following
|
|
709
|
+
a literal. In those cases, return ``None`` and no error.
|
|
710
|
+
"""
|
|
711
|
+
if cursor.done():
|
|
712
|
+
return None, None
|
|
713
|
+
|
|
714
|
+
result: Char
|
|
715
|
+
|
|
716
|
+
if cursor.try_literal("\\x"):
|
|
717
|
+
substring = cursor.try_substring(length=2)
|
|
718
|
+
if substring is None:
|
|
719
|
+
return None, Error("Expected two hexadecimal digits after \\x", cursor)
|
|
720
|
+
|
|
721
|
+
if not re.fullmatch(r"[a-fA-F0-9]{2}", substring):
|
|
722
|
+
return None, Error(
|
|
723
|
+
f"Expected two hexadecimal digits after \\x, but got {substring!r}",
|
|
724
|
+
cursor,
|
|
725
|
+
)
|
|
726
|
+
|
|
727
|
+
result = Char(character=chr(int(substring, 16)), explicitly_encoded=True)
|
|
728
|
+
|
|
729
|
+
elif cursor.try_literal("\\u"):
|
|
730
|
+
substring = cursor.try_substring(length=4)
|
|
731
|
+
if substring is None:
|
|
732
|
+
return None, Error("Expected four hexadecimal digits after \\u", cursor)
|
|
733
|
+
|
|
734
|
+
if not re.fullmatch(r"[a-fA-F0-9]{4}", substring):
|
|
735
|
+
return None, Error(
|
|
736
|
+
f"Expected four hexadecimal digits after \\u, "
|
|
737
|
+
f"but got {substring!r}",
|
|
738
|
+
cursor,
|
|
739
|
+
)
|
|
740
|
+
|
|
741
|
+
result = Char(character=chr(int(substring, 16)), explicitly_encoded=True)
|
|
742
|
+
|
|
743
|
+
elif cursor.try_literal("\\U"):
|
|
744
|
+
substring = cursor.try_substring(length=8)
|
|
745
|
+
if substring is None:
|
|
746
|
+
return None, Error("Expected eight hexadecimal digits after \\U", cursor)
|
|
747
|
+
|
|
748
|
+
if not re.fullmatch(r"[a-fA-F0-9]{8}", substring):
|
|
749
|
+
return None, Error(
|
|
750
|
+
f"Expected eight hexadecimal digits after \\U, "
|
|
751
|
+
f"but got {substring!r}",
|
|
752
|
+
cursor,
|
|
753
|
+
)
|
|
754
|
+
|
|
755
|
+
code = int(substring, 16)
|
|
756
|
+
if code < 0x00010000 or code > 0x0010FFFF:
|
|
757
|
+
# noinspection SpellCheckingInspection
|
|
758
|
+
return None, Error(
|
|
759
|
+
f"Expected the character code in the range \\U00010000-\\U0010FFFF, "
|
|
760
|
+
f"but got \\U{code:08x}; "
|
|
761
|
+
f"the code can not be represented with high/low surrogates in UTF-16",
|
|
762
|
+
cursor,
|
|
763
|
+
)
|
|
764
|
+
|
|
765
|
+
result = Char(character=chr(code), explicitly_encoded=True)
|
|
766
|
+
elif cursor.try_literal("\\t"):
|
|
767
|
+
result = Char(character="\t")
|
|
768
|
+
|
|
769
|
+
elif cursor.try_literal("\\n"):
|
|
770
|
+
result = Char(character="\n")
|
|
771
|
+
|
|
772
|
+
elif cursor.try_literal("\\r"):
|
|
773
|
+
result = Char(character="\r")
|
|
774
|
+
|
|
775
|
+
elif cursor.try_literal("\\f"):
|
|
776
|
+
result = Char(character="\f")
|
|
777
|
+
|
|
778
|
+
elif cursor.try_literal("\\v"):
|
|
779
|
+
result = Char(character="\v")
|
|
780
|
+
|
|
781
|
+
elif cursor.try_literal("\\."):
|
|
782
|
+
result = Char(character=".")
|
|
783
|
+
|
|
784
|
+
elif cursor.try_literal("\\#"):
|
|
785
|
+
result = Char(character="#")
|
|
786
|
+
|
|
787
|
+
elif cursor.try_literal("\\^"):
|
|
788
|
+
result = Char(character="^")
|
|
789
|
+
|
|
790
|
+
elif cursor.try_literal("\\$"):
|
|
791
|
+
result = Char(character="$")
|
|
792
|
+
|
|
793
|
+
elif cursor.try_literal("\\("):
|
|
794
|
+
result = Char(character="(")
|
|
795
|
+
|
|
796
|
+
elif cursor.try_literal("\\)"):
|
|
797
|
+
result = Char(character=")")
|
|
798
|
+
|
|
799
|
+
elif cursor.try_literal("\\["):
|
|
800
|
+
result = Char(character="[")
|
|
801
|
+
|
|
802
|
+
elif cursor.try_literal("\\]"):
|
|
803
|
+
result = Char(character="]")
|
|
804
|
+
|
|
805
|
+
elif cursor.try_literal("\\\\"):
|
|
806
|
+
result = Char(character="\\")
|
|
807
|
+
|
|
808
|
+
elif cursor.try_literal("\\*"):
|
|
809
|
+
result = Char(character="*")
|
|
810
|
+
|
|
811
|
+
elif cursor.try_literal("\\+"):
|
|
812
|
+
result = Char(character="+")
|
|
813
|
+
|
|
814
|
+
elif cursor.try_literal("\\?"):
|
|
815
|
+
result = Char(character="?")
|
|
816
|
+
|
|
817
|
+
elif cursor.try_literal("\\s") or cursor.try_literal("\\S"):
|
|
818
|
+
return None, Error(
|
|
819
|
+
"We do not handle whitespace escaping at the moment (2022-06-09), "
|
|
820
|
+
"as the notion of a whitespace depends on the regex engine",
|
|
821
|
+
cursor,
|
|
822
|
+
)
|
|
823
|
+
|
|
824
|
+
elif cursor.try_literal("\\w") or cursor.try_literal("\\W"):
|
|
825
|
+
return None, Error(
|
|
826
|
+
"We do not handle word escaping at the moment (2022-06-09), "
|
|
827
|
+
"as the notion of a word depends on the regex engine",
|
|
828
|
+
cursor,
|
|
829
|
+
)
|
|
830
|
+
|
|
831
|
+
elif cursor.try_literal("\\d") or cursor.try_literal("\\D"):
|
|
832
|
+
return None, Error(
|
|
833
|
+
"We do not handle digit escaping at the moment (2022-06-09), "
|
|
834
|
+
"as the notion of a digit depends on the regex engine",
|
|
835
|
+
cursor,
|
|
836
|
+
)
|
|
837
|
+
|
|
838
|
+
elif cursor.try_literal("\\"):
|
|
839
|
+
return None, Error("Unexpected escaping", cursor)
|
|
840
|
+
|
|
841
|
+
elif cursor.try_literal("^"):
|
|
842
|
+
raise AssertionError(
|
|
843
|
+
"Expected to handle the start symbol before, outside of this function"
|
|
844
|
+
)
|
|
845
|
+
|
|
846
|
+
elif cursor.try_literal("$"):
|
|
847
|
+
raise AssertionError(
|
|
848
|
+
"Expected to handle the end symbol before, outside of this function"
|
|
849
|
+
)
|
|
850
|
+
|
|
851
|
+
elif cursor.try_literal("*"):
|
|
852
|
+
raise AssertionError(
|
|
853
|
+
"Expected to handle the ``*`` quantifier before, outside of this function"
|
|
854
|
+
)
|
|
855
|
+
|
|
856
|
+
elif cursor.try_literal("+"):
|
|
857
|
+
raise AssertionError(
|
|
858
|
+
"Expected to handle the ``+`` quantifier before, outside of this function"
|
|
859
|
+
)
|
|
860
|
+
|
|
861
|
+
elif cursor.try_literal("?"):
|
|
862
|
+
raise AssertionError(
|
|
863
|
+
"Expected to handle the ``?`` quantifier before, outside of this function"
|
|
864
|
+
)
|
|
865
|
+
|
|
866
|
+
elif cursor.try_literal("{"):
|
|
867
|
+
raise AssertionError(
|
|
868
|
+
"Expected to handle the opening ``{`` of a quantifier before, "
|
|
869
|
+
"outside of this function"
|
|
870
|
+
)
|
|
871
|
+
|
|
872
|
+
elif cursor.peek_literal(")") or cursor.peek_literal("|"):
|
|
873
|
+
# NOTE (mristin, 2022-06-08):
|
|
874
|
+
# We encountered a closing bracket or a delimiter in a union,
|
|
875
|
+
# so no concatenation is possible anymore, and we need to match an "empty"
|
|
876
|
+
# character literal.
|
|
877
|
+
return None, None
|
|
878
|
+
|
|
879
|
+
else:
|
|
880
|
+
character = cursor.try_substring(length=1)
|
|
881
|
+
assert character is not None, (
|
|
882
|
+
"Expected to read at least one character since we explicitly checked "
|
|
883
|
+
"that the cursor is not done before"
|
|
884
|
+
)
|
|
885
|
+
result = Char(character=character)
|
|
886
|
+
|
|
887
|
+
return result, None
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
_SUPPLEMENTARY_PLANE_START = 0x00010000
|
|
891
|
+
|
|
892
|
+
|
|
893
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
894
|
+
def _parse_concatenation(
|
|
895
|
+
cursor: Cursor,
|
|
896
|
+
) -> Tuple[Optional[Concatenation], Optional[Error]]:
|
|
897
|
+
"""Try to parse a concatenation of regex terms."""
|
|
898
|
+
if cursor.done():
|
|
899
|
+
return None, Error(
|
|
900
|
+
"Expected at least one term, but reached the end of input.", cursor
|
|
901
|
+
)
|
|
902
|
+
|
|
903
|
+
concatenants = [] # type: List[Term]
|
|
904
|
+
|
|
905
|
+
while True:
|
|
906
|
+
old_cursor_position = (
|
|
907
|
+
cursor.major_cursor,
|
|
908
|
+
cursor.minor_cursor if cursor.minor_cursor is not None else math.inf,
|
|
909
|
+
)
|
|
910
|
+
|
|
911
|
+
if cursor.done():
|
|
912
|
+
break
|
|
913
|
+
|
|
914
|
+
if cursor.peek_literal("|"):
|
|
915
|
+
break
|
|
916
|
+
|
|
917
|
+
value: Optional[TermValueUnion]
|
|
918
|
+
|
|
919
|
+
# noinspection GrazieInspection
|
|
920
|
+
if cursor.try_literal("^"):
|
|
921
|
+
value = Symbol(kind=SymbolKind.START)
|
|
922
|
+
|
|
923
|
+
elif cursor.try_literal("$"):
|
|
924
|
+
value = Symbol(kind=SymbolKind.END)
|
|
925
|
+
|
|
926
|
+
elif cursor.try_literal("."):
|
|
927
|
+
value = Symbol(kind=SymbolKind.DOT)
|
|
928
|
+
|
|
929
|
+
elif cursor.try_literal("("):
|
|
930
|
+
if cursor.try_literal("?"):
|
|
931
|
+
return None, Error(
|
|
932
|
+
"At this moment (2022-06-09), we did not have time to implement "
|
|
933
|
+
"the support for the directives in the groups (``?``). "
|
|
934
|
+
"Please inform the developers if you need this feature.",
|
|
935
|
+
cursor,
|
|
936
|
+
)
|
|
937
|
+
|
|
938
|
+
union, error = _parse_union(cursor)
|
|
939
|
+
if error is not None:
|
|
940
|
+
return None, error
|
|
941
|
+
assert union is not None
|
|
942
|
+
|
|
943
|
+
found_closing_bracket = cursor.try_literal(")")
|
|
944
|
+
if not found_closing_bracket:
|
|
945
|
+
return None, Error(
|
|
946
|
+
"Expected a closing bracket for the group, but found none.", cursor
|
|
947
|
+
)
|
|
948
|
+
|
|
949
|
+
value = Group(union=union)
|
|
950
|
+
elif cursor.try_literal("[^"):
|
|
951
|
+
ranges, error = _parse_ranges_and_closing(cursor)
|
|
952
|
+
if error is not None:
|
|
953
|
+
return None, error
|
|
954
|
+
assert ranges is not None
|
|
955
|
+
|
|
956
|
+
for a_range in ranges:
|
|
957
|
+
if ord(a_range.start.character) > _SUPPLEMENTARY_PLANE_START or (
|
|
958
|
+
a_range.end is not None
|
|
959
|
+
and ord(a_range.end.character) > _SUPPLEMENTARY_PLANE_START
|
|
960
|
+
):
|
|
961
|
+
range_str = (
|
|
962
|
+
f"\\U{a_range.start:08x}"
|
|
963
|
+
if a_range.end is None
|
|
964
|
+
else f"\\U{a_range.start:08x}-\\U{a_range.end:08x}"
|
|
965
|
+
)
|
|
966
|
+
return None, Error(
|
|
967
|
+
f"Complementing character sets with a range {range_str} "
|
|
968
|
+
f"involving UTF-32 characters can not be supported, "
|
|
969
|
+
f"since we can not represent them in implementations relying "
|
|
970
|
+
f"on UTF-16-only regex engines (such as C# as of 2022-06-11)",
|
|
971
|
+
cursor,
|
|
972
|
+
)
|
|
973
|
+
|
|
974
|
+
value = CharSet(complementing=True, ranges=ranges)
|
|
975
|
+
|
|
976
|
+
elif cursor.try_literal("["):
|
|
977
|
+
ranges, error = _parse_ranges_and_closing(cursor)
|
|
978
|
+
if error is not None:
|
|
979
|
+
return None, error
|
|
980
|
+
assert ranges is not None
|
|
981
|
+
|
|
982
|
+
value = CharSet(complementing=False, ranges=ranges)
|
|
983
|
+
|
|
984
|
+
elif isinstance(cursor.pointed_value(), FormattedValue):
|
|
985
|
+
formatted_value = cursor.try_formatted_value()
|
|
986
|
+
assert formatted_value is not None
|
|
987
|
+
|
|
988
|
+
value = formatted_value
|
|
989
|
+
|
|
990
|
+
elif cursor.try_literal("*"):
|
|
991
|
+
return None, Error("Unexpected ``*`` quantifier without a term", cursor)
|
|
992
|
+
|
|
993
|
+
elif cursor.try_literal("+"):
|
|
994
|
+
return None, Error("Unexpected ``+`` quantifier without a term", cursor)
|
|
995
|
+
|
|
996
|
+
elif cursor.try_literal("?"):
|
|
997
|
+
return None, Error("Unexpected ``?`` quantifier without a term", cursor)
|
|
998
|
+
|
|
999
|
+
else:
|
|
1000
|
+
value, error = _parse_char_literal(cursor)
|
|
1001
|
+
if error is not None:
|
|
1002
|
+
return None, error
|
|
1003
|
+
|
|
1004
|
+
# NOTE (mristin, 2022-06-08):
|
|
1005
|
+
# The ``value`` can be None here. For example, if we peeked a closing
|
|
1006
|
+
# ``)`` or a delimiting ``|``.
|
|
1007
|
+
|
|
1008
|
+
if value is not None:
|
|
1009
|
+
quantifier = None # type: Optional[Quantifier]
|
|
1010
|
+
if cursor.try_literal("*?"):
|
|
1011
|
+
quantifier = Quantifier(non_greedy=True, minimum=0, maximum=None)
|
|
1012
|
+
elif cursor.try_literal("+?"):
|
|
1013
|
+
quantifier = Quantifier(non_greedy=True, minimum=1, maximum=None)
|
|
1014
|
+
elif cursor.try_literal("??"):
|
|
1015
|
+
quantifier = Quantifier(non_greedy=True, minimum=0, maximum=1)
|
|
1016
|
+
elif cursor.try_literal("*"):
|
|
1017
|
+
quantifier = Quantifier(non_greedy=False, minimum=0, maximum=None)
|
|
1018
|
+
elif cursor.try_literal("+"):
|
|
1019
|
+
quantifier = Quantifier(non_greedy=False, minimum=1, maximum=None)
|
|
1020
|
+
elif cursor.try_literal("?"):
|
|
1021
|
+
quantifier = Quantifier(non_greedy=False, minimum=0, maximum=1)
|
|
1022
|
+
elif cursor.try_literal("{"):
|
|
1023
|
+
cursor.try_spaces_or_tabs()
|
|
1024
|
+
minimum = cursor.try_positive_integer_without_sign()
|
|
1025
|
+
cursor.try_spaces_or_tabs()
|
|
1026
|
+
found_comma = cursor.try_literal(",")
|
|
1027
|
+
cursor.try_spaces_or_tabs()
|
|
1028
|
+
maximum = cursor.try_positive_integer_without_sign()
|
|
1029
|
+
cursor.try_spaces_or_tabs()
|
|
1030
|
+
|
|
1031
|
+
if minimum is None and maximum is None:
|
|
1032
|
+
return None, Error(
|
|
1033
|
+
"Encountered an opening ``{`` for a quantifier, "
|
|
1034
|
+
"but both minimum and the maximum could not be parsed",
|
|
1035
|
+
cursor,
|
|
1036
|
+
)
|
|
1037
|
+
|
|
1038
|
+
if not found_comma:
|
|
1039
|
+
maximum = minimum
|
|
1040
|
+
|
|
1041
|
+
minimum_zero_if_none = minimum if minimum is not None else 0
|
|
1042
|
+
|
|
1043
|
+
if cursor.try_literal("}?"):
|
|
1044
|
+
quantifier = Quantifier(
|
|
1045
|
+
non_greedy=True, minimum=minimum_zero_if_none, maximum=maximum
|
|
1046
|
+
)
|
|
1047
|
+
elif cursor.try_literal("}"):
|
|
1048
|
+
quantifier = Quantifier(
|
|
1049
|
+
non_greedy=False, minimum=minimum_zero_if_none, maximum=maximum
|
|
1050
|
+
)
|
|
1051
|
+
else:
|
|
1052
|
+
return None, Error(
|
|
1053
|
+
"Expected closing ``}`` for the quantifier", cursor
|
|
1054
|
+
)
|
|
1055
|
+
else:
|
|
1056
|
+
pass
|
|
1057
|
+
|
|
1058
|
+
if isinstance(value, Symbol) and (
|
|
1059
|
+
value.kind is SymbolKind.START or value.kind is SymbolKind.END
|
|
1060
|
+
):
|
|
1061
|
+
assert quantifier is None, (
|
|
1062
|
+
f"Unexpected the symbol {value.kind.value} with a quantifier. "
|
|
1063
|
+
f"This should have been detected before."
|
|
1064
|
+
)
|
|
1065
|
+
|
|
1066
|
+
concatenants.append(Term(value=value, quantifier=quantifier))
|
|
1067
|
+
else:
|
|
1068
|
+
break
|
|
1069
|
+
|
|
1070
|
+
cursor_position = (
|
|
1071
|
+
cursor.major_cursor,
|
|
1072
|
+
cursor.minor_cursor if cursor.minor_cursor is not None else math.inf,
|
|
1073
|
+
)
|
|
1074
|
+
assert (
|
|
1075
|
+
old_cursor_position < cursor_position
|
|
1076
|
+
), f"Loop invariant: {old_cursor_position=}, {cursor_position=}"
|
|
1077
|
+
|
|
1078
|
+
# NOTE (mristin, 2022-06-03):
|
|
1079
|
+
# Empty terms are possible! For example, parsing ``(())`` needs to allow for an
|
|
1080
|
+
# empty union expression in the inner group.
|
|
1081
|
+
|
|
1082
|
+
return Concatenation(concatenants=concatenants), None
|
|
1083
|
+
|
|
1084
|
+
|
|
1085
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
1086
|
+
def _parse_union(cursor: Cursor) -> Tuple[Optional[UnionExpr], Optional[Error]]:
|
|
1087
|
+
"""Try to parse a union of concatenations."""
|
|
1088
|
+
if cursor.done():
|
|
1089
|
+
return UnionExpr(uniates=[]), None
|
|
1090
|
+
|
|
1091
|
+
concatenation, error = _parse_concatenation(cursor)
|
|
1092
|
+
if error is not None:
|
|
1093
|
+
return None, error
|
|
1094
|
+
assert concatenation is not None
|
|
1095
|
+
|
|
1096
|
+
uniates = [concatenation]
|
|
1097
|
+
|
|
1098
|
+
while cursor.try_literal(literal="|"):
|
|
1099
|
+
if cursor.done():
|
|
1100
|
+
# NOTE (mristin, 2022-06-09):
|
|
1101
|
+
# An empty term at the end of input is allowed.
|
|
1102
|
+
# For example, consider ``"|"``.
|
|
1103
|
+
uniates.append(Concatenation(concatenants=[]))
|
|
1104
|
+
break
|
|
1105
|
+
|
|
1106
|
+
concatenation, error = _parse_concatenation(cursor)
|
|
1107
|
+
if error is not None:
|
|
1108
|
+
return None, error
|
|
1109
|
+
assert concatenation is not None
|
|
1110
|
+
|
|
1111
|
+
uniates.append(concatenation)
|
|
1112
|
+
|
|
1113
|
+
return UnionExpr(uniates=uniates), None
|
|
1114
|
+
|
|
1115
|
+
|
|
1116
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
1117
|
+
def _parse_regex(cursor: Cursor) -> Tuple[Optional[Regex], Optional[Error]]:
|
|
1118
|
+
"""Try to parse the regular expression and move the cursor."""
|
|
1119
|
+
union, error = _parse_union(cursor)
|
|
1120
|
+
if error is not None:
|
|
1121
|
+
return None, error
|
|
1122
|
+
|
|
1123
|
+
if not cursor.done():
|
|
1124
|
+
return None, Error(
|
|
1125
|
+
message=(
|
|
1126
|
+
"Expected to reach the end of input, "
|
|
1127
|
+
"but there is still some unconsumed input left"
|
|
1128
|
+
),
|
|
1129
|
+
cursor=cursor,
|
|
1130
|
+
)
|
|
1131
|
+
|
|
1132
|
+
assert union is not None
|
|
1133
|
+
return Regex(union=union), None
|
|
1134
|
+
|
|
1135
|
+
|
|
1136
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
1137
|
+
def parse(
|
|
1138
|
+
values: Sequence[Union[str, FormattedValue]]
|
|
1139
|
+
) -> Tuple[Optional[Regex], Optional[Error]]:
|
|
1140
|
+
"""Try to parse the ``values`` into an AST representing the regular expression."""
|
|
1141
|
+
cursor = Cursor(values=values)
|
|
1142
|
+
parsed, error = _parse_regex(cursor)
|
|
1143
|
+
return parsed, error
|