source: icGREP/icgrep-devel/icgrep/re/Unicode/decomposition.cpp @ 6139

Last change on this file since 6139 was 6139, checked in by cameron, 10 months ago

Adding Hangul decomposition algorithm

File size: 9.6 KB
Line 
1/*
2 *  Copyright (c) 2018 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
7#include <string>
8#include <vector>
9#include <locale>
10#include <codecvt>
11#include <re/Unicode/decomposition.h>
12#include <re/re_cc.h>
13#include <re/re_seq.h>
14#include <re/re_alt.h>
15#include <re/re_group.h>
16#include <re/re_range.h>
17#include <re/re_diff.h>
18#include <re/re_intersect.h>
19#include <re/re_assertion.h>
20#include <UCD/unicode_set.h>
21#include <UCD/PropertyAliases.h>
22#include <UCD/PropertyObjects.h>
23#include <UCD/PropertyObjectTable.h>
24#include <UCD/PropertyValueAliases.h>
25#include <llvm/Support/Casting.h>
26
27using namespace UCD;
28using namespace llvm;
29using namespace re;
30
31// Constants for computation of Hangul decompositions, see Unicode Standard, section 3.12.
32const codepoint_t Hangul_SBase = 0xAC00;
33const codepoint_t Hangul_LBase = 0x1100;
34const codepoint_t Hangul_VBase = 0x1161;
35const codepoint_t Hangul_TBase = 0x11A7;
36const unsigned Hangul_TCount = 28;
37const unsigned Hangul_NCount = 588;
38const unsigned Hangul_SCount = 11172;
39static UnicodeSet HangulPrecomposed = UnicodeSet(Hangul_SBase, Hangul_SBase + Hangul_SCount - 1);
40
41static RE * HangulDecomposition(codepoint_t cp) {
42    auto SIndex = cp - Hangul_SBase;
43    auto LIndex = SIndex / Hangul_NCount;
44    auto VIndex = (SIndex % Hangul_NCount) / Hangul_TCount;
45    auto TIndex = SIndex % Hangul_TCount;
46    auto L = makeCC(Hangul_LBase + LIndex);
47    auto V = makeCC(Hangul_VBase + VIndex);
48    if (TIndex > 0) {
49        return makeSeq({L, V, makeCC(Hangul_TBase + TIndex)});
50    } else {
51        return makeSeq({L, V});
52    }
53}
54
55RE * NFD_CC(CC * cc) {
56    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv;
57    const auto & decompMappingObj = cast<StringPropertyObject>(property_object_table[dm]);
58    const auto & decompTypeObj = cast<EnumeratedPropertyObject>(property_object_table[dt]);
59    UnicodeSet canonicalMapped = decompTypeObj->GetCodepointSet(DT_ns::Can);
60    UnicodeSet mappingRequired = *cc & (canonicalMapped + HangulPrecomposed);
61    if (mappingRequired.empty()) return cc;
62    std::vector<RE *> alts;
63    CC * finalCC = makeCC(*cc - mappingRequired);
64    for (const interval_t & i : mappingRequired) {
65        for (codepoint_t cp = lo_codepoint(i); cp <= hi_codepoint(i); cp++) {
66            if (HangulPrecomposed.contains(cp)) {
67                alts.push_back(HangulDecomposition(cp));
68            } else {
69                std::u32string dms = conv.from_bytes(decompMappingObj->GetStringValue(cp));
70                RE * dm = u32string2re(dms);
71                if (Seq * s = dyn_cast<Seq>(dm)) {
72                    if (s->size() == 1) {
73                        finalCC = makeCC(finalCC, cast<CC>(s->front()));
74                    } else {
75                        alts.push_back(s);
76                    }
77                } else {
78                    alts.push_back(dm);
79                }
80            }
81        }
82    }
83    if (!finalCC->empty()) alts.push_back(finalCC);
84    return makeAlt(alts.begin(), alts.end());
85}
86
87
88RE * NFKD_CC(CC * cc) {
89    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv;
90    const auto & decompMappingObj = cast<StringPropertyObject>(property_object_table[dm]);
91    UnicodeSet reflexiveSet = decompMappingObj->GetReflexiveSet() - HangulPrecomposed;
92    UnicodeSet mappingRequired = *cc - reflexiveSet;
93    if (mappingRequired.empty()) return cc;
94    std::vector<RE *> alts;
95    CC * finalCC = makeCC(*cc - mappingRequired);
96    for (const interval_t & i : mappingRequired) {
97        for (codepoint_t cp = lo_codepoint(i); cp <= hi_codepoint(i); cp++) {
98            if (HangulPrecomposed.contains(cp)) {
99                alts.push_back(HangulDecomposition(cp));
100            } else {
101                std::u32string dms = conv.from_bytes(decompMappingObj->GetStringValue(cp));
102                RE * dm = u32string2re(dms);
103                if (Seq * s = dyn_cast<Seq>(dm)) {
104                    if (s->size() == 1) {
105                        finalCC = makeCC(finalCC, cast<CC>(s->front()));
106                    } else {
107                        alts.push_back(s);
108                    }
109                } else {
110                    alts.push_back(dm);
111                }
112            }
113        }
114    }
115    if (!finalCC->empty()) alts.push_back(finalCC);
116    return makeAlt(alts.begin(), alts.end());
117}
118
119RE * Casefold_CC(CC * cc) {
120    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv;
121    const auto & caseFoldObj = cast<StringOverridePropertyObject>(property_object_table[cf]);
122    UnicodeSet reflexiveSet = caseFoldObj->GetReflexiveSet();
123    UnicodeSet foldingRequired = *cc - reflexiveSet;
124    if (foldingRequired.empty()) return cc;
125    std::vector<RE *> alts;
126    CC * finalCC = makeCC(*cc - foldingRequired);
127    for (const interval_t & i : foldingRequired) {
128        for (codepoint_t cp = lo_codepoint(i); cp <= hi_codepoint(i); cp++) {
129            std::u32string dms = conv.from_bytes(caseFoldObj->GetStringValue(cp));
130            RE * dm = u32string2re(dms);
131            if (Seq * s = dyn_cast<Seq>(dm)) {
132                if (s->size() == 1) {
133                    finalCC = makeCC(finalCC, cast<CC>(s->front()));
134                } else {
135                    alts.push_back(s);
136                }
137            } else {
138                alts.push_back(dm);
139            }
140        }
141    }
142    if (!finalCC->empty()) alts.push_back(finalCC);
143    return makeAlt(alts.begin(), alts.end());
144}
145
146RE * NFD_RE(RE * re) {
147    if (Alt * alt = dyn_cast<Alt>(re)) {
148        std::vector<RE *> list;
149        list.reserve(alt->size());
150        for (RE * re : *alt) {
151            list.push_back(NFD_RE(re));
152        }
153        return makeAlt(list.begin(), list.end());
154    } else if (CC * cc = dyn_cast<CC>(re)) {
155        return NFD_CC(cc);
156    } else if (Seq * seq = dyn_cast<Seq>(re)) {
157        std::vector<RE *> list;
158        list.reserve(seq->size());
159        for (RE * re : *seq) {
160            list.push_back(NFD_RE(re));
161        }
162        return makeSeq(list.begin(), list.end());
163    } else if (Assertion * a = dyn_cast<Assertion>(re)) {
164        return makeAssertion(NFD_RE(a->getAsserted()), a->getKind(), a->getSense());
165    } else if (Rep * rep = dyn_cast<Rep>(re)) {
166        RE * expr = NFD_RE(rep->getRE());
167        return makeRep(expr, rep->getLB(), rep->getUB());
168    } else if (Diff * diff = dyn_cast<Diff>(re)) {
169        return makeDiff(NFD_RE(diff->getLH()), NFD_RE(diff->getRH()));
170    } else if (Intersect * e = dyn_cast<Intersect>(re)) {
171        return makeIntersect(NFD_RE(e->getLH()), NFD_RE(e->getRH()));
172    } else if (Range * rg = dyn_cast<Range>(re)) {
173        return makeRange(NFD_RE(rg->getLo()), NFD_RE(rg->getHi()));
174    } else if (Group * g = dyn_cast<Group>(re)) {
175        return makeGroup(g->getMode(), NFD_RE(g->getRE()), g->getSense());
176    }
177    return re;
178}
179   
180RE * NFKD_RE(RE * re) {
181    if (Alt * alt = dyn_cast<Alt>(re)) {
182        std::vector<RE *> list;
183        list.reserve(alt->size());
184        for (RE * re : *alt) {
185            list.push_back(NFKD_RE(re));
186        }
187        return makeAlt(list.begin(), list.end());
188    } else if (CC * cc = dyn_cast<CC>(re)) {
189        return NFKD_CC(cc);
190    } else if (Seq * seq = dyn_cast<Seq>(re)) {
191        std::vector<RE *> list;
192        list.reserve(seq->size());
193        for (RE * re : *seq) {
194            list.push_back(NFKD_RE(re));
195        }
196        return makeSeq(list.begin(), list.end());
197    } else if (Assertion * a = dyn_cast<Assertion>(re)) {
198        return makeAssertion(NFKD_RE(a->getAsserted()), a->getKind(), a->getSense());
199    } else if (Rep * rep = dyn_cast<Rep>(re)) {
200        RE * expr = NFKD_RE(rep->getRE());
201        return makeRep(expr, rep->getLB(), rep->getUB());
202    } else if (Diff * diff = dyn_cast<Diff>(re)) {
203        return makeDiff(NFKD_RE(diff->getLH()), NFKD_RE(diff->getRH()));
204    } else if (Intersect * e = dyn_cast<Intersect>(re)) {
205        return makeIntersect(NFKD_RE(e->getLH()), NFKD_RE(e->getRH()));
206    } else if (Range * rg = dyn_cast<Range>(re)) {
207        return makeRange(NFKD_RE(rg->getLo()), NFKD_RE(rg->getHi()));
208    } else if (Group * g = dyn_cast<Group>(re)) {
209        return makeGroup(g->getMode(), NFKD_RE(g->getRE()), g->getSense());
210    }
211    return re;
212}
213
214RE * Casefold_RE(RE * re) {
215    if (Alt * alt = dyn_cast<Alt>(re)) {
216        std::vector<RE *> list;
217        list.reserve(alt->size());
218        for (RE * re : *alt) {
219            list.push_back(Casefold_RE(re));
220        }
221        return makeAlt(list.begin(), list.end());
222    } else if (CC * cc = dyn_cast<CC>(re)) {
223        return Casefold_CC(cc);
224    } else if (Seq * seq = dyn_cast<Seq>(re)) {
225        std::vector<RE *> list;
226        list.reserve(seq->size());
227        for (RE * re : *seq) {
228            list.push_back(Casefold_RE(re));
229        }
230        return makeSeq(list.begin(), list.end());
231    } else if (Assertion * a = dyn_cast<Assertion>(re)) {
232        return makeAssertion(Casefold_RE(a->getAsserted()), a->getKind(), a->getSense());
233    } else if (Rep * rep = dyn_cast<Rep>(re)) {
234        RE * expr = Casefold_RE(rep->getRE());
235        return makeRep(expr, rep->getLB(), rep->getUB());
236    } else if (Diff * diff = dyn_cast<Diff>(re)) {
237        return makeDiff(Casefold_RE(diff->getLH()), Casefold_RE(diff->getRH()));
238    } else if (Intersect * e = dyn_cast<Intersect>(re)) {
239        return makeIntersect(Casefold_RE(e->getLH()), Casefold_RE(e->getRH()));
240    } else if (Range * rg = dyn_cast<Range>(re)) {
241        return makeRange(Casefold_RE(rg->getLo()), Casefold_RE(rg->getHi()));
242    } else if (Group * g = dyn_cast<Group>(re)) {
243        return makeGroup(g->getMode(), Casefold_RE(g->getRE()), g->getSense());
244    }
245    return re;
246}
Note: See TracBrowser for help on using the repository browser.