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

Last change on this file since 5233 was 5233, checked in by nmedfort, 2 years ago

Bug fixes for Carry Manager and issues reported by Fahad

File size: 6.6 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_analysis.h>
13#include <re/re_memoizer.hpp>
14#include <UCD/ucd_compiler.hpp>
15#include <UCD/resolve_properties.h>
16#include <boost/container/flat_set.hpp>
17#include <sstream>
18
19#include <re/printer_re.h>
20#include <iostream>
21
22using NameMap = UCD::UCDCompiler::NameMap;
23
24using namespace boost::container;
25
26namespace re {
27 
28static inline CC * getDefinition(RE * re) {
29    if (isa<CC>(re)) {
30        return cast<CC>(re);
31    } else if (isa<Name>(re)) {
32        return getDefinition(cast<Name>(re)->getDefinition());
33    }
34    return nullptr;
35}
36
37struct NameResolver {
38
39    RE * resolve(RE * re) {
40        if (Name * name = dyn_cast<Name>(re)) {
41            auto f = mMemoizer.find(name);
42            if (f == mMemoizer.end()) {
43                if (LLVM_LIKELY(name->getDefinition() != nullptr)) {
44                    name->setDefinition(resolve(name->getDefinition()));
45                } else if (LLVM_LIKELY(name->getType() == Name::Type::UnicodeProperty || name->getType() == Name::Type::ZeroWidth)) {
46                    if (UCD::resolvePropertyDefinition(name)) {
47                        if (name->getType() == Name::Type::ZeroWidth) {
48                            mZeroWidth = name;
49                        }
50                        resolve(name->getDefinition());
51                    } else {
52                        #ifndef DISABLE_PREGENERATED_UCD_FUNCTIONS
53                        if (AlgorithmOptionIsSet(UsePregeneratedUnicode)) {
54                            const std::string functionName = UCD::resolvePropertyFunction(name);
55                            const UCD::ExternalProperty & ep = UCD::resolveExternalProperty(functionName);
56                            Call * call = mPB.createCall(Prototype::Create(functionName, std::get<1>(ep), std::get<2>(ep), std::get<0>(ep)), mCCCompiler.getBasisBits());
57                            name->setCompiled(call);
58                        } else {
59                        #endif
60                            name->setDefinition(makeCC(UCD::resolveUnicodeSet(name)));
61                        #ifndef DISABLE_PREGENERATED_UCD_FUNCTIONS
62                        }
63                        #endif
64                    }
65                } else {
66                throw std::runtime_error("All non-unicode-property Name objects should have been defined prior to Unicode property resolution.");
67                }
68            } else {
69                return *f;
70            }
71        } else if (Seq * seq = dyn_cast<Seq>(re)) {
72            for (auto si = seq->begin(); si != seq->end(); ++si) {
73                *si = resolve(*si);
74            }
75        } else if (Alt * alt = dyn_cast<Alt>(re)) {
76            CC * unionCC = nullptr;
77            std::stringstream name;
78            for (auto ai = alt->begin(); ai != alt->end(); ) {
79                RE * re = resolve(*ai);
80                if (CC * cc = getDefinition(re)) {
81                    if (unionCC == nullptr) {
82                        unionCC = cc;
83                    } else {
84                        unionCC = makeCC(unionCC, cc);
85                        name << '+';
86                    }
87                    if (LLVM_LIKELY(isa<Name>(re))) {
88                        Name * n = cast<Name>(re);
89                        if (n->hasNamespace()) {
90                            name << n->getNamespace() << ':';
91                        }
92                        name << n->getName();
93                    } else if (isa<CC>(re)) {
94                        name << cast<CC>(re)->canonicalName(UnicodeClass);
95                    }
96                    ai = alt->erase(ai);
97                } else {
98                    *ai++ = re;
99                }
100            }
101            if (unionCC) {
102                alt->push_back(resolve(makeName(name.str(), unionCC)));
103            }
104            if (alt->size() == 1) {
105                return alt->front();
106            }
107        } else if (Rep * rep = dyn_cast<Rep>(re)) {
108            rep->setRE(resolve(rep->getRE()));
109        } else if (Assertion * a = dyn_cast<Assertion>(re)) {
110            a->setAsserted(resolve(a->getAsserted()));
111        } else if (Diff * diff = dyn_cast<Diff>(re)) {
112            diff->setLH(resolve(diff->getLH()));
113            diff->setRH(resolve(diff->getRH()));
114            CC * lh = getDefinition(diff->getLH());
115            CC * rh = getDefinition(diff->getRH());
116            if (lh && rh) {
117                return resolve(makeName("diff", subtractCC(lh, rh)));
118            }
119        } else if (Intersect * ix = dyn_cast<Intersect>(re)) {
120            ix->setLH(resolve(ix->getLH()));
121            ix->setRH(resolve(ix->getRH()));
122            CC * lh = getDefinition(ix->getLH());
123            CC * rh = getDefinition(ix->getRH());
124            if (lh && rh) {
125                return resolve(makeName("intersect", intersectCC(lh, rh)));
126            }
127        }
128        return re;
129    }
130
131    void gather(RE * re) {
132        assert ("RE object cannot be null!" && re);
133        if (isa<Name>(re)) {
134            if (mVisited.insert(cast<Name>(re)).second) {
135                if (isa<CC>(cast<Name>(re)->getDefinition())) {
136                    mNameMap.emplace(cast<Name>(re), nullptr);
137                } else {
138                    gather(cast<Name>(re)->getDefinition());
139                }
140            }
141        } else if (isa<Seq>(re)) {
142            for (RE * item : *cast<Seq>(re)) {
143                gather(item);
144            }
145        } else if (isa<Alt>(re)) {
146            for (RE * item : *cast<Alt>(re)) {
147                gather(item);
148            }
149        } else if (isa<Rep>(re)) {
150            gather(cast<Rep>(re)->getRE());
151        } else if (isa<Assertion>(re)) {
152            gather(cast<Assertion>(re)->getAsserted());
153        } else if (isa<Diff>(re)) {
154            gather(cast<Diff>(re)->getLH());
155            gather(cast<Diff>(re)->getRH());
156        } else if (isa<Intersect>(re)) {
157            gather(cast<Intersect>(re)->getLH());
158            gather(cast<Intersect>(re)->getRH());
159        }
160    }
161
162    NameResolver(NameMap & nameMap, Name *& zeroWidth)
163    : mZeroWidth(zeroWidth)
164    , mNameMap(nameMap) {
165
166    }
167
168private:
169
170    Name *&                 mZeroWidth;
171    NameMap &               mNameMap;
172    Memoizer                mMemoizer;
173    flat_set<Name *>        mVisited;
174
175};
176   
177NameMap resolveNames(RE *& re, Name *& zeroWidth) {
178    NameMap nameMap;
179    NameResolver nameResolver(nameMap, zeroWidth);
180    re = nameResolver.resolve(re);
181    nameResolver.gather(re);
182    return nameMap;
183   
184}
185
186}
Note: See TracBrowser for help on using the repository browser.