source: icGREP/icgrep-devel/icgrep/re/re_compiler.cpp @ 5565

Last change on this file since 5565 was 5565, checked in by xuedongx, 22 months ago

Separate name resolve and gather for future use. Add re_colloect_unicodesets and re_multiplex.

File size: 23.3 KB
Line 
1/*
2 *  Copyright (c) 2014 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
8
9#include "re_compiler.h"
10#include <pablo/pe_ones.h>          // for Ones
11#include <pablo/pe_var.h>           // for Var
12#include <pablo/pe_zeroes.h>        // for Zeroes
13#include <re/printer_re.h>
14#include <re/re_alt.h>
15#include <re/re_analysis.h>         // for isByteLength, isUnicodeUnitLength
16#include <re/re_any.h>
17#include <re/re_assertion.h>        // for Assertion, Assertion::Sense, Asse...
18#include <re/re_cc.h>               // for makeCC
19#include <re/re_diff.h>             // for Diff
20#include <re/re_end.h>
21#include <re/re_intersect.h>        // for Intersect
22#include <re/re_name.h>             // for Name, Name::Type, Name::Type::Zer...
23#include <re/re_name_resolve.h>     // for resolveNames
24#include <re/re_name_gather.h>      // for gatherNames
25#include <re/re_rep.h>              // for Rep, Rep::::UNBOUNDED_REP
26#include <re/re_seq.h>              // for Seq
27#include <re/re_start.h>
28#include <re/re_toolchain.h>        // for AlgorithmOptionIsSet, RE_Algorith...
29#include "cc/cc_compiler.h"         // for CC_Compiler
30#include "pablo/builder.hpp"        // for PabloBuilder
31namespace pablo { class PabloAST; }
32namespace pablo { class PabloKernel; }
33namespace re { class Alt; }
34namespace re { class RE; }
35
36
37#define UNICODE_LINE_BREAK (!AlgorithmOptionIsSet(DisableUnicodeLineBreak))
38
39using namespace pablo;
40using namespace llvm;
41
42namespace re {
43
44
45RE * RE_Compiler::resolveUnicodeProperties(RE * re) {
46    Name * ZeroWidth = nullptr;
47    mCompiledName = &mBaseMap;
48
49    re = resolveNames(re);
50    auto nameMap = gatherNames(re, ZeroWidth);
51    if (LLVM_LIKELY(nameMap.size() > 0)) {
52        UCD::UCDCompiler ucdCompiler(mCCCompiler);
53        if (LLVM_UNLIKELY(AlgorithmOptionIsSet(DisableIfHierarchy))) {
54            ucdCompiler.generateWithoutIfHierarchy(nameMap, mPB);
55        } else {
56            ucdCompiler.generateWithDefaultIfHierarchy(nameMap, mPB);
57        }
58        for (auto t : nameMap) {
59            if (t.second) {
60                mCompiledName->add(t.first, makeMarker(MarkerPosition::FinalMatchUnit, mPB.createAnd(t.second, mAny)));
61            }
62        }
63    }
64
65    // Now precompile any grapheme segmentation rules
66    if (ZeroWidth) {
67        mCompiledName->add(ZeroWidth, compileName(ZeroWidth, mPB));
68    }
69    return re;
70}
71
72void RE_Compiler::compileUnicodeNames(RE *& re) {
73    re = resolveUnicodeProperties(re);
74}
75
76void RE_Compiler::compile(RE * re) {
77    MarkerType match_results = compile(re, mPB);
78    PabloAST * match_post = markerVar(AdvanceMarker(match_results, MarkerPosition::FinalPostPositionUnit, mPB));
79    Var * const output = mKernel->getOutputStreamVar("matches");
80   
81    mPB.createAssign(mPB.createExtract(output, mPB.getInteger(0)), match_post);
82}
83   
84MarkerType RE_Compiler::compile(RE * re, PabloBuilder & pb) {
85    return process(re, makeMarker(MarkerPosition::FinalPostPositionUnit, pb.createOnes()), pb);
86}
87   
88MarkerType RE_Compiler::process(RE * re, MarkerType marker, PabloBuilder & pb) {
89    if (isa<Name>(re)) {
90        return compileName(cast<Name>(re), marker, pb);
91    } else if (isa<Seq>(re)) {
92        return compileSeq(cast<Seq>(re), marker, pb);
93    } else if (isa<Alt>(re)) {
94        return compileAlt(cast<Alt>(re), marker, pb);
95    } else if (isa<Rep>(re)) {
96        return compileRep(cast<Rep>(re), marker, pb);
97    } else if (isa<Assertion>(re)) {
98        return compileAssertion(cast<Assertion>(re), marker, pb);
99    } else if (isa<Any>(re)) {
100        return compileAny(marker, pb);
101    } else if (isa<Diff>(re)) {
102        return compileDiff(cast<Diff>(re), marker, pb);
103    } else if (isa<Intersect>(re)) {
104        return compileIntersect(cast<Intersect>(re), marker, pb);
105    } else if (isa<Start>(re)) {
106        return compileStart(marker, pb);
107    } else if (isa<End>(re)) {
108        return compileEnd(marker, pb);
109    } else if (isa<CC>(re)) {
110        // CCs may be passed through the toolchain directly to the compiler.
111        return compileCC(cast<CC>(re), marker, pb);
112    }
113    UnsupportedRE("RE Compiler failed to process " + Printer_RE::PrintRE(re));
114}
115
116inline MarkerType RE_Compiler::compileAny(const MarkerType m, PabloBuilder & pb) {
117    PabloAST * nextFinalByte = markerVar(AdvanceMarker(m, MarkerPosition::FinalPostPositionUnit, pb));
118    PabloAST * lb = mLineBreak;
119    if (UNICODE_LINE_BREAK) {
120        lb = pb.createOr(mLineBreak, mCRLF);
121    }
122    return makeMarker(MarkerPosition::FinalMatchUnit, pb.createAnd(nextFinalByte, pb.createNot(lb), "dot"));
123}
124
125MarkerType RE_Compiler::compileCC(CC * cc, MarkerType marker, PabloBuilder & pb) {
126    MarkerType nextPos;
127    if (markerPos(marker) == MarkerPosition::FinalPostPositionUnit) {
128        nextPos = marker;
129    } else {
130        nextPos = AdvanceMarker(marker, MarkerPosition::FinalPostPositionUnit, pb);
131    }
132    return makeMarker(MarkerPosition::FinalMatchUnit, pb.createAnd(markerVar(marker), pb.createAnd(mCCCompiler.compileCC(cc), mFinal)));
133}
134
135inline MarkerType RE_Compiler::compileName(Name * name, MarkerType marker, PabloBuilder & pb) {
136    if (isUnicodeUnitLength(name)) {
137        MarkerType nameMarker = compileName(name, pb);
138        MarkerType nextPos;
139        if (markerPos(marker) == MarkerPosition::FinalPostPositionUnit) {
140            nextPos = marker;
141        } else {
142            nextPos = AdvanceMarker(marker, MarkerPosition::FinalPostPositionUnit, pb);
143        }
144        nameMarker.stream = pb.createAnd(markerVar(nextPos), markerVar(nameMarker), name->getName());
145        return nameMarker;
146    } else if (name->getType() == Name::Type::ZeroWidth) {
147        RE * zerowidth = name->getDefinition();
148        MarkerType zero = compile(zerowidth, pb);
149        AlignMarkers(marker, zero, pb);
150        PabloAST * ze = markerVar(zero);
151        const std::string value = name->getName();
152        if (value == "NonGCB") {
153            ze = pb.createNot(ze);
154        }
155        return makeMarker(markerPos(marker), pb.createAnd(markerVar(marker), ze, "zerowidth"));
156    } else {
157        return process(name->getDefinition(), marker, pb);
158    }
159}
160
161inline MarkerType RE_Compiler::compileName(Name * name, PabloBuilder & pb) {
162    MarkerType m;
163    if (LLVM_LIKELY(mCompiledName->get(name, m))) {
164        return m;
165    } else if (LLVM_LIKELY(name->getDefinition() != nullptr)) {
166        m = compile(name->getDefinition(), pb);
167        mCompiledName->add(name, m);
168        return m;
169    }
170    UnsupportedRE("Unresolved name " + name->getName());
171}
172
173MarkerType RE_Compiler::compileSeq(Seq * seq, MarkerType marker, PabloBuilder & pb) {
174    // if-hierarchies are not inserted within unbounded repetitions
175    if (mStarDepth > 0) {
176        for (RE * re : *seq) {
177            marker = process(re, marker, pb);
178        }
179        return marker;
180    } else {
181        return compileSeqTail(seq->begin(), seq->end(), 0, marker, pb);
182    }
183}
184
185MarkerType RE_Compiler::compileSeqTail(Seq::iterator current, Seq::iterator end, int matchLenSoFar, MarkerType marker, PabloBuilder & pb) {
186    if (current == end) {
187        return marker;
188    } else if (matchLenSoFar < IfInsertionGap) {
189        RE * r = *current;
190        marker = process(r, marker, pb);
191        current++;
192        return compileSeqTail(current, end, matchLenSoFar + minMatchLength(r), marker, pb);
193    } else {
194        Var * m = pb.createVar("m", pb.createZeroes());
195        NameMap nestedMap(mCompiledName);
196        mCompiledName = &nestedMap;
197        PabloBuilder nested = PabloBuilder::Create(pb);
198        MarkerType m1 = compileSeqTail(current, end, 0, marker, nested);
199        nested.createAssign(m, markerVar(m1));
200        pb.createIf(markerVar(marker), nested);
201        mCompiledName = nestedMap.getParent();
202        return makeMarker(m1.pos, m);
203    }
204}
205
206MarkerType RE_Compiler::compileAlt(Alt * alt, MarkerType marker, PabloBuilder & pb) {
207    std::vector<PabloAST *>  accum(3, pb.createZeroes());
208    MarkerType const base = marker;
209    // The following may be useful to force a common Advance rather than separate
210    // Advances in each alternative.
211    for (RE * re : *alt) {
212        MarkerType m = process(re, base, pb);
213        MarkerPosition p = markerPos(m);
214        accum[p] = pb.createOr(accum[p], markerVar(m), "alt");
215    }
216    if (isa<Zeroes>(accum[MarkerPosition::FinalPostPositionUnit])) {
217        return makeMarker(MarkerPosition::FinalMatchUnit, accum[MarkerPosition::FinalMatchUnit]);
218    }
219    PabloAST * combine = pb.createAdvance(accum[MarkerPosition::FinalMatchUnit], 1);
220    combine = pb.createOr(pb.createScanThru(pb.createAnd(mInitial, combine), mNonFinal), accum[MarkerPosition::FinalPostPositionUnit], "alt");
221    return makeMarker(MarkerPosition::FinalPostPositionUnit, combine);
222}
223
224MarkerType RE_Compiler::compileAssertion(Assertion * a, MarkerType marker, PabloBuilder & pb) {
225    RE * asserted = a->getAsserted();
226    if (a->getKind() == Assertion::Kind::Lookbehind) {
227        MarkerType lookback = compile(asserted, pb);
228        AlignMarkers(marker, lookback, pb);
229        PabloAST * lb = markerVar(lookback);
230        if (a->getSense() == Assertion::Sense::Negative) {
231            lb = pb.createNot(lb);
232        }
233        return makeMarker(markerPos(marker), pb.createAnd(markerVar(marker), lb, "lookback"));
234    } else if (a->getKind() == Assertion::Kind::Boundary) {
235        MarkerType cond = compile(asserted, pb);
236        if (LLVM_LIKELY(markerPos(cond) == MarkerPosition::FinalMatchUnit)) {
237            MarkerType postCond = AdvanceMarker(cond, MarkerPosition::FinalPostPositionUnit, pb);
238            PabloAST * boundaryCond = pb.createAnd(mAny, pb.createXor(markerVar(cond), markerVar(postCond)));
239            if (a->getSense() == Assertion::Sense::Negative) {
240                boundaryCond = pb.createNot(boundaryCond);
241            }
242            MarkerType fbyte = AdvanceMarker(marker, MarkerPosition::FinalPostPositionUnit, pb);
243            return makeMarker(MarkerPosition::FinalPostPositionUnit, pb.createAnd(markerVar(fbyte), boundaryCond, "boundary"));
244        }
245        else UnsupportedRE("Unsupported boundary assertion");
246    } else if (isUnicodeUnitLength(asserted)) {
247        MarkerType lookahead = compile(asserted, pb);
248        if (LLVM_LIKELY(markerPos(lookahead) == MarkerPosition::FinalMatchUnit)) {
249            PabloAST * la = markerVar(lookahead);
250            if (a->getSense() == Assertion::Sense::Negative) {
251                la = pb.createNot(la);
252            }
253            MarkerType fbyte = AdvanceMarker(marker, MarkerPosition::FinalPostPositionUnit, pb);
254            return makeMarker(MarkerPosition::FinalPostPositionUnit, pb.createAnd(markerVar(fbyte), la, "lookahead"));
255        }
256    }
257    UnsupportedRE("Unsupported lookahead assertion.");
258}
259
260inline bool alignedUnicodeLength(const RE * lh, const RE * rh) {
261    const auto lhl = getUnicodeUnitLengthRange(lh);
262    const auto rhl = getUnicodeUnitLengthRange(rh);
263    return (lhl.first == lhl.second && lhl.first == rhl.first && lhl.second == rhl.second);
264}
265
266MarkerType RE_Compiler::compileDiff(Diff * diff, MarkerType marker, PabloBuilder & pb) {
267    RE * lh = diff->getLH();
268    RE * rh = diff->getRH();
269    if (alignedUnicodeLength(lh, rh)) {
270        MarkerType t1 = process(lh, marker, pb);
271        MarkerType t2 = process(rh, marker, pb);
272        AlignMarkers(t1, t2, pb);
273        return makeMarker(markerPos(t1), pb.createAnd(markerVar(t1), pb.createNot(markerVar(t2)), "diff"));
274    }
275    UnsupportedRE("Unsupported Diff operands: " + Printer_RE::PrintRE(diff));
276}
277
278MarkerType RE_Compiler::compileIntersect(Intersect * x, MarkerType marker, PabloBuilder & pb) {
279    RE * lh = x->getLH();
280    RE * rh = x->getRH();
281    if (alignedUnicodeLength(lh, rh)) {
282        MarkerType t1 = process(lh, marker, pb);
283        MarkerType t2 = process(rh, marker, pb);
284        AlignMarkers(t1, t2, pb);
285        return makeMarker(markerPos(t1), pb.createAnd(markerVar(t1), markerVar(t2), "intersect"));
286    }
287    UnsupportedRE("Unsupported Intersect operands: " + Printer_RE::PrintRE(x));
288}
289
290MarkerType RE_Compiler::compileRep(Rep * rep, MarkerType marker, PabloBuilder & pb) {
291    int lb = rep->getLB();
292    int ub = rep->getUB();
293    if (lb > 0) {
294        marker = processLowerBound(rep->getRE(), lb, marker, IfInsertionGap, pb);
295    }
296    if (ub == Rep::UNBOUNDED_REP) {
297        marker = processUnboundedRep(rep->getRE(), marker, pb);
298    } else if (lb < ub) {
299        marker = processBoundedRep(rep->getRE(), ub - lb, marker, IfInsertionGap, pb);
300    }
301    return marker;
302}
303
304/*
305   Given a stream |repeated| marking positions associated with matches to an item
306   of length |repeated_lgth|, compute a stream marking |repeat_count| consecutive
307   occurrences of such items.
308*/
309
310inline PabloAST * RE_Compiler::consecutive_matches(PabloAST * repeated, int length, int repeat_count, PabloBuilder & pb) {
311    int i = length;
312    int total = repeat_count * length;
313    PabloAST * consecutive_i = repeated;
314    while ((i * 2) < total) {
315        PabloAST * v = consecutive_i;
316        PabloAST * v2 =  pb.createAdvance(v, i);
317        i *= 2;
318        consecutive_i = pb.createAnd(v, v2, "at" + std::to_string(i) + "of" + std::to_string(total));
319    }
320    if (LLVM_LIKELY(i < total)) {
321        PabloAST * v = consecutive_i;
322        consecutive_i = pb.createAnd(v, pb.createAdvance(v, total - i), "at" + std::to_string(total));
323    }
324    return consecutive_i;
325}
326
327inline PabloAST * RE_Compiler::reachable(PabloAST * repeated, int length, int repeat_count, PabloBuilder & pb) {
328    int i = length;
329    int total_lgth = repeat_count * length;
330    if (repeat_count == 0) {
331        return repeated;
332    }
333    PabloAST * reachable_i = pb.createOr(repeated, pb.createAdvance(repeated, 1), "within1");
334    while ((i * 2) < total_lgth) {
335        PabloAST * v = reachable_i;
336        PabloAST * v2 =  pb.createAdvance(v, i);
337        i *= 2;
338        reachable_i = pb.createOr(v, v2, "within" + std::to_string(i));
339    }
340    if (LLVM_LIKELY(i < total_lgth)) {
341        PabloAST * v = reachable_i;
342        reachable_i = pb.createOr(v, pb.createAdvance(v, total_lgth - i), "within" + std::to_string(total_lgth));
343    }
344    return reachable_i;
345}
346
347MarkerType RE_Compiler::processLowerBound(RE * repeated, int lb, MarkerType marker, int ifGroupSize, PabloBuilder & pb) {
348    if (lb == 0) {
349        return marker;
350    } else if (!mGraphemeBoundaryRule && isByteLength(repeated) && !AlgorithmOptionIsSet(DisableLog2BoundedRepetition)) {
351        PabloAST * cc = markerVar(compile(repeated, pb));
352        PabloAST * cc_lb = consecutive_matches(cc, 1, lb, pb);
353        PabloAST * marker_fwd = pb.createAdvance(markerVar(marker), markerPos(marker) == MarkerPosition::FinalMatchUnit ? lb : lb - 1);
354        return makeMarker(MarkerPosition::FinalMatchUnit, pb.createAnd(marker_fwd, cc_lb, "lowerbound"));
355    }
356    // Fall through to general case.  Process the first item and insert the rest into an if-structure.
357    auto group = ifGroupSize < lb ? ifGroupSize : lb;
358    for (auto i = 0; i < group; i++) {
359        marker = process(repeated, marker, pb);
360        if (mGraphemeBoundaryRule) {
361            marker = AdvanceMarker(marker, MarkerPosition::FinalPostPositionUnit, pb);
362        }
363    }
364    if (lb == group) {
365        return marker;
366    }
367    Var * m = pb.createVar("m", pb.createZeroes());
368    PabloBuilder nested = PabloBuilder::Create(pb);
369    MarkerType m1 = processLowerBound(repeated, lb - group, marker, ifGroupSize * 2, nested);
370    nested.createAssign(m, markerVar(m1));
371    pb.createIf(markerVar(marker), nested);
372    return makeMarker(m1.pos, m);
373}
374   
375MarkerType RE_Compiler::processBoundedRep(RE * repeated, int ub, MarkerType marker, int ifGroupSize,  PabloBuilder & pb) {
376    if (ub == 0) {
377        return marker;
378    } else if (!mGraphemeBoundaryRule && isByteLength(repeated) && ub > 1 && !AlgorithmOptionIsSet(DisableLog2BoundedRepetition)) {
379        // log2 upper bound for fixed length (=1) class
380        // Create a mask of positions reachable within ub from current marker.
381        // Use matchstar, then apply filter.
382        PabloAST * match = markerVar(AdvanceMarker(marker, MarkerPosition::FinalPostPositionUnit, pb));
383        PabloAST * upperLimitMask = reachable(match, 1, ub, pb);
384        PabloAST * cursor = markerVar(AdvanceMarker(marker, MarkerPosition::FinalPostPositionUnit, pb));
385        PabloAST * rep_class_var = markerVar(compile(repeated, pb));
386        return makeMarker(MarkerPosition::FinalPostPositionUnit, pb.createAnd(pb.createMatchStar(cursor, rep_class_var), upperLimitMask, "bounded"));
387    }
388    // Fall through to general case.  Process the first item and insert the rest into an if-structure.   
389    auto group = ifGroupSize < ub ? ifGroupSize : ub;
390    for (auto i = 0; i < group; i++) {
391        MarkerType a = process(repeated, marker, pb);
392        MarkerType m = marker;
393        AlignMarkers(a, m, pb);
394        marker = makeMarker(markerPos(a), pb.createOr(markerVar(a), markerVar(m)));
395        if (mGraphemeBoundaryRule) {
396            marker = AdvanceMarker(marker, MarkerPosition::FinalPostPositionUnit, pb);
397        }
398    }
399    if (ub == group) {
400        return marker;
401    }
402    Var * m1a = pb.createVar("m", pb.createZeroes());
403    PabloBuilder nested = PabloBuilder::Create(pb);
404    MarkerType m1 = processBoundedRep(repeated, ub - group, marker, ifGroupSize * 2, nested);
405    nested.createAssign(m1a, markerVar(m1));
406    pb.createIf(markerVar(marker), nested);
407    return makeMarker(m1.pos, m1a);
408}
409
410MarkerType RE_Compiler::processUnboundedRep(RE * repeated, MarkerType marker, PabloBuilder & pb) {
411    // always use PostPosition markers for unbounded repetition.
412    PabloAST * base = markerVar(AdvanceMarker(marker, MarkerPosition::FinalPostPositionUnit, pb));
413    if (!mGraphemeBoundaryRule && isByteLength(repeated)  && !AlgorithmOptionIsSet(DisableMatchStar)) {
414        PabloAST * cc = markerVar(compile(repeated, pb));
415        PabloAST * mstar = nullptr;
416        mstar = pb.createMatchStar(base, cc, "unbounded");
417        return makeMarker(MarkerPosition::FinalPostPositionUnit, mstar);
418    } else if (isUnicodeUnitLength(repeated) && !AlgorithmOptionIsSet(DisableMatchStar) && !AlgorithmOptionIsSet(DisableUnicodeMatchStar)) {
419        PabloAST * cc = markerVar(compile(repeated, pb));
420        PabloAST * mstar = nullptr;
421        PabloAST * nonFinal = mNonFinal;
422        if (mGraphemeBoundaryRule) {
423            nonFinal = pb.createOr(nonFinal, pb.createNot(mGraphemeBoundaryRule, "gext"));
424        }
425        cc = pb.createOr(cc, nonFinal);
426        mstar = pb.createMatchStar(base, cc);
427        PabloAST * final = mFinal;
428        if (mGraphemeBoundaryRule) {
429            final = mGraphemeBoundaryRule;
430        }
431        return makeMarker(MarkerPosition::FinalPostPositionUnit, pb.createAnd(mstar, final, "unbounded"));
432    } else if (mStarDepth > 0){
433        PabloBuilder * const outer = pb.getParent();
434        Var * starPending = outer->createVar("pending", outer->createZeroes());
435        Var * starAccum = outer->createVar("accum", outer->createZeroes());
436        mStarDepth++;
437        PabloAST * m1 = pb.createOr(base, starPending);
438        PabloAST * m2 = pb.createOr(base, starAccum);
439        MarkerType result = process(repeated, makeMarker(MarkerPosition::FinalPostPositionUnit, m1), pb);
440        result = AdvanceMarker(result, MarkerPosition::FinalPostPositionUnit, pb);
441        PabloAST * loopComputation = markerVar(result);
442        pb.createAssign(starPending, pb.createAnd(loopComputation, pb.createNot(m2)));
443        pb.createAssign(starAccum, pb.createOr(loopComputation, m2));
444        mWhileTest = pb.createOr(mWhileTest, starPending);
445        mStarDepth--;     
446        return makeMarker(markerPos(result), pb.createOr(base, starAccum, "unbounded"));
447    } else {
448        Var * whileTest = pb.createVar("test", base);
449        Var * whilePending = pb.createVar("pending", base);
450        Var * whileAccum = pb.createVar("accum", base);
451        mWhileTest = pb.createZeroes();
452        PabloBuilder wb = PabloBuilder::Create(pb);
453        mStarDepth++;
454        MarkerType result = process(repeated, makeMarker(MarkerPosition::FinalPostPositionUnit, whilePending), wb);
455        result = AdvanceMarker(result, MarkerPosition::FinalPostPositionUnit, wb);
456        PabloAST * loopComputation = markerVar(result);
457        wb.createAssign(whilePending, wb.createAnd(loopComputation, wb.createNot(whileAccum)));
458        wb.createAssign(whileAccum, wb.createOr(loopComputation, whileAccum));
459        wb.createAssign(whileTest, wb.createOr(mWhileTest, whilePending));
460        pb.createWhile(whileTest, wb);
461        mStarDepth--;
462        return makeMarker(markerPos(result), whileAccum);
463    }
464}
465
466inline MarkerType RE_Compiler::compileStart(const MarkerType marker, pablo::PabloBuilder & pb) {
467    MarkerType m = AdvanceMarker(marker, MarkerPosition::FinalPostPositionUnit, pb);
468    if (UNICODE_LINE_BREAK) {
469        PabloAST * line_end = mPB.createOr(mLineBreak, mCRLF);
470        PabloAST * sol_init = pb.createNot(pb.createOr(pb.createAdvance(pb.createNot(line_end), 1), mCRLF));
471        PabloAST * sol = pb.createScanThru(pb.createAnd(mInitial, sol_init), mNonFinal);
472        return makeMarker(MarkerPosition::FinalPostPositionUnit, pb.createAnd(markerVar(m), sol, "sol"));
473    } else {
474        PabloAST * sol = pb.createNot(pb.createAdvance(pb.createNot(mLineBreak), 1));
475        return makeMarker(MarkerPosition::FinalPostPositionUnit, pb.createAnd(markerVar(m), sol, "sol"));
476    }
477}
478
479inline MarkerType RE_Compiler::compileEnd(const MarkerType marker, pablo::PabloBuilder & pb) {
480    PabloAST * nextPos = markerVar(AdvanceMarker(marker, MarkerPosition::FinalPostPositionUnit, pb));
481    return makeMarker(MarkerPosition::FinalPostPositionUnit, pb.createAnd(nextPos, mLineBreak, "eol"));
482}
483
484inline MarkerType RE_Compiler::AdvanceMarker(MarkerType marker, const MarkerPosition newpos, PabloBuilder & pb) {
485    if (marker.pos != newpos) {
486        if (marker.pos == MarkerPosition::FinalMatchUnit) {
487            marker.stream = pb.createAdvance(marker.stream, 1, "ipp");
488            PabloAST * nonFinal = mNonFinal;
489            if (mGraphemeBoundaryRule) {
490                nonFinal = pb.createOr(nonFinal, pb.createNot(mGraphemeBoundaryRule, "gext"));
491            }
492            marker.stream = pb.createScanThru(pb.createAnd(mInitial, marker.stream), nonFinal, "fpp");
493            marker.pos = MarkerPosition::FinalPostPositionUnit;
494        }
495    }
496    return marker;
497}
498
499inline void RE_Compiler::AlignMarkers(MarkerType & m1, MarkerType & m2, PabloBuilder & pb) {
500    if (m1.pos < m2.pos) {
501        m1 = AdvanceMarker(m1, m2.pos, pb);
502    } else if (m2.pos < m1.pos) {
503        m2 = AdvanceMarker(m2, m1.pos, pb);
504    }
505}
506   
507LLVM_ATTRIBUTE_NORETURN void RE_Compiler::UnsupportedRE(std::string errmsg) {
508    llvm::report_fatal_error(errmsg);
509}
510   
511   
512
513RE_Compiler::RE_Compiler(PabloKernel * kernel, cc::CC_Compiler & ccCompiler)
514: mKernel(kernel)
515, mCCCompiler(ccCompiler)
516, mLineBreak(nullptr)
517, mCRLF(nullptr)
518, mAny(nullptr)
519, mGraphemeBoundaryRule(nullptr)
520, mInitial(nullptr)
521, mNonFinal(nullptr)
522, mFinal(nullptr)
523, mWhileTest(nullptr)
524, mStarDepth(0)
525, mPB(ccCompiler.getBuilder())
526, mCompiledName(&mBaseMap) {
527    Var * const linebreak = mKernel->getInputStreamVar("linebreak");
528    mLineBreak = mPB.createExtract(linebreak, mPB.getInteger(0));
529    mAny = mPB.createNot(mLineBreak, "any");
530    Var * const required = mKernel->getInputStreamVar("required");
531    mInitial = mPB.createExtract(required, mPB.getInteger(0));
532    mNonFinal = mPB.createExtract(required, mPB.getInteger(1));
533    mFinal = mPB.createExtract(required, mPB.getInteger(2));
534    mCRLF = mPB.createExtract(required, mPB.getInteger(3));
535}
536
537} // end of namespace re
Note: See TracBrowser for help on using the repository browser.