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

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

First attempt to intergrate 'generate_predefined_ucd_functions' into build process.

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