File size: 3,898 Bytes
f211247
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/usr/bin/env python3
"""Build MZL ↔ ABZ mapping from Oracc OSL (osl.asl).

Input: /tmp/osl/00lib/osl.asl (Oracc Global Sign List, CC0)
Output: JSON with:
  - mzl_to_abz: MZL_num → ABZ_num
  - mzl_to_sign: MZL_num → canonical sign name
  - abz_to_sign: ABZ_num → canonical sign name
  - sign_to_mzl: sign → MZL_num
  - sign_to_abz: sign → ABZ_num
"""
import json, re, argparse
from pathlib import Path


def parse_asl(path):
    """Parse @sign ... @end sign blocks from osl.asl."""
    blocks = []
    cur = None
    with open(path) as f:
        for line in f:
            line = line.rstrip()
            if line.startswith('@sign '):
                name = line[6:].strip()
                cur = {'sign': name, 'lists': {}, 'uname': None, 'ucun': None}
            elif line.startswith('@sign- '):
                cur = None  # skip deprecated signs
            elif cur is not None and line.startswith('@list\t'):
                token = line[6:].strip()
                # token format: "MZL001" or "ABZ123" or "ABZ123v" etc
                m = re.match(r'^([A-Z]+)(\S+)$', token)
                if m:
                    lst, num = m.group(1), m.group(2)
                    # Prefer first occurrence per list
                    if lst not in cur['lists']:
                        cur['lists'][lst] = num
            elif cur is not None and line.startswith('@uname\t'):
                cur['uname'] = line[7:].strip()
            elif cur is not None and line.startswith('@ucun\t'):
                cur['ucun'] = line[6:].strip()
            elif line.startswith('@end sign'):
                if cur and cur['sign']:
                    blocks.append(cur)
                cur = None
    return blocks


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument('--osl', default='/tmp/osl/00lib/osl.asl')
    ap.add_argument('--output', required=True)
    args = ap.parse_args()

    blocks = parse_asl(args.osl)
    print(f"Parsed {len(blocks)} signs")

    mzl_to_abz = {}
    mzl_to_sign = {}
    abz_to_sign = {}
    sign_to_mzl = {}
    sign_to_abz = {}

    for b in blocks:
        sign = b['sign']
        mzl = b['lists'].get('MZL')
        # In Oracc OSL the Borger list appears as ABZL (Assyrisch-Babylonische
        # Zeichenliste); our codebase historically calls it "ABZ", so treat
        # ABZL as the ABZ source.
        abz = b['lists'].get('ABZL') or b['lists'].get('ABZ')
        if mzl:
            # MZL numbers may have leading zeros and optional 'a','b','v' suffixes
            # strip leading zeros of pure-numeric prefix
            mzl_clean = re.sub(r'^0+', '', mzl) or '0'
            mzl_to_sign[mzl] = sign
            mzl_to_sign[mzl_clean] = sign  # also with stripped
            sign_to_mzl[sign] = mzl
            if abz:
                abz_clean = re.sub(r'^0+', '', abz) or '0'
                mzl_to_abz[mzl] = abz
                mzl_to_abz[mzl_clean] = abz
        if abz:
            abz_to_sign[abz] = sign
            abz_to_sign[re.sub(r'^0+', '', abz) or '0'] = sign
            sign_to_abz[sign] = abz

    print(f"MZL entries: {len(sign_to_mzl)}")
    print(f"ABZ entries: {len(sign_to_abz)}")
    print(f"MZL→ABZ mappings: {len(mzl_to_abz)}")

    # Report a few examples
    for mzl in ['MZL001', 'MZL839', 'MZL252', 'MZL090']:
        if mzl in mzl_to_sign:
            print(f"  {mzl} = {mzl_to_sign[mzl]} (ABZ: {mzl_to_abz.get(mzl, '?')})")

    out = {
        'mzl_to_abz': mzl_to_abz,
        'mzl_to_sign': mzl_to_sign,
        'abz_to_sign': abz_to_sign,
        'sign_to_mzl': sign_to_mzl,
        'sign_to_abz': sign_to_abz,
        'n_signs_total': len(blocks),
    }
    Path(args.output).parent.mkdir(parents=True, exist_ok=True)
    with open(args.output, 'w') as f:
        json.dump(out, f, indent=1, ensure_ascii=False)
    print(f"Saved → {args.output}")

if __name__ == '__main__':
    main()