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

Last change on this file since 5593 was 5593, checked in by nmedfort, 15 months ago

Bug fix for RE_Compiler.

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