aboutsummaryrefslogtreecommitdiffstats
path: root/text/syllabic.py
diff options
context:
space:
mode:
Diffstat (limited to 'text/syllabic.py')
-rw-r--r--text/syllabic.py40
1 files changed, 39 insertions, 1 deletions
diff --git a/text/syllabic.py b/text/syllabic.py
index 6eb7c93..4a79869 100644
--- a/text/syllabic.py
+++ b/text/syllabic.py
@@ -12,6 +12,10 @@ HARFBUZZ_SRC is HarfBuzz 10.2.0's src/ directory; what is read from it:
read cell for cell (Unicode here is 15.1: the table is taken as HarfBuzz
has it). Khmer and Myanmar read the same table.
+- Each character's category for the Universal Shaping Engine: hb-ot-
+ shaper-use-table.hh, whose arrays and lookup (gen-use-table.py's) are
+ carried over as they are, the categories named in them resolved.
+
- The syllable machines: hb-ot-shaper-*-machine.rl, the Ragel grammars.
This compiles each to a DFA with Ragel's scanner semantics (the longest
match from each position, ties to the pattern listed first), its symbols
@@ -27,7 +31,7 @@ import sys
from pathlib import Path
HB = Path(sys.argv[1] if len(sys.argv) > 1 else '.')
-MACHINES = ['indic', 'khmer', 'myanmar']
+MACHINES = ['indic', 'khmer', 'myanmar', 'use']
ALPHABET = 64 # categories past 63 are folded into 63, which only `any` takes
@@ -277,6 +281,22 @@ def runs_of(cells):
return runs
+def use_table(grammar):
+ """HarfBuzz's USE lookup: its arrays (categories resolved to numbers)
+ and its expression, as C."""
+ text = (HB / 'hb-ot-shaper-use-table.hh').read_text()
+ part = text[text.index('#ifndef HB_OPTIMIZE_SIZE'):text.index('#else')]
+ arrays = []
+ for kind, name, n, body in re.findall(r'static const (uint8_t|uint16_t)\s+(hb_use_\w+)\[(\d+)\] =\s*\{(.*?)\};',
+ part, re.S):
+ values = [int(t) if t.isdigit() else grammar.symbols[t] for t in re.findall(r'[A-Za-z_]\w*|\d+', body)]
+ assert len(values) == int(n), name
+ arrays.append((kind, name.replace('hb_use_', 'use_'), values))
+ expression = re.search(r'return (u<.*?);\n', part).group(1).replace('hb_use_', 'use_')
+ assert expression.endswith(':O')
+ return arrays, expression[:-1] + str(grammar.symbols['O'])
+
+
# ---- Checking against Ragel's machines (hb-ot-shaper-*-machine.hh)
def ragel(name):
@@ -445,6 +465,24 @@ def main():
out.append(f' return 0x{default[0] | default[1] << 8:04X};')
out.append('}')
out.append('')
+ arrays, expression = use_table(grammars['use'])
+ out.append('/* Each character\'s USE category (hb-ot-shaper-use-table.hh, Unicode 16): HarfBuzz\'s arrays and')
+ out.append(' * lookup. */')
+ for kind, name, values in arrays:
+ out.append(f'static const {kind} {name}[{len(values)}] = {{')
+ for k in range(0, len(values), 16):
+ out.append(' ' + ', '.join(str(v) for v in values[k:k + 16]) + ',')
+ out.append('};')
+ out.append('static unsigned use_b4(const uint8_t *a, unsigned i) { return (a[i >> 1] >> ((i & 1u) << 2)) & 15u; }')
+ out.append(f'uint8_t vega_use_category(uint32_t u) {{ return (uint8_t)({expression}); }}')
+ out.append('')
+ out.append('/* The categories syllabic.h names are the machines\' own. */')
+ for name, prefix in (('indic', 'VEGA_OT_'), ('khmer', 'VEGA_OT_'), ('myanmar', 'VEGA_OT_'), ('use', 'VEGA_USE_')):
+ for symbol, value in sorted(grammars[name].symbols.items()):
+ if name == 'myanmar' and symbol in ('IV', 'DB', 'GB'):
+ continue # Myanmar's names for V, N and PLACEHOLDER
+ out.append(f'_Static_assert({prefix}{symbol.upper()} == {value}, "{name} {symbol}");')
+ out.append('')
out.append('/* The syllable machines: a DFA over classes of symbol; a state\'s accept is')
out.append(' * the syllable type it ends, plus one. */')
for name in MACHINES: