source: icGREP/icgrep-devel/icgrep/resolve_properties.cpp @ 4388

Last change on this file since 4388 was 4388, checked in by cameron, 4 years ago

Add derived core properties such as math, alpha; refine the property resolver

File size: 7.8 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
7#include <string>
8#include <re/re_re.h>
9#include <re/re_alt.h>
10#include <re/re_cc.h>
11#include <re/re_seq.h>
12#include <re/re_rep.h>
13#include <re/re_name.h>
14#include <re/re_diff.h>
15#include <re/re_intersect.h>
16#include <re/re_start.h>
17#include <re/re_end.h>
18
19#include <cc/cc_namemap.hpp>
20#include "UCD/PropertyAliases.h"
21#include "UCD/PropertyObjects.h"
22#include "UCD/PropertyObjectTable.h"
23#include "UCD/PropertyValueAliases.h"
24
25class UnicodePropertyExpressionError : public std::exception {
26public:
27    UnicodePropertyExpressionError(const std::string && msg) noexcept : _msg(msg) {};
28    const char* what() const noexcept { return _msg.c_str();};
29private:
30    inline UnicodePropertyExpressionError() noexcept {}
31    const std::string _msg;
32};
33
34std::string canonicalize(std::string prop_or_val) {
35    std::locale loc;
36    std::string s = "";
37    for (unsigned int i = 0; i < prop_or_val.length(); ++i) {
38        char c = prop_or_val.at(i);
39        if ((c != '_') && (c != ' ') && (c != '-')) {
40            s += std::tolower(c, loc);
41        }
42    }
43    return s;
44}
45
46std::string lowercase(std::string prop_or_val) {
47    std::locale loc;
48    std::string s = "";
49    for (unsigned int i = 0; i < prop_or_val.length(); ++i) {
50        char c = prop_or_val.at(i);
51        s += std::tolower(c, loc);
52    }
53    return s;
54}
55
56using namespace re;
57
58void resolveProperties(RE * re) {
59    if (Alt * alt = dyn_cast<Alt>(re)) {
60        for (auto i = alt->begin(); i != alt->end(); ++i) {
61            resolveProperties(*i);
62        }
63    }
64    else if (Seq * seq = dyn_cast<Seq>(re)) {
65        for (auto i = seq->begin(); i != seq->end(); ++i) {
66            resolveProperties(*i);
67        }
68    }
69    else if (Rep * rep = dyn_cast<Rep>(re)) {
70        resolveProperties(rep->getRE());
71    }
72    else if (Diff * diff = dyn_cast<Diff>(re)) {
73        resolveProperties(diff->getRH());
74        resolveProperties(diff->getLH());
75    }
76    else if (Intersect * e = dyn_cast<Intersect>(re)) {
77        resolveProperties(e->getRH());
78        resolveProperties(e->getLH());
79    }
80    else if (Name * name = dyn_cast<Name>(re)) {
81        if (name->getType() == Name::Type::UnicodeProperty) {
82            std::string prop = name->getNamespace();
83            std::string v = canonicalize_value_name(name->getName());
84            UCD::property_t theprop;
85            if (prop != "") {
86                prop = canonicalize_value_name(prop);
87                auto propit = UCD::alias_map.find(prop);
88                if (propit == UCD::alias_map.end()) {
89                    throw UnicodePropertyExpressionError("Expected a property name, but '" + name->getNamespace() + "' found instead");
90                }
91                theprop = propit->second;
92                if (theprop == UCD::gc) {
93                    // General Category
94                    int valcode = dynamic_cast<UCD::EnumeratedPropertyObject *> (UCD::property_object_table[UCD::gc])->GetPropertyValueEnumCode(v);                   
95                    if (valcode > 0) {
96                        name->setName("__get_gc_" + UCD::GC_ns::enum_names[valcode]);
97                    }
98                    else throw UnicodePropertyExpressionError("Erroneous property value for general_category property");
99                }
100                else if (theprop == UCD::sc) {
101                    // Script property identified
102                    int valcode = dynamic_cast<UCD::EnumeratedPropertyObject *> (UCD::property_object_table[UCD::sc])->GetPropertyValueEnumCode(v);                   
103                    if (valcode > 0) {
104                        name->setName("__get_sc_" + UCD::SC_ns::enum_names[valcode]);
105                    }
106                    else throw UnicodePropertyExpressionError("Erroneous property value for script property");
107                }
108                else if (theprop == UCD::scx) {
109                    // Script extension property identified
110                    int valcode = dynamic_cast<UCD::EnumeratedPropertyObject *> (UCD::property_object_table[UCD::sc])->GetPropertyValueEnumCode(v);                   
111                    if (valcode > 0) {
112                        name->setName("__get_scx_" + UCD::SC_ns::enum_names[valcode]);
113                    }
114                    else throw UnicodePropertyExpressionError("Erroneous property value for script_extension property");
115                }
116                else if (theprop == UCD::blk) {
117                    // Block property identified
118                    int valcode = dynamic_cast<UCD::EnumeratedPropertyObject *> (UCD::property_object_table[UCD::blk])->GetPropertyValueEnumCode(v);                   
119                    if (valcode > 0) {
120                        name->setName("__get_blk_" + UCD::BLK_ns::enum_names[valcode]);
121                    }
122                    else throw UnicodePropertyExpressionError("Erroneous property value for block property");
123                }
124                else if (UCD::property_object_table[theprop]->the_kind == UCD::BinaryProperty){
125                    auto valit = UCD::Binary_ns::aliases_only_map.find(v);
126                    if (valit == UCD::Binary_ns::aliases_only_map.end()) {
127                        throw UnicodePropertyExpressionError("Erroneous property value for binary property " + UCD::property_full_name[theprop]);
128                    }
129                    if (valit->second == UCD::Binary_ns::Y) {
130                        name->setName("__get_" + lowercase(UCD::property_enum_name[theprop]) + "_Y");
131                        return;
132                    }
133                    else {
134                        throw UnicodePropertyExpressionError("Negated binary property " + UCD::property_full_name[theprop] + " recognized, but not supported");
135                    }
136                }
137                else {
138                    throw UnicodePropertyExpressionError("Property " + UCD::property_full_name[theprop] + " recognized, but not supported in icgrep 1.0");
139                }
140            }
141            else {
142                // No namespace (property) name.   Try as a general category.
143                int valcode = dynamic_cast<UCD::EnumeratedPropertyObject *> (UCD::property_object_table[UCD::gc])->GetPropertyValueEnumCode(v);
144                if (valcode > 0) {
145                    theprop = UCD::gc;
146                    name->setName("__get_gc_" + UCD::GC_ns::enum_names[valcode]);
147                    return;
148                }
149                valcode = dynamic_cast<UCD::EnumeratedPropertyObject *> (UCD::property_object_table[UCD::sc])->GetPropertyValueEnumCode(v);
150                if (valcode > 0) {
151                    theprop = UCD::sc;
152                    name->setName("__get_sc_" + UCD::SC_ns::enum_names[valcode]);
153                    return;
154                }
155                // Try as a binary property.
156                auto propit = UCD::alias_map.find(v);
157                if (propit == UCD::alias_map.end()) {
158                    throw UnicodePropertyExpressionError("Expected a general category, script or binary property name, but '" + name->getName() + "' found instead");
159                }
160                theprop = propit->second;
161                if (UCD::property_object_table[theprop]->the_kind == UCD::BinaryProperty) {
162                    name->setName("__get_" + lowercase(UCD::property_enum_name[theprop]) + "_Y");
163                    return;
164                }
165                else {
166                    throw UnicodePropertyExpressionError("Error: property " + UCD::property_full_name[theprop] + " specified without a value");
167                }
168            }
169           
170                //name->setCompiled(compileCC(cast<CC>(d), mCG));
171        }
172    }
173    else if (!isa<CC>(re) && !isa<Start>(re) && !isa<End>(re) && !isa<Any>(re)) {
174        throw UnicodePropertyExpressionError("Unknown RE type in resolveProperties.");
175    }
176}
177
Note: See TracBrowser for help on using the repository browser.