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

Last change on this file since 6132 was 5998, checked in by nmedfort, 16 months ago

Added temporary buffer functionality to the pipeline for single stream source buffers. Fixed memory leak from UCD::UnicodeBreakRE()

File size: 9.4 KB
Line 
1/*
2 *  Copyright (c) 2018 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 <re/re_re.h>
7#include "resolve_properties.h"
8#include <re/re_alt.h>
9#include <re/re_any.h>
10#include <re/re_name.h>
11#include <re/re_diff.h>
12#include <re/re_start.h>
13#include <re/re_end.h>
14#include <re/re_cc.h>
15#include <re/re_seq.h>
16#include <re/re_assertion.h>
17#include <re/parsers/parser.h>
18#include <re/re_name_resolve.h>
19#include <re/grapheme_clusters.h>
20#include <re/re_compiler.h>
21#include "UCD/PropertyAliases.h"
22#include "UCD/PropertyObjects.h"
23#include "UCD/PropertyObjectTable.h"
24#include "UCD/PropertyValueAliases.h"
25#include <llvm/Support/ErrorHandling.h>
26
27using namespace UCD;
28using namespace re;
29using namespace llvm;
30
31namespace UCD {
32   
33void UnicodePropertyExpressionError(std::string errmsg) {
34    llvm::report_fatal_error(errmsg);
35}
36
37bool resolvePropertyDefinition(Name * const property) {
38    if (property->hasNamespace()) {
39        auto propit = alias_map.find(property->getNamespace());
40        if (propit == alias_map.end()) {
41            UnicodePropertyExpressionError("Expected a property name but '" + property->getNamespace() + "' was found instead");
42        }
43        auto theprop = propit->second;
44        if (isa<BinaryPropertyObject>(property_object_table[theprop])){
45            auto valit = Binary_ns::aliases_only_map.find(property->getName());
46            if (valit != Binary_ns::aliases_only_map.end()) {
47                if (valit->second == Binary_ns::N) {
48                    Name * binprop = makeName(property_enum_name[theprop], Name::Type::UnicodeProperty);
49                    property->setDefinition(makeDiff(makeAny(), binprop));
50                    return true;
51                }
52            }
53        }
54    } else {
55        const std::string value = property->getName();
56        // Try special cases of Unicode TR #18
57        if ((value == "any") || (value == ".")) {
58            property->setDefinition(makeCC(0, 0x10FFFF));
59            return true;
60        } else if (value == "ascii") {
61            property->setDefinition(makeName("blk", "ascii", Name::Type::UnicodeProperty));
62            return true;
63        } else if (value == "assigned") {
64            Name * unassigned = makeName("cn", Name::Type::UnicodeProperty);
65            property->setDefinition(makeDiff(makeAny(), unassigned));
66            return true;
67        } else if (value == "\\b{g}") {
68            RE * gcb = generateGraphemeClusterBoundaryRule();
69            property->setDefinition(resolveUnicodeProperties(gcb));
70            return true;
71        } else if (value == "^s") {  // "start anchor (^) in single-line mode"
72            property->setDefinition(makeNegativeLookBehindAssertion(makeCC(0, 0x10FFFF)));
73            return true;
74        } else if (value == "$s") { // "end anchor ($) in single-line mode"
75            property->setDefinition(makeNegativeLookAheadAssertion(makeCC(0, 0x10FFFF)));
76            return true;
77        }
78    }
79    return false;
80}
81
82const std::string & getPropertyValueGrepString(const std::string & prop) {
83    auto propit = alias_map.find(canonicalize_value_name(prop));
84    if (propit == alias_map.end()) {
85        UnicodePropertyExpressionError("Expected a property name, but '" + prop + "' found instead");
86    }
87    auto theprop = propit->second;
88    if (EnumeratedPropertyObject * p = dyn_cast<EnumeratedPropertyObject>(property_object_table[theprop])){
89        return p->GetPropertyValueGrepString();
90    } else if (BinaryPropertyObject * p = dyn_cast<BinaryPropertyObject>(property_object_table[theprop])) {
91        return p->GetPropertyValueGrepString();
92    }
93
94    UnicodePropertyExpressionError("Property " + property_full_name[theprop] + " recognized but not supported in icgrep 1.0");
95}
96
97UnicodeSet resolveUnicodeSet(Name * const name) {
98    if (name->getType() == Name::Type::UnicodeProperty) {
99        std::string prop = name->getNamespace();
100        std::string value = name->getName();
101        if (prop.length() > 0) {
102            prop = canonicalize_value_name(prop);
103            auto propit = alias_map.find(prop);
104            if (propit == alias_map.end()) {
105                UnicodePropertyExpressionError("Expected a property name, but '" + name->getNamespace() + "' found instead");
106            }
107            auto propObj = property_object_table[propit->second];
108            if ((value.length() > 0) && (value[0] == '/')) {
109                // resolve a regular expression
110                re::RE * propValueRe = RE_Parser::parse(value.substr(1), re::DEFAULT_MODE, re::PCRE, false);
111                propValueRe = re::resolveNames(propValueRe);  // Recursive name resolution may be required.
112                return propObj->GetCodepointSetMatchingPattern(propValueRe);
113            }
114            if ((value.length() > 0) && (value[0] == '@')) {
115                // resolve a @property@ or @identity@ expression.
116                std::string otherProp = canonicalize_value_name(value.substr(1));
117                if (otherProp == "identity") {
118                    return propObj->GetReflexiveSet();
119                }
120                auto propit = alias_map.find(prop);
121                if (propit == alias_map.end()) {
122                    UnicodePropertyExpressionError("Expected a property name, but '" + value.substr(1) + "' found instead");
123                }
124                auto propObj2 = property_object_table[propit->second];
125                if (isa<BinaryPropertyObject>(propObj) && isa<BinaryPropertyObject>(propObj2)) {
126                    return ~(cast<BinaryPropertyObject>(propObj)->GetCodepointSet(UCD::Binary_ns::Y) ^
127                             cast<BinaryPropertyObject>(propObj2)->GetCodepointSet(UCD::Binary_ns::Y));
128                }
129                else {
130                    UnicodePropertyExpressionError("unsupported");
131                }
132            }
133            else {
134                return propObj->GetCodepointSet(value);
135            }
136        }
137        else {
138            // No namespace (property) name.   Try as a general category.
139            const auto & gcobj = cast<EnumeratedPropertyObject>(property_object_table[gc]);
140            int valcode = gcobj->GetPropertyValueEnumCode(value);
141            if (valcode >= 0) {
142                return gcobj->GetCodepointSet(valcode);
143            }
144            const auto & scObj = cast<EnumeratedPropertyObject>(property_object_table[sc]);
145            valcode = scObj->GetPropertyValueEnumCode(value);
146            if (valcode >= 0) {
147                return scObj->GetCodepointSet(valcode);
148            }
149            // Try as a binary property.
150            auto propit = alias_map.find(value);
151            if (propit != alias_map.end()) {
152                auto theprop = propit->second;
153                if (BinaryPropertyObject * p = dyn_cast<BinaryPropertyObject>(property_object_table[theprop])) {
154                    return p->GetCodepointSet(Binary_ns::Y);
155                }
156                else {
157                    UnicodePropertyExpressionError("Error: property " + property_full_name[theprop] + " specified without a value");
158                }
159            }
160            // Try special cases of Unicode TR #18
161            // Now compatibility properties of UTR #18 Annex C
162                   
163            else if (value == ".") return UnicodeSet(0, 0x10FFFF);
164            else if (value == "alnum") {
165                Name * digit = makeName("nd", Name::Type::UnicodeProperty);
166                Name * alpha = makeName("alphabetic", Name::Type::UnicodeProperty);
167                return resolveUnicodeSet(digit) + resolveUnicodeSet(alpha);
168            } else if (value == "xdigit") {
169                Name * digit = makeName("nd", Name::Type::UnicodeProperty);
170                Name * hexdigit = makeName("hexdigit", Name::Type::UnicodeProperty);
171                return resolveUnicodeSet(digit) + resolveUnicodeSet(hexdigit);
172            } else if (value == "blank") {
173                Name * space_sep = makeName("space_separator", Name::Type::UnicodeProperty);
174                return resolveUnicodeSet(space_sep) + UnicodeSet(0x09) /* tab */;
175            } else if (value == "print") {
176                Name * graph = makeName("graph", Name::Type::UnicodeProperty);
177                Name * space_sep = makeName("space_separator", Name::Type::UnicodeProperty);
178                return resolveUnicodeSet(graph) + resolveUnicodeSet(space_sep);
179            } else if (value == "word") {
180                Name * alnum = makeName("alnum", Name::Type::UnicodeProperty);
181                Name * mark = makeName("mark", Name::Type::UnicodeProperty);
182                Name * conn = makeName("connectorpunctuation", Name::Type::UnicodeProperty);
183                Name * join = makeName("joincontrol", Name::Type::UnicodeProperty);
184                return resolveUnicodeSet(alnum) + resolveUnicodeSet(mark) + resolveUnicodeSet(conn) + resolveUnicodeSet(join);
185            } else if (value == "graph") {
186                Name * space = makeName("space", Name::Type::UnicodeProperty);
187                Name * ctrl = makeName("control", Name::Type::UnicodeProperty);
188                Name * surr = makeName("surrogate", Name::Type::UnicodeProperty);
189                Name * unassigned = makeName("cn", Name::Type::UnicodeProperty);
190                return ~(resolveUnicodeSet(space) + resolveUnicodeSet(ctrl) + resolveUnicodeSet(surr) + resolveUnicodeSet(unassigned));
191            }
192
193
194        }
195    }
196    UnicodePropertyExpressionError("Expected a general category, script or binary property name, but '" + name->getName() + "' found instead");
197}
198
199}
Note: See TracBrowser for help on using the repository browser.