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

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

Modified function signature of the existing external UCD functions to match that of the JITed function. Updated pablo_compiler to produce the correct CallInsts?.

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