source: icGREP/icgrep-devel/icgrep/re/re_name_resolve.cpp @ 5083

Last change on this file since 5083 was 5083, checked in by xuedongx, 3 years ago

separate module for resolve names

File size: 7.8 KB
Line 
1#include <re/re_name.h>
2#include <re/re_any.h>
3#include <re/re_start.h>
4#include <re/re_end.h>
5#include <re/re_alt.h>
6#include <re/re_cc.h>
7#include <re/re_seq.h>
8#include <re/re_rep.h>
9#include <re/re_diff.h>
10#include <re/re_intersect.h>
11#include <re/re_assertion.h>
12#include <re/re_grapheme_boundary.hpp>
13#include <re/re_analysis.h>
14#include <re/re_memoizer.hpp>
15#include <UCD/ucd_compiler.hpp>
16#include <UCD/resolve_properties.h>
17#include <unordered_set>
18#include <sstream>
19
20namespace re {
21 
22static inline CC * getDefinitionIfCC(RE * re) {
23    if (LLVM_LIKELY(isa<Name>(re))) {
24        Name * name = cast<Name>(re);
25        if (name->getDefinition() && isa<CC>(name->getDefinition())) {
26            return cast<CC>(name->getDefinition());
27        }
28    }
29    return nullptr;
30}
31
32Name * generateGraphemeClusterBoundaryRule() {
33    // 3.1.1 Grapheme Cluster Boundary Rules
34    #define Behind(x) makeLookBehindAssertion(x)
35    #define Ahead(x) makeLookAheadAssertion(x)
36
37    RE * GCB_Control = makeName("gcb", "cn", Name::Type::UnicodeProperty);
38    RE * GCB_CR = makeName("gcb", "cr", Name::Type::UnicodeProperty);
39    RE * GCB_LF = makeName("gcb", "lf", Name::Type::UnicodeProperty);
40    RE * GCB_Control_CR_LF = makeAlt({GCB_CR, GCB_LF});
41
42    // Break at the start and end of text.
43    RE * GCB_1 = makeStart();
44    RE * GCB_2 = makeEnd();
45    // Do not break between a CR and LF.
46    RE * GCB_3 = makeSeq({Behind(GCB_CR), Ahead(GCB_LF)});
47    // Otherwise, break before and after controls.
48    RE * GCB_4 = Behind(GCB_Control_CR_LF);
49    RE * GCB_5 = Ahead(GCB_Control_CR_LF);
50    RE * GCB_1_5 = makeAlt({GCB_1, GCB_2, makeDiff(makeAlt({GCB_4, GCB_5}), GCB_3)});
51
52    RE * GCB_L = makeName("gcb", "l", Name::Type::UnicodeProperty);
53    RE * GCB_V = makeName("gcb", "v", Name::Type::UnicodeProperty);
54    RE * GCB_LV = makeName("gcb", "lv", Name::Type::UnicodeProperty);
55    RE * GCB_LVT = makeName("gcb", "lvt", Name::Type::UnicodeProperty);
56    RE * GCB_T = makeName("gcb", "t", Name::Type::UnicodeProperty);
57    RE * GCB_RI = makeName("gcb", "ri", Name::Type::UnicodeProperty);
58    // Do not break Hangul syllable sequences.
59    RE * GCB_6 = makeSeq({Behind(GCB_L), Ahead(makeAlt({GCB_L, GCB_V, GCB_LV, GCB_LVT}))});
60    RE * GCB_7 = makeSeq({Behind(makeAlt({GCB_LV, GCB_V})), Ahead(makeAlt({GCB_V, GCB_T}))});
61    RE * GCB_8 = makeSeq({Behind(makeAlt({GCB_LVT, GCB_T})), Ahead(GCB_T)});
62    // Do not break between regional indicator symbols.
63    RE * GCB_8a = makeSeq({Behind(GCB_RI), Ahead(GCB_RI)});
64    // Do not break before extending characters.
65    RE * GCB_9 = Ahead(makeName("gcb", "ex", Name::Type::UnicodeProperty));
66    // Do not break before SpacingMarks, or after Prepend characters.
67    RE * GCB_9a = Ahead(makeName("gcb", "sm", Name::Type::UnicodeProperty));
68    RE * GCB_9b = Behind(makeName("gcb", "pp", Name::Type::UnicodeProperty));
69    RE * GCB_6_9b = makeAlt({GCB_6, GCB_7, GCB_8, GCB_8a, GCB_9, GCB_9a, GCB_9b});
70    // Otherwise, break everywhere.
71    RE * GCB_10 = makeSeq({Behind(makeAny()), Ahead(makeAny())});
72
73    Name * gcb = makeName("gcb", Name::Type::UnicodeProperty);
74    gcb->setDefinition(makeAlt({GCB_1_5, makeDiff(GCB_10, GCB_6_9b)}));
75    return gcb;
76}
77
78Name * graphemeClusterRule = nullptr;
79
80RE * resolve(RE * re) {
81    Memoizer memoizer;
82    if (Name * name = dyn_cast<Name>(re)) {
83        auto f = memoizer.find(name);
84        if (f == memoizer.end()) {
85            if (LLVM_LIKELY(name->getDefinition() != nullptr)) {
86                name->setDefinition(resolve(name->getDefinition()));
87            } else if (LLVM_LIKELY(name->getType() == Name::Type::UnicodeProperty)) {
88                if (UCD::resolvePropertyDefinition(name)) {
89                    resolve(name->getDefinition());
90                } else {
91                    #ifndef DISABLE_PREGENERATED_UCD_FUNCTIONS
92                    if (AlgorithmOptionIsSet(UsePregeneratedUnicode)) {
93                        const std::string functionName = UCD::resolvePropertyFunction(name);
94                        const UCD::ExternalProperty & ep = UCD::resolveExternalProperty(functionName);
95                        Call * call = mPB.createCall(Prototype::Create(functionName, std::get<1>(ep), std::get<2>(ep), std::get<0>(ep)), mCCCompiler.getBasisBits());
96                        name->setCompiled(call);
97                    } else {
98                    #endif
99                        name->setDefinition(makeCC(UCD::resolveUnicodeSet(name)));
100                    #ifndef DISABLE_PREGENERATED_UCD_FUNCTIONS
101                    }
102                    #endif
103                }
104            } else {
105                throw std::runtime_error("All non-unicode-property Name objects should have been defined prior to Unicode property resolution.");
106            }
107        } else {
108            return *f;
109        }
110    } else if (Seq * seq = dyn_cast<Seq>(re)) {
111        for (auto si = seq->begin(); si != seq->end(); ++si) {
112            *si = resolve(*si);
113        }
114    } else if (Alt * alt = dyn_cast<Alt>(re)) {
115        CC * unionCC = nullptr;
116        std::stringstream name;
117        for (auto ai = alt->begin(); ai != alt->end(); ) {
118            RE * re = resolve(*ai);
119            if (CC * cc = getDefinitionIfCC(re)) {
120                if (unionCC == nullptr) {
121                    unionCC = cc;
122                } else {
123                    unionCC = makeCC(unionCC, cc);
124                    name << '+';
125                }
126                Name * n = cast<Name>(re);
127                if (n->hasNamespace()) {
128                    name << n->getNamespace() << ':';
129                }
130                name << n->getName();
131                ai = alt->erase(ai);
132            } else {
133                *ai++ = re;
134            }
135        }
136        if (unionCC) {
137            alt->push_back(makeName(name.str(), unionCC));
138        }
139        if (alt->size() == 1) {
140            return alt->front();
141        }
142    } else if (Rep * rep = dyn_cast<Rep>(re)) {
143        rep->setRE(resolve(rep->getRE()));
144    } else if (Assertion * a = dyn_cast<Assertion>(re)) {
145        a->setAsserted(resolve(a->getAsserted()));
146    } else if (Diff * diff = dyn_cast<Diff>(re)) {
147        diff->setLH(resolve(diff->getLH()));
148        diff->setRH(resolve(diff->getRH()));
149        CC * lh = getDefinitionIfCC(diff->getLH());
150        CC * rh = getDefinitionIfCC(diff->getRH());
151        if (lh && rh) {
152            return resolve(makeName("diff", subtractCC(lh, rh)));
153        }
154    } else if (Intersect * ix = dyn_cast<Intersect>(re)) {
155        ix->setLH(resolve(ix->getLH()));
156        ix->setRH(resolve(ix->getRH()));
157        CC * lh = getDefinitionIfCC(ix->getLH());
158        CC * rh = getDefinitionIfCC(ix->getRH());
159        if (lh && rh) {
160            return resolve(makeName("intersect", intersectCC(lh, rh)));
161        }
162    } else if (GraphemeBoundary * gb = dyn_cast<GraphemeBoundary>(re)) {
163        if (LLVM_LIKELY(gb->getBoundaryRule() == nullptr)) {
164            switch (gb->getType()) {
165                case GraphemeBoundary::Type::ClusterBoundary:
166                    if (graphemeClusterRule == nullptr) {
167                        graphemeClusterRule = cast<Name>(resolve(generateGraphemeClusterBoundaryRule()));
168                    }
169                    gb->setBoundaryRule(graphemeClusterRule);
170                    break;
171                default:
172                    throw std::runtime_error("Only grapheme cluster boundary rules are supported in icGrep 1.0");
173            }
174        }
175        if (gb->getExpression()) {
176            resolve(gb->getExpression());
177        }
178    }
179    return re;
180}
181
182UCD::UCDCompiler::NameMap nameMap;
183std::unordered_set<Name *> visited;
184   
185void gather(RE * re) {
186    assert ("RE object cannot be null!" && re);
187    if (isa<Name>(re)) {
188        if (visited.insert(cast<Name>(re)).second) {
189            if (isa<CC>(cast<Name>(re)->getDefinition())) {
190                nameMap.emplace(cast<Name>(re), nullptr);
191            } else {
192                gather(cast<Name>(re)->getDefinition());
193            }
194        }
195    } else if (isa<Seq>(re)) {
196        for (RE * item : *cast<Seq>(re)) {
197            gather(item);
198        }
199    } else if (isa<Alt>(re)) {
200        for (RE * item : *cast<Alt>(re)) {
201            gather(item);
202        }
203    } else if (isa<Rep>(re)) {
204        gather(cast<Rep>(re)->getRE());
205    } else if (isa<Assertion>(re)) {
206        gather(cast<Assertion>(re)->getAsserted());
207    } else if (isa<Diff>(re)) {
208        gather(cast<Diff>(re)->getLH());
209        gather(cast<Diff>(re)->getRH());
210    } else if (isa<Intersect>(re)) {
211        gather(cast<Intersect>(re)->getLH());
212        gather(cast<Intersect>(re)->getRH());
213    } else if (isa<GraphemeBoundary>(re)) {
214        if (cast<GraphemeBoundary>(re)->getExpression()) {
215            gather(cast<GraphemeBoundary>(re)->getExpression());
216        }
217        gather(cast<GraphemeBoundary>(re)->getBoundaryRule());
218    }
219}
220   
221UCD::UCDCompiler::NameMap resolveNames(RE * re, Name * &Rule) {
222
223    graphemeClusterRule = nullptr;
224    re = resolve(re);
225    gather(re);
226    Rule = graphemeClusterRule;
227   
228    return nameMap;
229   
230}
231
232}
Note: See TracBrowser for help on using the repository browser.