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

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

Restructure to eliminate unnecessary dependencies on RegExpCompiler? and UCDLIB

File size: 29.6 KB
Line 
1#
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
7# January 2, 2015
8#
9# Licensed under Open Software License 3.0.
10#
11#
12import string, os.path
13from UCD_parser import *
14from UCD_property_objects import *
15
16PropertyAliases_template = r"""
17namespace UCD {
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}};
26}
27"""
28
29EnumeratedProperty_template = r"""
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    }
40"""
41
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}**/
46       
47        ${null_set_value}
48
49        /** Code Point Ranges for ${prop_enum} mapping to <codepoint>
50        ${reflexive_set_ranges}**/
51       
52        ${reflexive_set_value}
53
54        const unsigned buffer_length = ${buffer_length};
55        const static char string_buffer LLVM_ALIGNAS(32) [${allocation_length}] = u8R"__(${string_buffer})__";
56
57        const static std::vector<codepoint_t> defined_cps{
58        ${explicitly_defined_cps}};
59        static StringPropertyObject property_object(${prop_enum},
60                                                    std::move(null_codepoint_set),
61                                                    std::move(reflexive_set),
62                                                    static_cast<const char *>(string_buffer),
63                                                    buffer_length,
64                                                    std::move(defined_cps));
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,
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                         ))
84
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 {
87        /** Code Point Ranges for ${prop_enum} (possibly overriding values from ${overridden})
88        ${overridden_set_ranges}**/
89
90        ${overridden_set_value}
91
92        const unsigned buffer_length = ${buffer_length};
93        const static char string_buffer LLVM_ALIGNAS(32) [${allocation_length}] = u8R"__(${string_buffer})__";
94
95        const static std::vector<codepoint_t> defined_cps{
96        ${explicitly_defined_cps}};
97        static StringOverridePropertyObject property_object(${prop_enum},
98                                                    ${overridden}_ns::property_object,
99                                                    std::move(explicitly_defined_set),
100                                                    static_cast<const char *>(string_buffer),
101                                                    buffer_length,
102                                                    std::move(defined_cps));
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,
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                         ))
121
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}**/
126
127        ${NaN_set_value}
128
129        const unsigned buffer_length = ${buffer_length};
130        const static char string_buffer LLVM_ALIGNAS(32) [${allocation_length}] = u8R"__(${string_buffer})__";
131
132        const static std::vector<codepoint_t> defined_cps = {
133        ${explicitly_defined_cps}};
134        static NumericPropertyObject property_object(${prop_enum},
135                                                    std::move(NaN_set),
136                                                    static_cast<const char *>(string_buffer),
137                                                    buffer_length,
138                                                    std::move(defined_cps));
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"
145    string_buffer += "NaN\n"  # This inserts the standard default value for strings as the last entry
146    buffer_length = len(string_buffer.encode("utf-8"))
147    f.write(s.substitute(prop_enum = property_code,
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                         ))
157
158
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))
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)
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))
173        f.write("**/\n\n")
174        f.write(value_map[v].generate(v.lower() + "_Set", 4))
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)
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")
185
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
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 {
291    const UCD::codepoint_t range_lo;
292    const int fold_offset;
293    const std::vector<UCD::interval_t> fold_pairs;
294};
295
296UCD::UnicodeSet * caseInsensitize(UCD::UnicodeSet * const cc);
297
298"""
299
300
301class UCD_generator():
302    def __init__(self):
303        self.supported_props = []
304        self.property_data_headers = []
305        self.missing_specs = {}
306        self.binary_properties = {}
307
308    def load_property_name_info(self):
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()
314
315
316    def generate_PropertyAliases_h(self):
317        f = cformat.open_header_file_for_write('PropertyAliases')
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)
323        f.write(PropertyAliases_template % (enum_text, enum_text2, full_name_text, map_text))
324        cformat.close_header_file(f)
325
326    def load_property_value_info(self):
327        initializePropertyValues(self.property_object_map, self.property_lookup_map)
328
329    def generate_PropertyValueAliases_h(self):
330        f = cformat.open_header_file_for_write('PropertyValueAliases')
331        cformat.write_imports(f, ['"PropertyAliases.h"', "<vector>", "<unordered_map>", "<string>"])
332        f.write("namespace UCD {\n")
333        #  Generate the aliases for all Binary properties.
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)
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:
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"""
349        };
350        const uint16_t enum_val[] = {
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))
366        f.write("}\n")
367        cformat.close_header_file(f)
368
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()])))
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)
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)
383        elif isinstance(property_object, NumericPropertyObject):
384            emit_numeric_property(f, property_code, property_object.NaN_set, property_object.cp_value_map)
385        elif isinstance(property_object, ObsoletePropertyObject):
386            emit_Obsolete_property(f, property_code)
387        else: 
388            print("%s: unsupported property.")
389            return
390        self.supported_props.append(property_code)
391
392    def generate_property_value_file(self, filename_root, property_code):
393        property_object = self.property_object_map[property_code]
394        parse_property_data(self.property_object_map[property_code], filename_root + '.txt')
395        basename = os.path.basename(filename_root)
396        f = cformat.open_header_file_for_write(basename)
397        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"unicode_set.h"'])
398        f.write("\nnamespace UCD {\n")
399        self.emit_property(f, property_code)
400        f.write("}\n")
401        cformat.close_header_file(f)
402        self.property_data_headers.append(basename)
403
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
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:
426            if p in self.property_object_map: self.emit_property(f, p)
427        f.write("}\n\n")
428        cformat.close_header_file(f)
429        self.property_data_headers.append(basename)
430
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"'])
436        prop_code_list = ['na', 'dm', 'suc', 'slc', 'stc', 'na1', 'isc', 'nv']
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
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)
449        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"UnicodeData.h"', '"unicode_set.h"'])
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
458    def generate_ScriptExtensions_h(self):
459        filename_root = 'ScriptExtensions'
460        property_code = 'scx'
461        extension_object = self.property_object_map['scx']
462        extension_object.setBaseProperty(self.property_object_map['sc'])
463        parse_property_data(extension_object, filename_root+'.txt')
464        basename = os.path.basename(filename_root)
465        f = cformat.open_header_file_for_write(basename)
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
469        f.write("\nnamespace UCD {\n")
470        f.write("    namespace SCX_ns {\n")
471        for v in prop_list:
472            f.write("        /** Code Point Ranges for %s\n        " % v)
473            f.write(cformat.multiline_fill(['[%04x, %04x]' % (lo, hi) for (lo, hi) in uset_to_range_list(value_map[v])], ',', 8))
474            f.write("**/\n")
475            f.write(value_map[v].generate(v.lower() + "_Ext", 8))
476        set_list = ['&%s_Ext' % v.lower() for v in prop_list]
477        f.write("        static ExtensionPropertyObject property_object\n")
478        f.write("       {%s,\n" % property_code)
479        f.write("        UCD::sc,\n")
480        f.write("       {")
481        f.write(cformat.multiline_fill(set_list, ',', 8))
482        f.write("\n        }};\n    }\n}\n")
483        cformat.close_header_file(f)
484        print("%s: %s bytes" % (basename, sum([value_map[v].bytes() for v in value_map.keys()])))
485        self.supported_props.append(property_code)
486        self.property_data_headers.append(basename)
487
488    def generate_PropertyObjectTable_h(self):
489        f = cformat.open_header_file_for_write('PropertyObjectTable')
490        cformat.write_imports(f, ['"PropertyObjects.h"', '"PropertyAliases.h"', '<array>'])
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:
495            k = self.property_object_map[p].getPropertyKind()
496            if p in self.supported_props:
497                objlist.append("&%s_ns::property_object" % p.upper())
498            else:
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')
502        cformat.close_header_file(f)
503
504    def generate_UCD_Config_h(self):
505        setVersionfromReadMe_txt()
506        f = cformat.open_header_file_for_write('UCD_Config')
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")
513        f.write("}\n")
514        cformat.close_header_file(f)
515
516
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')
522        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"unicode_set.h"', '<vector>'])
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)
532
533
534
535def UCD_main():
536    ucd = UCD_generator()
537
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()
547
548    ucd.generate_UnicodeData_h()
549   
550    ucd.generate_SpecialCasing_h()
551   
552    ucd.genCaseFolding_h()
553   
554    ucd.generate_multicolumn_properties_file('NameAliases', ['Name_Alias', 'Alias_Kind'])
555
556    #
557    # The Age property
558    ucd.generate_property_value_file('DerivedAge', 'age')
559    #
560    # The Block property
561    ucd.generate_property_value_file('Blocks', 'blk')
562   
563    # Scripts
564    ucd.generate_property_value_file('Scripts', 'sc')
565    #
566    # # Script Extensions
567    ucd.generate_ScriptExtensions_h()
568    # #
569    # General Category
570    ucd.generate_property_value_file('extracted/DerivedGeneralCategory', 'gc')
571   
572    # Binary properties from PropList.txt
573    ucd.generate_multisection_properties_file('PropList')
574   
575    # Binary properties from DerivedCoreProperties.txt
576    ucd.generate_multisection_properties_file('DerivedCoreProperties')
577    #
578    #
579    # LineBreak types
580    #ucd.generate_property_value_file('extracted/DerivedLineBreak', 'lb')
581    ucd.generate_property_value_file('LineBreak', 'lb')
582    #
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    #
592    # Vertical orientation property
593    ucd.generate_property_value_file('VerticalOrientation', 'vo')
594
595    # East Asian Width - can use either source
596    ucd.generate_property_value_file('EastAsianWidth', 'ea')
597    #ucd.generate_property_value_file('extracted/DerivedEastAsianWidth', 'ea')
598    #
599    # Hangul Syllable Type
600    ucd.generate_property_value_file('HangulSyllableType', 'hst')
601    #
602    ucd.generate_multisection_properties_file('extracted/DerivedBinaryProperties')
603    # #
604    # # Canonical_Combining_Class
605    ucd.generate_property_value_file('extracted/DerivedCombiningClass', 'ccc')
606    #
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    #
618    # Normalization properties.
619    ucd.generate_multisection_properties_file('DerivedNormalizationProps')
620    #
621    # Bidirectional properties
622    ucd.generate_property_value_file('extracted/DerivedBidiClass', 'bc')
623    ucd.generate_multicolumn_properties_file('BidiBrackets', ['bpb', 'bpt'])
624    ucd.generate_property_value_file('BidiMirroring', 'bmg')
625
626    # Indic properties
627    ucd.generate_property_value_file('IndicPositionalCategory', 'InPC')
628    ucd.generate_property_value_file('IndicSyllabicCategory', 'InSC')
629
630    ucd.generate_property_value_file('CompositionExclusions', 'CE')
631    #
632    ucd.generate_property_value_file('Jamo', 'JSN')
633    #
634    #
635    #
636    ucd.generate_PropertyValueAliases_h()
637
638    ucd.generate_PropertyObjectTable_h()
639
640    ucd.generate_UCD_Config_h()
641
642if __name__ == "__main__":
643  UCD_main()
Note: See TracBrowser for help on using the repository browser.