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

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

Back-up check in

File size: 10.2 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 "UCD/PropertyAliases.h"
12#include "UCD/PropertyObjects.h"
13#include "UCD/PropertyObjectTable.h"
14#include "UCD/PropertyValueAliases.h"
15#include <string>
16#include <iostream>
17
18using namespace UCD;
19using namespace re;
20
21
22inline int GetPropertyValueEnumCode(const UCD::property_t type, const std::string & value) {
23    return property_object_table[type]->GetPropertyValueEnumCode(value);
24}
25
26namespace UCD {
27
28bool resolvePropertyDefinition(Name * const property) {
29    if (property->hasNamespace()) {
30        auto propit = alias_map.find(property->getNamespace());
31        if (propit == alias_map.end()) {
32            throw UnicodePropertyExpressionError("Expected a property name but '" + property->getNamespace() + "' was found instead");
33        }
34        auto theprop = propit->second;
35        if (isa<BinaryPropertyObject>(property_object_table[theprop])){
36            auto valit = Binary_ns::aliases_only_map.find(property->getName());
37            if (valit != Binary_ns::aliases_only_map.end()) {
38                if (valit->second == Binary_ns::N) {
39                    Name * binprop = makeName(property_enum_name[theprop], Name::Type::UnicodeProperty);
40                    property->setDefinition(makeDiff(makeAny(), binprop));
41                    return true;
42                }
43            }
44        }
45    } else {
46        const std::string value = property->getName();
47        // Try special cases of Unicode TR #18
48        if (value == "any") {
49            property->setDefinition(makeAny());
50            return true;
51        } else if (value == "ascii") {
52            property->setDefinition(makeName("blk", "ascii", Name::Type::UnicodeProperty));
53            return true;
54        } else if (value == "assigned") {
55            Name * unassigned = makeName("cn", Name::Type::UnicodeProperty);
56            property->setDefinition(makeDiff(makeAny(), unassigned));
57            return true;
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            return true;
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            return true;
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            return true;
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            return true;
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            return true;
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            return true;
94        }
95    }
96    return false;
97}
98
99std::string resolvePropertyFunction(Name * const property) {
100    const std::string value = property->getName();
101    std::string functionName;
102    if (property->hasNamespace()) {
103        auto propit = alias_map.find(property->getNamespace());
104        if (propit == alias_map.end()) {
105            throw UnicodePropertyExpressionError("Expected a property name but '" + property->getNamespace() + "' was found instead");
106        }
107        auto theprop = propit->second;
108        if (EnumeratedPropertyObject * p = dyn_cast<EnumeratedPropertyObject>(property_object_table[theprop])){
109            int valcode = p->GetPropertyValueEnumCode(value);
110            if (valcode < 0) {
111                throw UnicodePropertyExpressionError("Erroneous property value '" + value + "' for " + property_full_name[theprop] + " property");
112            }
113            functionName = "__get_" + property_enum_name[theprop] + "_" + p->GetValueEnumName(valcode);
114        }
115        else if (theprop == scx) {
116            // Script extension property identified
117            int valcode = GetPropertyValueEnumCode(sc, value);
118            if (valcode < 0) {
119                throw UnicodePropertyExpressionError("Erroneous property value for script_extension property");
120            }
121            functionName = "__get_scx_" + SC_ns::enum_names[valcode];
122        }
123        else if (isa<BinaryPropertyObject>(property_object_table[theprop])){
124            auto valit = Binary_ns::aliases_only_map.find(value);
125            if (valit == Binary_ns::aliases_only_map.end()) {
126                throw UnicodePropertyExpressionError("Erroneous property value for binary property " + property_full_name[theprop]);
127            }
128            if (valit->second == Binary_ns::Y) {
129                functionName = "__get_" + property_enum_name[theprop] + "_Y";
130            } else {
131                throw UnicodePropertyExpressionError("Unexpected property value for binary property " + property_full_name[theprop]);
132            }
133        }
134        else {
135            throw UnicodePropertyExpressionError("Property " + property_full_name[theprop] + " recognized but not supported in icgrep 1.0");
136        }
137    } else { // No namespace (property) name.
138        // Try as a general category, script or binary property.
139        int valcode;
140        if ((valcode = GetPropertyValueEnumCode(gc, value)) >= 0) {
141            functionName = "__get_gc_" + GC_ns::enum_names[valcode];
142        }
143        else if ((valcode = GetPropertyValueEnumCode(sc, value)) >= 0) {
144            functionName = "__get_sc_" + SC_ns::enum_names[valcode];
145        }
146        else { // Try as a binary property.
147            auto propit = alias_map.find(value);
148            if (propit != alias_map.end()) {
149                auto theprop = propit->second;
150                if (isa<BinaryPropertyObject>(property_object_table[theprop])) {
151                    functionName = "__get_" + property_enum_name[theprop] + "_Y";
152                }
153                else {
154                    throw UnicodePropertyExpressionError("Error: property " + property_full_name[theprop] + " specified without a value");
155                }
156            }
157            else {
158                throw UnicodePropertyExpressionError("Expected a general category, script or binary property name but '" + value + "' was found instead");
159            }
160        }
161    }
162    assert (functionName.length() > 0);
163    return std::move(functionName);
164}
165
166UnicodeSet resolveUnicodeSet(Name * const name) {
167    if (name->getType() == Name::Type::UnicodeProperty) {
168        std::string prop = name->getNamespace();
169        std::string value = canonicalize_value_name(name->getName());
170        if (prop.length() > 0) {
171            prop = canonicalize_value_name(prop);
172            auto propit = alias_map.find(prop);
173            if (propit == alias_map.end()) {
174                throw UnicodePropertyExpressionError("Expected a property name, but '" + name->getNamespace() + "' found instead");
175            }
176            auto theprop = propit->second;
177            if (EnumeratedPropertyObject * p = dyn_cast<EnumeratedPropertyObject>(property_object_table[theprop])){
178                return p->GetCodepointSet(value);
179            }
180            else if (BinaryPropertyObject * p = dyn_cast<BinaryPropertyObject>(property_object_table[theprop])){
181                auto valit = Binary_ns::aliases_only_map.find(value);
182                if (valit == Binary_ns::aliases_only_map.end()) {
183                    throw UnicodePropertyExpressionError("Erroneous property value for binary property " + property_full_name[theprop]);
184                }
185                return p->GetCodepointSet(value);
186            }           
187            throw UnicodePropertyExpressionError("Property " + property_full_name[theprop] + " recognized but not supported in icgrep 1.0");
188        }
189        else {
190            // No namespace (property) name.   Try as a general category.
191            int valcode = GetPropertyValueEnumCode(gc, value);
192            if (valcode >= 0) {
193                return cast<EnumeratedPropertyObject>(property_object_table[gc])->GetCodepointSet(valcode);
194            }
195            valcode = GetPropertyValueEnumCode(sc, value);
196            if (valcode >= 0) {
197                return cast<EnumeratedPropertyObject>(property_object_table[sc])->GetCodepointSet(valcode);
198            }
199            // Try as a binary property.
200            auto propit = alias_map.find(value);
201            if (propit != alias_map.end()) {
202                auto theprop = propit->second;
203                if (BinaryPropertyObject * p = dyn_cast<BinaryPropertyObject>(property_object_table[theprop])) {
204                    return p->GetCodepointSet(Binary_ns::Y);
205                }
206                else {
207                    throw UnicodePropertyExpressionError("Error: property " + property_full_name[theprop] + " specified without a value");
208                }
209            }
210        }
211    }
212    throw UnicodePropertyExpressionError("Expected a general category, script or binary property name, but '" + name->getName() + "' found instead");
213}
214
215}
Note: See TracBrowser for help on using the repository browser.