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

Last change on this file since 5241 was 5241, checked in by nmedfort, 3 years ago

Potential fix for '\p{script=/.*hir.*/}'

File size: 5.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_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 * extractCC(RE * re) {
29    if (isa<CC>(re)) {
30        return cast<CC>(re);
31    } else if (isa<Name>(re)) {
32        return extractCC(cast<Name>(re)->getDefinition());
33    }
34    return nullptr;
35}
36
37struct NameResolver {
38    RE * resolve(RE * re) {
39        if (Name * name = dyn_cast<Name>(re)) {
40            auto f = mMemoizer.find(name);
41            if (f == mMemoizer.end()) {
42                if (LLVM_LIKELY(name->getDefinition() != nullptr)) {
43                    name->setDefinition(resolve(name->getDefinition()));
44                } else if (LLVM_LIKELY(name->getType() == Name::Type::UnicodeProperty || name->getType() == Name::Type::ZeroWidth)) {
45                    if (UCD::resolvePropertyDefinition(name)) {
46                        if (name->getType() == Name::Type::ZeroWidth) {
47                            mZeroWidth = name;
48                        }
49                        name->setDefinition(resolve(name->getDefinition()));
50                    } else {
51                        name->setDefinition(makeCC(UCD::resolveUnicodeSet(name)));
52                    }
53                } else {
54                    throw std::runtime_error("All non-unicode-property Name objects should have been defined prior to Unicode property resolution.");
55                }
56            } else {
57                return *f;
58            }
59        } else if (Seq * seq = dyn_cast<Seq>(re)) {
60            for (auto si = seq->begin(); si != seq->end(); ++si) {
61                *si = resolve(*si);
62            }
63        } else if (Alt * alt = dyn_cast<Alt>(re)) {
64            CC * unionCC = nullptr;
65            std::stringstream name;
66            for (auto ai = alt->begin(); ai != alt->end(); ) {
67                RE * re = resolve(*ai);
68                if (CC * cc = extractCC(re)) {
69                    if (unionCC == nullptr) {
70                        unionCC = cc;
71                    } else {
72                        unionCC = makeCC(unionCC, cc);
73                        name << '+';
74                    }
75                    if (LLVM_LIKELY(isa<Name>(re))) {
76                        Name * n = cast<Name>(re);
77                        if (n->hasNamespace()) {
78                            name << n->getNamespace() << ':';
79                        }
80                        name << n->getName();
81                    } else if (isa<CC>(re)) {
82                        name << cast<CC>(re)->canonicalName(UnicodeClass);
83                    }
84                    ai = alt->erase(ai);
85                } else {
86                    *ai++ = re;
87                }
88            }
89            if (unionCC) {
90                alt->push_back(resolve(makeName(name.str(), unionCC)));
91            }
92            if (alt->size() == 1) {
93                return alt->front();
94            }
95        } else if (Rep * rep = dyn_cast<Rep>(re)) {
96            rep->setRE(resolve(rep->getRE()));
97        } else if (Assertion * a = dyn_cast<Assertion>(re)) {
98            a->setAsserted(resolve(a->getAsserted()));
99        } else if (Diff * diff = dyn_cast<Diff>(re)) {
100            diff->setLH(resolve(diff->getLH()));
101            diff->setRH(resolve(diff->getRH()));
102            CC * lh = extractCC(diff->getLH());
103            CC * rh = extractCC(diff->getRH());
104            if (lh && rh) {
105                return resolve(makeName("diff", subtractCC(lh, rh)));
106            }
107        } else if (Intersect * ix = dyn_cast<Intersect>(re)) {
108            ix->setLH(resolve(ix->getLH()));
109            ix->setRH(resolve(ix->getRH()));
110            CC * lh = extractCC(ix->getLH());
111            CC * rh = extractCC(ix->getRH());
112            if (lh && rh) {
113                return resolve(makeName("intersect", intersectCC(lh, rh)));
114            }
115        }
116        return re;
117    }
118
119    void gather(RE * re) {
120        assert ("RE object cannot be null!" && re);
121        if (isa<Name>(re)) {
122            if (mVisited.insert(cast<Name>(re)).second) {
123                if (isa<CC>(cast<Name>(re)->getDefinition())) {
124                    mNameMap.emplace(cast<Name>(re), nullptr);
125                } else {
126                    gather(cast<Name>(re)->getDefinition());
127                }
128            }
129        } else if (isa<Seq>(re)) {
130            for (RE * item : *cast<Seq>(re)) {
131                gather(item);
132            }
133        } else if (isa<Alt>(re)) {
134            for (RE * item : *cast<Alt>(re)) {
135                gather(item);
136            }
137        } else if (isa<Rep>(re)) {
138            gather(cast<Rep>(re)->getRE());
139        } else if (isa<Assertion>(re)) {
140            gather(cast<Assertion>(re)->getAsserted());
141        } else if (isa<Diff>(re)) {
142            gather(cast<Diff>(re)->getLH());
143            gather(cast<Diff>(re)->getRH());
144        } else if (isa<Intersect>(re)) {
145            gather(cast<Intersect>(re)->getLH());
146            gather(cast<Intersect>(re)->getRH());
147        }
148    }
149
150    NameResolver(NameMap & nameMap, Name *& zeroWidth)
151    : mZeroWidth(zeroWidth)
152    , mNameMap(nameMap) {
153
154    }
155
156private:
157
158    Name *&                 mZeroWidth;
159    NameMap &               mNameMap;
160    Memoizer                mMemoizer;
161    flat_set<Name *>        mVisited;
162
163};
164   
165NameMap resolveNames(RE *& re, Name *& zeroWidth) {
166    NameMap nameMap;
167    NameResolver nameResolver(nameMap, zeroWidth);
168    re = nameResolver.resolve(re);
169    nameResolver.gather(re);
170    return nameMap;
171   
172}
173
174}
Note: See TracBrowser for help on using the repository browser.