source: icGREP/icgrep-devel/UCD-scripts/UCD_properties.py @ 6127

Last change on this file since 6127 was 5770, checked in by cameron, 22 months ago

Restructure to eliminate unnecessary dependencies on RegExpCompiler? and UCDLIB

File size: 29.6 KB
RevLine 
[4146]1#
[4147]2# UCD_properties.py - parsing Unicode Character Database (UCD) files
3# and generating C headers for property data using a compact bitset
4# representation.
5#
6# Robert D. Cameron
[4389]7# January 2, 2015
[4147]8#
[4146]9# Licensed under Open Software License 3.0.
[4147]10#
11#
[5749]12import string, os.path
[4367]13from UCD_parser import *
[5658]14from UCD_property_objects import *
[4146]15
[4150]16PropertyAliases_template = r"""
17namespace UCD {
[4632]18    enum property_t {
19        %s};
20    const static std::vector<std::string> property_enum_name = {
21        %s};
22    const static std::vector<std::string> property_full_name = {
23        %s};
24    static std::unordered_map<std::string, int> alias_map {{
25        %s}};
[4150]26}
27"""
28
[4185]29EnumeratedProperty_template = r"""
[4632]30    namespace %s_ns {
31        enum value_t {
32            %s};
33        const static std::vector<std::string> enum_names = {
34            %s};
35        const static std::vector<std::string> value_names = {
36            %s};
37        static std::unordered_map<std::string, int> aliases_only_map {{
38            %s}};
39    }
[4185]40"""
[4179]41
[5662]42def emit_string_property(f, property_code, null_set, reflexive_set, cp_value_map):
43    s = string.Template(r"""    namespace ${prop_enum_up}_ns {
44        /** Code Point Ranges for ${prop_enum} mapping to <none>
45        ${null_set_ranges}**/
[5749]46       
47        ${null_set_value}
[5658]48
[5662]49        /** Code Point Ranges for ${prop_enum} mapping to <codepoint>
50        ${reflexive_set_ranges}**/
[5749]51       
52        ${reflexive_set_value}
[5662]53
54        const unsigned buffer_length = ${buffer_length};
[5751]55        const static char string_buffer LLVM_ALIGNAS(32) [${allocation_length}] = u8R"__(${string_buffer})__";
[5662]56
[5749]57        const static std::vector<codepoint_t> defined_cps{
[5662]58        ${explicitly_defined_cps}};
59        static StringPropertyObject property_object(${prop_enum},
[5749]60                                                    std::move(null_codepoint_set),
61                                                    std::move(reflexive_set),
[5662]62                                                    static_cast<const char *>(string_buffer),
63                                                    buffer_length,
[5749]64                                                    std::move(defined_cps));
[5662]65    }
66""")
67    cps = sorted(cp_value_map.keys())
68    string_buffer = ""
69    for cp in cps: 
70        string_buffer += cp_value_map[cp] + "\n"
71    buffer_length = len(string_buffer.encode("utf-8"))
72    f.write(s.substitute(prop_enum = property_code,
[5749]73                         prop_enum_up = property_code.upper(),
74                         string_buffer = string_buffer,
75                         buffer_length = buffer_length,
76                         allocation_length = (buffer_length + 255) & -256,
77                         null_set_ranges = cformat.multiline_fill(['[%04x, %04x]' % (lo, hi) for (lo, hi) in uset_to_range_list(null_set)], ',', 8),
78                         null_set_value = null_set.generate("null_codepoint_set", 8),
79                         reflexive_set_ranges = cformat.multiline_fill(['[%04x, %04x]' % (lo, hi) for (lo, hi) in uset_to_range_list(reflexive_set)], ',', 8),
80                         reflexive_set_value = reflexive_set.generate("reflexive_set", 8),
81                         explicitly_defined_cp_count = len(cps),
82                         explicitly_defined_cps = cformat.multiline_fill(['0x%04x' % cp for cp in cps], ',', 8)
83                         ))
[5662]84
[5672]85def emit_string_override_property(f, property_code, overridden_code, override_set, cp_value_map):
86    s = string.Template(r"""    namespace ${prop_enum_up}_ns {
[5673]87        /** Code Point Ranges for ${prop_enum} (possibly overriding values from ${overridden})
[5672]88        ${overridden_set_ranges}**/
89
[5749]90        ${overridden_set_value}
[5672]91
92        const unsigned buffer_length = ${buffer_length};
[5751]93        const static char string_buffer LLVM_ALIGNAS(32) [${allocation_length}] = u8R"__(${string_buffer})__";
[5672]94
[5749]95        const static std::vector<codepoint_t> defined_cps{
[5672]96        ${explicitly_defined_cps}};
97        static StringOverridePropertyObject property_object(${prop_enum},
98                                                    ${overridden}_ns::property_object,
[5749]99                                                    std::move(explicitly_defined_set),
[5672]100                                                    static_cast<const char *>(string_buffer),
101                                                    buffer_length,
[5749]102                                                    std::move(defined_cps));
[5672]103    }
104""")
105    cps = sorted(cp_value_map.keys())
106    string_buffer = ""
107    for cp in cps: 
108        string_buffer += cp_value_map[cp] + "\n"
109    buffer_length = len(string_buffer.encode("utf-8"))
110    f.write(s.substitute(prop_enum = property_code,
[5749]111                         prop_enum_up = property_code.upper(),
112                         overridden = overridden_code.upper(),
113                         string_buffer = string_buffer,
114                         buffer_length = buffer_length,
115                         allocation_length = (buffer_length + 255) & -256,
116                         overridden_set_ranges = cformat.multiline_fill(['[%04x, %04x]' % (lo, hi) for (lo, hi) in uset_to_range_list(override_set)], ',', 8),
117                         overridden_set_value = override_set.generate("explicitly_defined_set", 8),
118                         explicitly_defined_cp_count = len(cps),
119                         explicitly_defined_cps = cformat.multiline_fill(['0x%04x' % cp for cp in cps], ',', 8)
120                         ))
[5672]121
[5670]122def emit_numeric_property(f, property_code, NaN_set, cp_value_map):
123    s = string.Template(r"""    namespace ${prop_enum_up}_ns {
124        /** Code Point Ranges for ${prop_enum} mapping to NaN
125        ${NaN_set_ranges}**/
[5662]126
[5749]127        ${NaN_set_value}
[5670]128
[5749]129        const unsigned buffer_length = ${buffer_length};
[5751]130        const static char string_buffer LLVM_ALIGNAS(32) [${allocation_length}] = u8R"__(${string_buffer})__";
[5670]131
132        const static std::vector<codepoint_t> defined_cps = {
133        ${explicitly_defined_cps}};
134        static NumericPropertyObject property_object(${prop_enum},
[5749]135                                                    std::move(NaN_set),
[5670]136                                                    static_cast<const char *>(string_buffer),
137                                                    buffer_length,
[5749]138                                                    std::move(defined_cps));
[5670]139    }
140""")
141    cps = sorted(cp_value_map.keys())
142    string_buffer = ""
143    for cp in cps: 
144        string_buffer += cp_value_map[cp] + "\n"
[5685]145    string_buffer += "NaN\n"  # This inserts the standard default value for strings as the last entry
[5670]146    buffer_length = len(string_buffer.encode("utf-8"))
147    f.write(s.substitute(prop_enum = property_code,
[5749]148                         prop_enum_up = property_code.upper(),
149                         string_buffer = string_buffer,
150                         buffer_length = buffer_length,
151                         allocation_length = (buffer_length + 255) & -256,
152                         NaN_set_ranges = cformat.multiline_fill(['[%04x, %04x]' % (lo, hi) for (lo, hi) in uset_to_range_list(NaN_set)], ',', 8),
153                         NaN_set_value = NaN_set.generate("NaN_set", 8),
154                         explicitly_defined_cp_count = len(cps),
155                         explicitly_defined_cps = cformat.multiline_fill(['0x%04x' % cp for cp in cps], ',', 8)
156                         ))
[5670]157
158
[5658]159def emit_binary_property(f, property_code, property_set):
160    f.write("    namespace %s_ns {\n" % property_code.upper())
161    f.write("        /** Code Point Ranges for %s\n        " % property_code)
162    f.write(cformat.multiline_fill(['[%04x, %04x]' % (lo, hi) for (lo, hi) in uset_to_range_list(property_set)], ',', 8))
[5749]163    f.write("**/\n\n")
164    f.write(property_set.generate("codepoint_set", 8))
165    f.write("        static BinaryPropertyObject property_object{%s, std::move(codepoint_set)};\n    }\n" % property_code)
[5658]166
167def emit_enumerated_property(f, property_code, independent_prop_values, prop_values, value_map):
168    f.write("  namespace %s_ns {\n" % property_code.upper())
169    f.write("    const unsigned independent_prop_values = %s;\n" % independent_prop_values)
170    for v in prop_values:
171        f.write("    /** Code Point Ranges for %s\n    " % v)
172        f.write(cformat.multiline_fill(['[%04x, %04x]' % (lo, hi) for (lo, hi) in uset_to_range_list(value_map[v])], ',', 4))
[5749]173        f.write("**/\n\n")
174        f.write(value_map[v].generate(v.lower() + "_Set", 4))
[5658]175    set_list = ['&%s_Set' % v.lower() for v in prop_values]
176    f.write("    static EnumeratedPropertyObject property_object\n")
177    f.write("        {%s,\n" % property_code)
[5749]178    f.write("        %s_ns::independent_prop_values,\n" % property_code.upper())
179    f.write("        std::move(%s_ns::enum_names),\n" % property_code.upper())
180    f.write("        std::move(%s_ns::value_names),\n" % property_code.upper())
181    f.write("        std::move(%s_ns::aliases_only_map),{\n" % property_code.upper())
182    f.write("        " + cformat.multiline_fill(set_list, ',', 8))
183    f.write("\n        }};"
184            "\n    }\n")
[5658]185
[5668]186def emit_Obsolete_property(f, property_code):
187    s = string.Template(r"""    namespace ${prop_enum_up}_ns {
188        static ObsoletePropertyObject property_object(${prop_enum});
189    }
190""")
191    f.write(s.substitute(prop_enum = property_code, prop_enum_up = property_code.upper()))
192
193
[5673]194def simple_CaseClosure_map(fold_data):
195   simpleFoldMap = {}
196   for k in fold_data['S'].keys(): simpleFoldMap[k] = int(fold_data['S'][k], 16)
197   for k in fold_data['C'].keys(): simpleFoldMap[k] = int(fold_data['C'][k], 16)
198   cl_map = {}
199   for k in simpleFoldMap.keys():
200      v = simpleFoldMap[k]
201      if not v in cl_map: cl_map[v] = [k]
202      else: cl_map[v].append(k)
203      if not k in cl_map: cl_map[k] = [v]
204      else: cl_map[k].append(v)
205   newEntries = True
206   while newEntries:
207      newEntries = False
208      for k in cl_map.keys():
209         vlist = cl_map[k]
210         for v in vlist:
211            for w in cl_map[v]:
212               if k != w and not k in cl_map[w]:
213                  cl_map[w].append(k)
214                  newEntries = True
215   return cl_map
216
217#
218# Simple case fold map.     
219# The simple case fold map is an ordered list of fold entries each of
220# the form (lo_codepoint, hicodepoint, offset).  Each entry describes
221# the case fold that applies for the consecutive entries in the given
222# codepoint range, according to the following equations. 
223# casefold(x) = x + offset, if ((x - low_codepoint) div offset) mod 2 = 0
224#             = x - offset, if ((x - low_codepoint) div offset) mod 2 = 1
225#
226#
227def caseFoldRangeMap(casemap):
228   foldable = sorted(casemap.keys())
229   entries = []
230   cp = foldable[0]
231   open_entries = [(cp, f - cp) for f in casemap[cp]]
232   last_cp = cp
233   for cp in foldable[1:]:
234      if cp != last_cp + 1:
235         # Close the pending range entries
236         for (cp0, offset) in open_entries:
237            entries.append((cp0, last_cp, offset))
238         open_entries = [(cp, f - cp) for f in casemap[cp]]
239      else:
240         new_open = []
241         projected = []
242         for (cp0, offset) in open_entries:
243            even_odd_offset_group = int(abs(cp - cp0)/ abs(offset)) & 1
244            if even_odd_offset_group == 0: 
245               projected_foldcp = cp + offset
246            else: projected_foldcp = cp - offset
247            if not projected_foldcp in casemap[cp]:
248               entries.append((cp0, last_cp, offset))
249            else:
250               new_open.append((cp0, offset))
251               projected.append(projected_foldcp)
252         open_entries = new_open
253         for f in casemap[cp]:
254            if not f in projected:
255               open_entries.append((cp, f-cp))
256      last_cp = cp
257   # Close the final entries.
258   for (cp0, offset) in open_entries:
259      entries.append((cp0, last_cp, offset))
260   return entries
261
262
263
264def genFoldEntryData(casemap):
265   rMap = caseFoldRangeMap(casemap)
266   individuals = [(m[0],m[0]+m[2]) for m in rMap if m[0] == m[1]]
267   ranges = [m for m in rMap if m[0] != m[1]]
268   last_hi = -1
269   generated = "const FoldEntry foldTable[foldTableSize] = {\n"
270   foldTableSize = 0
271   for (lo, hi, offset) in ranges:
272      if lo != last_hi + 1:
273         pairs = ["{0x%x, 0x%x}" % (m[0], m[1]) for m in individuals if m[0]>last_hi and m[0]< lo]
274         generated += "  {0x%x, 0, {" % (last_hi + 1) + cformat.multiline_fill(pairs) + "}},\n"
275         foldTableSize += 1
276      last_hi = hi
277      pairs = ["{0x%x, 0x%x}" % (m[0], m[1]) for m in individuals if m[0]>=lo and m[0]<= hi]
278      generated += "  {0x%x, %i, {" % (lo, offset) + cformat.multiline_fill(pairs) + "}},\n"
279      foldTableSize += 1
280   if last_hi != 0x10FFFF:
281      pairs = ["{0x%x, 0x%x}" % (m[0], m[1]) for m in individuals if m[0]>last_hi]
282      generated += "  {0x%x, 0, {" % (last_hi + 1) + cformat.multiline_fill(pairs) + "}},\n"
283      foldTableSize += 1
284   generated += "  {0x110000, 0, {}}};"
285   foldTableSize += 1
286   generated = "\nconst int foldTableSize = %s;\n\n" % foldTableSize  + generated
287   return generated
288
289foldDeclarations = r"""
290struct FoldEntry {
[5749]291    const UCD::codepoint_t range_lo;
292    const int fold_offset;
293    const std::vector<UCD::interval_t> fold_pairs;
[5673]294};
295
[5770]296UCD::UnicodeSet * caseInsensitize(UCD::UnicodeSet * const cc);
[5673]297
298"""
299
300
[4186]301class UCD_generator():
[4367]302    def __init__(self):
[4389]303        self.supported_props = []
304        self.property_data_headers = []
305        self.missing_specs = {}
[5653]306        self.binary_properties = {}
[4146]307
[4367]308    def load_property_name_info(self):
[5658]309        (self.property_enum_name_list, self.property_object_map) = parse_PropertyAlias_txt()
310        self.property_lookup_map = getPropertyLookupMap(self.property_object_map)
311        self.full_name_map = {}
312        for p in self.property_enum_name_list:
313            self.full_name_map[p] = self.property_object_map[p].getPropertyFullName()
[4186]314
[5658]315
[4363]316    def generate_PropertyAliases_h(self):
[4389]317        f = cformat.open_header_file_for_write('PropertyAliases')
[4632]318        cformat.write_imports(f, ["<string>", "<unordered_map>", "<vector>"])
319        enum_text = cformat.multiline_fill(self.property_enum_name_list, ',', 8)
320        enum_text2 = cformat.multiline_fill(['"%s"' % e for e in self.property_enum_name_list], ',', 8)
321        full_name_text = cformat.multiline_fill(['"%s"' % self.full_name_map[e] for e in self.property_enum_name_list], ',', 8)
322        map_text = cformat.multiline_fill(['{"%s", %s}' % (k, self.property_lookup_map[k]) for k in sorted(self.property_lookup_map.keys())], ',', 8)
[4389]323        f.write(PropertyAliases_template % (enum_text, enum_text2, full_name_text, map_text))
324        cformat.close_header_file(f)
[4186]325
[4367]326    def load_property_value_info(self):
[5658]327        initializePropertyValues(self.property_object_map, self.property_lookup_map)
[4186]328
[4363]329    def generate_PropertyValueAliases_h(self):
[4389]330        f = cformat.open_header_file_for_write('PropertyValueAliases')
[4632]331        cformat.write_imports(f, ['"PropertyAliases.h"', "<vector>", "<unordered_map>", "<string>"])
[4389]332        f.write("namespace UCD {\n")
333        #  Generate the aliases for all Binary properties.
[4632]334        enum_text = cformat.multiline_fill(['N', 'Y'], ',', 12)
335        enum_names = cformat.multiline_fill(['"N"', '"Y"'], ',', 12)
336        full_name_text = cformat.multiline_fill(['"No"', '"Yes"'], ',', 12)
337        binary_properties = ['{"n", N}', '{"y", Y}', '{"no", N}', '{"yes", Y}', '{"f", N}', '{"t", Y}', '{"false", N}', '{"true", Y}']
338        binary_map_text = cformat.multiline_fill(binary_properties, ',', 12)
[4389]339        f.write(EnumeratedProperty_template % ('Binary', enum_text, enum_names, full_name_text, binary_map_text))
340        #
341        for p in self.property_enum_name_list:
[5658]342            po = self.property_object_map[p]
343            if isinstance(po, EnumeratedPropertyObject):
344                ordered_enum_list = po.property_value_list
345                enum_text = cformat.multiline_fill(ordered_enum_list, ',', 12)
346                enum_names = cformat.multiline_fill(['"%s"' % s for s in ordered_enum_list], ',', 12)
347                if p == 'ccc': # Special case: add numeric value information for ccc.
348                    enum_text += r"""
[4363]349        };
[4632]350        const uint16_t enum_val[] = {
[5658]351        """
352                    enum_text += "      " + cformat.multiline_fill(["%s" % (po.property_value_enum_integer[e]) for e in ordered_enum_list], ',', 12)
353                full_names = [po.property_value_full_name_map[e] for e in ordered_enum_list]
354                full_name_text = cformat.multiline_fill(['"%s"' % name for name in full_names], ',', 12)
355                canon_full_names = [canonicalize(name) for name in full_names]
356                canon_enums = [canonicalize(e) for e in ordered_enum_list]
357                canon_keys = [canonicalize(k) for k in po.property_value_lookup_map.keys()]
358                aliases_only = []
359                for k in canon_keys:
360                    if k in canon_enums: continue
361                    if k in canon_full_names: continue
362                    if k in aliases_only: continue
363                    aliases_only.append(k)
364                map_text = cformat.multiline_fill(['{"%s", %s_ns::%s}' % (k, p.upper(), po.property_value_lookup_map[k]) for k in sorted(aliases_only)], ',', 12)
365                f.write(EnumeratedProperty_template % (p.upper(), enum_text, enum_names, full_name_text, map_text))
[4389]366        f.write("}\n")
367        cformat.close_header_file(f)
[4186]368
[5658]369    def emit_property(self, f, property_code):
370        property_object = self.property_object_map[property_code]
371        if isinstance(property_object, BinaryPropertyObject):
372            emit_binary_property(f, property_code, property_object.value_map['Y'])
373            print("%s: %s bytes" % (property_object.getPropertyFullName(), property_object.value_map['Y'].bytes()))
374        elif isinstance(property_object, EnumeratedPropertyObject):
375            prop_values = property_object.name_list_order
376            independent_prop_values = property_object.independent_prop_values
377            emit_enumerated_property(f, property_code, independent_prop_values, prop_values, property_object.value_map)
378            print("%s: %s bytes" % (property_object.getPropertyFullName(), sum([property_object.value_map[v].bytes() for v in property_object.value_map.keys()])))
[5662]379        elif isinstance(property_object, StringPropertyObject):
380            emit_string_property(f, property_code, property_object.null_str_set, property_object.reflexive_set, property_object.cp_value_map)
[5672]381        elif isinstance(property_object, StringOverridePropertyObject):
382            emit_string_override_property(f, property_code, property_object.overridden_code, property_object.overridden_set, property_object.cp_value_map)
[5670]383        elif isinstance(property_object, NumericPropertyObject):
384            emit_numeric_property(f, property_code, property_object.NaN_set, property_object.cp_value_map)
[5668]385        elif isinstance(property_object, ObsoletePropertyObject):
386            emit_Obsolete_property(f, property_code)
[5670]387        else: 
388            print("%s: unsupported property.")
389            return
[5664]390        self.supported_props.append(property_code)
[5658]391
[5153]392    def generate_property_value_file(self, filename_root, property_code):
[5658]393        property_object = self.property_object_map[property_code]
394        parse_property_data(self.property_object_map[property_code], filename_root + '.txt')
[5653]395        basename = os.path.basename(filename_root)
[5658]396        f = cformat.open_header_file_for_write(basename)
397        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"unicode_set.h"'])
[5653]398        f.write("\nnamespace UCD {\n")
[5658]399        self.emit_property(f, property_code)
400        f.write("}\n")
[4389]401        cformat.close_header_file(f)
402        self.property_data_headers.append(basename)
[4186]403
[5658]404    def generate_multisection_properties_file(self, filename_root):
405        props = parse_multisection_property_data(filename_root + '.txt', self.property_object_map, self.property_lookup_map)
406        #(props, prop_map) = parse_UCD_codepoint_name_map(filename_root + '.txt', self.property_lookup_map)
407        basename = os.path.basename(filename_root)
408        f = cformat.open_header_file_for_write(basename)
409        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"unicode_set.h"'])
410        f.write("\nnamespace UCD {\n")
411        for p in sorted(props):
412            self.emit_property(f, p)
413            property_object = self.property_object_map[p]
414        f.write("}\n\n")
415        cformat.close_header_file(f)
416        self.property_data_headers.append(basename)
417
[5661]418    def generate_multicolumn_properties_file(self, filename_root, prop_code_list):
419        props = parse_multicolumn_property_data(filename_root + '.txt', self.property_object_map, self.property_lookup_map, prop_code_list)
420        #(props, prop_map) = parse_UCD_codepoint_name_map(filename_root + '.txt', self.property_lookup_map)
421        basename = os.path.basename(filename_root)
422        f = cformat.open_header_file_for_write(basename)
423        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"unicode_set.h"'])
424        f.write("\nnamespace UCD {\n")
425        for p in prop_code_list:
[5671]426            if p in self.property_object_map: self.emit_property(f, p)
[5661]427        f.write("}\n\n")
428        cformat.close_header_file(f)
429        self.property_data_headers.append(basename)
430
[5662]431    def generate_UnicodeData_h(self):
432        basename = 'UnicodeData'
433        parse_UnicodeData_txt(self.property_object_map)
434        f = cformat.open_header_file_for_write(basename)
435        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"unicode_set.h"'])
[5670]436        prop_code_list = ['na', 'dm', 'suc', 'slc', 'stc', 'na1', 'isc', 'nv']
[5662]437        f.write("\nnamespace UCD {\n")
438        for p in prop_code_list:
439            self.emit_property(f, p)
440            property_object = self.property_object_map[p]
441        f.write("}\n\n")
442        cformat.close_header_file(f)
443        self.property_data_headers.append(basename)
444
[5669]445    def generate_SpecialCasing_h(self):
446        basename = 'SpecialCasing'
447        parse_SpecialCasing_txt(self.property_object_map)
448        f = cformat.open_header_file_for_write(basename)
[5672]449        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"UnicodeData.h"', '"unicode_set.h"'])
[5669]450        f.write("\nnamespace UCD {\n")
451        for p in ['lc', 'uc', 'tc']:
452            self.emit_property(f, p)
453            property_object = self.property_object_map[p]
454        f.write("}\n\n")
455        cformat.close_header_file(f)
456        self.property_data_headers.append(basename)
457
[4363]458    def generate_ScriptExtensions_h(self):
[4389]459        filename_root = 'ScriptExtensions'
460        property_code = 'scx'
[5658]461        extension_object = self.property_object_map['scx']
462        extension_object.setBaseProperty(self.property_object_map['sc'])
[5662]463        parse_property_data(extension_object, filename_root+'.txt')
[4389]464        basename = os.path.basename(filename_root)
465        f = cformat.open_header_file_for_write(basename)
[5658]466        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"unicode_set.h"'])
467        prop_list = self.property_object_map['sc'].name_list_order
468        value_map = extension_object.value_map
[4389]469        f.write("\nnamespace UCD {\n")
[4632]470        f.write("    namespace SCX_ns {\n")
[5658]471        for v in prop_list:
[4632]472            f.write("        /** Code Point Ranges for %s\n        " % v)
[5655]473            f.write(cformat.multiline_fill(['[%04x, %04x]' % (lo, hi) for (lo, hi) in uset_to_range_list(value_map[v])], ',', 8))
[4632]474            f.write("**/\n")
[5749]475            f.write(value_map[v].generate(v.lower() + "_Ext", 8))
[5658]476        set_list = ['&%s_Ext' % v.lower() for v in prop_list]
[4634]477        f.write("        static ExtensionPropertyObject property_object\n")
[4632]478        f.write("       {%s,\n" % property_code)
[4634]479        f.write("        UCD::sc,\n")
[4389]480        f.write("       {")
481        f.write(cformat.multiline_fill(set_list, ',', 8))
[4632]482        f.write("\n        }};\n    }\n}\n")
[4389]483        cformat.close_header_file(f)
[5653]484        print("%s: %s bytes" % (basename, sum([value_map[v].bytes() for v in value_map.keys()])))
[4632]485        self.supported_props.append(property_code)
[4389]486        self.property_data_headers.append(basename)
[4186]487
[4363]488    def generate_PropertyObjectTable_h(self):
[4389]489        f = cformat.open_header_file_for_write('PropertyObjectTable')
[4619]490        cformat.write_imports(f, ['"PropertyObjects.h"', '"PropertyAliases.h"', '<array>'])
[4389]491        cformat.write_imports(f, ['"%s.h"' % fname for fname in self.property_data_headers])
492        f.write("\nnamespace UCD {\n")
493        objlist = []
494        for p in self.property_enum_name_list:
[5658]495            k = self.property_object_map[p].getPropertyKind()
[4632]496            if p in self.supported_props:
[4389]497                objlist.append("&%s_ns::property_object" % p.upper())
[4363]498            else:
[4619]499                objlist.append("new UnsupportedPropertyObject(%s, PropertyObject::ClassTypeId::%sProperty)" % (p, k))
500        f.write("\n  const std::array<PropertyObject *, %i> property_object_table = {{\n    " % len(objlist))
501        f.write(",\n    ".join(objlist) + '  }};\n}\n')
[4389]502        cformat.close_header_file(f)
[4186]503
[5655]504    def generate_UCD_Config_h(self):
505        setVersionfromReadMe_txt()
506        f = cformat.open_header_file_for_write('UCD_Config')
[5749]507        f.write("#include <utility>\n")
508        f.write("namespace UCD {\n")
509        f.write("\tconst auto UnicodeVersion = \"%s\";\n" % UCD_config.version)
510        f.write("\tusing codepoint_t = unsigned;\n")
511        f.write("\tenum : codepoint_t { UNICODE_MAX = %s };\n" % UCD_config.UCD_max_code_point)
512        f.write("\tusing interval_t = std::pair<codepoint_t, codepoint_t>;\n")
[5655]513        f.write("}\n")
514        cformat.close_header_file(f)
[4363]515
516
[5673]517    def genCaseFolding_h(self):
518        basename = 'CaseFolding'
519        fold_data = parse_CaseFolding_txt(self.property_object_map)
520        cm = simple_CaseClosure_map(fold_data)
521        f = cformat.open_header_file_for_write(basename, 'casefold.py')
[5749]522        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"unicode_set.h"', '<vector>'])
[5673]523        f.write(foldDeclarations)
524        f.write(genFoldEntryData(cm))
525        f.write("\nnamespace UCD {\n")
526        self.emit_property(f, 'scf')
527        self.emit_property(f, 'cf')
528        f.write("}\n")
529        cformat.close_header_file(f)
530        self.supported_props.append(['scf', 'cf'])
531        self.property_data_headers.append(basename)
[5655]532
[5673]533
534
[4179]535def UCD_main():
[4389]536    ucd = UCD_generator()
[4186]537
[4389]538    # First parse all property names and their aliases
539    ucd.load_property_name_info()
540    #
541    # Generate the PropertyAliases.h file to define all the Unicode property_t enum
542    # and the basic property information.
543    ucd.generate_PropertyAliases_h()
544    #
545    # Next parse all property value names and their aliases.  Generate the data.
546    ucd.load_property_value_info()
[5662]547
548    ucd.generate_UnicodeData_h()
[5669]549   
550    ucd.generate_SpecialCasing_h()
551   
[5673]552    ucd.genCaseFolding_h()
553   
[5671]554    ucd.generate_multicolumn_properties_file('NameAliases', ['Name_Alias', 'Alias_Kind'])
555
[4389]556    #
[4740]557    # The Age property
558    ucd.generate_property_value_file('DerivedAge', 'age')
559    #
[4389]560    # The Block property
561    ucd.generate_property_value_file('Blocks', 'blk')
[5658]562   
[4389]563    # Scripts
564    ucd.generate_property_value_file('Scripts', 'sc')
565    #
[5658]566    # # Script Extensions
[4389]567    ucd.generate_ScriptExtensions_h()
[5658]568    # #
[4389]569    # General Category
570    ucd.generate_property_value_file('extracted/DerivedGeneralCategory', 'gc')
[5658]571   
[4389]572    # Binary properties from PropList.txt
[5658]573    ucd.generate_multisection_properties_file('PropList')
574   
[4389]575    # Binary properties from DerivedCoreProperties.txt
[5658]576    ucd.generate_multisection_properties_file('DerivedCoreProperties')
[4389]577    #
578    #
579    # LineBreak types
[4745]580    #ucd.generate_property_value_file('extracted/DerivedLineBreak', 'lb')
[4389]581    ucd.generate_property_value_file('LineBreak', 'lb')
582    #
[4735]583    # Grapheme Cluster Break property
584    ucd.generate_property_value_file('auxiliary/GraphemeBreakProperty', 'GCB')
585    #
586    # Sentence Break property
587    ucd.generate_property_value_file('auxiliary/SentenceBreakProperty', 'SB')
588    #
589    # Word Break property
590    ucd.generate_property_value_file('auxiliary/WordBreakProperty', 'WB')
591    #
[5686]592    # Vertical orientation property
593    ucd.generate_property_value_file('VerticalOrientation', 'vo')
594
[5658]595    # East Asian Width - can use either source
[4389]596    ucd.generate_property_value_file('EastAsianWidth', 'ea')
[4745]597    #ucd.generate_property_value_file('extracted/DerivedEastAsianWidth', 'ea')
[4389]598    #
599    # Hangul Syllable Type
600    ucd.generate_property_value_file('HangulSyllableType', 'hst')
601    #
[5658]602    ucd.generate_multisection_properties_file('extracted/DerivedBinaryProperties')
603    # #
604    # # Canonical_Combining_Class
[4743]605    ucd.generate_property_value_file('extracted/DerivedCombiningClass', 'ccc')
606    #
[4745]607    # Decomposition Type
608    ucd.generate_property_value_file('extracted/DerivedDecompositionType', 'dt')
609    #
610    # Joining Group and Type
611    ucd.generate_property_value_file('extracted/DerivedJoiningGroup', 'jg')
612    ucd.generate_property_value_file('extracted/DerivedJoiningType', 'jt')
613    #
614    # Numeric Type and Value
615    ucd.generate_property_value_file('extracted/DerivedNumericType', 'nt')
616    #ucd.generate_property_value_file('extracted/DerivedNumericValue', 'nv')
617    #
[5658]618    # Normalization properties.
619    ucd.generate_multisection_properties_file('DerivedNormalizationProps')
[5653]620    #
[5664]621    # Bidirectional properties
[5653]622    ucd.generate_property_value_file('extracted/DerivedBidiClass', 'bc')
[5661]623    ucd.generate_multicolumn_properties_file('BidiBrackets', ['bpb', 'bpt'])
[5664]624    ucd.generate_property_value_file('BidiMirroring', 'bmg')
[5159]625
[5655]626    # Indic properties
627    ucd.generate_property_value_file('IndicPositionalCategory', 'InPC')
628    ucd.generate_property_value_file('IndicSyllabicCategory', 'InSC')
629
[5658]630    ucd.generate_property_value_file('CompositionExclusions', 'CE')
[5159]631    #
[5666]632    ucd.generate_property_value_file('Jamo', 'JSN')
[4389]633    #
[5153]634    #
[4389]635    #
[5153]636    ucd.generate_PropertyValueAliases_h()
637
[4389]638    ucd.generate_PropertyObjectTable_h()
[4179]639
[5655]640    ucd.generate_UCD_Config_h()
641
[4180]642if __name__ == "__main__":
643  UCD_main()
Note: See TracBrowser for help on using the repository browser.