react-native-executorch 0.10.6 → 0.10.7
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.
- package/lib/module/fetcher/telemetry.js +1 -1
- package/package.json +1 -1
- package/react-native-executorch.podspec +2 -0
- package/src/fetcher/telemetry.ts +1 -1
- package/third-party/common/phonemis/CMakeLists.txt +70 -14
- package/third-party/common/phonemis/README.md +183 -33
- package/third-party/common/phonemis/THIRD_PARTY_NOTICES.md +57 -0
- package/third-party/common/phonemis/knowledge/code_style.md +642 -0
- package/third-party/common/phonemis/licenses/Unicode-3.0.txt +39 -0
- package/third-party/common/phonemis/licenses/misaki-Apache-2.0.txt +201 -0
- package/third-party/common/phonemis/licenses/nlohmann-json-MIT.txt +21 -0
- package/third-party/common/phonemis/licenses/xsimd-BSD-3-Clause.txt +29 -0
- package/third-party/common/phonemis/src/phonemis/base/config.h +6 -0
- package/third-party/common/phonemis/src/phonemis/base/ipipeline.cpp +75 -0
- package/third-party/common/phonemis/src/phonemis/base/ipipeline.h +21 -0
- package/third-party/common/phonemis/src/phonemis/base/phonemizer/constants.h +2 -5
- package/third-party/common/phonemis/src/phonemis/base/phonemizer/lexicon_phonemizer.cpp +3 -4
- package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/neural_phonemizer.cpp +17 -8
- package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/neural_phonemizer.h +4 -0
- package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/tokenizer.cpp +21 -6
- package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/tokenizer.h +13 -4
- package/third-party/common/phonemis/src/phonemis/base/pipeline.cpp +8 -0
- package/third-party/common/phonemis/src/phonemis/base/pipeline.h +19 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/conditions.cpp +37 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/conditions.h +45 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/constants.h +10 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/context.cpp +105 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/context.h +49 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/document.cpp +173 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/document.h +67 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/text.cpp +75 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/text.h +60 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/types.h +18 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/config.h +53 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layer.h +9 -7
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/constants.h +20 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/layer.cpp +89 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/layer.h +35 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/types.h +16 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/kind.h +40 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/layer.h +382 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/notation.h +30 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/numerals.cpp +51 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/numerals.h +31 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/pattern.h +30 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/pattern_set.cpp +17 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/pattern_set.h +31 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/patterns.cpp +811 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/patterns.h +285 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/primitives.cpp +64 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/primitives.h +23 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/types.h +94 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/sanitizer/layer.cpp +19 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/{sanitizer_layer.h → layers/sanitizer/layer.h} +8 -8
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/sym2word/layer.cpp +65 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/sym2word/layer.h +29 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/term2word/layer.cpp +170 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/term2word/layer.h +40 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/term2word/types.h +25 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/trim/layer.cpp +47 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/trim/layer.h +19 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/preprocessor.cpp +60 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/preprocessor.h +45 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/processor.cpp +6 -7
- package/third-party/common/phonemis/src/phonemis/base/processor/processor.h +14 -10
- package/third-party/common/phonemis/src/phonemis/base/tagger/hmm_tagger.cpp +89 -52
- package/third-party/common/phonemis/src/phonemis/base/tagger/hmm_tagger.h +16 -9
- package/third-party/common/phonemis/src/phonemis/base/tokenizer/tokenizer.cpp +13 -12
- package/third-party/common/phonemis/src/phonemis/lang/de/constants.h +183 -19
- package/third-party/common/phonemis/src/phonemis/lang/de/num2word.cpp +355 -309
- package/third-party/common/phonemis/src/phonemis/lang/de/num2word.h +42 -17
- package/third-party/common/phonemis/src/phonemis/lang/de/patterns.cpp +56 -0
- package/third-party/common/phonemis/src/phonemis/lang/de/patterns.h +15 -0
- package/third-party/common/phonemis/src/phonemis/lang/de/pipeline.h +3 -3
- package/third-party/common/phonemis/src/phonemis/lang/en/constants.h +181 -30
- package/third-party/common/phonemis/src/phonemis/lang/en/hmm_tagger.cpp +5 -7
- package/third-party/common/phonemis/src/phonemis/lang/en/num2word.cpp +232 -135
- package/third-party/common/phonemis/src/phonemis/lang/en/num2word.h +41 -16
- package/third-party/common/phonemis/src/phonemis/lang/en/pipeline.h +3 -10
- package/third-party/common/phonemis/src/phonemis/lang/es/constants.h +182 -60
- package/third-party/common/phonemis/src/phonemis/lang/es/num2word.cpp +247 -212
- package/third-party/common/phonemis/src/phonemis/lang/es/num2word.h +38 -18
- package/third-party/common/phonemis/src/phonemis/lang/es/patterns.cpp +50 -0
- package/third-party/common/phonemis/src/phonemis/lang/es/patterns.h +15 -0
- package/third-party/common/phonemis/src/phonemis/lang/es/pipeline.h +3 -3
- package/third-party/common/phonemis/src/phonemis/lang/fr/constants.h +152 -26
- package/third-party/common/phonemis/src/phonemis/lang/fr/num2word.cpp +252 -179
- package/third-party/common/phonemis/src/phonemis/lang/fr/num2word.h +38 -15
- package/third-party/common/phonemis/src/phonemis/lang/fr/patterns.cpp +83 -0
- package/third-party/common/phonemis/src/phonemis/lang/fr/patterns.h +15 -0
- package/third-party/common/phonemis/src/phonemis/lang/fr/pipeline.h +3 -3
- package/third-party/common/phonemis/src/phonemis/lang/hi/constants.h +62 -10
- package/third-party/common/phonemis/src/phonemis/lang/hi/num2word.cpp +74 -123
- package/third-party/common/phonemis/src/phonemis/lang/hi/num2word.h +27 -16
- package/third-party/common/phonemis/src/phonemis/lang/hi/pipeline.h +5 -3
- package/third-party/common/phonemis/src/phonemis/lang/it/constants.h +122 -42
- package/third-party/common/phonemis/src/phonemis/lang/it/num2word.cpp +200 -207
- package/third-party/common/phonemis/src/phonemis/lang/it/num2word.h +30 -18
- package/third-party/common/phonemis/src/phonemis/lang/it/patterns.cpp +25 -0
- package/third-party/common/phonemis/src/phonemis/lang/it/patterns.h +15 -0
- package/third-party/common/phonemis/src/phonemis/lang/it/pipeline.h +3 -3
- package/third-party/common/phonemis/src/phonemis/lang/pl/constants.h +346 -77
- package/third-party/common/phonemis/src/phonemis/lang/pl/num2word.cpp +631 -246
- package/third-party/common/phonemis/src/phonemis/lang/pl/num2word.h +47 -15
- package/third-party/common/phonemis/src/phonemis/lang/pl/pipeline.h +6 -6
- package/third-party/common/phonemis/src/phonemis/lang/pt/constants.h +201 -0
- package/third-party/common/phonemis/src/phonemis/lang/pt/num2word.cpp +365 -0
- package/third-party/common/phonemis/src/phonemis/lang/pt/num2word.h +53 -0
- package/third-party/common/phonemis/src/phonemis/lang/pt/pipeline.h +4 -2
- package/third-party/common/phonemis/src/phonemis/main.cpp +42 -11
- package/third-party/common/phonemis/src/phonemis/protophone/meta.h +24 -0
- package/third-party/common/phonemis/src/phonemis/protophone/numeric.h +26 -0
- package/third-party/common/phonemis/src/phonemis/protophone/protophone.cpp +525 -0
- package/third-party/common/phonemis/src/phonemis/protophone/protophone.h +80 -0
- package/third-party/common/phonemis/src/phonemis/protophone/tensor.h +76 -0
- package/third-party/common/phonemis/src/phonemis/protophone/tensor_utils.h +89 -0
- package/third-party/common/phonemis/src/phonemis/protophone/tensor_view.h +125 -0
- package/third-party/common/phonemis/src/phonemis/protophone/types.h +43 -0
- package/third-party/common/phonemis/src/phonemis/utils/strings.h +20 -14
- package/third-party/common/phonemis/src/phonemis/utils/unicode.h +15 -1
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_arithmetic.hpp +267 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_bit.hpp +232 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_cast.hpp +43 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_complex.hpp +112 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_details.hpp +386 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_logical.hpp +240 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_math.hpp +2601 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_memory.hpp +1006 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_rounding.hpp +72 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_swizzle.hpp +260 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_trigo.hpp +996 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/utils/shifts.hpp +82 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx.hpp +2111 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx2.hpp +1591 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx2_128.hpp +170 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512bw.hpp +724 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512cd.hpp +28 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512dq.hpp +270 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512er.hpp +17 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512f.hpp +2919 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512ifma.hpp +17 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512pf.hpp +17 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vbmi.hpp +76 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vbmi2.hpp +130 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vnni_avx512bw.hpp +17 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vnni_avx512vbmi2.hpp +17 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx_128.hpp +164 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avxvnni.hpp +17 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_common.hpp +26 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_common_fwd.hpp +127 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_constants.hpp +393 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_emulated.hpp +787 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma3_avx.hpp +93 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma3_avx2.hpp +46 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma3_sse.hpp +97 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma4.hpp +92 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_i8mm_neon64.hpp +17 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_isa.hpp +148 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_neon.hpp +3580 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_neon64.hpp +1614 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_rvv.hpp +1515 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_scalar.hpp +1210 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse2.hpp +2333 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse3.hpp +66 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse4_1.hpp +510 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse4_2.hpp +44 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_ssse3.hpp +186 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sve.hpp +1186 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_vsx.hpp +947 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_vxe.hpp +787 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_wasm.hpp +1819 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_arch.hpp +242 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_config.hpp +633 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features.hpp +50 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_arm.hpp +132 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_ppc.hpp +54 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_riscv.hpp +95 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_s390x.hpp +56 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_x86.hpp +1121 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpuid.hpp +144 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_getauxval.hpp +159 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_macros.hpp +78 -0
- package/third-party/common/phonemis/src/third-party/xsimd/math/xsimd_rem_pio2.hpp +707 -0
- package/third-party/common/phonemis/src/third-party/xsimd/memory/xsimd_aligned_allocator.hpp +349 -0
- package/third-party/common/phonemis/src/third-party/xsimd/memory/xsimd_alignment.hpp +102 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_all_registers.hpp +57 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_api.hpp +3106 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx2_register.hpp +57 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512bw_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512cd_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512dq_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512er_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512f_register.hpp +77 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512ifma_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512pf_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vbmi2_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vbmi_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vnni_avx512bw_register.hpp +54 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vnni_avx512vbmi2_register.hpp +53 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx_register.hpp +79 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avxvnni_register.hpp +44 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_batch.hpp +1666 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_batch_constant.hpp +572 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_batch_fwd.hpp +41 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_common_arch.hpp +49 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_emulated_register.hpp +80 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma3_avx2_register.hpp +50 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma3_avx_register.hpp +50 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma3_sse_register.hpp +50 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma4_register.hpp +50 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_i8mm_neon64_register.hpp +55 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_neon64_register.hpp +55 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_neon_register.hpp +130 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_register.hpp +96 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_rvv_register.hpp +491 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse2_register.hpp +59 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse3_register.hpp +49 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse4_1_register.hpp +48 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse4_2_register.hpp +48 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_ssse3_register.hpp +48 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sve_register.hpp +216 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_traits.hpp +409 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_utils.hpp +462 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_vsx_register.hpp +84 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_vxe_register.hpp +86 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_wasm_register.hpp +59 -0
- package/third-party/common/phonemis/src/third-party/xsimd/utils/bits.hpp +122 -0
- package/third-party/common/phonemis/src/third-party/xsimd/utils/xsimd_type_traits.hpp +145 -0
- package/third-party/common/phonemis/src/third-party/xsimd/xsimd.hpp +43 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/constants.h +0 -11
- package/third-party/common/phonemis/src/phonemis/base/processor/num2word/config.h +0 -16
- package/third-party/common/phonemis/src/phonemis/base/processor/num2word/layer.cpp +0 -271
- package/third-party/common/phonemis/src/phonemis/base/processor/num2word/layer.h +0 -45
- package/third-party/common/phonemis/src/phonemis/base/processor/num2word/types.h +0 -29
- package/third-party/common/phonemis/src/phonemis/base/processor/sanitizer_layer.cpp +0 -22
- package/third-party/common/phonemis/src/phonemis/base/processor/trim_layer.cpp +0 -40
- package/third-party/common/phonemis/src/phonemis/base/processor/trim_layer.h +0 -22
|
@@ -1,393 +1,439 @@
|
|
|
1
|
-
#include "num2word.h"
|
|
2
1
|
#include "constants.h"
|
|
3
|
-
#include
|
|
4
|
-
#include
|
|
2
|
+
#include "num2word.h"
|
|
3
|
+
#include "patterns.h"
|
|
4
|
+
#include <phonemis/base/processor/layers/num2word/numerals.h>
|
|
5
|
+
#include <phonemis/base/processor/layers/num2word/patterns.h>
|
|
6
|
+
#include <phonemis/base/processor/layers/num2word/primitives.h>
|
|
7
|
+
#include <phonemis/utils/strings.h>
|
|
5
8
|
#include <phonemis/utils/unicode.h>
|
|
6
|
-
|
|
7
|
-
#include <
|
|
8
|
-
#include <cmath>
|
|
9
|
-
#include <cstdlib>
|
|
9
|
+
|
|
10
|
+
#include <array>
|
|
10
11
|
|
|
11
12
|
namespace phonemis::de {
|
|
12
13
|
|
|
13
|
-
using namespace constants;
|
|
14
|
-
using namespace
|
|
15
|
-
using processor::num2word
|
|
16
|
-
using
|
|
14
|
+
using namespace constants::num2word;
|
|
15
|
+
using namespace processor;
|
|
16
|
+
using namespace processor::num2word;
|
|
17
|
+
using namespace utils;
|
|
17
18
|
|
|
18
19
|
namespace {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return !utils::unicode::isalnum(c) && c != U'_';
|
|
20
|
+
uint64_t value(const Number& number) {
|
|
21
|
+
return value_of(number.integer).value_or(0);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
// ------------------------
|
|
25
|
+
// ----- Number words -----
|
|
26
|
+
// ------------------------
|
|
27
|
+
|
|
28
|
+
std::u32string cardinal(uint64_t n);
|
|
29
|
+
|
|
30
|
+
// A cardinal as the first part of a compound: ein, einundzwanzig, einhundertein
|
|
31
|
+
std::u32string stem(uint64_t n) {
|
|
32
|
+
std::u32string words = cardinal(n);
|
|
33
|
+
return words.ends_with(U"eins") ? words.substr(0, words.size() - 1) : words;
|
|
30
34
|
}
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
std::u32string cardinal(uint64_t n) {
|
|
37
|
+
if (n < 20) {
|
|
38
|
+
return std::u32string(kOnes[n]);
|
|
39
|
+
}
|
|
40
|
+
if (n < 100) {
|
|
41
|
+
return (n % 10 ? stem(n % 10) + U"und" : U"") + std::u32string(kTens[n / 10]);
|
|
42
|
+
}
|
|
43
|
+
if (n < 1000) {
|
|
44
|
+
return stem(n / 100) + U"hundert" + (n % 100 ? cardinal(n % 100) : U"");
|
|
45
|
+
}
|
|
46
|
+
if (n < 1000000) {
|
|
47
|
+
return stem(n / 1000) + U"tausend" + (n % 1000 ? cardinal(n % 1000) : U"");
|
|
48
|
+
}
|
|
49
|
+
for (auto [scale, one, many] :
|
|
50
|
+
{std::tuple{1000000000ULL, U"Milliarde", U"Milliarden"}, std::tuple{1000000ULL, U"Million", U"Millionen"}}) {
|
|
51
|
+
if (n >= scale) {
|
|
52
|
+
uint64_t q = n / scale, r = n % scale;
|
|
53
|
+
std::u32string head = q == 1 ? U"eine " + std::u32string(one) : cardinal(q) + U" " + std::u32string(many);
|
|
54
|
+
return head + (r ? U" " + cardinal(r) : U"");
|
|
55
|
+
}
|
|
36
56
|
}
|
|
37
|
-
return
|
|
57
|
+
return U"";
|
|
38
58
|
}
|
|
39
59
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
60
|
+
// 1100-1999 in hundreds (neunzehnhundertneunzig); later years read like cardinals
|
|
61
|
+
std::u32string year(uint64_t n) {
|
|
62
|
+
if (n >= 1100 && n <= 1999) {
|
|
63
|
+
return cardinal(n / 100) + U"hundert" + (n % 100 ? cardinal(n % 100) : U"");
|
|
44
64
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
65
|
+
return cardinal(n);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
std::u32string ordinal(uint64_t n, std::u32string_view ending) {
|
|
69
|
+
std::u32string words = cardinal(n);
|
|
70
|
+
uint64_t r = n % 100;
|
|
71
|
+
if (r > 0 && r < 20) {
|
|
72
|
+
std::u32string one(kOnes[r]);
|
|
73
|
+
auto it = kOrdinalStems.find(one);
|
|
74
|
+
std::u32string base = words.substr(0, words.size() - one.size());
|
|
75
|
+
return base + (it != kOrdinalStems.end() ? it->second : one) + U"t" + std::u32string(ending);
|
|
48
76
|
}
|
|
49
|
-
|
|
77
|
+
return words + U"st" + std::u32string(ending);
|
|
78
|
+
}
|
|
50
79
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
80
|
+
std::u32string digits(std::u32string_view text) {
|
|
81
|
+
std::vector<std::u32string> words;
|
|
82
|
+
for (char32_t c : text) {
|
|
83
|
+
words.emplace_back(kOnes[c - U'0']);
|
|
54
84
|
}
|
|
85
|
+
return join(words);
|
|
86
|
+
}
|
|
55
87
|
|
|
56
|
-
|
|
57
|
-
|
|
88
|
+
// "1" said like an article, by case and gender: eine Stunde, mit einem Mal
|
|
89
|
+
std::u32string article(Case c, Gender g) {
|
|
90
|
+
static const std::array<std::array<std::u32string_view, 3>, 4> forms = {{
|
|
91
|
+
{U"ein", U"eine", U"ein"}, // Nominative
|
|
92
|
+
{U"eines", U"einer", U"eines"}, // Genitive
|
|
93
|
+
{U"einem", U"einer", U"einem"}, // Dative
|
|
94
|
+
{U"einen", U"eine", U"ein"}, // Accusative
|
|
95
|
+
}};
|
|
96
|
+
size_t row = c == Case::GENITIVE ? 1 : c == Case::DATIVE ? 2 : c == Case::ACCUSATIVE ? 3 : 0;
|
|
97
|
+
return std::u32string(forms[row][static_cast<size_t>(g)]);
|
|
58
98
|
}
|
|
59
|
-
} // namespace
|
|
60
99
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
std::
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
100
|
+
// The adjective ending of an ordinal: am dritten, der dritte, ein zweiter, dritter
|
|
101
|
+
std::u32string_view ending(const NumberReading& reading) {
|
|
102
|
+
static const std::array<std::array<std::u32string_view, 3>, 4> strong = {{
|
|
103
|
+
{U"er", U"e", U"es"}, // Nominative
|
|
104
|
+
{U"en", U"er", U"en"}, // Genitive
|
|
105
|
+
{U"em", U"er", U"em"}, // Dative
|
|
106
|
+
{U"en", U"e", U"es"}, // Accusative
|
|
107
|
+
}};
|
|
108
|
+
switch (reading.declension) {
|
|
109
|
+
case Declension::WEAK:
|
|
110
|
+
return reading.grammatical_case == Case::NOMINATIVE ? U"e" : U"en";
|
|
111
|
+
case Declension::MIXED:
|
|
112
|
+
return reading.gender == Gender::NEUTER ? U"es" : U"er";
|
|
113
|
+
default:
|
|
114
|
+
Case c = reading.grammatical_case;
|
|
115
|
+
size_t row = c == Case::GENITIVE ? 1 : c == Case::DATIVE ? 2 : c == Case::ACCUSATIVE ? 3 : 0;
|
|
116
|
+
return strong[row][static_cast<size_t>(reading.gender)];
|
|
76
117
|
}
|
|
118
|
+
}
|
|
77
119
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
size_t last_pos = 0;
|
|
82
|
-
for (size_t i = 0; i < work.size(); ++i) {
|
|
83
|
-
if (!utils::unicode::isdigit(work[i])) continue;
|
|
84
|
-
if (i > 0 && !is_boundary(work[i - 1])) continue;
|
|
85
|
-
|
|
86
|
-
size_t start = i;
|
|
87
|
-
size_t len = 0;
|
|
88
|
-
Mode mode = Mode::CARDINAL;
|
|
89
|
-
|
|
90
|
-
size_t p1 = count_digits(work, start);
|
|
91
|
-
size_t curr = start + p1;
|
|
92
|
-
|
|
93
|
-
if (curr < work.size() && (work[curr] == U'.' || work[curr] == U'-' || work[curr] == U'/')) {
|
|
94
|
-
char32_t sep = work[curr];
|
|
95
|
-
size_t p2 = count_digits(work, curr + 1);
|
|
96
|
-
|
|
97
|
-
if (p2 > 0) {
|
|
98
|
-
size_t next_curr = curr + 1 + p2;
|
|
99
|
-
|
|
100
|
-
if (next_curr < work.size() && work[next_curr] == sep && (sep == U'.' || sep == U'-')) {
|
|
101
|
-
size_t p3 = count_digits(work, next_curr + 1);
|
|
102
|
-
if (p3 > 0 &&
|
|
103
|
-
(next_curr + 1 + p3 == work.size() || is_boundary(work[next_curr + 1 + p3]))) {
|
|
104
|
-
if (p1 <= 4 && p2 <= 2 && p3 <= 4) {
|
|
105
|
-
len = next_curr + 1 + p3 - start;
|
|
106
|
-
mode = Mode::DATE;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
120
|
+
// -------------------
|
|
121
|
+
// ----- Context -----
|
|
122
|
+
// -------------------
|
|
110
123
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
size_t after = start + len;
|
|
114
|
-
if (sep != U'/' && after < work.size() && is_currency(work[after]) &&
|
|
115
|
-
(after + 1 == work.size() || is_boundary(work[after + 1]))) {
|
|
116
|
-
len++;
|
|
117
|
-
mode = Mode::CURRENCY;
|
|
118
|
-
} else {
|
|
119
|
-
mode = (sep == U'/') ? Mode::FRACTION : Mode::CARDINAL;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
} else if (sep == U'.') {
|
|
123
|
-
len = p1 + 1;
|
|
124
|
-
mode = Mode::ORDINAL;
|
|
124
|
+
Gender gender_of(std::u32string_view noun) {
|
|
125
|
+
std::u32string word = strings::to_lower(noun);
|
|
125
126
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
len--;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
127
|
+
// The longest known ending decides, then the regular ones
|
|
128
|
+
size_t longest = 0;
|
|
129
|
+
Gender gender = Gender::MASCULINE;
|
|
130
|
+
for (const auto& [key, key_gender] : kGenders) {
|
|
131
|
+
if (key.size() > longest && word.ends_with(key)) {
|
|
132
|
+
longest = key.size();
|
|
133
|
+
gender = key_gender;
|
|
136
134
|
}
|
|
135
|
+
}
|
|
136
|
+
if (longest > 0) {
|
|
137
|
+
return gender;
|
|
138
|
+
}
|
|
137
139
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
while (curr + alpha < work.size() && utils::unicode::isalpha(work[curr + alpha])) {
|
|
146
|
-
alpha++;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (alpha > 0 && (curr + alpha == work.size() || is_boundary(work[curr + alpha]))) {
|
|
150
|
-
len = p1 + alpha;
|
|
151
|
-
mode = Mode::POTENTIALLY_ORDINAL;
|
|
152
|
-
} else if (curr == work.size() || is_boundary(work[curr])) {
|
|
153
|
-
len = p1;
|
|
154
|
-
mode = Mode::CARDINAL;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
140
|
+
auto ends_with_any = [&](const std::vector<std::u32string>& endings) {
|
|
141
|
+
return std::ranges::any_of(endings, [&](const auto& e) { return word.ends_with(e); });
|
|
142
|
+
};
|
|
143
|
+
return ends_with_any(kFeminineEndings) ? Gender::FEMININE :
|
|
144
|
+
ends_with_any(kNeuterEndings) ? Gender::NEUTER :
|
|
145
|
+
Gender::MASCULINE;
|
|
146
|
+
}
|
|
158
147
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
std::u32string_view p1 = work.substr(start, first_sep - start);
|
|
168
|
-
std::u32string_view p2 = work.substr(first_sep + 1, second_sep - first_sep - 1);
|
|
169
|
-
std::u32string_view p3 = work.substr(second_sep + 1, start + len - second_sep - 1);
|
|
170
|
-
|
|
171
|
-
auto val1 = as_int(p1);
|
|
172
|
-
auto val2 = as_int(p2);
|
|
173
|
-
auto val3 = as_int(p3);
|
|
174
|
-
|
|
175
|
-
if (!val1 || !val2 || !val3) {
|
|
176
|
-
result.append(work.substr(start, len));
|
|
177
|
-
} else {
|
|
178
|
-
bool nominative = has_nominative_article(work, start);
|
|
179
|
-
std::u32string day_word;
|
|
180
|
-
|
|
181
|
-
if (p1.size() == 4) {
|
|
182
|
-
day_word = to_ordinal_int(static_cast<int32_t>(*val3), nominative ? U"e" : U"en");
|
|
183
|
-
result.append(day_word + U" " + to_month(*val2) + U" " + to_year(*val1));
|
|
184
|
-
} else {
|
|
185
|
-
day_word = to_ordinal_int(static_cast<int32_t>(*val1), nominative ? U"e" : U"en");
|
|
186
|
-
result.append(day_word + U" " + to_month(*val2) + U" " + to_year(*val3));
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
} else {
|
|
190
|
-
result.append(verbalize({work.substr(start, len), mode}));
|
|
191
|
-
}
|
|
148
|
+
Case case_after(std::u32string_view word) {
|
|
149
|
+
std::u32string w(word);
|
|
150
|
+
return kDative.contains(w) ? Case::DATIVE :
|
|
151
|
+
kAccusative.contains(w) ? Case::ACCUSATIVE :
|
|
152
|
+
kGenitive.contains(w) ? Case::GENITIVE :
|
|
153
|
+
Case::NOMINATIVE;
|
|
154
|
+
}
|
|
192
155
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
156
|
+
bool capitalized(std::u32string_view word) {
|
|
157
|
+
return !word.empty() && unicode::isupper(word[0]);
|
|
158
|
+
}
|
|
197
159
|
|
|
198
|
-
|
|
199
|
-
return
|
|
160
|
+
bool all_digits(std::u32string_view word) {
|
|
161
|
+
return !word.empty() && std::ranges::all_of(word, unicode::isdigit);
|
|
200
162
|
}
|
|
201
163
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
164
|
+
// A number right after a capitalized noun is its label: Seite 1, Platz 1
|
|
165
|
+
bool labelled(const Context& context) {
|
|
166
|
+
auto head = words_of(context.head());
|
|
167
|
+
return !head.empty() && capitalized(head.back()) &&
|
|
168
|
+
!(head.size() == 1 || strings::contains(std::u32string_view(U".!?"), head[head.size() - 2].back()));
|
|
169
|
+
}
|
|
206
170
|
|
|
207
|
-
|
|
208
|
-
|
|
171
|
+
// The ending of an ordinal from the words before it, and the noun it qualifies.
|
|
172
|
+
void resolve_ending(const Context& context, std::u32string_view noun, NumberReading& reading) {
|
|
173
|
+
std::vector<std::u32string> before;
|
|
174
|
+
for (auto word : words_of(context.head())) {
|
|
175
|
+
before.push_back(strings::to_lower(stripped(word)));
|
|
209
176
|
}
|
|
210
177
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
178
|
+
// "in 2. und 3. Lesung", "vom 1. 5. bis 3. 5.": both take the ending of the first
|
|
179
|
+
static const std::array<std::u32string_view, 4> joining = {U"und", U"oder", U"bis", U"sowie"};
|
|
180
|
+
while (before.size() >= 2 && std::ranges::find(joining, before.back()) != joining.end() &&
|
|
181
|
+
all_digits(before[before.size() - 2])) {
|
|
182
|
+
before.resize(before.size() - 2);
|
|
183
|
+
while (!before.empty() && all_digits(before.back())) {
|
|
184
|
+
before.pop_back();
|
|
216
185
|
}
|
|
217
|
-
std::u32string unit_str = (units == 1) ? U"ein" : num2word::kCardinals.at(units);
|
|
218
|
-
return unit_str + U"und" + num2word::kCardinals.at(tens);
|
|
219
186
|
}
|
|
187
|
+
std::u32string w1 = before.empty() ? U"" : before.back();
|
|
188
|
+
std::u32string w2 = before.size() < 2 ? U"" : before[before.size() - 2];
|
|
189
|
+
|
|
190
|
+
reading.gender = gender_of(noun);
|
|
191
|
+
if (kWeak.contains(w1) || (w1 == U"der" && (kDative.contains(w2) || kGenitive.contains(w2)))) {
|
|
192
|
+
reading.declension = Declension::WEAK;
|
|
193
|
+
reading.grammatical_case = Case::DATIVE;
|
|
194
|
+
} else if (kWeakNominative.contains(w1)) {
|
|
195
|
+
reading.declension = Declension::WEAK;
|
|
196
|
+
reading.grammatical_case = Case::NOMINATIVE;
|
|
197
|
+
} else if (kMixed.contains(w1)) {
|
|
198
|
+
reading.declension = Declension::MIXED;
|
|
199
|
+
} else {
|
|
200
|
+
reading.declension = Declension::STRONG;
|
|
201
|
+
reading.grammatical_case = case_after(w1);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
} // namespace
|
|
220
205
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
std::u32string head;
|
|
228
|
-
if (high == 1) {
|
|
229
|
-
head = (base >= 1000000LL) ? U"eine " : U"ein";
|
|
230
|
-
} else {
|
|
231
|
-
head = to_cardinal_int(high);
|
|
232
|
-
if (base >= 1000000LL) {
|
|
233
|
-
head += U" ";
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
std::u32string scale = it->second;
|
|
238
|
-
if (base >= 1000000LL && high > 1) {
|
|
239
|
-
if (base == 1000000LL) scale = U"Millionen";
|
|
240
|
-
else if (base == 1000000000LL) scale = U"Milliarden";
|
|
241
|
-
}
|
|
206
|
+
Num2Word::Num2Word() : Num2WordLayer(kNotation, kJoiners) {
|
|
207
|
+
add_pattern(std::make_unique<DatePattern>(kDateFormat));
|
|
208
|
+
add_pattern(std::make_unique<PhonePattern>());
|
|
209
|
+
add_pattern(std::make_unique<DotOrdinalPattern>());
|
|
210
|
+
add_pattern(std::make_unique<SuffixPattern>(Kind::DECADE, kDecadeSuffixes, kDecadeFormat));
|
|
211
|
+
}
|
|
242
212
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
213
|
+
// -----------------------
|
|
214
|
+
// ----- Resolution -----
|
|
215
|
+
// -----------------------
|
|
216
|
+
|
|
217
|
+
bool Num2Word::accept(const Match& match, const Context& context) const {
|
|
218
|
+
switch (match.kind) {
|
|
219
|
+
case Kind::DATE:
|
|
220
|
+
// "am 12. 3." is a date, "Platz 1. 2 Tore" is not
|
|
221
|
+
return match.text.find(U' ') == std::u32string_view::npos || kDateCues.contains(context.before());
|
|
222
|
+
case Kind::TIME:
|
|
223
|
+
if (match.numbers.size() == 2) {
|
|
224
|
+
bool decimal = match.separator == U'.' && match.suffix.empty();
|
|
225
|
+
return value(match.numbers[0]) <= 24 && value(match.numbers[1]) <= 59 && !decimal;
|
|
247
226
|
}
|
|
248
|
-
return
|
|
227
|
+
return true;
|
|
228
|
+
case Kind::ORDINAL: {
|
|
229
|
+
// "Platz 3. Danach", "Platz 1. 2 Tore": a sentence end, not an ordinal
|
|
230
|
+
static const std::unordered_set<std::u32string> inflecting = [] {
|
|
231
|
+
std::unordered_set<std::u32string> words = {U"und", U"oder", U"bis"};
|
|
232
|
+
for (const auto* set : {&kWeak, &kWeakNominative, &kMixed, &kDative, &kAccusative, &kGenitive}) {
|
|
233
|
+
words.insert(set->begin(), set->end());
|
|
234
|
+
}
|
|
235
|
+
return words;
|
|
236
|
+
}();
|
|
237
|
+
auto words = words_of(context.tail());
|
|
238
|
+
std::u32string_view next = words.empty() ? U"" : words[0];
|
|
239
|
+
bool month = std::ranges::find(kMonths, next) != kMonths.end();
|
|
240
|
+
bool sentence = capitalized(next) && !month && !inflecting.contains(context.before());
|
|
241
|
+
return !next.empty() && !unicode::isdigit(next[0]) && !sentence;
|
|
249
242
|
}
|
|
243
|
+
default:
|
|
244
|
+
return true;
|
|
250
245
|
}
|
|
251
|
-
|
|
252
|
-
return conversions::utf8_to_u32(std::to_string(value));
|
|
253
246
|
}
|
|
254
247
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
248
|
+
NumberReading Num2Word::resolve(const Match& match, const Context& context) const {
|
|
249
|
+
NumberReading reading;
|
|
250
|
+
|
|
251
|
+
switch (match.kind) {
|
|
252
|
+
case Kind::DATE:
|
|
253
|
+
resolve_ending(context, U"Monat", reading);
|
|
254
|
+
return reading;
|
|
255
|
+
|
|
256
|
+
case Kind::ORDINAL: {
|
|
257
|
+
// The noun is the first capitalized word after it: der 3. Platz
|
|
258
|
+
std::u32string_view noun;
|
|
259
|
+
for (auto word : words_of(context.tail())) {
|
|
260
|
+
if (capitalized(word)) {
|
|
261
|
+
size_t end = word.find_last_not_of(U".,;:!?");
|
|
262
|
+
noun = word.substr(0, end == std::u32string_view::npos ? 0 : end + 1);
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
resolve_ending(context, noun, reading);
|
|
267
|
+
return reading;
|
|
268
|
+
}
|
|
259
269
|
|
|
260
|
-
|
|
261
|
-
|
|
270
|
+
case Kind::DECADE: {
|
|
271
|
+
std::u32string next = context.after();
|
|
272
|
+
reading.capitalized = next != U"Jahre" && next != U"Jahren" && next != U"Jahrgang";
|
|
273
|
+
return reading;
|
|
274
|
+
}
|
|
262
275
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
if (!value_str.empty() && value_str.back() == '.') {
|
|
266
|
-
value_str.pop_back();
|
|
276
|
+
default:
|
|
277
|
+
break;
|
|
267
278
|
}
|
|
268
279
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
280
|
+
// "1" before a noun is said like an article, in the case of the word before it: mit einer Stimme
|
|
281
|
+
std::u32string next = context.after();
|
|
282
|
+
std::u32string noun = next;
|
|
283
|
+
if ((next == U"bis" || next == U"oder") && all_digits(context.after(2))) {
|
|
284
|
+
// "1 bis 2 Werktage": gendered by the plural noun
|
|
285
|
+
noun = context.after(3);
|
|
286
|
+
if (noun.ends_with(U"en")) {
|
|
287
|
+
noun.pop_back();
|
|
288
|
+
} else if (noun.ends_with(U'e')) {
|
|
289
|
+
noun.pop_back();
|
|
290
|
+
}
|
|
272
291
|
}
|
|
292
|
+
reading.article = capitalized(noun) && noun != U"Quadrat" && (noun != next || !labelled(context));
|
|
293
|
+
reading.grammatical_case = case_after(context.before());
|
|
294
|
+
reading.gender = gender_of(noun);
|
|
295
|
+
|
|
296
|
+
// 1998 Abi gemacht, im Jahr 1945; but 1945 Einwohner, 1920 mal 1080
|
|
297
|
+
bool month = std::ranges::find(kMonths, next) != kMonths.end();
|
|
298
|
+
bool measure = next.ends_with(U'e') || next.ends_with(U'n') || next.ends_with(U"er") || next.ends_with(U's') ||
|
|
299
|
+
kMeasureWords.contains(next);
|
|
300
|
+
bool counted = capitalized(next) && measure && !month;
|
|
301
|
+
std::u32string previous = context.before();
|
|
302
|
+
bool times = next == U"mal" || previous == U"mal";
|
|
303
|
+
reading.year = !times && (kYearCues.contains(previous) || !counted);
|
|
304
|
+
return reading;
|
|
305
|
+
}
|
|
273
306
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
int32_t integer_part = integer_part_str.empty() ? 0 : std::stoi(integer_part_str);
|
|
307
|
+
// --------------------
|
|
308
|
+
// ----- Readings -----
|
|
309
|
+
// --------------------
|
|
278
310
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
311
|
+
std::u32string Num2Word::read_number(const Number& number, const NumberReading& reading) const {
|
|
312
|
+
if (!number.fraction.empty()) {
|
|
313
|
+
std::u32string head = number.integer.empty() ? U"" : cardinal(value(number)) + U" ";
|
|
314
|
+
return head + U"Komma " + digits(number.fraction);
|
|
284
315
|
}
|
|
285
316
|
|
|
286
|
-
|
|
317
|
+
auto n = value_of(number.integer);
|
|
318
|
+
if (!n || spoken_digits(number, 5)) {
|
|
319
|
+
return digits(number.integer);
|
|
320
|
+
}
|
|
321
|
+
if (*n == 1 && reading.article) {
|
|
322
|
+
return article(reading.grammatical_case, reading.gender);
|
|
323
|
+
}
|
|
324
|
+
if (number.integer.size() == 4 && !number.grouped && reading.year) {
|
|
325
|
+
return year(*n);
|
|
326
|
+
}
|
|
327
|
+
return cardinal(*n);
|
|
287
328
|
}
|
|
288
329
|
|
|
289
|
-
std::u32string Num2Word::
|
|
290
|
-
|
|
291
|
-
|
|
330
|
+
std::u32string Num2Word::read_code_digits(std::u32string_view text) const {
|
|
331
|
+
auto n = value_of(text);
|
|
332
|
+
if ((text.size() > 1 && text[0] == U'0') || text.size() > 4 || !n) {
|
|
333
|
+
return digits(text);
|
|
292
334
|
}
|
|
335
|
+
return year(*n);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
std::u32string Num2Word::read_date(const Match& match, const NumberReading& reading) const {
|
|
339
|
+
std::u32string words =
|
|
340
|
+
ordinal(value(match.numbers[0]), ending(reading)) + U" " + kMonths[value(match.numbers[1]) - 1];
|
|
341
|
+
return match.numbers.size() < 3 ? words : words + U" " + year(value(match.numbers[2]));
|
|
342
|
+
}
|
|
293
343
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
else if (value == 8) stem = U"acht";
|
|
299
|
-
else if (value < 20) stem = to_cardinal_int(value) + U"t";
|
|
300
|
-
else stem = to_cardinal_int(value) + U"st";
|
|
301
|
-
|
|
302
|
-
std::u32string ending = U"e";
|
|
303
|
-
if (!suffix.empty()) {
|
|
304
|
-
char32_t last = utils::unicode::tolower(suffix.back());
|
|
305
|
-
if (last == U'n') ending = U"en";
|
|
306
|
-
else if (last == U'r') ending = U"er";
|
|
307
|
-
else if (last == U's') ending = U"es";
|
|
308
|
-
else if (last == U'm') ending = U"em";
|
|
344
|
+
std::u32string Num2Word::read_phone(const Match& match, const NumberReading& reading) const {
|
|
345
|
+
std::u32string all;
|
|
346
|
+
for (const auto& group : match.numbers) {
|
|
347
|
+
all += group.integer;
|
|
309
348
|
}
|
|
349
|
+
return digits(all);
|
|
350
|
+
}
|
|
310
351
|
|
|
311
|
-
|
|
352
|
+
std::u32string Num2Word::read_fraction(const Match& match, const NumberReading& reading) const {
|
|
353
|
+
uint64_t a = value(match.numbers[0]), b = value(match.numbers[1]);
|
|
354
|
+
auto it = kFractions.find({a, b});
|
|
355
|
+
return it != kFractions.end() ? it->second : cardinal(a) + U" durch " + cardinal(b);
|
|
312
356
|
}
|
|
313
357
|
|
|
314
|
-
std::u32string Num2Word::
|
|
315
|
-
|
|
316
|
-
|
|
358
|
+
std::u32string Num2Word::read_time(const Match& match, const NumberReading& reading) const {
|
|
359
|
+
std::u32string words = stem(value(match.numbers[0])) + U" Uhr";
|
|
360
|
+
if (match.numbers.size() == 2 && value(match.numbers[1]) > 0) {
|
|
361
|
+
words += U" " + cardinal(value(match.numbers[1]));
|
|
317
362
|
}
|
|
318
|
-
return
|
|
363
|
+
return words;
|
|
319
364
|
}
|
|
320
365
|
|
|
321
|
-
std::u32string Num2Word::
|
|
322
|
-
|
|
323
|
-
return num2word::kMonths[month];
|
|
324
|
-
}
|
|
325
|
-
return U"";
|
|
366
|
+
std::u32string Num2Word::read_ordinal(const Match& match, const NumberReading& reading) const {
|
|
367
|
+
return ordinal(value(match.numbers[0]), ending(reading));
|
|
326
368
|
}
|
|
327
369
|
|
|
328
|
-
std::u32string Num2Word::
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
return res;
|
|
370
|
+
std::u32string Num2Word::read_decade(const Match& match, const NumberReading& reading) const {
|
|
371
|
+
// 90er, 90ern: neunziger, neunzigern; 1990er: neunzehnhundertneunziger
|
|
372
|
+
const auto& digits = match.numbers[0].integer;
|
|
373
|
+
std::u32string number = digits.size() > 1 && digits[0] == U'0' ? U"null" + cardinal(value(match.numbers[0])) :
|
|
374
|
+
year(value(match.numbers[0]));
|
|
375
|
+
std::u32string words = number + std::u32string(match.suffix);
|
|
376
|
+
if (reading.capitalized) {
|
|
377
|
+
words[0] = unicode::toupper(words[0]);
|
|
337
378
|
}
|
|
338
|
-
return
|
|
379
|
+
return words;
|
|
339
380
|
}
|
|
340
381
|
|
|
341
|
-
|
|
342
|
-
|
|
382
|
+
std::u32string Num2Word::read_compound(const Match& match, const NumberReading& reading) const {
|
|
383
|
+
// 30-jährige: dreißigjährige; 4-Zimmer-Wohnung: Vier-Zimmer-Wohnung
|
|
384
|
+
const Number& number = match.numbers[0];
|
|
385
|
+
std::u32string words =
|
|
386
|
+
number.fraction.empty() && !number.grouped ? stem(value(number)) : read_number(number, reading);
|
|
387
|
+
if (capitalized(match.suffix)) {
|
|
388
|
+
words[0] = unicode::toupper(words[0]);
|
|
389
|
+
return words + U"-" + std::u32string(match.suffix);
|
|
390
|
+
}
|
|
391
|
+
return words + std::u32string(match.suffix);
|
|
343
392
|
}
|
|
344
393
|
|
|
345
|
-
std::u32string Num2Word::
|
|
346
|
-
std::u32string
|
|
347
|
-
std::u32string
|
|
348
|
-
if (
|
|
349
|
-
|
|
350
|
-
} else if (denominator == 3) {
|
|
351
|
-
den_word = U"drittel";
|
|
352
|
-
} else if (denominator == 4) {
|
|
353
|
-
den_word = U"viertel";
|
|
354
|
-
} else if (denominator < 20) {
|
|
355
|
-
den_word = to_cardinal_int(denominator) + U"tel";
|
|
356
|
-
} else {
|
|
357
|
-
den_word = to_cardinal_int(denominator) + U"stel";
|
|
394
|
+
std::u32string Num2Word::read_money(const Number& number, const Match& match, const NumberReading& reading) const {
|
|
395
|
+
const std::u32string& noun = kCurrencies.at(std::u32string(match.unit));
|
|
396
|
+
std::u32string one = article(reading.grammatical_case, gender_of(noun));
|
|
397
|
+
if (!match.scale.empty()) {
|
|
398
|
+
return read_scale(number, match, reading) + U" " + noun;
|
|
358
399
|
}
|
|
359
400
|
|
|
360
|
-
|
|
361
|
-
|
|
401
|
+
// A price: drei Euro fünfzig, neunundneunzig Cent
|
|
402
|
+
if (number.fraction.size() == 2) {
|
|
403
|
+
uint64_t cents = value_of(number.fraction).value_or(0);
|
|
404
|
+
if (value(number) == 0) {
|
|
405
|
+
return cardinal(cents) + U" Cent";
|
|
406
|
+
}
|
|
407
|
+
Number whole{.integer = number.integer, .grouped = number.grouped};
|
|
408
|
+
std::u32string words = number.integer == U"1" ? one : read_number(whole, reading);
|
|
409
|
+
return words + U" " + noun + U" " + cardinal(cents);
|
|
362
410
|
}
|
|
363
|
-
return num_word + U" " + den_word;
|
|
364
|
-
}
|
|
365
411
|
|
|
366
|
-
|
|
367
|
-
return
|
|
412
|
+
bool single = number.integer == U"1" && number.fraction.empty();
|
|
413
|
+
return (single ? one : read_number(number, reading)) + U" " + noun;
|
|
368
414
|
}
|
|
369
415
|
|
|
370
|
-
std::u32string Num2Word::
|
|
371
|
-
|
|
372
|
-
|
|
416
|
+
std::u32string Num2Word::read_scale(const Number& number, const Match& match, const NumberReading& reading) const {
|
|
417
|
+
const Forms& scale = kScales.at(std::u32string(match.scale));
|
|
418
|
+
if (scale.many == U"tausend") {
|
|
419
|
+
return read_number(number, reading) + U"tausend";
|
|
373
420
|
}
|
|
421
|
+
bool single = number.integer == U"1" && number.fraction.empty();
|
|
422
|
+
return single ? U"eine " + scale.one : read_number(number, reading) + U" " + scale.many;
|
|
423
|
+
}
|
|
374
424
|
|
|
375
|
-
|
|
376
|
-
std::
|
|
425
|
+
std::u32string Num2Word::read_percent(const Number& number, const Match& match, const NumberReading& reading) const {
|
|
426
|
+
std::u32string words = read_number(number, reading);
|
|
427
|
+
// 8%ige: achtprozentige
|
|
428
|
+
return match.suffix.empty() ? words + U" Prozent" : words + U"prozent" + std::u32string(match.suffix);
|
|
429
|
+
}
|
|
377
430
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
std::u32string amount = singular ? U"ein" : to_cardinal_float(*val, num_part);
|
|
383
|
-
return amount + U" " + to_currency(currency, *val);
|
|
431
|
+
std::u32string Num2Word::read_unit(const Number& number, const Match& match, const NumberReading& reading) const {
|
|
432
|
+
const Forms& unit = kUnits.at(std::u32string(match.unit));
|
|
433
|
+
if (number.integer == U"1" && number.fraction.empty()) {
|
|
434
|
+
return article(reading.grammatical_case, gender_of(unit.one)) + U" " + unit.one;
|
|
384
435
|
}
|
|
385
|
-
|
|
386
|
-
auto val = as_int(num_part);
|
|
387
|
-
if (!val) return U"";
|
|
388
|
-
bool singular = (*val == 1);
|
|
389
|
-
std::u32string amount = singular ? U"ein" : to_cardinal_int(*val);
|
|
390
|
-
return amount + U" " + to_currency(currency, *val);
|
|
436
|
+
return read_number(number, reading) + U" " + unit.many;
|
|
391
437
|
}
|
|
392
438
|
|
|
393
439
|
} // namespace phonemis::de
|