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

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

Refactored UCD property resolution.

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