source: icGREP/icgrep-devel/icgrep/re/grapheme_clusters.cpp @ 5796

Last change on this file since 5796 was 5796, checked in by cameron, 15 months ago

Alphabet fixes

File size: 5.5 KB
Line 
1#include "grapheme_clusters.h"
2#include <re/re_cc.h>
3#include <re/re_name.h>
4#include <re/re_alt.h>             // for Alt, makeAlt
5#include <re/re_any.h>             // for makeAny, Any
6#include <re/re_assertion.h>       // for Assertion, Assertion::Sense, Asser...
7#include <re/re_diff.h>            // for Diff, makeDiff
8#include <re/re_group.h>
9#include <re/re_intersect.h>       // for Intersect
10#include <re/re_name.h>            // for Name
11#include <re/re_rep.h>             // for Rep, makeRep
12#include <re/re_seq.h>             // for Seq, makeSeq
13#include <re/re_start.h>
14#include <re/re_end.h>
15#include <re/re_range.h>
16#include <re/printer_re.h>
17#include <vector>                  // for vector, allocator
18#include <llvm/Support/Casting.h>  // for dyn_cast, isa
19#include <llvm/Support/ErrorHandling.h>
20#include <llvm/Support/raw_ostream.h>
21
22/*
23 Unicode Technical Standard #18 defines grapheme cluster mode, signified by the (?g) switch.
24 The mode is defined in terms of the assertion of grapheme cluster boundary assertions \b{g}
25 after every atomic literal.
26 
27 resolveGraphemeMode transforms a regular expression to perform the required insertion of
28 grapheme cluster boundaries, and the elimination of grapheme cluster mode groups.
29
30*/
31
32using namespace llvm;
33
34namespace re {
35bool hasGraphemeClusterBoundary(const RE * re) {
36    if (isa<CC>(re)) {
37        return false;
38    } else if (const Name * n = dyn_cast<Name>(re)) {
39        if (n->getType() == Name::Type::ZeroWidth) {
40            const std::string nameString = n->getName();
41            return (nameString == "\\b{g}") || (nameString == "\\B{g}");
42        }
43        return false;
44    } else if (const Alt * alt = dyn_cast<Alt>(re)) {
45        for (const RE * re : *alt) {
46            if (hasGraphemeClusterBoundary(re)) return true;
47        }
48        return false;
49    } else if (const Seq * seq = dyn_cast<Seq>(re)) {
50        for (const RE * re : *seq) {
51            if (hasGraphemeClusterBoundary(re)) return true;
52        }
53        return false;
54    } else if (const Rep * rep = dyn_cast<Rep>(re)) {
55        return hasGraphemeClusterBoundary(rep->getRE());
56    } else if (const Diff * diff = dyn_cast<Diff>(re)) {
57        return hasGraphemeClusterBoundary(diff->getLH()) || hasGraphemeClusterBoundary(diff->getRH());
58    } else if (const Intersect * e = dyn_cast<Intersect>(re)) {
59        return hasGraphemeClusterBoundary(e->getLH()) || hasGraphemeClusterBoundary(e->getRH());
60    } else if (isa<Start>(re) || isa<End>(re)) {
61        return false;
62    } else if (const Assertion * a = dyn_cast<Assertion>(re)) {
63        return hasGraphemeClusterBoundary(a->getAsserted());
64    } else if (const Group * g = dyn_cast<Group>(re)) {
65        if ((g->getMode() == Group::Mode::GraphemeMode) && (g->getSense() == Group::Sense::On)) return true;
66        else return hasGraphemeClusterBoundary(g->getRE());
67    }
68    else llvm_unreachable("Unknown RE type");
69}
70   
71RE * resolveGraphemeMode(RE * re, bool inGraphemeMode) {
72    if (isa<Name>(re)) {
73        if (inGraphemeMode && (cast<Name>(re)->getName() == "."))
74            return makeSeq({makeAny(), makeRep(makeSeq({makeZeroWidth("\\B{g}"), makeAny()}), 0, Rep::UNBOUNDED_REP), makeZeroWidth("\\b{g}")});
75        else return re;
76    }
77    else if (isa<CC>(re) || isa<Range>(re)) {
78        if (inGraphemeMode) return makeSeq({re, makeZeroWidth("\\b{g}")});
79        else return re;
80    }
81    else if (Seq * seq = dyn_cast<Seq>(re)) {
82        std::vector<RE*> list;
83        bool afterSingleChar = false;
84        for (auto i = seq->begin(); i != seq->end(); ++i) {
85            bool atSingleChar = isa<CC>(re) && (cast<CC>(re)->count() == 1);
86            if (afterSingleChar && inGraphemeMode && !atSingleChar)
87                list.push_back(makeZeroWidth("\\b{g}"));
88            if (isa<CC>(re)) list.push_back(*i);
89            else {
90                list.push_back(resolveGraphemeMode(*i, inGraphemeMode));
91            }
92            afterSingleChar = atSingleChar;
93        }
94        if (afterSingleChar && inGraphemeMode) list.push_back(makeZeroWidth("\\b{g}"));
95        return makeSeq(list.begin(), list.end());
96    } else if (Group * g = dyn_cast<Group>(re)) {
97        if (g->getMode() == Group::Mode::GraphemeMode) {
98            return resolveGraphemeMode(g->getRE(), g->getSense() == Group::Sense::On);
99        }
100        else {
101            return makeGroup(g->getMode(), resolveGraphemeMode(g->getRE(), inGraphemeMode), g->getSense());
102        }
103    } else if (Alt * alt = dyn_cast<Alt>(re)) {
104        std::vector<RE*> list;
105        for (auto i = alt->begin(); i != alt->end(); ++i) {
106            list.push_back(resolveGraphemeMode(*i, inGraphemeMode));
107        }
108        return makeAlt(list.begin(), list.end());
109    } else if (Rep * rep = dyn_cast<Rep>(re)) {
110        return makeRep(resolveGraphemeMode(rep->getRE(), inGraphemeMode), rep->getLB(), rep->getUB());
111    } else if (const Diff * diff = dyn_cast<const Diff>(re)) {
112        return makeDiff(resolveGraphemeMode(diff->getLH(), inGraphemeMode),
113                        resolveGraphemeMode(diff->getRH(), inGraphemeMode));
114    } else if (const Intersect * e = dyn_cast<const Intersect>(re)) {
115        return makeIntersect(resolveGraphemeMode(e->getLH(), inGraphemeMode),
116                             resolveGraphemeMode(e->getRH(), inGraphemeMode));
117    } else if (const Assertion * a = dyn_cast<Assertion>(re)) {
118        return makeAssertion(resolveGraphemeMode(a->getAsserted(), inGraphemeMode), a->getKind(), a->getSense());
119    } else if (isa<Start>(re) || isa<End>(re)) {
120        return re;
121    } else llvm_unreachable("Unknown RE type");
122}
123
124}
Note: See TracBrowser for help on using the repository browser.