scriptconv 0.0.3a12__tar.gz → 0.0.3a14__tar.gz

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.
Files changed (81) hide show
  1. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/PKG-INFO +29 -1
  2. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/pyproject.toml +8 -1
  3. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/__main__.py +18 -0
  4. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/phonemizers/__init__.py +4 -0
  5. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/__init__.py +7 -0
  6. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/bw2ipa.py +207 -0
  7. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/hangul2ipa.py +784 -0
  8. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/ko_tables/aspiration.csv +20 -0
  9. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/ko_tables/assimilation.csv +31 -0
  10. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/ko_tables/double_coda.csv +17 -0
  11. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/ko_tables/hanja.tsv +8525 -0
  12. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/ko_tables/ipa.csv +22 -0
  13. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/ko_tables/neutralization.csv +11 -0
  14. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/ko_tables/tensification.csv +56 -0
  15. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/ko_tables/yale.csv +22 -0
  16. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/shami/__init__.py +29 -0
  17. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/shami/codeswitch.py +91 -0
  18. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/shami/diacritize.py +89 -0
  19. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/shami/dialectal.py +43 -0
  20. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/shami/english_g2p.py +67 -0
  21. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/shami/espeak.py +51 -0
  22. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/shami/frontend.py +135 -0
  23. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/shami/levantine_g2p.py +317 -0
  24. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/shami/normalize.py +254 -0
  25. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/shami/phoneme_inventory.py +219 -0
  26. scriptconv-0.0.3a14/scriptconv/phonemizers/_thirdparty/zh_num.py +238 -0
  27. scriptconv-0.0.3a14/scriptconv/phonemizers/ar.py +96 -0
  28. scriptconv-0.0.3a14/scriptconv/phonemizers/en.py +187 -0
  29. scriptconv-0.0.3a14/scriptconv/phonemizers/ja.py +104 -0
  30. scriptconv-0.0.3a14/scriptconv/phonemizers/ko.py +65 -0
  31. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/phonemizers/registry.py +39 -0
  32. scriptconv-0.0.3a14/scriptconv/phonemizers/shami.py +81 -0
  33. scriptconv-0.0.3a14/scriptconv/phonemizers/zh.py +266 -0
  34. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/version.py +1 -1
  35. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv.egg-info/PKG-INFO +29 -1
  36. scriptconv-0.0.3a14/scriptconv.egg-info/SOURCES.txt +78 -0
  37. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv.egg-info/requires.txt +34 -0
  38. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/tests/test_phonemizers_base.py +29 -0
  39. scriptconv-0.0.3a14/tests/test_phonemizers_cjk_ar.py +69 -0
  40. scriptconv-0.0.3a12/scriptconv.egg-info/SOURCES.txt +0 -49
  41. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/LICENSE +0 -0
  42. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/README.md +0 -0
  43. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/requirements.txt +0 -0
  44. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/__init__.py +0 -0
  45. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/cangjie.py +0 -0
  46. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/conventions.py +0 -0
  47. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/data/__init__.py +0 -0
  48. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/data/cangjie5_tc.tsv.gz +0 -0
  49. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/graph.py +0 -0
  50. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/notation.py +0 -0
  51. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/phonemizers/base.py +0 -0
  52. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/phonemizers/enums.py +0 -0
  53. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/phonemizers/eu.py +0 -0
  54. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/phonemizers/fa.py +0 -0
  55. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/phonemizers/gl.py +0 -0
  56. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/phonemizers/he.py +0 -0
  57. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/phonemizers/mul.py +0 -0
  58. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/phonemizers/mwl.py +0 -0
  59. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/phonemizers/o2ipa.py +0 -0
  60. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/phonemizers/pt.py +0 -0
  61. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/phonemizers/vi.py +0 -0
  62. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/py.typed +0 -0
  63. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/readings.py +0 -0
  64. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/scripts.py +0 -0
  65. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv/translit.py +0 -0
  66. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv.egg-info/dependency_links.txt +0 -0
  67. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/scriptconv.egg-info/top_level.txt +0 -0
  68. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/setup.cfg +0 -0
  69. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/tests/test_arpa_stress.py +0 -0
  70. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/tests/test_cangjie.py +0 -0
  71. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/tests/test_cli.py +0 -0
  72. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/tests/test_conventions.py +0 -0
  73. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/tests/test_errors_policy.py +0 -0
  74. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/tests/test_examples.py +0 -0
  75. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/tests/test_graph.py +0 -0
  76. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/tests/test_notation.py +0 -0
  77. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/tests/test_readings.py +0 -0
  78. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/tests/test_readings_zh.py +0 -0
  79. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/tests/test_scripts.py +0 -0
  80. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/tests/test_scripts_stressonnx_compat.py +0 -0
  81. {scriptconv-0.0.3a12 → scriptconv-0.0.3a14}/tests/test_translit.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scriptconv
