source: icGREP/icgrep-devel/icgrep/UCD/resolve_properties.cpp @ 5276

Last change on this file since 5276 was 5267, checked in by nmedfort, 3 years ago

Code clean-up. Removed Pablo Call, SetIthBit? and Prototype.

File size: 13.6 KB
Line 
1/*
2 *  Copyright (c) 2015 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6#include "resolve_properties.h"
7#include <re/re_alt.h>
8#include <re/re_any.h>
9#include <re/re_name.h>
10#include <re/re_diff.h>
11#include <re/re_start.h>
12#include <re/re_end.h>
13#include <re/re_cc.h>
14#include <re/re_seq.h>
15#include <re/re_assertion.h>
16#include "UCD/PropertyAliases.h"
17#include "UCD/PropertyObjects.h"
18#include "UCD/PropertyObjectTable.h"
19#include "UCD/PropertyValueAliases.h"
20
21using namespace UCD;
22using namespace re;
23using namespace llvm;
24
25inline int GetPropertyValueEnumCode(const UCD::property_t type, const std::string & value) {
26    return property_object_table[type]->GetPropertyValueEnumCode(value);
27}
28
29namespace UCD {
30
31void generateGraphemeClusterBoundaryRule(Name * const &property) {
32    // 3.1.1 Grapheme Cluster Boundary Rules
33#define Behind(x) makeLookBehindAssertion(x)
34#define Ahead(x) makeLookAheadAssertion(x)
35
36//    RE * GCB_Control = makeName("gcb", "cn", Name::Type::UnicodeProperty);
37    RE * GCB_CR = makeName("gcb", "cr", Name::Type::UnicodeProperty);
38    RE * GCB_LF = makeName("gcb", "lf", Name::Type::UnicodeProperty);
39    RE * GCB_Control_CR_LF = makeAlt({GCB_CR, GCB_LF});
40
41    // Break at the start and end of text.
42    RE * GCB_1 = makeStart();
43    RE * GCB_2 = makeEnd();
44    // Do not break between a CR and LF.
45    RE * GCB_3 = makeSeq({Behind(GCB_CR), Ahead(GCB_LF)});
46    // Otherwise, break before and after controls.
47    RE * GCB_4 = Behind(GCB_Control_CR_LF);
48    RE * GCB_5 = Ahead(GCB_Control_CR_LF);
49    RE * GCB_1_5 = makeAlt({GCB_1, GCB_2, makeDiff(makeAlt({GCB_4, GCB_5}), GCB_3)});
50
51    RE * GCB_L = makeName("gcb", "l", Name::Type::UnicodeProperty);
52    RE * GCB_V = makeName("gcb", "v", Name::Type::UnicodeProperty);
53    RE * GCB_LV = makeName("gcb", "lv", Name::Type::UnicodeProperty);
54    RE * GCB_LVT = makeName("gcb", "lvt", Name::Type::UnicodeProperty);
55    RE * GCB_T = makeName("gcb", "t", Name::Type::UnicodeProperty);
56    RE * GCB_RI = makeName("gcb", "ri", Name::Type::UnicodeProperty);
57    // Do not break Hangul syllable sequences.
58    RE * GCB_6 = makeSeq({Behind(GCB_L), Ahead(makeAlt({GCB_L, GCB_V, GCB_LV, GCB_LVT}))});
59    RE * GCB_7 = makeSeq({Behind(makeAlt({GCB_LV, GCB_V})), Ahead(makeAlt({GCB_V, GCB_T}))});
60    RE * GCB_8 = makeSeq({Behind(makeAlt({GCB_LVT, GCB_T})), Ahead(GCB_T)});
61    // Do not break between regional indicator symbols.
62    RE * GCB_8a = makeSeq({Behind(GCB_RI), Ahead(GCB_RI)});
63    // Do not break before extending characters.
64    RE * GCB_9 = Ahead(makeName("gcb", "ex", Name::Type::UnicodeProperty));
65    // Do not break before SpacingMarks, or after Prepend characters.
66    RE * GCB_9a = Ahead(makeName("gcb", "sm", Name::Type::UnicodeProperty));
67    RE * GCB_9b = Behind(makeName("gcb", "pp", Name::Type::UnicodeProperty));
68    RE * GCB_6_9b = makeAlt({GCB_6, GCB_7, GCB_8, GCB_8a, GCB_9, GCB_9a, GCB_9b});
69    // Otherwise, break everywhere.
70    RE * GCB_10 = makeSeq({Behind(makeAny()), Ahead(makeAny())});
71
72    //Name * gcb = makeName("gcb", Name::Type::UnicodeProperty);
73    property->setDefinition(makeAlt({GCB_1_5, makeDiff(GCB_10, GCB_6_9b)}));
74}
75
76bool resolvePropertyDefinition(Name * const property) {
77    if (property->hasNamespace()) {
78        auto propit = alias_map.find(property->getNamespace());
79        if (propit == alias_map.end()) {
80            throw UnicodePropertyExpressionError("Expected a property name but '" + property->getNamespace() + "' was found instead");
81        }
82        auto theprop = propit->second;
83        if (isa<BinaryPropertyObject>(property_object_table[theprop])){
84            auto valit = Binary_ns::aliases_only_map.find(property->getName());
85            if (valit != Binary_ns::aliases_only_map.end()) {
86                if (valit->second == Binary_ns::N) {
87                    Name * binprop = makeName(property_enum_name[theprop], Name::Type::UnicodeProperty);
88                    property->setDefinition(makeDiff(makeAny(), binprop));
89                    return true;
90                }
91            }
92        }
93    } else {
94        const std::string value = property->getName();
95        // Try special cases of Unicode TR #18
96        if (value == "any") {
97            property->setDefinition(makeAny());
98            return true;
99        } else if (value == "ascii") {
100            property->setDefinition(makeName("blk", "ascii", Name::Type::UnicodeProperty));
101            return true;
102        } else if (value == "assigned") {
103            Name * unassigned = makeName("cn", Name::Type::UnicodeProperty);
104            property->setDefinition(makeDiff(makeAny(), unassigned));
105            return true;
106        }
107        // Now compatibility properties of UTR #18 Annex C
108        else if (value == "xdigit") {
109            Name * digit = makeName("nd", Name::Type::UnicodeProperty);
110            Name * hexdigit = makeName("hexdigit", Name::Type::UnicodeProperty);
111            property->setDefinition(makeAlt({digit, hexdigit}));
112            return true;
113        } else if (value == "alnum") {
114            Name * digit = makeName("nd", Name::Type::UnicodeProperty);
115            Name * alpha = makeName("alphabetic", Name::Type::UnicodeProperty);
116            property->setDefinition(makeAlt({digit, alpha}));
117            return true;
118        } else if (value == "blank") {
119            Name * space_sep = makeName("space_separator", Name::Type::UnicodeProperty);
120            CC * tab = makeCC(0x09);
121            property->setDefinition(makeAlt({space_sep, tab}));
122            return true;
123        } else if (value == "graph") {
124            Name * space = makeName("space", Name::Type::UnicodeProperty);
125            Name * ctrl = makeName("control", Name::Type::UnicodeProperty);
126            Name * surr = makeName("surrogate", Name::Type::UnicodeProperty);
127            Name * unassigned = makeName("cn", Name::Type::UnicodeProperty);
128            property->setDefinition(makeDiff(makeAny(), makeAlt({space, ctrl, surr, unassigned})));
129            return true;
130        } else if (value == "print") {
131            Name * graph = makeName("graph", Name::Type::UnicodeProperty);
132            Name * space_sep = makeName("space_separator", Name::Type::UnicodeProperty);
133            property->setDefinition(makeAlt({graph, space_sep}));
134            return true;
135        } else if (value == "word") {
136            Name * alnum = makeName("alnum", Name::Type::UnicodeProperty);
137            Name * mark = makeName("mark", Name::Type::UnicodeProperty);
138            Name * conn = makeName("connectorpunctuation", Name::Type::UnicodeProperty);
139            Name * join = makeName("joincontrol", Name::Type::UnicodeProperty);
140            property->setDefinition(makeAlt({alnum, mark, conn, join}));
141            return true;
142        } else if (value == "GCB" || value == "NonGCB"){
143            generateGraphemeClusterBoundaryRule(property);
144            return true;
145        }
146    }
147    return false;
148}
149
150std::string resolvePropertyFunction(Name * const property) {
151    const std::string value = property->getName();
152    std::string functionName;
153    if (property->hasNamespace()) {
154        auto propit = alias_map.find(property->getNamespace());
155        if (propit == alias_map.end()) {
156            throw UnicodePropertyExpressionError("Expected a property name but '" + property->getNamespace() + "' was found instead");
157        }
158        auto theprop = propit->second;
159        if (EnumeratedPropertyObject * p = dyn_cast<EnumeratedPropertyObject>(property_object_table[theprop])){
160            int valcode = p->GetPropertyValueEnumCode(value);
161            if (valcode < 0) {
162                throw UnicodePropertyExpressionError("Erroneous property value '" + value + "' for " + property_full_name[theprop] + " property");
163            }
164            functionName = "__get_" + property_enum_name[theprop] + "_" + p->GetValueEnumName(valcode);
165        }
166        else if (theprop == scx) {
167            // Script extension property identified
168            int valcode = GetPropertyValueEnumCode(sc, value);
169            if (valcode < 0) {
170                throw UnicodePropertyExpressionError("Erroneous property value for script_extension property");
171            }
172            functionName = "__get_scx_" + SC_ns::enum_names[valcode];
173        }
174        else if (isa<BinaryPropertyObject>(property_object_table[theprop])){
175            auto valit = Binary_ns::aliases_only_map.find(value);
176            if (valit == Binary_ns::aliases_only_map.end()) {
177                throw UnicodePropertyExpressionError("Erroneous property value for binary property " + property_full_name[theprop]);
178            }
179            if (valit->second == Binary_ns::Y) {
180                functionName = "__get_" + property_enum_name[theprop] + "_Y";
181            } else {
182                throw UnicodePropertyExpressionError("Unexpected property value for binary property " + property_full_name[theprop]);
183            }
184        }
185        else {
186            throw UnicodePropertyExpressionError("Property " + property_full_name[theprop] + " recognized but not supported in icgrep 1.0");
187        }
188    } else { // No namespace (property) name.
189        // Try as a general category, script or binary property.
190        int valcode;
191        if ((valcode = GetPropertyValueEnumCode(gc, value)) >= 0) {
192            functionName = "__get_gc_" + GC_ns::enum_names[valcode];
193        }
194        else if ((valcode = GetPropertyValueEnumCode(sc, value)) >= 0) {
195            functionName = "__get_sc_" + SC_ns::enum_names[valcode];
196        }
197        else { // Try as a binary property.
198            auto propit = alias_map.find(value);
199            if (propit != alias_map.end()) {
200                auto theprop = propit->second;
201                if (isa<BinaryPropertyObject>(property_object_table[theprop])) {
202                    functionName = "__get_" + property_enum_name[theprop] + "_Y";
203                }
204                else {
205                    throw UnicodePropertyExpressionError("Error: property " + property_full_name[theprop] + " specified without a value");
206                }
207            }
208            else {
209                throw UnicodePropertyExpressionError("Expected a general category, script or binary property name but '" + value + "' was found instead");
210            }
211        }
212    }
213    assert (functionName.length() > 0);
214    return functionName;
215}
216
217const std::string & getPropertyValueGrepString(const std::string & prop) {
218    auto propit = alias_map.find(canonicalize_value_name(prop));
219    if (propit == alias_map.end()) {
220        throw UnicodePropertyExpressionError("Expected a property name, but '" + prop + "' found instead");
221    }
222    auto theprop = propit->second;
223    if (EnumeratedPropertyObject * p = dyn_cast<EnumeratedPropertyObject>(property_object_table[theprop])){
224        return p->GetPropertyValueGrepString();
225    } else if (BinaryPropertyObject * p = dyn_cast<BinaryPropertyObject>(property_object_table[theprop])) {
226        return p->GetPropertyValueGrepString();
227    }
228
229    throw UnicodePropertyExpressionError("Property " + property_full_name[theprop] + " recognized but not supported in icgrep 1.0");
230}
231
232UnicodeSet resolveUnicodeSet(Name * const name) {
233    if (name->getType() == Name::Type::UnicodeProperty) {
234        std::string prop = name->getNamespace();
235        std::string value = canonicalize_value_name(name->getName());
236        if (prop.length() > 0) {
237            prop = canonicalize_value_name(prop);
238            auto propit = alias_map.find(prop);
239            if (propit == alias_map.end()) {
240                throw UnicodePropertyExpressionError("Expected a property name, but '" + name->getNamespace() + "' found instead");
241            }
242            auto theprop = propit->second;
243            if (EnumeratedPropertyObject * p = dyn_cast<EnumeratedPropertyObject>(property_object_table[theprop])){
244                return p->GetCodepointSet(value);
245            }
246            else if (BinaryPropertyObject * p = dyn_cast<BinaryPropertyObject>(property_object_table[theprop])){
247                auto valit = Binary_ns::aliases_only_map.find(value);
248                if (valit == Binary_ns::aliases_only_map.end()) {
249                    throw UnicodePropertyExpressionError("Erroneous property value for binary property " + property_full_name[theprop]);
250                }
251                return p->GetCodepointSet(value);
252            }           
253            throw UnicodePropertyExpressionError("Property " + property_full_name[theprop] + " recognized but not supported in icgrep 1.0");
254        }
255        else {
256            // No namespace (property) name.   Try as a general category.
257            int valcode = GetPropertyValueEnumCode(gc, value);
258            if (valcode >= 0) {
259                return cast<EnumeratedPropertyObject>(property_object_table[gc])->GetCodepointSet(valcode);
260            }
261            valcode = GetPropertyValueEnumCode(sc, value);
262            if (valcode >= 0) {
263                return cast<EnumeratedPropertyObject>(property_object_table[sc])->GetCodepointSet(valcode);
264            }
265            // Try as a binary property.
266            auto propit = alias_map.find(value);
267            if (propit != alias_map.end()) {
268                auto theprop = propit->second;
269                if (BinaryPropertyObject * p = dyn_cast<BinaryPropertyObject>(property_object_table[theprop])) {
270                    return p->GetCodepointSet(Binary_ns::Y);
271                }
272                else {
273                    throw UnicodePropertyExpressionError("Error: property " + property_full_name[theprop] + " specified without a value");
274                }
275            }
276        }
277    }
278    throw UnicodePropertyExpressionError("Expected a general category, script or binary property name, but '" + name->getName() + "' found instead");
279}
280
281}
Note: See TracBrowser for help on using the repository browser.