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

Last change on this file since 4661 was 4661, checked in by nmedfort, 4 years ago

Start of work to make the pablo compiler reenterant. Fixed bug that prevented it from using Less optimization level.

File size: 11.1 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_re.h>
8#include <re/re_alt.h>
9#include <re/re_any.h>
10#include <re/re_cc.h>
11#include <re/re_seq.h>
12#include <re/re_rep.h>
13#include <re/re_name.h>
14#include <re/re_diff.h>
15#include <re/re_intersect.h>
16#include <re/re_assertion.h>
17#include <re/re_start.h>
18#include <re/re_end.h>
19#include <cc/cc_namemap.hpp>
20#include "UCD/PropertyAliases.h"
21#include "UCD/PropertyObjects.h"
22#include "UCD/PropertyObjectTable.h"
23#include "UCD/PropertyValueAliases.h"
24#include <boost/algorithm/string/case_conv.hpp>
25#include <string>
26#include <iostream>
27
28using namespace UCD;
29using namespace re;
30
31class UnicodePropertyExpressionError : public std::exception {
32public:
33    UnicodePropertyExpressionError(const std::string && msg) noexcept : _msg(msg) {}
34    const char* what() const noexcept { return _msg.c_str();}
35private:
36    inline UnicodePropertyExpressionError() noexcept {}
37    const std::string _msg;
38};
39
40inline std::string lowercase(const std::string & name) {
41    std::locale loc;
42    return boost::algorithm::to_lower_copy(name, loc);
43}
44
45inline int GetPropertyValueEnumCode(const UCD::property_t type, const std::string & value) {
46    return property_object_table[type]->GetPropertyValueEnumCode(value);
47}
48
49void resolveProperty(Name * name) {
50    const std::string prop = canonicalize_value_name(name->getNamespace());
51    const std::string value = canonicalize_value_name(name->getName());
52    if (prop.length() != 0) {
53        auto propit = alias_map.find(prop);
54        if (propit == alias_map.end()) {
55            throw UnicodePropertyExpressionError("Expected a property name, but '" + name->getNamespace() + "' found instead");
56        }
57        auto theprop = propit->second;
58        if (theprop == gc) {
59            // General Category
60            int valcode = GetPropertyValueEnumCode(gc, value);
61            if (valcode < 0) {
62                throw UnicodePropertyExpressionError("Erroneous property value for general_category property");
63            }
64            name->setFunctionName("__get_gc_" + GC_ns::enum_names[valcode]);
65        }
66        else if (theprop == sc) {
67            // Script property identified
68            int valcode = GetPropertyValueEnumCode(sc, value);
69            if (valcode < 0) {
70                throw UnicodePropertyExpressionError("Erroneous property value for script property");
71            }
72            name->setFunctionName("__get_sc_" + SC_ns::enum_names[valcode]);
73        }
74        else if (theprop == scx) {
75            // Script extension property identified
76            int valcode = GetPropertyValueEnumCode(sc, value);
77            if (valcode < 0) {
78                throw UnicodePropertyExpressionError("Erroneous property value for script_extension property");
79            }
80            name->setFunctionName("__get_scx_" + SC_ns::enum_names[valcode]);
81        }
82        else if (theprop == blk) {
83            // Block property identified
84            int valcode = GetPropertyValueEnumCode(blk, value);
85            if (valcode < 0) {
86                 throw UnicodePropertyExpressionError("Erroneous property value for block property");
87            }
88            name->setFunctionName("__get_blk_" + BLK_ns::enum_names[valcode]);
89        }
90        else if (isa<BinaryPropertyObject>(property_object_table[theprop])){
91            auto valit = Binary_ns::aliases_only_map.find(value);
92            if (valit == Binary_ns::aliases_only_map.end()) {
93                throw UnicodePropertyExpressionError("Erroneous property value for binary property " + property_full_name[theprop]);
94            }
95            if (valit->second == Binary_ns::Y) {
96                name->setFunctionName("__get_" + lowercase(property_enum_name[theprop]) + "_Y");
97            }
98            else {
99                Name * binprop = makeName("__get_" + lowercase(property_enum_name[theprop]) + "_Y", Name::Type::UnicodeProperty);
100                name->setDefinition(makeDiff(makeAny(), binprop));
101            }
102        }
103        else {
104            throw UnicodePropertyExpressionError("Property " + property_full_name[theprop] + " recognized, but not supported in icgrep 1.0");
105        }
106    }
107    else {
108
109        // No namespace (property) name.   Try as a general category.
110
111        int valcode;
112
113        if ((valcode = GetPropertyValueEnumCode(gc, value)) >= 0) {
114            name->setFunctionName("__get_gc_" + GC_ns::enum_names[valcode]);
115            return;
116        }
117
118        if ((valcode = GetPropertyValueEnumCode(sc, value)) >= 0) {
119            name->setFunctionName("__get_sc_" + SC_ns::enum_names[valcode]);
120            return;
121        }
122
123        // Try as a binary property.
124        auto propit = alias_map.find(value);
125        if (propit != alias_map.end()) {
126            auto theprop = propit->second;
127            if (isa<BinaryPropertyObject>(property_object_table[theprop])) {
128                name->setFunctionName("__get_" + lowercase(property_enum_name[theprop]) + "_Y");
129            }
130            else {
131                throw UnicodePropertyExpressionError("Error: property " + property_full_name[theprop] + " specified without a value");
132            }
133        }
134        // Now try special cases of Unicode TR #18
135        else if (value == "any") {
136            name->setDefinition(makeAny());
137        }
138        else if (value == "assigned") {
139            Name * Cn = makeName("Cn", Name::Type::UnicodeProperty);
140            name->setDefinition(makeDiff(makeAny(), Cn));
141        }
142        else if (value == "ascii") {
143            name->setFunctionName("__get_blk_ASCII");
144        }
145        // Now compatibility properties of UTR #18 Annex C
146        else if (value == "xdigit") {
147            Name * Nd = makeName("Nd", Name::Type::UnicodeProperty);
148            Name * hexdigit = makeName("Hex_digit", Name::Type::UnicodeProperty);
149            name->setDefinition(makeAlt({Nd, hexdigit}));
150        }
151        else if (value == "alnum") {
152            Name * digit = makeName("Nd", Name::Type::UnicodeProperty);
153            Name * alpha = makeName("alphabetic", Name::Type::UnicodeProperty);
154            name->setDefinition(makeAlt({digit, alpha}));
155        }
156        else if (value == "blank") {
157            Name * space_sep = makeName("space_separator", Name::Type::UnicodeProperty);
158            CC * tab = makeCC(0x09);
159            name->setDefinition(makeAlt({space_sep, tab}));
160        }
161        else if (value == "graph") {
162            Name * space = makeName("space", Name::Type::UnicodeProperty);
163            Name * ctrl = makeName("control", Name::Type::UnicodeProperty);
164            Name * surr = makeName("surrogate", Name::Type::UnicodeProperty);
165            Name * unassigned = makeName("Cn", Name::Type::UnicodeProperty);
166            Name * nongraph = makeName("[^graph]", Name::Type::UnicodeProperty);
167            nongraph->setDefinition(makeAlt({space, ctrl, surr, unassigned}));
168            name->setDefinition(makeDiff(makeAny(), nongraph));
169        }
170        else if (value == "print") {
171            Name * graph = makeName("graph", Name::Type::UnicodeProperty);
172            Name * space_sep = makeName("space_separator", Name::Type::UnicodeProperty);
173            name->setDefinition(makeAlt({graph, space_sep}));
174        }
175        else if (value == "word") {
176            Name * alnum = makeName("alnum", Name::Type::UnicodeProperty);
177            Name * mark = makeName("mark", Name::Type::UnicodeProperty);
178            Name * conn = makeName("Connector_Punctuation", Name::Type::UnicodeProperty);
179            Name * join = makeName("Join_Control", Name::Type::UnicodeProperty);
180            name->setDefinition(makeAlt({alnum, mark, conn, join}));
181        }
182        else {
183            throw UnicodePropertyExpressionError("Expected a general category, script or binary property name, but '" + name->getName() + "' found instead");
184        }
185    }
186}
187
188UnicodeSet resolveUnicodeSet(Name * const name) {
189    if (name->getType() == Name::Type::UnicodeProperty) {
190        std::string prop = name->getNamespace();
191        std::string value = canonicalize_value_name(name->getName());
192        if (prop.length() > 0) {
193            prop = canonicalize_value_name(prop);
194            auto propit = alias_map.find(prop);
195            if (propit == alias_map.end()) {
196                throw UnicodePropertyExpressionError("Expected a property name, but '" + name->getNamespace() + "' found instead");
197            }
198            auto theprop = propit->second;
199            if (theprop == gc) {
200                // General Category
201                return cast<EnumeratedPropertyObject>(property_object_table[gc])->GetCodepointSet(value);
202            }
203            else if (theprop == sc) {
204                // Script property identified
205                return cast<EnumeratedPropertyObject>(property_object_table[sc])->GetCodepointSet(value);
206            }
207            else if (theprop == scx) {
208                // Script extension property identified
209                return cast<ExtensionPropertyObject>(property_object_table[scx])->GetCodepointSet(value);
210            }
211            else if (theprop == blk) {
212                // Block property identified
213                return cast<EnumeratedPropertyObject>(property_object_table[blk])->GetCodepointSet(value);
214            }
215            else if (BinaryPropertyObject * p = dyn_cast<BinaryPropertyObject>(property_object_table[theprop])){
216                auto valit = Binary_ns::aliases_only_map.find(value);
217                if (valit == Binary_ns::aliases_only_map.end()) {
218                    throw UnicodePropertyExpressionError("Erroneous property value for binary property " + property_full_name[theprop]);
219                }
220                return p->GetCodepointSet(value);
221            }           
222            throw UnicodePropertyExpressionError("Property " + property_full_name[theprop] + " recognized but not supported in icgrep 1.0");
223        }
224        else {
225            // No namespace (property) name.   Try as a general category.
226            int valcode = GetPropertyValueEnumCode(gc, value);
227            if (valcode >= 0) {
228                return cast<EnumeratedPropertyObject>(property_object_table[gc])->GetCodepointSet(valcode);
229            }
230            valcode = GetPropertyValueEnumCode(sc, value);
231            if (valcode >= 0) {
232                return cast<EnumeratedPropertyObject>(property_object_table[sc])->GetCodepointSet(valcode);
233            }
234            // Try as a binary property.
235            auto propit = alias_map.find(value);
236            if (propit != alias_map.end()) {
237                auto theprop = propit->second;
238                if (BinaryPropertyObject * p = dyn_cast<BinaryPropertyObject>(property_object_table[theprop])) {
239                    return p->GetCodepointSet(Binary_ns::Y);
240                }
241                else {
242                    throw UnicodePropertyExpressionError("Error: property " + property_full_name[theprop] + " specified without a value");
243                }
244            }
245        }
246    }
247    throw UnicodePropertyExpressionError("Expected a general category, script or binary property name, but '" + name->getName() + "' found instead");
248}
Note: See TracBrowser for help on using the repository browser.