3
- Version: 0.0.3a12
3
+ Version: 0.0.3a14
4
4
  Summary: Zero-dependency script & phoneme-notation core — ISO-15924 detection & metadata, IPA↔ARPABET/X-SAMPA/Lexique/Kirshenbaum/Cotovía/RFE, Buckwalter↔Arabic, Hangul→jamo, kana
5
5
  License: Apache-2.0
6
6
  Project-URL: Homepage, https://github.com/TigreGotico/scriptconv
@@ -78,6 +78,33 @@ Requires-Dist: viphoneme; extra == "vi"
78
78
  Provides-Extra: tashkeel
79
79
  Requires-Dist: scriptconv[phonemizers]; extra == "tashkeel"
80
80
  Requires-Dist: text2tashkeel; extra == "tashkeel"
81
+ Provides-Extra: ja-phonemizers
82
+ Requires-Dist: scriptconv[phonemizers]; extra == "ja-phonemizers"
83
+ Requires-Dist: pyopenjtalk; extra == "ja-phonemizers"
84
+ Requires-Dist: cutlet; extra == "ja-phonemizers"
85
+ Requires-Dist: pykakasi<3,>=2.3; extra == "ja-phonemizers"
86
+ Provides-Extra: ko
87
+ Requires-Dist: scriptconv[phonemizers]; extra == "ko"
88
+ Requires-Dist: g2pk; extra == "ko"
89
+ Requires-Dist: regex; extra == "ko"
90
+ Provides-Extra: zh-phonemizers
91
+ Requires-Dist: scriptconv[phonemizers]; extra == "zh-phonemizers"
92
+ Requires-Dist: jieba; extra == "zh-phonemizers"
93
+ Requires-Dist: pypinyin<1,>=0.50; extra == "zh-phonemizers"
94
+ Requires-Dist: xpinyin; extra == "zh-phonemizers"
95
+ Requires-Dist: g2pM; extra == "zh-phonemizers"
96
+ Requires-Dist: pinyin_to_ipa; extra == "zh-phonemizers"
97
+ Provides-Extra: en-phonemizers
98
+ Requires-Dist: scriptconv[phonemizers]; extra == "en-phonemizers"
99
+ Requires-Dist: g2p_en; extra == "en-phonemizers"
100
+ Requires-Dist: openphonemizer; extra == "en-phonemizers"
101
+ Requires-Dist: deep-phonemizer; extra == "en-phonemizers"
102
+ Provides-Extra: ar-phonemizers
103
+ Requires-Dist: scriptconv[phonemizers]; extra == "ar-phonemizers"
104
+ Requires-Dist: arbtok; extra == "ar-phonemizers"
105
+ Provides-Extra: shami
106
+ Requires-Dist: scriptconv[phonemizers]; extra == "shami"
107
+ Requires-Dist: regex; extra == "shami"
81
108
  Provides-Extra: test
82
109
  Requires-Dist: pytest; extra == "test"
83
110
  Requires-Dist: pytest-timeout; extra == "test"
@@ -85,6 +112,7 @@ Requires-Dist: pykakasi<3,>=2.3; extra == "test"
85
112
  Requires-Dist: pypinyin<1,>=0.50; extra == "test"
