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

Last change on this file since 5881 was 5881, checked in by cameron, 20 months ago

Grapheme Cluster Break kernel

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