source: icGREP/icgrep-devel/icgrep/re/to_utf8.cpp @ 5760

Last change on this file since 5760 was 5760, checked in by cameron, 17 months ago

to_utf8

File size: 3.4 KB
Line 
1/*
2 *  Copyright (c) 2017 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 <re/to_utf8.h>
8#include <UCD/unicode_set.h>
9#include <UCD/UTF.h>
10#include <re/re_name.h>
11#include <re/re_start.h>
12#include <re/re_end.h>
13#include <re/re_cc.h>
14#include <re/re_seq.h>
15#include <re/re_alt.h>
16#include <re/re_rep.h>
17#include <re/re_diff.h>
18#include <re/re_intersect.h>
19#include <re/re_assertion.h>
20#include <llvm/Support/Casting.h>
21
22using namespace llvm;
23
24namespace re {
25   
26static RE * rangeCodeUnits(codepoint_t lo, codepoint_t hi, unsigned index, const unsigned lgth){
27    const codepoint_t hunit = UTF<8>::nthCodeUnit(hi, index);
28    const codepoint_t lunit = UTF<8>::nthCodeUnit(lo, index);
29    if (index == lgth) {
30        return makeCC(lunit, hunit);
31    }
32    else if (hunit == lunit) {
33        return makeSeq({makeCC(hunit), rangeCodeUnits(lo, hi, index + 1, lgth)});
34    }
35    else {
36        const unsigned suffix_mask = (static_cast<unsigned>(1) << ((lgth - index) * 6)) - 1;
37        if ((hi & suffix_mask) != suffix_mask) {
38            const unsigned hi_floor = (~suffix_mask) & hi;
39            return makeAlt({rangeCodeUnits(hi_floor, hi, index, lgth), rangeCodeUnits(lo, hi_floor - 1, index, lgth)});
40        }
41        else if ((lo & suffix_mask) != 0) {
42            const unsigned low_ceil = lo | suffix_mask;
43            return makeAlt({rangeCodeUnits(low_ceil + 1, hi, index, lgth), rangeCodeUnits(lo, low_ceil, index, lgth)});
44        }
45        else {
46            return makeSeq({makeCC(lunit, hunit), rangeCodeUnits(lo, hi, index + 1, lgth)});
47        }
48    }
49}
50
51static RE * rangeToUTF8(codepoint_t lo, codepoint_t hi) {
52    const auto min_lgth = UTF<8>::encoded_length(lo);
53    const auto max_lgth = UTF<8>::encoded_length(hi);
54    if (min_lgth < max_lgth) {
55        const auto m = UTF<8>::max_codepoint_of_length(lo);
56        return makeAlt({rangeToUTF8(lo, m), rangeToUTF8(m + 1, hi)});
57    }
58    else {
59        return rangeCodeUnits(lo, hi, 1, max_lgth);
60    }
61}
62
63RE * toUTF8(RE * r) {
64    if (isa<Name>(r) || isa<Start>(r) || isa<End>(r)) {
65        return r;
66    } else if (const CC * cc = dyn_cast<CC>(r)) {
67        std::vector<RE *> alt;
68        for (const interval_t & i : *cc) {
69            alt.push_back(rangeToUTF8(lo_codepoint(i), hi_codepoint(i)));
70        }
71        return makeAlt(alt.begin(), alt.end());
72    } else if (Alt * alt = dyn_cast<Alt>(r)) {
73        std::vector<RE *> list;
74        list.reserve(alt->size());
75        for (RE * a : *alt) {
76            list.push_back(toUTF8(a));
77        }
78        return makeAlt(list.begin(), list.end());
79    } else if (Seq * seq = dyn_cast<Seq>(r)) {
80        std::vector<RE *> list;
81        list.reserve(seq->size());
82        for (RE * s : *seq) {
83            list.push_back(toUTF8(s));
84        }
85        return makeSeq(list.begin(), list.end());
86    } else if (Assertion * a = dyn_cast<Assertion>(r)) {
87        return makeAssertion(toUTF8(a->getAsserted()), a->getKind(), a->getSense());
88    } else if (Rep * rep = dyn_cast<Rep>(r)) {
89        RE * expr = toUTF8(rep->getRE());
90        return makeRep(expr, rep->getLB(), rep->getUB());
91    } else if (Diff * diff = dyn_cast<Diff>(r)) {
92        return makeDiff(toUTF8(diff->getLH()), toUTF8(diff->getRH()));
93    } else if (Intersect * e = dyn_cast<Intersect>(r)) {
94        return makeIntersect(toUTF8(e->getLH()), toUTF8(e->getRH()));
95    }
96}
97}
98
Note: See TracBrowser for help on using the repository browser.