86
113
  Requires-Dist: quebra-frases; extra == "test"
87
114
  Requires-Dist: langcodes; extra == "test"
115
+ Requires-Dist: regex; extra == "test"
88
116
  Dynamic: license-file
89
117
 
90
118
  # scriptconv
@@ -53,7 +53,13 @@ he = ["scriptconv[phonemizers]", "phonikud-onnx"]
53
53
  fa = ["scriptconv[phonemizers]", "persian_phonemizer"]
54
54
  vi = ["scriptconv[phonemizers]", "viphoneme"]
55
55
  tashkeel = ["scriptconv[phonemizers]", "text2tashkeel"]
56
- test = ["pytest", "pytest-timeout", "pykakasi>=2.3,<3", "pypinyin>=0.50,<1", "quebra-frases", "langcodes"]
56
+ ja-phonemizers = ["scriptconv[phonemizers]", "pyopenjtalk", "cutlet", "pykakasi>=2.3,<3"]
57
+ ko = ["scriptconv[phonemizers]", "g2pk", "regex"]
58
+ zh-phonemizers = ["scriptconv[phonemizers]", "jieba", "pypinyin>=0.50,<1", "xpinyin", "g2pM", "pinyin_to_ipa"]
59
+ en-phonemizers = ["scriptconv[phonemizers]", "g2p_en", "openphonemizer", "deep-phonemizer"]
60
+ ar-phonemizers = ["scriptconv[phonemizers]", "arbtok"]
61
+ shami = ["scriptconv[phonemizers]", "regex"]
62
+ test = ["pytest", "pytest-timeout", "pykakasi>=2.3,<3", "pypinyin>=0.50,<1", "quebra-frases", "langcodes", "regex"]
57
63
 
58
64
  [project.urls]
59
65
  Homepage = "https://github.com/TigreGotico/scriptconv"
@@ -65,6 +71,7 @@ include = ["scriptconv*"]
65
71
  [tool.setuptools.package-data]
66
72
  scriptconv = ["py.typed"]
67
73
  "scriptconv.data" = ["*.tsv.gz"]
74
+ "scriptconv.phonemizers._thirdparty" = ["ko_tables/*.csv", "ko_tables/*.tsv"]
68
75
 
69
76
  [tool.pytest.ini_options]
70
77
  testpaths = ["tests"]
@@ -12,6 +12,7 @@ Usage
12
12
  python -m scriptconv restyle <convention> <style> <text>
13
13
  python -m scriptconv conventions [--script CODE]
14
14
  python -m scriptconv route <src> <dst>
15
+ python -m scriptconv phonemize <lang> <text> [--phonemizer ID] [--alphabet A]
15
16
 
16
17
  Examples
17
18
  --------
@@ -69,6 +70,12 @@ def main(argv: list[str] | None = None) -> int:
69
70
  rt.add_argument("src", help="Source representation id")
70
71
  rt.add_argument("dst", help="Target representation id")
71
72
 
73
+ ph = sub.add_parser("phonemize", help="Phonemize text (per-language default backend)")
74
+ ph.add_argument("lang", help="Language code")
75
+ ph.add_argument("text", help="Text to phonemize")
76
+ ph.add_argument("--phonemizer", default=None, help="Backend override (Phonemizer value)")
77
+ ph.add_argument("--alphabet", default="ipa", help="Output alphabet (default ipa)")
78
+
72
79
  args = p.parse_args(argv)
73
80
 
74
81
  if args.command is None:
@@ -86,6 +93,7 @@ def main(argv: list[str] | None = None) -> int:
86
93
  "restyle": lambda: _do_restyle(args),
87
94
  "conventions": lambda: _do_conventions(args),
88
95
  "route": lambda: _do_route(args),
96
+ "phonemize": lambda: _do_phonemize(args),
89
97
  }
90
98
  dispatch[args.command]()
91
99
  return 0
@@ -108,6 +116,16 @@ def _do_convert(args: argparse.Namespace) -> None:
108
116
  f"graph nodes: {', '.join(DEFAULT_GRAPH.nodes)})")
