mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-10-31 21:39:47 +00:00
The mapping of the script labels in the UCD data to ISO 15924
script tags is now done using the sc property map in the
PropertyValueAliases data.
This has the following benefits:
1. It removes the dependency on the IANA subtag registry.
2. It ensures the scripts are correct as specified in the
UCD data files.
196 lines
4.5 KiB
Python
Executable File
196 lines
4.5 KiB
Python
Executable File
#!/usr/bin/python
|
|
|
|
# Copyright (C) 2012 Reece H. Dunn
|
|
#
|
|
# This file is part of ucd-tools.
|
|
#
|
|
# ucd-tools is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# ucd-tools is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with ucd-tools. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import os
|
|
import sys
|
|
import iana
|
|
|
|
script_map = {}
|
|
|
|
class CodePoint:
|
|
def __init__(self, x):
|
|
if isinstance(x, str):
|
|
self.codepoint = int(x, 16)
|
|
else:
|
|
self.codepoint = x
|
|
|
|
def __repr__(self):
|
|
return '%06X' % self.codepoint
|
|
|
|
def __str__(self):
|
|
return '%06X' % self.codepoint
|
|
|
|
def __iter__(self):
|
|
yield self
|
|
|
|
def __hash__(self):
|
|
return self.codepoint
|
|
|
|
def __eq__(self, other):
|
|
return self.codepoint == other.codepoint
|
|
|
|
def __ne__(self, other):
|
|
return self.codepoint != other.codepoint
|
|
|
|
def __lt__(self, other):
|
|
return self.codepoint < other.codepoint
|
|
|
|
class CodeRange:
|
|
def __init__(self, x):
|
|
f, l = x.split('..')
|
|
self.first = CodePoint(f)
|
|
self.last = CodePoint(l)
|
|
|
|
def __repr__(self):
|
|
return '%s..%s' % (self.first, self.last)
|
|
|
|
def __str__(self):
|
|
return '%s..%s' % (self.first, self.last)
|
|
|
|
def __iter__(self):
|
|
for c in range(self.first.codepoint, self.last.codepoint + 1):
|
|
yield CodePoint(c)
|
|
|
|
def size(self):
|
|
return self.last.codepoint - self.first.codepoint + 1
|
|
|
|
def codepoint(x):
|
|
if '..' in x[0]:
|
|
return CodeRange(x[0]), x[1:]
|
|
if ' ' in x:
|
|
return [CodePoint(c) for c in x[0].split()], x[1:]
|
|
if x[0] == '':
|
|
return CodePoint('0000'), x[1:]
|
|
return CodePoint(x[0]), x[1:]
|
|
|
|
def string(x):
|
|
if x[0] == '':
|
|
return None, x[1:]
|
|
return x[0], x[1:]
|
|
|
|
def integer(x):
|
|
return int(x[0]), x[1:]
|
|
|
|
def boolean(x):
|
|
if x[0] == 'Y':
|
|
return True, x[1:]
|
|
return False, x[1:]
|
|
|
|
def script(x):
|
|
return script_map[x[0]], x[1:]
|
|
|
|
def strlist(x):
|
|
return x, []
|
|
|
|
data_items = {
|
|
'Blocks': [
|
|
('Range', codepoint),
|
|
('Name', string)
|
|
],
|
|
'DerivedAge': [
|
|
('Range', codepoint),
|
|
('Age', string),
|
|
],
|
|
'PropList': [
|
|
('Range', codepoint),
|
|
('Property', string),
|
|
],
|
|
'PropertyValueAliases': [
|
|
('Property', string),
|
|
('Key', string),
|
|
('Value', string),
|
|
('Aliases', strlist),
|
|
],
|
|
'Scripts': [
|
|
('Range', codepoint),
|
|
('Script', script),
|
|
],
|
|
'UnicodeData': [
|
|
('CodePoint', codepoint),
|
|
('Name', string),
|
|
('GeneralCategory', string),
|
|
('CanonicalCombiningClass', integer),
|
|
('BidiClass', string),
|
|
('DecompositionType', string),
|
|
('DecompositionMapping', string),
|
|
('NumericType', string),
|
|
('NumericValue', string),
|
|
('BidiMirrored', boolean),
|
|
('UnicodeName', string),
|
|
('ISOComment', string),
|
|
('UpperCase', codepoint),
|
|
('LowerCase', codepoint),
|
|
('TitleCase', codepoint),
|
|
],
|
|
# Supplemental Data:
|
|
'Klingon': [
|
|
('CodePoint', codepoint),
|
|
('Script', string),
|
|
('GeneralCategory', string),
|
|
('Name', string),
|
|
('Transliteration', string),
|
|
],
|
|
}
|
|
|
|
def parse_ucd_data(ucd_rootdir, dataset):
|
|
keys = data_items[dataset]
|
|
first = None
|
|
with open(os.path.join(ucd_rootdir, '%s.txt' % dataset)) as f:
|
|
for line in f:
|
|
line = line.replace('\n', '').split('#')[0]
|
|
linedata = [' '.join(x.split()) for x in line.split(';')]
|
|
if len(linedata) > 1:
|
|
if linedata[1].endswith(', First>'):
|
|
first = linedata
|
|
continue
|
|
|
|
if linedata[1].endswith(', Last>'):
|
|
linedata[0] = '%s..%s' % (first[0], linedata[0])
|
|
linedata[1] = linedata[1].replace(', Last>', '').replace('<', '')
|
|
first = None
|
|
|
|
data = {}
|
|
for key, typemap in keys:
|
|
data[key], linedata = typemap(linedata)
|
|
yield data
|
|
|
|
def parse_property_mapping(ucd_rootdir, propname, reverse=False):
|
|
ret = {}
|
|
for data in parse_ucd_data(ucd_rootdir, 'PropertyValueAliases'):
|
|
if data['Property'] == propname:
|
|
if reverse:
|
|
ret[data['Value']] = data['Key']
|
|
else:
|
|
ret[data['Key']] = data['Value']
|
|
return ret
|
|
|
|
if __name__ == '__main__':
|
|
try:
|
|
items = sys.argv[3].split(',')
|
|
except:
|
|
items = None
|
|
script_map = parse_property_mapping(sys.argv[1], 'sc', reverse=True)
|
|
for entry in parse_ucd_data(sys.argv[1], sys.argv[2]):
|
|
if items:
|
|
print ','.join([str(entry[item]) for item in items])
|
|
else:
|
|
print entry
|
|
else:
|
|
script_map = parse_property_mapping('data/ucd', 'sc', reverse=True)
|