source: icGREP/icgrep-devel/icgrep/re/re_parser.cpp @ 5781

Last change on this file since 5781 was 5772, checked in by cameron, 18 months ago

resolveGraphemeMode

File size: 39.8 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/re_parser.h>
8#include <re/re_parser_helper.h>
9#include <re/re_parser_pcre.h>
10#include <re/re_parser_ere.h>
11#include <re/re_parser_bre.h>
12#include <re/re_parser_prosite.h>
13#include <re/parse_fixed_strings.h>
14#include <re/re_name.h>
15#include <re/re_alt.h>
16#include <re/re_any.h>
17#include <re/re_end.h>
18#include <re/re_rep.h>
19#include <re/re_seq.h>
20#include <re/re_start.h>
21#include <re/re_range.h>
22#include <re/re_diff.h>
23#include <re/re_intersect.h>
24#include <re/re_group.h>
25#include <re/re_assertion.h>
26#include <re/printer_re.h>
27#include <sstream>
28#include <string>
29#include <algorithm>
30#include <iostream>
31#include <llvm/Support/Casting.h>
32#include <llvm/Support/ErrorHandling.h>
33#include <llvm/Support/raw_ostream.h>
34#include <llvm/ADT/STLExtras.h> // for make_unique
35
36using namespace llvm;
37
38namespace re {
39
40
41RE * RE_Parser::parse(const std::string & regular_expression, ModeFlagSet initialFlags, RE_Syntax syntax, bool ByteMode) {
42
43    std::unique_ptr<RE_Parser> parser = nullptr;
44    switch (syntax) {
45        case RE_Syntax::PCRE:
46            parser = make_unique<RE_Parser_PCRE>(regular_expression);
47            break;
48        case RE_Syntax::ERE:
49            parser = make_unique<RE_Parser_ERE>(regular_expression);
50            break;
51        case RE_Syntax ::BRE:
52            parser = make_unique<RE_Parser_BRE>(regular_expression);
53            break;
54        case RE_Syntax ::PROSITE:
55            parser = make_unique<RE_Parser_PROSITE>(regular_expression);
56            break;
57        default:
58            parser = make_unique<FixedStringParser>(regular_expression);
59            break;
60    }
61    parser->fByteMode = ByteMode;
62    parser->fModeFlagSet = initialFlags;
63    parser->mGroupsOpen = 0;
64    parser->fNested = false;
65    parser->fGraphemeBoundaryPending = false;
66    parser->mCaptureGroupCount = 0;
67    RE * re = parser->parse_RE();
68    if (re == nullptr) {
69        ParseFailure("An unexpected parsing error occurred!");
70    }
71    return re;
72}
73
74RE_Parser::RE_Parser(const std::string & regular_expression)
75: fByteMode(false)
76, fModeFlagSet(0)
77, fNested(false)
78, mGroupsOpen(0)
79, fGraphemeBoundaryPending(false)
80, fSupportNonCaptureGroup(false)
81, mCursor(regular_expression)
82, mCaptureGroupCount(0)
83, mReSyntax(RE_Syntax::PCRE)
84{
85
86}
87
88RE * makeAtomicGroup(RE * r) {
89    RE_Parser::ParseFailure("Atomic grouping not supported.");
90}
91
92RE * makeBranchResetGroup(RE * r) {
93    // Branch reset groups only affect submatch numbering, but
94    // this has no effect in icgrep.
95    return r;
96}
97
98RE * RE_Parser::parse_RE() {
99    return parse_alt();
100}
101
102RE * RE_Parser::parse_alt() {
103    std::vector<RE *> alt;
104    do {
105        alt.push_back(parse_seq());
106    }
107    while (accept_alt_mark());
108    return makeAlt(alt.begin(), alt.end());
109}
110   
111bool RE_Parser::accept_alt_mark() {
112    if (!mCursor.more() || (*mCursor != '|')) return false;
113    mCursor++;
114    return true;
115}
116
117RE * RE_Parser::parse_seq() {
118    std::vector<RE *> seq;
119    if (!mCursor.more() || (*mCursor == '|') || ((mGroupsOpen > 0) && (*mCursor == ')'))) return makeSeq();
120    for (;;) {
121        RE * re = parse_next_item();
122        if (re == nullptr) {
123            break;
124        }
125        re = extend_item(re);
126        seq.push_back(re);
127    }
128    return makeSeq(seq.begin(), seq.end());
129}
130
131RE * RE_Parser::parse_next_item() {
132    RE * re = nullptr;
133    if (fModeFlagSet & IGNORE_SPACE_MODE_FLAG) {
134        while (mCursor.more() && *mCursor == ' ') {
135            ++mCursor;
136        }
137    }
138    if (mCursor.more()) {
139        switch (*mCursor) {
140            case '(':
141                ++mCursor;
142                return parse_group();
143            case '^':
144                ++mCursor;
145                if ((fModeFlagSet & ModeFlagType::UNIX_LINES_MODE_FLAG) != 0) {
146                    return makeNegativeLookBehindAssertion(makeByte(makeCC(makeCC(0, '\n'-1), makeCC('\n'+1, 0xFF))));
147                }
148                return makeStart();
149            case '$':
150                ++mCursor;
151                if ((fModeFlagSet & ModeFlagType::UNIX_LINES_MODE_FLAG) != 0) {
152                    return makeLookAheadAssertion(makeCC('\n'));
153                }
154                return makeEnd();
155            case '|':
156                break;
157            case ')':
158                if (mGroupsOpen > 0) break;
159                if (LEGACY_UNESCAPED_RBRAK_RBRACE_ALLOWED) {
160                    return createCC(parse_literal_codepoint());
161                }
162                ParseFailure("Use  \\) for literal ).");
163            case '*': case '+': case '?': case '{':
164                ParseFailure("Need something to repeat before *, +, ? or {.");
165            case ']':
166                if (LEGACY_UNESCAPED_RBRAK_RBRACE_ALLOWED) {
167                    return createCC(parse_literal_codepoint());
168                }
169                ParseFailure("Use  \\] for literal ].");
170            case '}':
171                if (fNested) {
172                    break;  //  a recursive invocation for a regexp in \N{...}
173                } else if (LEGACY_UNESCAPED_RBRAK_RBRACE_ALLOWED) {
174                    return createCC(parse_literal_codepoint());
175                }
176                ParseFailure("Use \\} for literal }.");
177            case '[':
178                mCursor++;
179                re = parse_charset();
180                break;
181            case '.': // the 'any' metacharacter
182                mCursor++;
183                return makeAny();
184            case '\\'// escape processing
185                ++mCursor;
186                return parse_escaped();
187            default:
188                re = createCC(parse_literal_codepoint());
189        }
190    }
191    return re;
192}
193
194
195// Parse some kind of parenthesized group.  Input precondition: mCursor
196// after the (
197RE * RE_Parser::parse_group() {
198    const ModeFlagSet savedModeFlagSet = fModeFlagSet;
199    mGroupsOpen++;
200    RE * group_expr = nullptr;
201    if (*mCursor == '?' && fSupportNonCaptureGroup) {
202        switch (*++mCursor) {
203            case '#'// comment
204                while (*++mCursor != ')');
205                ++mCursor;
206                return parse_next_item();
207            case ':':  // Non-capturing paren
208                ++mCursor;
209                group_expr = parse_alt();
210                break;
211            case '=':
212                ++mCursor;
213                group_expr = makeLookAheadAssertion(parse_alt());
214                break;
215            case '!':
216                ++mCursor;
217                group_expr = makeNegativeLookAheadAssertion(parse_alt());
218                break;
219            case '>':
220                ++mCursor;
221                group_expr = makeAtomicGroup(parse_alt());
222                break;
223            case '|':
224                ++mCursor;
225                group_expr = makeBranchResetGroup(parse_alt());
226                break;
227            case '<':
228                ++mCursor;
229                if (*mCursor == '=') {
230                    ++mCursor;
231                    group_expr = makeLookBehindAssertion(parse_alt());
232                }
233                else if (*mCursor == '!') {
234                    ++mCursor;
235                    group_expr = makeNegativeLookBehindAssertion(parse_alt());
236                } else {
237                    ParseFailure("Illegal lookbehind assertion syntax.");
238                }
239                break;
240            case '-': case 'd' : case 'i': case 'm': case 's': case 'x': case 'g':
241                while (*mCursor != ')' && *mCursor != ':') {
242                    bool negateMode = false;
243                    ModeFlagType modeBit;
244                    if (*mCursor == '-') {
245                        negateMode = true;
246                        ++mCursor;
247                    }
248                    switch (*mCursor) {
249                        case 'i': modeBit = CASE_INSENSITIVE_MODE_FLAG; break;
250                        case 'g': modeBit = GRAPHEME_CLUSTER_MODE; break;
251                        case 'm': modeBit = MULTILINE_MODE_FLAG; break;
252                        //case 's': modeBit = DOTALL_MODE_FLAG; break;
253                        case 'x': modeBit = IGNORE_SPACE_MODE_FLAG; break;
254                        case 'd': modeBit = UNIX_LINES_MODE_FLAG; break;
255                        default: ParseFailure("Unsupported mode flag.");
256                    }
257                    ++mCursor;
258                    if (negateMode) {
259                        fModeFlagSet &= ~modeBit;
260                        negateMode = false;  // for next flag
261                    } else {
262                        fModeFlagSet |= modeBit;
263                    }
264                }
265                if (*mCursor == ':') {
266                    ++mCursor;
267                    group_expr = parse_alt();
268                    auto changed = fModeFlagSet ^ savedModeFlagSet;
269                    if ((changed & CASE_INSENSITIVE_MODE_FLAG) != 0) {
270                        group_expr = makeGroup(Group::Mode::CaseInsensitiveMode, group_expr,
271                                               (fModeFlagSet & CASE_INSENSITIVE_MODE_FLAG) == 0 ? Group::Sense::Off : Group::Sense::On);
272                    }
273                    if ((changed & GRAPHEME_CLUSTER_MODE) != 0) {
274                        group_expr = makeGroup(Group::Mode::GraphemeMode, group_expr,
275                                               (fModeFlagSet & GRAPHEME_CLUSTER_MODE) == 0 ? Group::Sense::Off : Group::Sense::On);
276                    }
277                    fModeFlagSet = savedModeFlagSet;
278                    break;
279                } else {  // if *_cursor == ')'
280                    ++mCursor;
281                    auto changed = fModeFlagSet ^ savedModeFlagSet;
282                    if ((changed & (CASE_INSENSITIVE_MODE_FLAG|GRAPHEME_CLUSTER_MODE)) != 0) {
283                        group_expr = parse_seq();
284                        if ((changed & CASE_INSENSITIVE_MODE_FLAG) != 0) {
285                            group_expr = makeGroup(Group::Mode::CaseInsensitiveMode, group_expr,
286                                                   (fModeFlagSet & CASE_INSENSITIVE_MODE_FLAG) == 0 ? Group::Sense::Off : Group::Sense::On);
287                        }
288                        if ((changed & GRAPHEME_CLUSTER_MODE) != 0) {
289                            group_expr = makeGroup(Group::Mode::GraphemeMode, group_expr,
290                                                   (fModeFlagSet & GRAPHEME_CLUSTER_MODE) == 0 ? Group::Sense::Off : Group::Sense::On);
291                        }
292                        return group_expr;
293                    }
294                    else return parse_next_item();
295                }
296            default:
297                ParseFailure("Illegal (? syntax.");
298        }
299    } else { // Capturing paren group.
300        RE * captured = parse_alt();
301        mCaptureGroupCount++;
302        std::string captureName = "\\" + std::to_string(mCaptureGroupCount);
303        Name * const capture  = mMemoizer.memoize(makeCapture(captureName, captured));
304        auto key = std::make_pair("", captureName);
305        mNameMap.insert(std::make_pair(std::move(key), capture));
306        group_expr = capture;
307    }
308    if (*mCursor != ')') {
309        ParseFailure("Closing parenthesis required.");
310    }
311    mGroupsOpen--;
312    ++mCursor;
313    return group_expr;
314}
315
316// TODO: Set ENABLE_EXTENDED_QUANTIFIERS false for ERE, BRE
317#define ENABLE_EXTENDED_QUANTIFIERS true
318   
319// Extend a RE item with one or more quantifiers
320RE * RE_Parser::extend_item(RE * re) {
321    if (LLVM_UNLIKELY(!(mCursor.more()))) return re;
322    int lb = 0, ub = 0;
323    switch (*mCursor) {
324        case '*':
325            lb = 0;
326            ub = Rep::UNBOUNDED_REP;
327            break;
328        case '?':
329            lb = 0;
330            ub = 1;
331            break;
332        case '+':
333            lb = 1;
334            ub = Rep::UNBOUNDED_REP;
335            break;
336        case '{':
337            std::tie(lb, ub) = parse_range_bound();
338            if ((ub != Rep::UNBOUNDED_REP) && (lb > ub)) {
339                ParseFailure("Lower bound cannot exceed upper bound in bounded repetition");
340            }
341            break;
342        default:
343            // No quantifiers
344            return re;
345    }
346    ++mCursor;
347    if (ENABLE_EXTENDED_QUANTIFIERS) {
348        if (LLVM_UNLIKELY(!(mCursor.more()))) return makeRep(re, lb, ub);;
349        if (*mCursor == '?') { // Non-greedy qualifier
350            // Greedy vs. non-greedy makes no difference for icgrep.
351            ++mCursor;
352            re = makeRep(re, lb, ub);
353        } else if (*mCursor == '+') {
354            ++mCursor;
355            if (ub == Rep::UNBOUNDED_REP) {
356                re = makeSeq({makeRep(re, lb, ub), makeNegativeLookAheadAssertion(re)});
357            } else if (lb == ub) {
358                re = makeRep(re, ub, ub);
359            } else /* if (lb < ub) */{
360                re = makeAlt({makeSeq({makeRep(re, lb, ub-1), makeNegativeLookAheadAssertion(re)}), makeRep(re, ub, ub)});
361            }
362        } else {
363            re = makeRep(re, lb, ub);
364        } 
365    } else {
366        re = makeRep(re, lb, ub);
367    }
368    // The quantified expression may be extended with a further quantifier, e,g., [a-z]{6,7}{2,3}
369    return extend_item(re);
370}
371
372std::pair<int, int> RE_Parser::parse_range_bound() {
373    int lower_bound = 0, upper_bound = 0;
374    if (*++mCursor != ',') {
375        lower_bound = parse_int();
376    }
377    if (*mCursor == '}') {
378        upper_bound = lower_bound;
379    } else if (*mCursor != ',') {
380        ParseFailure("Bad lower bound!");
381    } else if (*++mCursor == '}') {
382        upper_bound = Rep::UNBOUNDED_REP;
383    } else {
384        upper_bound = parse_int();
385        if (*mCursor != '}') {
386            ParseFailure("Bad upper bound!");
387        }
388    }
389    return std::make_pair(lower_bound, upper_bound);
390}
391
392unsigned RE_Parser::parse_int() {
393    unsigned value = 0;
394    while (isdigit(*mCursor)) {
395        value *= 10;
396        value += static_cast<int>(*mCursor++) - 48;
397    }
398    return value;
399}
400
401
402const uint64_t setEscapeCharacters = bit3C('b') | bit3C('p') | bit3C('q') | bit3C('d') | bit3C('w') | bit3C('s') | bit3C('<') | bit3C('>') |
403                                     bit3C('B') | bit3C('P') | bit3C('Q') | bit3C('D') | bit3C('W') | bit3C('S') | bit3C('N') | bit3C('X');
404
405bool RE_Parser::isSetEscapeChar(char c) {
406    return c >= 0x3C && c <= 0x7B && ((setEscapeCharacters >> (c - 0x3C)) & 1) == 1;
407}
408                                 
409
410RE * RE_Parser::parse_escaped() {
411   
412    if (isSetEscapeChar(*mCursor)) {
413        return parseEscapedSet();
414    }
415    else if ((*mCursor == 'x') || (*mCursor == 'o') || (*mCursor == '0')) {
416        codepoint_t cp = parse_escaped_codepoint();
417        if ((cp >= 0x80) && (cp <= 0xFF)) {
418            return makeByte(makeCC(cp));
419        }
420        else return createCC(cp);
421    }
422    else if (isdigit(*mCursor)) {
423        mCursor++;
424        std::string backref = std::string(mCursor.pos()-2, mCursor.pos());
425        auto key = std::make_pair("", backref);
426        auto f = mNameMap.find(key);
427        if (f != mNameMap.end()) {
428            return makeReference(backref, f->second);
429        }
430        else {
431            ParseFailure("Back reference " + backref + " without prior capture group.");
432        }
433    }
434    else {
435        return createCC(parse_escaped_codepoint());
436    }
437}
438   
439RE * RE_Parser::parseEscapedSet() {
440    bool complemented = false;
441    RE * re = nullptr;
442    switch (*mCursor) {
443        case 'B': complemented = true;
444        case 'b':
445            if (*++mCursor != '{') {
446                return complemented ? makeWordNonBoundary() : makeWordBoundary();
447            } else {
448                ++mCursor;
449                if (isCharAhead('}')) {
450                    switch (*mCursor) {
451                        case 'g':
452                            re = complemented ? makeZeroWidth("NonGCB") : makeZeroWidth("GCB");
453                            ++mCursor;
454                            ++mCursor;
455                            break;
456                        case 'w': ParseFailure("\\b{w} not yet supported.");
457                        case 'l': ParseFailure("\\b{l} not yet supported.");
458                        case 's': ParseFailure("\\b{s} not yet supported.");
459//                        default: ParseFailure("Unrecognized boundary assertion");
460                    }
461                }
462                if (!re) {
463                    auto propExpr = parsePropertyExpression();
464                    if (*mCursor++ != '}') {
465                        ParseFailure("Malformed boundary assertion");
466                    }
467                    re = complemented ? makeReNonBoundary(propExpr) : makeReBoundary(propExpr);
468                }
469                return re;
470            }
471        case 'd':
472            ++mCursor;
473            return makeDigitSet();
474        case 'D':
475            ++mCursor;
476            return makeComplement(makeDigitSet());
477        case 's':
478            ++mCursor;
479            return makeWhitespaceSet();
480        case 'S':
481            ++mCursor;
482            return makeComplement(makeWhitespaceSet());
483        case 'w':
484            ++mCursor;
485            return makeWordSet();
486        case 'W':
487            ++mCursor;
488            return makeComplement(makeWordSet());
489        case 'Q':
490            complemented = true;
491        case 'q':
492            if (*++mCursor != '{') {
493                ParseFailure("Malformed grapheme cluster expression");
494            }
495            ++mCursor;
496            ParseFailure("Literal grapheme cluster expressions not yet supported.");
497            if (*mCursor != '}') {
498                ParseFailure("Malformed grapheme cluster expression");
499            }
500            ++mCursor;
501            return complemented ? makeComplement(re) : re;
502        case 'P':
503            complemented = true;
504        case 'p':
505            if (*++mCursor != '{') {
506                ParseFailure("Malformed property expression");
507            }
508            ++mCursor;
509            re = parsePropertyExpression();
510            if (*mCursor != '}') {
511                ParseFailure("Malformed property expression");
512            }
513            ++mCursor;
514            return complemented ? makeComplement(re) : re;
515        case 'X':
516            // \X is equivalent to ".+?\b{g}"; proceed the minimal number of characters (but at least one)
517            // to get to the next extended grapheme cluster boundary.
518            ++mCursor;
519            return makeSeq({makeAny(), makeRep(makeSeq({makeZeroWidth("NonGCB"), makeAny()}), 0, Rep::UNBOUNDED_REP), makeZeroWidth("GCB")});
520        case 'N':
521            if (*++mCursor != '{') {
522                ParseFailure("Malformed \\N expression");
523            }
524            ++mCursor;
525            re = parseNamePatternExpression();
526            if (*mCursor != '}') {
527                ParseFailure("Malformed \\N expression");
528            }
529            ++mCursor;
530            assert (re);
531            return re;
532        case '<':
533            ++mCursor;
534            return makeWordBegin();
535        case '>':
536            ++mCursor;
537            return makeWordEnd();
538        default:
539            ParseFailure("Internal error");
540    }
541}
542   
543void InvalidUTF8Encoding() {
544    RE_Parser::ParseFailure("Invalid UTF-8 encoding!");
545}
546
547codepoint_t RE_Parser::parse_literal_codepoint() {
548    if (fByteMode) {
549       return static_cast<uint8_t>(*mCursor++);
550    }
551    else return parse_utf8_codepoint();
552}
553
554codepoint_t RE_Parser::parse_utf8_codepoint() {
555    // Must cast to unsigned char to avoid sign extension.
556    unsigned char pfx = static_cast<unsigned char>(*mCursor++);
557    codepoint_t cp = pfx;
558    if (pfx < 0x80) return cp;
559    unsigned suffix_bytes = 0;
560    if (pfx < 0xE0) {
561        if (pfx < 0xC2) {  // bare suffix or illegal prefix 0xC0 or 0xC2
562            InvalidUTF8Encoding();
563        }
564        suffix_bytes = 1;
565        cp &= 0x1F;
566    } else if (pfx < 0xF0) { // [0xE0, 0xEF]
567        cp &= 0x0F;
568        suffix_bytes = 2;
569    } else { // [0xF0, 0xFF]
570        cp &= 0x0F;
571        suffix_bytes = 3;
572    }
573    while (suffix_bytes--) {
574        if (mCursor.noMore()) {
575            InvalidUTF8Encoding();
576        }
577        char_t sfx = *mCursor++;
578        if ((sfx & 0xC0) != 0x80) {
579            InvalidUTF8Encoding();
580        }
581        cp = (cp << 6) | (sfx & 0x3F);
582    }
583    // It is an error if a 3-byte sequence is used to encode a codepoint < 0x800
584    // or a 4-byte sequence is used to encode a codepoint < 0x10000.
585    if ((pfx == 0xE0 && cp < 0x800) || (pfx == 0xF0 && cp < 0x10000)) {
586        InvalidUTF8Encoding();
587    }
588    // It is an error if a 4-byte sequence is used to encode a codepoint
589    // above the Unicode maximum.
590    if (cp > UCD::UNICODE_MAX) {
591        InvalidUTF8Encoding();
592    }
593    return cp;
594}
595
596std::string RE_Parser::canonicalize(const cursor_t begin, const cursor_t end) {
597    std::locale loc;
598    std::stringstream s;   
599    for (auto i = begin; i != end; ++i) {
600        switch (*i) {
601            case '_': case ' ': case '-':
602                break;
603            default:
604                s << std::tolower(*i, loc);
605        }
606    }
607    return s.str();
608}
609
610bool RE_Parser::isCharAhead(char c) {
611    if (mCursor.remaining() < 2) {
612        return false;
613    }
614    auto nextCursor = mCursor.pos() + 1;
615    return *nextCursor == c;
616}
617
618RE * RE_Parser::parsePropertyExpression() {
619    const auto start = mCursor.pos();
620    while (mCursor.more()) {
621        bool done = false;
622        switch (*mCursor) {
623            case '}': case ':': case '=':
624                done = true;
625        }
626        if (done) {
627            break;
628        }
629        ++mCursor;
630    }
631    if (*mCursor == '=') {
632        // We have a property-name = value expression
633        const auto prop_end = mCursor.pos();
634        mCursor++;
635        auto val_start = mCursor.pos();
636        if (*val_start == '/') {
637            // property-value is another regex
638            auto previous = val_start;
639            auto current = (++mCursor).pos();
640            val_start = current;
641           
642            while (true) {
643                if (*current == '/' && *previous != '\\') {
644                    break;
645                }
646               
647                if (!mCursor.more()) {
648                    ParseFailure("Malformed property expression");
649                }
650               
651                previous = current;
652                current = (++mCursor).pos();
653            }
654            ++mCursor;
655            //return parseRegexPropertyValue(canonicalize(start, prop_end), std::string(val_start, current));
656            return createName(canonicalize(start, prop_end), std::string(val_start-1, current));
657        }
658        if (*val_start == '@') {
659            // property-value is @property@ or @identity@
660            auto previous = val_start;
661            auto current = (++mCursor).pos();
662            val_start = current;
663           
664            while (true) {
665                if (*current == '@' && *previous != '\\') {
666                    break;
667                }
668               
669                if (!mCursor.more()) {
670                    ParseFailure("Malformed property expression");
671                }
672               
673                previous = current;
674                current = (++mCursor).pos();
675            }
676            ++mCursor;
677            //return parseRegexPropertyValue(canonicalize(start, prop_end), std::string(val_start, current));
678            return createName(canonicalize(start, prop_end), std::string(val_start-1, current));
679        }
680        else {
681            // property-value is normal string
682            while (mCursor.more()) {
683                bool done = false;
684                switch (*mCursor) {
685                    case '}': case ':':
686                        done = true;
687                }
688                if (done) {
689                    break;
690                }
691                ++mCursor;
692            }
693            return createName(canonicalize(start, prop_end), std::string(val_start, mCursor.pos()));
694        }
695    }
696    return createName(canonicalize(start, mCursor.pos()));
697}
698
699Name * RE_Parser::parseNamePatternExpression(){
700
701    const auto start = mCursor.pos();
702    while (mCursor.more()) {
703        if (*mCursor == '\\') {
704            ++mCursor;
705            if (!mCursor.more()) {
706                break;
707            }
708        }
709        else if (*mCursor == '}') {
710            break;
711        }
712        ++mCursor;
713    }
714    std::string nameRegexp = "/(?i)" + std::string(start, mCursor.pos());
715    return createName("na", nameRegexp);
716}
717
718bool RE_Parser::isUnsupportChartsetOperator(char c) {
719    return false;
720}
721
722CharsetOperatorKind RE_Parser::getCharsetOperator() {
723    if (isUnsupportChartsetOperator(*mCursor)) {
724        return emptyOperator;
725    }
726    switch (*mCursor) {
727        case '&':
728            ++mCursor;
729            if (*mCursor == '&') {
730                ++mCursor;
731                return intersectOp;
732            } else if (*mCursor == '[') {
733                // Short-hand for intersectOp when a set follows
734                return intersectOp;
735            }
736            return ampChar;
737        case '-':
738            ++mCursor;
739            if (*mCursor == '-') {
740                ++mCursor;
741                return setDiffOp;
742            } else if (*mCursor == '[') {
743                return setDiffOp;
744            } else if (*mCursor == ']') {
745                return hyphenChar;
746            }
747            return rangeHyphen;
748        case '[':
749            ++mCursor;
750            if (*mCursor == ':') {
751                ++mCursor;
752                return posixPropertyOpener;
753            }
754            return setOpener;
755        case ']':
756            ++mCursor;
757            return setCloser;
758        case '\\':
759            ++mCursor;
760            return backSlash;
761        default:
762            return emptyOperator;
763    }
764}
765
766// Precondition: cursor is immediately after opening '[' character
767RE * RE_Parser::parse_charset() {
768    // Sets are accumulated using two variables:
769    // subexprs accumulates set expressions such as \p{Lu}, [\w && \p{Greek}]
770    // cc accumulates the literal and calculated codepoints and ranges
771    std::vector<RE *> subexprs;
772    CC * cc = makeCC();
773    // When the last item deal with is a single literal charcacter or calculated codepoint,
774    // a following hyphen can indicate a range.   When the last item is a set subexpression,
775    // a following hyphen can indicate set subtraction.
776    enum {NoItem, CodepointItem, RangeItem, SetItem, BrackettedSetItem} lastItemKind = NoItem;
777
778    codepoint_t lastCodepointItem = 0;
779    bool havePendingOperation = false;
780    bool possibleByteCodeEscape = false;  // set to true when \x, \o or \0 hex or octal escapes seen.
781    CharsetOperatorKind pendingOperationKind = intersectOp;
782    RE * pendingOperand = nullptr;
783
784    // If the first character after the [ is a ^ (caret) then the matching character class is complemented.
785    bool negated = false;
786    if (*mCursor == '^') {
787        negated = true;
788        ++mCursor;
789    }
790    // Legacy rule: an unescaped ] may appear as a literal set character
791    // if and only if it appears immediately after the opening [ or [^
792    if ( *mCursor == ']' && LEGACY_UNESCAPED_RBRAK_RBRACE_ALLOWED) {
793        insert(cc, ']');
794        lastItemKind = CodepointItem;
795        lastCodepointItem = static_cast<codepoint_t> (']');
796        ++mCursor;
797    } else if ( *mCursor == '-' && LEGACY_UNESCAPED_HYPHEN_ALLOWED) {
798        ++mCursor;
799        insert(cc, '-');
800        lastItemKind = CodepointItem;
801        lastCodepointItem = static_cast<codepoint_t> ('-');
802        if (*mCursor == '-') {
803            ParseFailure("Set operator has no left operand.");
804        }
805    }
806    while (mCursor.more()) {
807        const CharsetOperatorKind op = getCharsetOperator();
808        switch (op) {
809            case intersectOp:
810            case setDiffOp: {
811                if (lastItemKind == NoItem) {
812                    ParseFailure("Set operator has no left operand.");
813                }
814                if (!cc->empty()) {
815                    subexprs.push_back(mMemoizer.memoize(cc));
816                }
817                RE * newOperand = makeAlt(subexprs.begin(), subexprs.end());
818                subexprs.clear();
819                cc = makeCC();
820                if (havePendingOperation) {
821                    if (pendingOperationKind == intersectOp) {
822                        pendingOperand = makeIntersect(pendingOperand, newOperand);
823                    }
824                    else {
825                        pendingOperand = makeDiff(pendingOperand, newOperand);
826                    }
827                }
828                else {
829                    pendingOperand = newOperand;
830                }
831                havePendingOperation = true;
832                pendingOperationKind = op;
833                lastItemKind = NoItem;
834            }
835            break;
836            case setCloser: {
837                if (lastItemKind == NoItem) {
838                    ParseFailure("Set operator has no right operand.");
839                }
840                if (!cc->empty()) {
841                    if (possibleByteCodeEscape && (cc->max_codepoint() <= 0xFF) && subexprs.empty() && !havePendingOperation) {
842                        subexprs.push_back(makeByte(cc));
843                    }
844                    else {
845                        subexprs.push_back(mMemoizer.memoize(cc));
846                    }
847                }
848                RE * newOperand = makeAlt(subexprs.begin(), subexprs.end());
849                if (havePendingOperation) {
850                    if (pendingOperationKind == intersectOp) {
851                        newOperand = makeIntersect(pendingOperand, newOperand);
852                    }
853                    else {
854                        newOperand = makeDiff(pendingOperand, newOperand);
855                    }
856                }
857                return negated ? makeComplement(newOperand) : newOperand;
858            }
859            case setOpener:
860            case posixPropertyOpener: {
861                if (lastItemKind != NoItem) {
862                    if (!cc->empty()) {
863                        subexprs.push_back(mMemoizer.memoize(cc));
864                    }
865                    RE * newOperand = makeAlt(subexprs.begin(), subexprs.end());
866                    subexprs.clear();
867                    cc = makeCC();
868                    if (havePendingOperation) {
869                        if (pendingOperationKind == intersectOp) {
870                            pendingOperand = makeIntersect(pendingOperand, newOperand);
871                        } else {
872                            pendingOperand = makeDiff(pendingOperand, newOperand);
873                        }
874                    }
875                    else {
876                        pendingOperand = newOperand;
877                    }
878                    subexprs.push_back(pendingOperand);
879                    havePendingOperation = false;
880                }
881                if (op == setOpener) {
882                    subexprs.push_back(parse_charset());
883                    lastItemKind = SetItem;
884                }
885                else if (op == posixPropertyOpener) {
886                    bool negated = false;
887                    if (*mCursor == '^') {
888                        negated = true;
889                        mCursor++;
890                    }
891                    RE * posixSet = parsePropertyExpression();
892                    subexprs.push_back(negated ? makeComplement(posixSet) : posixSet);
893                    lastItemKind = BrackettedSetItem;
894                    if (*mCursor++ != ':' || *mCursor++ != ']')
895                        ParseFailure("Posix set expression improperly terminated.");
896                }
897            }
898            break;
899            case rangeHyphen:
900                if (lastItemKind != CodepointItem) {
901                    ParseFailure("Range operator - has illegal left operand.");
902                }
903                if (*mCursor == '\\') {
904                    mCursor++;
905                    if ((*mCursor == 'x') || (*mCursor == 'o') || (*mCursor == '0')) possibleByteCodeEscape = true;
906                    insert_range(cc, lastCodepointItem, parse_escaped_codepoint());
907                    //subexprs.push_back(makeRange(makeCC(lastCodepointItem), makeCC(parse_escaped_codepoint())));
908                } else {
909                    insert_range(cc, lastCodepointItem, parse_literal_codepoint());
910                    //subexprs.push_back(makeRange(makeCC(lastCodepointItem), makeCC(parse_literal_codepoint())));
911                }
912                lastItemKind = RangeItem;
913                break;
914            case hyphenChar:
915                insert(cc, '-');
916                lastItemKind = CodepointItem;
917                lastCodepointItem = static_cast<codepoint_t> ('-');
918                break;
919            case ampChar:
920                insert(cc, '&');
921                lastItemKind = CodepointItem;
922                lastCodepointItem = static_cast<codepoint_t> ('&');
923                break;
924            case backSlash:
925                if (isSetEscapeChar(*mCursor)) {
926                    subexprs.push_back(parseEscapedSet());
927                    lastItemKind = SetItem;
928                }
929                else {
930                    if ((*mCursor == 'x') || (*mCursor == 'o') || (*mCursor == '0')) possibleByteCodeEscape = true;
931                    lastCodepointItem = parse_escaped_codepoint();
932                    insert(cc, lastCodepointItem);
933                    lastItemKind = CodepointItem;
934                }
935                break;
936            case emptyOperator:
937                lastCodepointItem = parse_literal_codepoint();
938                insert(cc, lastCodepointItem);
939                lastItemKind = CodepointItem;
940                break;
941        }
942    }
943    ParseFailure("Set expression not properly terminated.");
944}
945
946
947// A backslash escape was found, and various special cases (back reference,
948// quoting with \Q, \E, sets (\p, \P, \d, \D, \w, \W, \s, \S, \b, \B), grapheme
949// cluster \X have been ruled out.
950// It may be one of several possibilities or an error sequence.
951// 1. Special control codes (\a, \e, \f, \n, \r, \t, \v)
952// 2. General control codes c[@-_a-z?]
953// 3. Restricted octal notation 0 - 0777
954// 4. General octal notation o\{[0-7]+\}
955// 5. General hex notation x\{[0-9A-Fa-f]+\}
956// 6. An error for any unrecognized alphabetic escape
957// 7. An escaped ASCII symbol, standing for itself
958
959codepoint_t RE_Parser::parse_escaped_codepoint() {
960    codepoint_t cp_value;
961    switch (*mCursor) {
962        case 'a': ++mCursor; return 0x07; // BEL
963        case 'e': ++mCursor; return 0x1B; // ESC
964        case 'f': ++mCursor; return 0x0C; // FF
965        case 'n': ++mCursor; return 0x0A; // LF
966        case 'r': ++mCursor; return 0x0D; // CR
967        case 't': ++mCursor; return 0x09; // HT
968        case 'v': ++mCursor; return 0x0B; // VT
969        case 'c': // Control-escape based on next char
970            ++mCursor;
971            // \c@, \cA, ... \c_, or \ca, ..., \cz
972            if (((*mCursor >= '@') && (*mCursor <= '_')) || ((*mCursor >= 'a') && (*mCursor <= 'z'))) {
973                cp_value = static_cast<codepoint_t>(*mCursor & 0x1F);
974                mCursor++;
975                return cp_value;
976            }
977            else if (*mCursor++ == '?') return 0x7F;  // \c? ==> DEL
978            else ParseFailure("Illegal \\c escape sequence");
979        case '0': // Octal escape:  0 - 0377
980            ++mCursor;
981            return parse_octal_codepoint(0,3);
982        case 'o':
983            ++mCursor;
984            if (*mCursor == '{') {
985                ++mCursor;
986                cp_value = parse_octal_codepoint(1, 7);
987                if (*mCursor++ != '}') ParseFailure("Malformed octal escape sequence");
988                return cp_value;
989            }
990            else {
991                ParseFailure("Malformed octal escape sequence");
992            }
993        case 'x':
994            ++mCursor;
995            if (*mCursor == '{') {
996              ++mCursor;
997              cp_value = parse_hex_codepoint(1, 6);
998              if (*mCursor++ != '}') ParseFailure("Malformed hex escape sequence");
999              return cp_value;
1000            }
1001            else {
1002                return parse_hex_codepoint(1,2);  // ICU compatibility
1003            }
1004        case 'u':
1005            ++mCursor;
1006            if (*mCursor == '{') {
1007                ++mCursor;
1008                cp_value = parse_hex_codepoint(1, 6);
1009                if (*mCursor++ != '}') ParseFailure("Malformed hex escape sequence");
1010                return cp_value;
1011            }
1012            else {
1013                return parse_hex_codepoint(4,4);  // ICU compatibility
1014            }
1015        case 'U':
1016            ++mCursor;
1017            return parse_hex_codepoint(8,8);  // ICU compatibility
1018        default:
1019            // Escaped letters should be reserved for special functions.
1020            if (((*mCursor >= 'A') && (*mCursor <= 'Z')) || ((*mCursor >= 'a') && (*mCursor <= 'z'))){
1021                //Escape unknown letter will be parse as normal letter
1022                return parse_literal_codepoint();
1023                //ParseFailure("Undefined or unsupported escape sequence");
1024            }
1025            else if ((*mCursor < 0x20) || (*mCursor >= 0x7F))
1026                ParseFailure("Illegal escape sequence");
1027            else return static_cast<codepoint_t>(*mCursor++);
1028    }
1029}
1030
1031codepoint_t RE_Parser::parse_octal_codepoint(int mindigits, int maxdigits) {
1032    codepoint_t value = 0;
1033    int count = 0;
1034    while (mCursor.more() && count < maxdigits) {
1035        const char t = *mCursor;
1036        if (t < '0' || t > '7') {
1037            break;
1038        }
1039        value = value * 8 | (t - '0');
1040        ++mCursor;
1041        ++count;
1042    }
1043    if (count < mindigits) ParseFailure("Octal sequence has too few digits");
1044    if (value > UCD::UNICODE_MAX) ParseFailure("Octal value too large");
1045    return value;
1046}
1047
1048codepoint_t RE_Parser::parse_hex_codepoint(int mindigits, int maxdigits) {
1049    codepoint_t value = 0;
1050    int count = 0;
1051    while (mCursor.more() && isxdigit(*mCursor) && count < maxdigits) {
1052        const char t = *mCursor;
1053        if (isdigit(t)) {
1054            value = (value * 16) | (t - '0');
1055        }
1056        else {
1057            value = ((value * 16) | ((t | 32) - 'a')) + 10;
1058        }
1059        ++mCursor;
1060        ++count;
1061    }
1062    if (count < mindigits) ParseFailure("Hexadecimal sequence has too few digits");
1063    if (value > UCD::UNICODE_MAX) ParseFailure("Hexadecimal value too large");
1064    return value;
1065}
1066
1067Name * RE_Parser::createCC(const codepoint_t cp) {
1068    CC * cc = makeCC(cp);
1069    return mMemoizer.memoize(cc);
1070}
1071
1072void RE_Parser::insert(CC * cc, const codepoint_t cp) {
1073    cc->insert(cp);
1074}
1075
1076void RE_Parser::insert_range(CC * cc, const codepoint_t lo, const codepoint_t hi) {
1077    cc->insert_range(lo, hi);
1078}
1079
1080RE * RE_Parser::makeComplement(RE * s) {
1081  return makeDiff(makeAny(), s);
1082}
1083
1084           
1085
1086                           
1087RE * RE_Parser::makeWordBoundary() {
1088    Name * wordC = makeWordSet();
1089    return makeReBoundary(wordC);
1090}
1091
1092RE * RE_Parser::makeWordNonBoundary() {
1093    Name * wordC = makeWordSet();
1094    return makeReNonBoundary(wordC);
1095}
1096
1097inline RE * RE_Parser::makeReBoundary(RE * re) {
1098    return makeBoundaryAssertion(re);
1099}
1100inline RE * RE_Parser::makeReNonBoundary(RE * re) {
1101    return makeNegativeBoundaryAssertion(re);
1102}
1103
1104RE * RE_Parser::makeWordBegin() {
1105    Name * wordC = makeWordSet();
1106    return makeNegativeLookBehindAssertion(wordC);
1107}
1108
1109RE * RE_Parser::makeWordEnd() {
1110    Name * wordC = makeWordSet();
1111    return makeNegativeLookAheadAssertion(wordC);
1112}
1113
1114Name * RE_Parser::makeDigitSet() {
1115    return mMemoizer.memoize(createName("nd"));
1116}
1117
1118Name * RE_Parser::makeAlphaNumeric() {
1119    return mMemoizer.memoize(createName("alnum"));
1120}
1121
1122Name * RE_Parser::makeWhitespaceSet() {
1123    return mMemoizer.memoize(createName("whitespace"));
1124}
1125
1126Name * RE_Parser::makeWordSet() {
1127    return mMemoizer.memoize(createName("word"));
1128}
1129
1130Name * RE_Parser::createName(std::string value) {
1131    auto key = std::make_pair("", value);
1132    auto f = mNameMap.find(key);
1133    if (f != mNameMap.end()) {
1134        return f->second;
1135    }
1136    Name * const property = mMemoizer.memoize(makeName(value, Name::Type::UnicodeProperty));
1137    mNameMap.insert(std::make_pair(std::move(key), property));
1138    return property;
1139    }
1140
1141Name * RE_Parser::createName(std::string prop, std::string value) {
1142    auto key = std::make_pair(prop, value);
1143    auto f = mNameMap.find(key);
1144    if (f != mNameMap.end()) {
1145        return f->second;
1146    }
1147    Name * const property = mMemoizer.memoize(makeName(prop, value, Name::Type::UnicodeProperty));
1148    mNameMap.insert(std::make_pair(std::move(key), property));
1149    return property;
1150}
1151
1152LLVM_ATTRIBUTE_NORETURN void RE_Parser::ParseFailure(std::string errmsg) {
1153    llvm::report_fatal_error(errmsg);
1154}
1155
1156}
Note: See TracBrowser for help on using the repository browser.