109
117
 
110
118
 
119
+ def _do_phonemize(args: argparse.Namespace) -> None:
120
+ from scriptconv.phonemizers import Alphabet, Phonemizer, phonemize
121
+ try:
122
+ override = Phonemizer(args.phonemizer) if args.phonemizer else None
123
+ print(phonemize(args.text, args.lang, Alphabet(args.alphabet),
124
+ override=override))
125
+ except (ValueError, ImportError) as e:
126
+ raise SystemExit(f"error: {e}")
127
+
128
+
111
129
  def _do_route(args: argparse.Namespace) -> None:
112
130
  from scriptconv.graph import DEFAULT_GRAPH
113
131
  try:
@@ -21,6 +21,8 @@ from scriptconv.phonemizers.registry import (
21
21
  get_phonemizer,
22
22
  get_phonemizer_class,
23
23
  phonemizer_for_lang,
24
+ phonemize,
25
+ register,
24
26
  )
25
27
 
26
28
  __all__ = [
@@ -37,4 +39,6 @@ __all__ = [
37
39
  "get_phonemizer",
38
40
  "get_phonemizer_class",
39
41
  "phonemizer_for_lang",
42
+ "phonemize",
43
+ "register",
40
44
  ]
@@ -0,0 +1,7 @@
1
+ """Vendored first-party-maintained G2P implementations.
2
+
3
+ Each module carries its upstream provenance and license in its header; only
4
+ permissively-licensed code lives here (MIT/Apache). GPL or NonCommercial
5
+ upstreams (KoG2P, mantoq's pyarabic/phonetise) are NOT vendored — their
6
+ wrapper classes raise with an explanation instead.
7
+ """
@@ -0,0 +1,207 @@
1
+ # translate.py
2
+ # Deterministic Mantoq → IPA converter
3
+ # Assumes the input is already tokenized using the Mantoq inventory.
4
+
5
+ # ---------------------------------------------------------------------------
6
+ # Token → IPA maps
7
+ # ---------------------------------------------------------------------------
8
+
9
+ CONSONANTS = {
10
+ "b": "b",
11
+ "t": "t",
12
+ "^": "θ",
13
+ "j": "d͡ʒ",
14
+ "H": "ħ",
15
+ "x": "x",
16
+ "d": "d",
17
+ "*": "ð",
18
+ "r": "r",
19
+ "z": "z",
20
+ "s": "s",
21
+ "$": "ʃ",
22
+ "S": "sˤ",
23
+ "D": "dˤ",
24
+ "T": "tˤ",
25
+ "Z": "ðˤ",
26
+ "E": "ʕ",
27
+ "g": "ɣ",
28
+ "f": "f",
29
+ "q": "q",
30
+ "k": "k",
31
+ "l": "l",
32
+ "m": "m",
33
+ "n": "n",
34
+ "h": "h",
35
+ "w": "w",
36
+ "y": "j",
37
+ "v": "v"
38
+ }
39
+
40
+ VOWELS = {
41
+ "a": "a",
42
+ "aa": "aː",
43
+ "aaaa": "aːː",
44
+ "i": "i",
45
+ "ii": "iː",
46
+ "u": "u",
47
+ "uu": "uː",
48
+ }
49
+
50
+
51
+ # Punctuation is passed through unchanged:
52
+ PUNCTUATION = set(list(".,;:!?()[]{}\"'"))
53
+
54
+ # ---------------------------------------------------------------------------
55
+ # Tokenizer
56
+ # ---------------------------------------------------------------------------
57
+
58
+ def tokenize_mantoq(text):
59
+ """
60
+ Tokenize Mantoq string deterministically.
61
+
62
+ Priority:
63
+ 1. _dbl_
64
+ 2. aaaa
65
+ 3. ii / uu / aa
66
+ 4. single char tokens
67
+ 5. punctuation and raw chars are passed through
68
+ """
69
+ tokens = []
70
+ i = 0
71
+ L = len(text)
72
+
73
+ while i < L:
74
+
75
+ # doubling marker
76
+ if text.startswith("_dbl_", i):
77
+ tokens.append("_dbl_")
78
+ i += 5
79
+ continue
80
+
81
+ # word separator
82
+ if text.startswith("_+_", i):
83
+ tokens.append("_+_")
84
+ i += 3
85
+ continue
86
+
87
+ # longest vowel first
88
+ if text.startswith("aaaa", i):
89
+ tokens.append("aaaa")
90
+ i += 4
91
+ continue
92
+
93
+ if text.startswith("aa", i):
94
+ tokens.append("aa")
95
+ i += 2
96
+ continue
97
+
98
+ if text.startswith("ii", i):
99
+ tokens.append("ii")
100
+ i += 2
101
+ continue
102
+
103
+ if text.startswith("uu", i):
104
+ tokens.append("uu")
105
+ i += 2
106
+ continue
107
+
108
+ # single-character consonant or vowel
109
+ ch = text[i]
110
+
111
+ if ch in CONSONANTS or ch in VOWELS:
112
+ tokens.append(ch)
113
+ i += 1
114
+ continue
115
+ if ch == "<":
116
+ tokens.append("ʔ")
117
+ i += 1
118
+ continue
119
+
120
+ # punctuation
121
+ if ch in PUNCTUATION:
122
+ tokens.append(ch)
123
+ i += 1
124
+ continue
125
+
126
+ # fallback: pass through unknown characters
127
+ tokens.append(ch)
128
+ i += 1
129
+
130
+ return tokens
131
+
132
+ # ---------------------------------------------------------------------------
133
+ # IPA Assembly
134
+ # ---------------------------------------------------------------------------
135
+
136
+ def apply_doubling(prev_token, prev_ipa):
137
+ """
138
+ Mantoq doubling rule:
139
+ - If previous token is a vowel token: lengthen it.
140
+ - If previous token is a consonant: mark gemination using ː.
141
+ """
142
+ if prev_token in VOWELS:
143
+ # ensure single long marker; long tokens already contain ː
144
+ if prev_ipa.endswith("ː"):
145
+ return prev_ipa + "ː"
146
+ return prev_ipa + "ː"
147
+
148
+ if prev_token in CONSONANTS:
149
+ # consonant gemination: use length mark, not duplication
150
+ if prev_ipa.endswith("ː"):
151
+ return prev_ipa # already geminated
152
+ return prev_ipa + "ː"
153
+
154
+ return prev_ipa
155
+
156
+
157
+ def mantoq_to_ipa(text):
158
+ tokens = tokenize_mantoq(text)
159
+
160
+ ipa_out = []
161
+ last_token = None
162
+ last_ipa = None
163
+
164
+ for tok in tokens:
165
+
166
+ # doubling applies to the previous symbol
167
+ if tok == "_dbl_":
168
+ if last_token is None:
169
+ continue
170
+ new_ipa = apply_doubling(last_token, last_ipa)
171
+ ipa_out[-1] = new_ipa
172
+ last_ipa = new_ipa
173
+ continue
174
+
175
+ # explicit word separation
176
+ if tok == "_+_":
177
+ ipa_out.append(" ")
178
+ last_token = tok
179
+ last_ipa = " "
180
+ continue
181
+
182
+ # vowels
183
+ if tok in VOWELS:
184
+ ipa_val = VOWELS[tok]
185
+ ipa_out.append(ipa_val)
186
+ last_token = tok
187
+ last_ipa = ipa_val
188
+ continue
189
+
190
+ # consonants
191
+ if tok in CONSONANTS:
192
+ ipa_val = CONSONANTS[tok]
193
+ ipa_out.append(ipa_val)
194
+ last_token = tok
195
+ last_ipa = ipa_val
196
+ continue
197
+
198
+ # punctuation and fallthrough
199
+ ipa_out.append(tok)
200
+ last_token = tok
201
+ last_ipa = tok
202
+
203
+ return "".join(ipa_out)
204
+
205
+
206
+ # backwards compat alias
207
+ bw2ipa = mantoq_to_ipa