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

Last change on this file since 5585 was 5585, checked in by xuedongx, 21 months ago

use multiplexed character classes as the input to grep kernel, restructure the icGrep pipeline: Matches = RE_compiler<regexp>(CharacterClasses?, LineBreaks?)

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