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

Last change on this file since 5671 was 5667, checked in by cameron, 22 months ago

Fix Mac OS compile bugs and some property object issues

File size: 9.6 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_start.h>
12#include <re/re_end.h>
13#include <re/re_cc.h>
14#include <re/re_seq.h>
15#include <re/re_assertion.h>
16#include "UCD/PropertyAliases.h"
17#include "UCD/PropertyObjects.h"
18#include "UCD/PropertyObjectTable.h"
19#include "UCD/PropertyValueAliases.h"
20#include <llvm/Support/ErrorHandling.h>
21
22using namespace UCD;
23using namespace re;
24using namespace llvm;
25
26namespace UCD {
27   
28void UnicodePropertyExpressionError(std::string errmsg) {
29    llvm::report_fatal_error(errmsg);
30
31}
32
33
34void generateGraphemeClusterBoundaryRule(Name * const &property) {
35    // 3.1.1 Grapheme Cluster Boundary Rules
36#define Behind(x) makeLookBehindAssertion(x)
37#define Ahead(x) makeLookAheadAssertion(x)
38
39//    RE * GCB_Control = makeName("gcb", "cn", Name::Type::UnicodeProperty);
40    RE * GCB_CR = makeName("gcb", "cr", Name::Type::UnicodeProperty);
41    RE * GCB_LF = makeName("gcb", "lf", Name::Type::UnicodeProperty);
42    RE * GCB_Control_CR_LF = makeAlt({GCB_CR, GCB_LF});
43
44    // Break at the start and end of text.
45    RE * GCB_1 = makeStart();
46    RE * GCB_2 = makeEnd();
47    // Do not break between a CR and LF.
48    RE * GCB_3 = makeSeq({Behind(GCB_CR), Ahead(GCB_LF)});
49    // Otherwise, break before and after controls.
50    RE * GCB_4 = Behind(GCB_Control_CR_LF);
51    RE * GCB_5 = Ahead(GCB_Control_CR_LF);
52    RE * GCB_1_5 = makeAlt({GCB_1, GCB_2, makeDiff(makeAlt({GCB_4, GCB_5}), GCB_3)});
53
54    RE * GCB_L = makeName("gcb", "l", Name::Type::UnicodeProperty);
55    RE * GCB_V = makeName("gcb", "v", Name::Type::UnicodeProperty);
56    RE * GCB_LV = makeName("gcb", "lv", Name::Type::UnicodeProperty);
57    RE * GCB_LVT = makeName("gcb", "lvt", Name::Type::UnicodeProperty);
58    RE * GCB_T = makeName("gcb", "t", Name::Type::UnicodeProperty);
59    RE * GCB_RI = makeName("gcb", "ri", Name::Type::UnicodeProperty);
60    // Do not break Hangul syllable sequences.
61    RE * GCB_6 = makeSeq({Behind(GCB_L), Ahead(makeAlt({GCB_L, GCB_V, GCB_LV, GCB_LVT}))});
62    RE * GCB_7 = makeSeq({Behind(makeAlt({GCB_LV, GCB_V})), Ahead(makeAlt({GCB_V, GCB_T}))});
63    RE * GCB_8 = makeSeq({Behind(makeAlt({GCB_LVT, GCB_T})), Ahead(GCB_T)});
64    // Do not break between regional indicator symbols.
65    RE * GCB_8a = makeSeq({Behind(GCB_RI), Ahead(GCB_RI)});
66    // Do not break before extending characters.
67    RE * GCB_9 = Ahead(makeName("gcb", "ex", Name::Type::UnicodeProperty));
68    // Do not break before SpacingMarks, or after Prepend characters.
69    RE * GCB_9a = Ahead(makeName("gcb", "sm", Name::Type::UnicodeProperty));
70    RE * GCB_9b = Behind(makeName("gcb", "pp", Name::Type::UnicodeProperty));
71    RE * GCB_6_9b = makeAlt({GCB_6, GCB_7, GCB_8, GCB_8a, GCB_9, GCB_9a, GCB_9b});
72    // Otherwise, break everywhere.
73    RE * GCB_10 = makeSeq({Behind(makeAny()), Ahead(makeAny())});
74
75    //Name * gcb = makeName("gcb", Name::Type::UnicodeProperty);
76    property->setDefinition(makeAlt({GCB_1_5, makeDiff(GCB_10, GCB_6_9b)}));
77}
78
79bool resolvePropertyDefinition(Name * const property) {
80    if (property->hasNamespace()) {
81        auto propit = alias_map.find(property->getNamespace());
82        if (propit == alias_map.end()) {
83            UnicodePropertyExpressionError("Expected a property name but '" + property->getNamespace() + "' was found instead");
84        }
85        auto theprop = propit->second;
86        if (isa<BinaryPropertyObject>(property_object_table[theprop])){
87            auto valit = Binary_ns::aliases_only_map.find(property->getName());
88            if (valit != Binary_ns::aliases_only_map.end()) {
89                if (valit->second == Binary_ns::N) {
90                    Name * binprop = makeName(property_enum_name[theprop], Name::Type::UnicodeProperty);
91                    property->setDefinition(makeDiff(makeAny(), binprop));
92                    return true;
93                }
94            }
95        }
96    } else {
97        const std::string value = property->getName();
98        // Try special cases of Unicode TR #18
99        if (value == "any") {
100            property->setDefinition(makeAny());
101            return true;
102        } else if (value == "ascii") {
103            property->setDefinition(makeName("blk", "ascii", Name::Type::UnicodeProperty));
104            return true;
105        } else if (value == "assigned") {
106            Name * unassigned = makeName("cn", Name::Type::UnicodeProperty);
107            property->setDefinition(makeDiff(makeAny(), unassigned));
108            return true;
109        } else if (value == "GCB" || value == "NonGCB"){
110            generateGraphemeClusterBoundaryRule(property);
111            return true;
112        }
113    }
114    return false;
115}
116
117const std::string & getPropertyValueGrepString(const std::string & prop) {
118    auto propit = alias_map.find(canonicalize_value_name(prop));
119    if (propit == alias_map.end()) {
120        UnicodePropertyExpressionError("Expected a property name, but '" + prop + "' found instead");
121    }
122    auto theprop = propit->second;
123    if (EnumeratedPropertyObject * p = dyn_cast<EnumeratedPropertyObject>(property_object_table[theprop])){
124        return p->GetPropertyValueGrepString();
125    } else if (BinaryPropertyObject * p = dyn_cast<BinaryPropertyObject>(property_object_table[theprop])) {
126        return p->GetPropertyValueGrepString();
127    }
128
129    UnicodePropertyExpressionError("Property " + property_full_name[theprop] + " recognized but not supported in icgrep 1.0");
130}
131
132UnicodeSet resolveUnicodeSet(Name * const name) {
133    if (name->getType() == Name::Type::UnicodeProperty) {
134        std::string prop = name->getNamespace();
135        std::string value = name->getName();
136        if (prop.length() > 0) {
137            prop = canonicalize_value_name(prop);
138            auto propit = alias_map.find(prop);
139            if (propit == alias_map.end()) {
140                UnicodePropertyExpressionError("Expected a property name, but '" + name->getNamespace() + "' found instead");
141            }
142            auto theprop = propit->second;
143            return property_object_table[theprop]->GetCodepointSet(value);
144        }
145        else {
146            // No namespace (property) name.   Try as a general category.
147            const auto & gcobj = cast<EnumeratedPropertyObject>(property_object_table[gc]);
148            int valcode = gcobj->GetPropertyValueEnumCode(value);
149            if (valcode >= 0) {
150                return gcobj->GetCodepointSet(valcode);
151            }
152            const auto & scObj = cast<EnumeratedPropertyObject>(property_object_table[sc]);
153            valcode = scObj->GetPropertyValueEnumCode(value);
154            if (valcode >= 0) {
155                return scObj->GetCodepointSet(valcode);
156            }
157            // Try as a binary property.
158            auto propit = alias_map.find(value);
159            if (propit != alias_map.end()) {
160                auto theprop = propit->second;
161                if (BinaryPropertyObject * p = dyn_cast<BinaryPropertyObject>(property_object_table[theprop])) {
162                    return p->GetCodepointSet(Binary_ns::Y);
163                }
164                else {
165                    UnicodePropertyExpressionError("Error: property " + property_full_name[theprop] + " specified without a value");
166                }
167            }
168            // Try special cases of Unicode TR #18
169            // Now compatibility properties of UTR #18 Annex C
170                   
171            else if (value == "alnum") {
172                Name * digit = makeName("nd", Name::Type::UnicodeProperty);
173                Name * alpha = makeName("alphabetic", Name::Type::UnicodeProperty);
174                return resolveUnicodeSet(digit) + resolveUnicodeSet(alpha);
175            } else if (value == "xdigit") {
176                Name * digit = makeName("nd", Name::Type::UnicodeProperty);
177                Name * hexdigit = makeName("hexdigit", Name::Type::UnicodeProperty);
178                return resolveUnicodeSet(digit) + resolveUnicodeSet(hexdigit);
179            } else if (value == "blank") {
180                Name * space_sep = makeName("space_separator", Name::Type::UnicodeProperty);
181                return resolveUnicodeSet(space_sep) + UnicodeSet(0x09) /* tab */;
182            } else if (value == "print") {
183                Name * graph = makeName("graph", Name::Type::UnicodeProperty);
184                Name * space_sep = makeName("space_separator", Name::Type::UnicodeProperty);
185                return resolveUnicodeSet(graph) + resolveUnicodeSet(space_sep);
186            } else if (value == "word") {
187                Name * alnum = makeName("alnum", Name::Type::UnicodeProperty);
188                Name * mark = makeName("mark", Name::Type::UnicodeProperty);
189                Name * conn = makeName("connectorpunctuation", Name::Type::UnicodeProperty);
190                Name * join = makeName("joincontrol", Name::Type::UnicodeProperty);
191                return resolveUnicodeSet(alnum) + resolveUnicodeSet(mark) + resolveUnicodeSet(conn) + resolveUnicodeSet(join);
192            } else if (value == "graph") {
193                Name * space = makeName("space", Name::Type::UnicodeProperty);
194                Name * ctrl = makeName("control", Name::Type::UnicodeProperty);
195                Name * surr = makeName("surrogate", Name::Type::UnicodeProperty);
196                Name * unassigned = makeName("cn", Name::Type::UnicodeProperty);
197                return ~(resolveUnicodeSet(space) + resolveUnicodeSet(ctrl) + resolveUnicodeSet(surr) + resolveUnicodeSet(unassigned));
198            }
199
200
201        }
202    }
203    UnicodePropertyExpressionError("Expected a general category, script or binary property name, but '" + name->getName() + "' found instead");
204}
205
206}
Note: See TracBrowser for help on using the repository browser.