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

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

Added union/diff/intersection functionality to RE_Compiler. Removed toUTF8 pass in favour of using the UCD_Compiler.

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