Ignore:
Timestamp:
Dec 18, 2017, 1:56:51 PM (16 months ago)
Author:
cameron
Message:

RE parser restructuring; parsing symbolic ranges, collation and equivalence exprs

File:
1 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/re/re_parser.cpp

    r5786 r5787  
    6363    parser->mGroupsOpen = 0;
    6464    parser->fNested = false;
    65     parser->fGraphemeBoundaryPending = false;
    6665    parser->mCaptureGroupCount = 0;
    6766    RE * re = parser->parse_RE();
     
    7776, fNested(false)
    7877, mGroupsOpen(0)
    79 , fGraphemeBoundaryPending(false)
    8078, fSupportNonCaptureGroup(false)
    8179, mCursor(regular_expression)
     
    105103        alt.push_back(parse_seq());
    106104    }
    107     while (accept_alt_mark());
     105    while (accept('|'));
    108106    return makeAlt(alt.begin(), alt.end());
    109107}
    110108   
    111 bool RE_Parser::accept_alt_mark() {
    112     if (!mCursor.more() || (*mCursor != '|')) return false;
    113     mCursor++;
    114     return true;
    115 }
    116 
    117109RE * RE_Parser::parse_seq() {
    118110    std::vector<RE *> seq;
     
    129121}
    130122
     123RE * createStart(ModeFlagSet flags) {
     124    if ((flags && ModeFlagType::MULTILINE_MODE_FLAG) == 0) return makeZeroWidth("^s");  //single-line mode
     125    if ((flags & ModeFlagType::UNIX_LINES_MODE_FLAG) != 0) {
     126        return makeNegativeLookBehindAssertion(makeByte(makeCC(makeCC(0, '\n'-1), makeCC('\n'+1, 0xFF))));
     127    }
     128    return makeStart();
     129}
     130RE * createEnd(ModeFlagSet flags) {
     131    if ((flags && ModeFlagType::MULTILINE_MODE_FLAG) == 0) return makeZeroWidth("$s");  //single-line mode
     132    if ((flags & ModeFlagType::UNIX_LINES_MODE_FLAG) != 0) {
     133        return makeNegativeLookAheadAssertion(makeByte(makeCC(makeCC(0, '\n'-1), makeCC('\n'+1, 0xFF))));
     134    }
     135    return makeEnd();
     136}
     137RE * createAny(ModeFlagSet flags) {
     138    return makeAny();
     139}
     140   
     141   
    131142RE * 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::MULTILINE_MODE_FLAG) == 0) {
    146                     return makeZeroWidth("^s");  //single-line mode
    147                 }
    148                 if ((fModeFlagSet & ModeFlagType::UNIX_LINES_MODE_FLAG) != 0) {
    149                     return makeNegativeLookBehindAssertion(makeByte(makeCC(makeCC(0, '\n'-1), makeCC('\n'+1, 0xFF))));
    150                 }
    151                 return makeStart();
    152             case '$':
    153                 ++mCursor;
    154                 if ((fModeFlagSet & ModeFlagType::MULTILINE_MODE_FLAG) == 0) {
    155                     return makeZeroWidth("$s");  //single-line mode
    156                 }
    157                 if ((fModeFlagSet & ModeFlagType::UNIX_LINES_MODE_FLAG) != 0) {
    158                     return makeLookAheadAssertion(makeCC('\n'));
    159                 }
    160                 return makeEnd();
    161             case '|':
    162                 break;
    163             case ')':
    164                 if (mGroupsOpen > 0) break;
    165                 if (LEGACY_UNESCAPED_RBRAK_RBRACE_ALLOWED) {
    166                     return createCC(parse_literal_codepoint());
    167                 }
    168                 ParseFailure("Use  \\) for literal ).");
    169             case '*': case '+': case '?': case '{':
    170                 ParseFailure("Need something to repeat before *, +, ? or {.");
    171             case ']':
    172                 if (LEGACY_UNESCAPED_RBRAK_RBRACE_ALLOWED) {
    173                     return createCC(parse_literal_codepoint());
    174                 }
    175                 ParseFailure("Use  \\] for literal ].");
    176             case '}':
    177                 if (fNested) {
    178                     break;  //  a recursive invocation for a regexp in \N{...}
    179                 } else if (LEGACY_UNESCAPED_RBRAK_RBRACE_ALLOWED) {
    180                     return createCC(parse_literal_codepoint());
    181                 }
    182                 ParseFailure("Use \\} for literal }.");
    183             case '[':
    184                 mCursor++;
    185                 re = parse_charset();
    186                 break;
    187             case '.': // the 'any' metacharacter
    188                 mCursor++;
    189                 return makeAny();
    190             case '\\':  // escape processing
    191                 ++mCursor;
    192                 return parse_escaped();
    193             default:
    194                 re = createCC(parse_literal_codepoint());
    195         }
    196     }
    197     return re;
    198 }
    199 
     143    if (mCursor.noMore() || atany("*?+{|")) return nullptr;
     144    else if (((mGroupsOpen > 0) && at(')')) || (fNested && at('}'))) return nullptr;
     145    else if (accept('^')) return createStart(fModeFlagSet);
     146    else if (accept('$')) return createEnd(fModeFlagSet);
     147    else if (accept('.')) return createAny(fModeFlagSet);
     148    else if (accept('(')) return parse_group();
     149    else if (accept('[')) return parse_extended_bracket_expression();
     150    else if (accept('\\')) return parse_escaped();
     151    else return createCC(parse_literal_codepoint());
     152}
     153                                                         
    200154
    201155// Parse some kind of parenthesized group.  Input precondition: mCursor
     
    325279// Extend a RE item with one or more quantifiers
    326280RE * RE_Parser::extend_item(RE * re) {
    327     if (LLVM_UNLIKELY(!(mCursor.more()))) return re;
    328     int lb = 0, ub = 0;
    329     switch (*mCursor) {
    330         case '*':
    331             lb = 0;
    332             ub = Rep::UNBOUNDED_REP;
    333             break;
    334         case '?':
    335             lb = 0;
    336             ub = 1;
    337             break;
    338         case '+':
    339             lb = 1;
    340             ub = Rep::UNBOUNDED_REP;
    341             break;
    342         case '{':
    343             std::tie(lb, ub) = parse_range_bound();
    344             if ((ub != Rep::UNBOUNDED_REP) && (lb > ub)) {
    345                 ParseFailure("Lower bound cannot exceed upper bound in bounded repetition");
    346             }
    347             break;
    348         default:
    349             // No quantifiers
    350             return re;
    351     }
    352     ++mCursor;
    353     if (ENABLE_EXTENDED_QUANTIFIERS) {
    354         if (LLVM_UNLIKELY(!(mCursor.more()))) return makeRep(re, lb, ub);;
    355         if (*mCursor == '?') { // Non-greedy qualifier
    356             // Greedy vs. non-greedy makes no difference for icgrep.
    357             ++mCursor;
    358             re = makeRep(re, lb, ub);
    359         } else if (*mCursor == '+') {
    360             ++mCursor;
    361             if (ub == Rep::UNBOUNDED_REP) {
    362                 re = makeSeq({makeRep(re, lb, ub), makeNegativeLookAheadAssertion(re)});
    363             } else if (lb == ub) {
    364                 re = makeRep(re, ub, ub);
    365             } else /* if (lb < ub) */{
    366                 re = makeAlt({makeSeq({makeRep(re, lb, ub-1), makeNegativeLookAheadAssertion(re)}), makeRep(re, ub, ub)});
    367             }
    368         } else {
    369             re = makeRep(re, lb, ub);
    370         }
     281    int lb, ub;
     282    if (accept('*')) {lb = 0; ub = Rep::UNBOUNDED_REP;}
     283    else if (accept('?')) {lb = 0; ub = 1;}
     284    else if (accept('+')) {lb = 1; ub = Rep::UNBOUNDED_REP;}
     285    else if (accept('{')) std::tie(lb, ub) = parse_range_bound();
     286    else {
     287        // No quantifier found.
     288        return re;
     289    }
     290    if (ENABLE_EXTENDED_QUANTIFIERS && accept('?')) {
     291        // Non-greedy qualifier: no difference for Parabix RE matching
     292        re = makeRep(re, lb, ub);
     293    } else if (ENABLE_EXTENDED_QUANTIFIERS && accept('+')) {
     294        // Possessive qualifier
     295        if (ub == Rep::UNBOUNDED_REP) {
     296            re = makeSeq({makeRep(re, lb, ub), makeNegativeLookAheadAssertion(re)});
     297        } else if (lb == ub) {
     298            re = makeRep(re, ub, ub);
     299        } else /* if (lb < ub) */{
     300            re = makeAlt({makeSeq({makeRep(re, lb, ub-1), makeNegativeLookAheadAssertion(re)}), makeRep(re, ub, ub)});
     301        }
    371302    } else {
    372303        re = makeRep(re, lb, ub);
     
    377308
    378309std::pair<int, int> RE_Parser::parse_range_bound() {
    379     int lower_bound = 0, upper_bound = 0;
    380     if (*++mCursor != ',') {
    381         lower_bound = parse_int();
    382     }
    383     if (*mCursor == '}') {
    384         upper_bound = lower_bound;
    385     } else if (*mCursor != ',') {
    386         ParseFailure("Bad lower bound!");
    387     } else if (*++mCursor == '}') {
    388         upper_bound = Rep::UNBOUNDED_REP;
     310    int lb, ub;
     311    if (accept(',')) {
     312        lb = 0;
     313        ub = parse_int();
    389314    } else {
    390         upper_bound = parse_int();
    391         if (*mCursor != '}') {
    392             ParseFailure("Bad upper bound!");
    393         }
    394     }
    395     return std::make_pair(lower_bound, upper_bound);
     315        lb = parse_int();
     316        if (accept('}')) return std::make_pair(lb, lb);
     317        if (!accept(',')) ParseFailure("Expecting , or }");
     318        if (accept('}')) return std::make_pair(lb, Rep::UNBOUNDED_REP);
     319        ub = parse_int();
     320        if (ub < lb) ParseFailure("Upper bound less than lower bound");
     321    }
     322    if (accept('}')) return std::make_pair(lb, ub);
     323    else ParseFailure("Expecting }");
    396324}
    397325
     
    456384                    switch (*mCursor) {
    457385                        case 'g':
    458                             re = complemented ? makeZeroWidth("NonGCB") : makeZeroWidth("GCB");
     386                            re = complemented ? makeZeroWidth("\\B{g}") : makeZeroWidth("\\b{g}");
    459387                            ++mCursor;
    460388                            ++mCursor;
     
    523451            // to get to the next extended grapheme cluster boundary.
    524452            ++mCursor;
    525             return makeSeq({makeAny(), makeRep(makeSeq({makeZeroWidth("NonGCB"), makeAny()}), 0, Rep::UNBOUNDED_REP), makeZeroWidth("GCB")});
     453            return makeSeq({makeAny(), makeRep(makeSeq({makeZeroWidth("\\B{g}"), makeAny()}), 0, Rep::UNBOUNDED_REP), makeZeroWidth("\\b{g}")});
    526454        case 'N':
    527             if (*++mCursor != '{') {
    528                 ParseFailure("Malformed \\N expression");
    529             }
    530455            ++mCursor;
    531456            re = parseNamePatternExpression();
    532             if (*mCursor != '}') {
    533                 ParseFailure("Malformed \\N expression");
    534             }
    535             ++mCursor;
    536457            assert (re);
    537458            return re;
     
    705626Name * RE_Parser::parseNamePatternExpression(){
    706627
     628    if (!accept('{')) ParseFailure("Expecting { after \\N");
    707629    const auto start = mCursor.pos();
    708630    while (mCursor.more()) {
     
    719641    }
    720642    std::string nameRegexp = "/(?i)" + std::string(start, mCursor.pos());
     643    if (!accept('}')) ParseFailure("Expecting } after \\N{...");
    721644    return createName("na", nameRegexp);
    722645}
    723646
    724 bool RE_Parser::isUnsupportChartsetOperator(char c) {
    725     return false;
    726 }
    727 
    728 CharsetOperatorKind RE_Parser::getCharsetOperator() {
    729     if (isUnsupportChartsetOperator(*mCursor)) {
    730         return emptyOperator;
    731     }
    732     switch (*mCursor) {
    733         case '&':
    734             ++mCursor;
    735             if (*mCursor == '&') {
    736                 ++mCursor;
    737                 return intersectOp;
    738             } else if (*mCursor == '[') {
    739                 // Short-hand for intersectOp when a set follows
    740                 return intersectOp;
    741             }
    742             return ampChar;
    743         case '-':
    744             ++mCursor;
    745             if (*mCursor == '-') {
    746                 ++mCursor;
    747                 return setDiffOp;
    748             } else if (*mCursor == '[') {
    749                 return setDiffOp;
    750             } else if (*mCursor == ']') {
    751                 return hyphenChar;
    752             }
    753             return rangeHyphen;
    754         case '[':
    755             ++mCursor;
    756             if (*mCursor == ':') {
    757                 ++mCursor;
    758                 return posixPropertyOpener;
    759             }
    760             return setOpener;
    761         case ']':
    762             ++mCursor;
    763             return setCloser;
    764         case '\\':
    765             ++mCursor;
    766             return backSlash;
    767         default:
    768             return emptyOperator;
    769     }
    770 }
    771 
    772 // Precondition: cursor is immediately after opening '[' character
    773 RE * RE_Parser::parse_charset() {
    774     // Sets are accumulated using two variables:
    775     // subexprs accumulates set expressions such as \p{Lu}, [\w && \p{Greek}]
    776     // cc accumulates the literal and calculated codepoints and ranges
    777     std::vector<RE *> subexprs;
    778     CC * cc = makeCC();
    779     // When the last item deal with is a single literal charcacter or calculated codepoint,
    780     // a following hyphen can indicate a range.   When the last item is a set subexpression,
    781     // a following hyphen can indicate set subtraction.
    782     enum {NoItem, CodepointItem, RangeItem, SetItem, BrackettedSetItem} lastItemKind = NoItem;
    783 
    784     codepoint_t lastCodepointItem = 0;
    785     bool havePendingOperation = false;
    786     bool possibleByteCodeEscape = false;  // set to true when \x, \o or \0 hex or octal escapes seen.
    787     CharsetOperatorKind pendingOperationKind = intersectOp;
    788     RE * pendingOperand = nullptr;
    789 
    790     // If the first character after the [ is a ^ (caret) then the matching character class is complemented.
    791     bool negated = false;
    792     if (*mCursor == '^') {
    793         negated = true;
     647
     648// Parse a bracketted expression with possible && (intersection) or
     649// -- (set difference) operators.
     650// Initially, the opening bracket has been consumed.
     651RE * RE_Parser::parse_extended_bracket_expression () {
     652    bool negated = accept('^');
     653    RE * t1 = parse_bracketed_items();
     654    bool have_new_expr = true;
     655    while (have_new_expr) {
     656        if (accept("&&")) {
     657            RE * t2 = parse_bracketed_items();
     658            t1 = makeIntersect(t1, t2);
     659        } else if (accept("--")) {
     660            RE * t2 = parse_bracketed_items();
     661            t1 = makeDiff(t1, t2);
     662        }
     663        else have_new_expr = false;
     664    }
     665    if (!accept(']')) ParseFailure("Expecting ]");
     666    if (negated) return makeComplement(t1);
     667    else return t1;
     668}
     669
     670// Parsing items within a bracket expression.
     671// Items represent individual characters or sets of characters.
     672// Ranges may be formed by individual character items separated by '-'.
     673RE * RE_Parser::parse_bracketed_items () {
     674    std::vector<RE *> items;
     675    do {
     676        if (accept('[')) {
     677            if (accept('=')) items.push_back(parse_equivalence_class());
     678            else if (accept('.')) items.push_back(range_extend(parse_collation_element()));
     679            else if (accept(':')) items.push_back(parse_Posix_class());
     680            else items.push_back(parse_extended_bracket_expression());
     681        } else if (accept('\\')) {
     682            if (at('N') || !isSetEscapeChar(*mCursor)) items.push_back(range_extend(parse_escaped_char_item()));
     683            else items.push_back(parseEscapedSet());
     684        } else {
     685            items.push_back(range_extend(makeCC(parse_literal_codepoint())));
     686        }
     687    } while (mCursor.more() && !at(']') && !at("&&") && (!at("--") || at("--]")));
     688    return makeAlt(items.begin(), items.end());
     689}
     690
     691//  Given an individual character expression, check for and parse
     692//  a range extension if one exists, or return the individual expression.
     693RE * RE_Parser::range_extend(RE * char_expr1) {
     694    // A range extension is signalled by a hyphen '-', except for special cases:
     695    // (a) if the following character is "]" the hyphen is a literal set character.
     696    // (b) if the following character is "-" the hyphen is part of a set subtract
     697    // operator, unless it the set is immediately closed by "--]".
     698    if (!at('-') || at("-]") || (at("--") && !at("--]"))) return char_expr1;
     699    accept('-');
     700    RE * char_expr2 = nullptr;
     701    if (accept('\\')) char_expr2 = parse_escaped_char_item();
     702    else if (accept('[')) {
     703        if (accept('.')) char_expr2 = parse_collation_element();
     704        else ParseFailure("Error in range expression");
     705    } else {
     706        char_expr2 = makeCC(parse_literal_codepoint());
     707    }
     708    return makeRange(char_expr1, char_expr2);
     709}
     710
     711RE * RE_Parser::parse_equivalence_class() {
     712    const auto start = mCursor.pos() - 1;
     713    while (mCursor.more() && !at('=')) {
    794714        ++mCursor;
    795715    }
    796     // Legacy rule: an unescaped ] may appear as a literal set character
    797     // if and only if it appears immediately after the opening [ or [^
    798     if ( *mCursor == ']' && LEGACY_UNESCAPED_RBRAK_RBRACE_ALLOWED) {
    799         insert(cc, ']');
    800         lastItemKind = CodepointItem;
    801         lastCodepointItem = static_cast<codepoint_t> (']');
     716    std::string name = std::string(start, mCursor.pos());
     717    if (!accept("=]")) ParseFailure("Posix equivalence class improperly terminated.");
     718    return createName(name);
     719}
     720RE * RE_Parser::parse_collation_element() {
     721    const auto start = mCursor.pos() - 1;
     722    while (mCursor.more() && !at('.')) {
    802723        ++mCursor;
    803     } else if ( *mCursor == '-' && LEGACY_UNESCAPED_HYPHEN_ALLOWED) {
    804         ++mCursor;
    805         insert(cc, '-');
    806         lastItemKind = CodepointItem;
    807         lastCodepointItem = static_cast<codepoint_t> ('-');
    808         if (*mCursor == '-') {
    809             ParseFailure("Set operator has no left operand.");
    810         }
    811     }
    812     while (mCursor.more()) {
    813         const CharsetOperatorKind op = getCharsetOperator();
    814         switch (op) {
    815             case intersectOp:
    816             case setDiffOp: {
    817                 if (lastItemKind == NoItem) {
    818                     ParseFailure("Set operator has no left operand.");
    819                 }
    820                 if (!cc->empty()) {
    821                     subexprs.push_back(mMemoizer.memoize(cc));
    822                 }
    823                 RE * newOperand = makeAlt(subexprs.begin(), subexprs.end());
    824                 subexprs.clear();
    825                 cc = makeCC();
    826                 if (havePendingOperation) {
    827                     if (pendingOperationKind == intersectOp) {
    828                         pendingOperand = makeIntersect(pendingOperand, newOperand);
    829                     }
    830                     else {
    831                         pendingOperand = makeDiff(pendingOperand, newOperand);
    832                     }
    833                 }
    834                 else {
    835                     pendingOperand = newOperand;
    836                 }
    837                 havePendingOperation = true;
    838                 pendingOperationKind = op;
    839                 lastItemKind = NoItem;
    840             }
    841             break;
    842             case setCloser: {
    843                 if (lastItemKind == NoItem) {
    844                     ParseFailure("Set operator has no right operand.");
    845                 }
    846                 if (!cc->empty()) {
    847                     if (possibleByteCodeEscape && (cc->max_codepoint() <= 0xFF) && subexprs.empty() && !havePendingOperation) {
    848                         subexprs.push_back(makeByte(cc));
    849                     }
    850                     else {
    851                         subexprs.push_back(mMemoizer.memoize(cc));
    852                     }
    853                 }
    854                 RE * newOperand = makeAlt(subexprs.begin(), subexprs.end());
    855                 if (havePendingOperation) {
    856                     if (pendingOperationKind == intersectOp) {
    857                         newOperand = makeIntersect(pendingOperand, newOperand);
    858                     }
    859                     else {
    860                         newOperand = makeDiff(pendingOperand, newOperand);
    861                     }
    862                 }
    863                 return negated ? makeComplement(newOperand) : newOperand;
    864             }
    865             case setOpener:
    866             case posixPropertyOpener: {
    867                 if (lastItemKind != NoItem) {
    868                     if (!cc->empty()) {
    869                         subexprs.push_back(mMemoizer.memoize(cc));
    870                     }
    871                     RE * newOperand = makeAlt(subexprs.begin(), subexprs.end());
    872                     subexprs.clear();
    873                     cc = makeCC();
    874                     if (havePendingOperation) {
    875                         if (pendingOperationKind == intersectOp) {
    876                             pendingOperand = makeIntersect(pendingOperand, newOperand);
    877                         } else {
    878                             pendingOperand = makeDiff(pendingOperand, newOperand);
    879                         }
    880                     }
    881                     else {
    882                         pendingOperand = newOperand;
    883                     }
    884                     subexprs.push_back(pendingOperand);
    885                     havePendingOperation = false;
    886                 }
    887                 if (op == setOpener) {
    888                     subexprs.push_back(parse_charset());
    889                     lastItemKind = SetItem;
    890                 }
    891                 else if (op == posixPropertyOpener) {
    892                     bool negated = false;
    893                     if (*mCursor == '^') {
    894                         negated = true;
    895                         mCursor++;
    896                     }
    897                     RE * posixSet = parsePropertyExpression();
    898                     subexprs.push_back(negated ? makeComplement(posixSet) : posixSet);
    899                     lastItemKind = BrackettedSetItem;
    900                     if (*mCursor++ != ':' || *mCursor++ != ']')
    901                         ParseFailure("Posix set expression improperly terminated.");
    902                 }
    903             }
    904             break;
    905             case rangeHyphen:
    906                 if (lastItemKind != CodepointItem) {
    907                     ParseFailure("Range operator - has illegal left operand.");
    908                 }
    909                 if (*mCursor == '\\') {
    910                     mCursor++;
    911                     if ((*mCursor == 'x') || (*mCursor == 'o') || (*mCursor == '0')) possibleByteCodeEscape = true;
    912                     insert_range(cc, lastCodepointItem, parse_escaped_codepoint());
    913                     //subexprs.push_back(makeRange(makeCC(lastCodepointItem), makeCC(parse_escaped_codepoint())));
    914                 } else {
    915                     insert_range(cc, lastCodepointItem, parse_literal_codepoint());
    916                     //subexprs.push_back(makeRange(makeCC(lastCodepointItem), makeCC(parse_literal_codepoint())));
    917                 }
    918                 lastItemKind = RangeItem;
    919                 break;
    920             case hyphenChar:
    921                 insert(cc, '-');
    922                 lastItemKind = CodepointItem;
    923                 lastCodepointItem = static_cast<codepoint_t> ('-');
    924                 break;
    925             case ampChar:
    926                 insert(cc, '&');
    927                 lastItemKind = CodepointItem;
    928                 lastCodepointItem = static_cast<codepoint_t> ('&');
    929                 break;
    930             case backSlash:
    931                 if (isSetEscapeChar(*mCursor)) {
    932                     subexprs.push_back(parseEscapedSet());
    933                     lastItemKind = SetItem;
    934                 }
    935                 else {
    936                     if ((*mCursor == 'x') || (*mCursor == 'o') || (*mCursor == '0')) possibleByteCodeEscape = true;
    937                     lastCodepointItem = parse_escaped_codepoint();
    938                     insert(cc, lastCodepointItem);
    939                     lastItemKind = CodepointItem;
    940                 }
    941                 break;
    942             case emptyOperator:
    943                 lastCodepointItem = parse_literal_codepoint();
    944                 insert(cc, lastCodepointItem);
    945                 lastItemKind = CodepointItem;
    946                 break;
    947         }
    948     }
    949     ParseFailure("Set expression not properly terminated.");
     724    }
     725    std::string name = std::string(start, mCursor.pos());
     726    if (!accept(".]")) ParseFailure("Posix equivalence class improperly terminated.");
     727    return createName(name);
     728}
     729
     730RE * RE_Parser::parse_Posix_class() {
     731    bool negated = accept('^');
     732    RE * posixSet = parsePropertyExpression();
     733    if (!accept(":]")) ParseFailure("Posix set expression improperly terminated.");
     734    if (negated) return makeComplement(posixSet);
     735    else return posixSet;
     736}
     737
     738RE * RE_Parser::parse_escaped_char_item() {
     739    if (accept('N')) return parseNamePatternExpression();
     740    else return makeCC(parse_escaped_codepoint());
    950741}
    951742
     
    965756codepoint_t RE_Parser::parse_escaped_codepoint() {
    966757    codepoint_t cp_value;
    967     switch (*mCursor) {
    968         case 'a': ++mCursor; return 0x07; // BEL
    969         case 'e': ++mCursor; return 0x1B; // ESC
    970         case 'f': ++mCursor; return 0x0C; // FF
    971         case 'n': ++mCursor; return 0x0A; // LF
    972         case 'r': ++mCursor; return 0x0D; // CR
    973         case 't': ++mCursor; return 0x09; // HT
    974         case 'v': ++mCursor; return 0x0B; // VT
    975         case 'c': // Control-escape based on next char
    976             ++mCursor;
     758    if (accept('a')) return 0x07; // BEL
     759    else if (accept('e')) return 0x1B; // ESC
     760    else if (accept('f')) return 0x0C; // FF
     761    else if (accept('n')) return 0x0A; // LF
     762    else if (accept('r')) return 0x0D; // CR
     763    else if (accept('t')) return 0x09; // HT
     764    else if (accept('v')) return 0x0B; // VT
     765    else if (accept('c')) {// Control-escape based on next char
    977766            // \c@, \cA, ... \c_, or \ca, ..., \cz
    978767            if (((*mCursor >= '@') && (*mCursor <= '_')) || ((*mCursor >= 'a') && (*mCursor <= 'z'))) {
     
    981770                return cp_value;
    982771            }
    983             else if (*mCursor++ == '?') return 0x7F;  // \c? ==> DEL
     772            else if (accept('?')) return 0x7F;  // \c? ==> DEL
    984773            else ParseFailure("Illegal \\c escape sequence");
    985         case '0': // Octal escape:  0 - 0377
    986             ++mCursor;
    987             return parse_octal_codepoint(0,3);
    988         case 'o':
    989             ++mCursor;
    990             if (*mCursor == '{') {
    991                 ++mCursor;
    992                 cp_value = parse_octal_codepoint(1, 7);
    993                 if (*mCursor++ != '}') ParseFailure("Malformed octal escape sequence");
    994                 return cp_value;
    995             }
    996             else {
    997                 ParseFailure("Malformed octal escape sequence");
    998             }
    999         case 'x':
    1000             ++mCursor;
    1001             if (*mCursor == '{') {
    1002               ++mCursor;
    1003               cp_value = parse_hex_codepoint(1, 6);
    1004               if (*mCursor++ != '}') ParseFailure("Malformed hex escape sequence");
    1005               return cp_value;
    1006             }
    1007             else {
    1008                 return parse_hex_codepoint(1,2);  // ICU compatibility
    1009             }
    1010         case 'u':
    1011             ++mCursor;
    1012             if (*mCursor == '{') {
    1013                 ++mCursor;
    1014                 cp_value = parse_hex_codepoint(1, 6);
    1015                 if (*mCursor++ != '}') ParseFailure("Malformed hex escape sequence");
    1016                 return cp_value;
    1017             }
    1018             else {
    1019                 return parse_hex_codepoint(4,4);  // ICU compatibility
    1020             }
    1021         case 'U':
    1022             ++mCursor;
    1023             return parse_hex_codepoint(8,8);  // ICU compatibility
    1024         default:
    1025             // Escaped letters should be reserved for special functions.
    1026             if (((*mCursor >= 'A') && (*mCursor <= 'Z')) || ((*mCursor >= 'a') && (*mCursor <= 'z'))){
    1027                 //Escape unknown letter will be parse as normal letter
    1028                 return parse_literal_codepoint();
    1029                 //ParseFailure("Undefined or unsupported escape sequence");
    1030             }
    1031             else if ((*mCursor < 0x20) || (*mCursor >= 0x7F))
    1032                 ParseFailure("Illegal escape sequence");
    1033             else return static_cast<codepoint_t>(*mCursor++);
     774    } else if (accept('0')) {
     775        return parse_octal_codepoint(0,3);
     776    } else if (accept('o')) {
     777        if (!accept('{')) ParseFailure("Malformed octal escape sequence");
     778        cp_value = parse_octal_codepoint(1, 7);
     779        if (!accept('}')) ParseFailure("Malformed octal escape sequence");
     780        return cp_value;
     781    } else if (accept('x')) {
     782        if (!accept('{')) return parse_hex_codepoint(1,2);  // ICU compatibility
     783        cp_value = parse_hex_codepoint(1, 6);
     784        if (!accept('}')) ParseFailure("Malformed hex escape sequence");
     785        return cp_value;
     786    } else if (accept('u')) {
     787        if (!accept('{')) return parse_hex_codepoint(4,4);  // ICU compatibility
     788        cp_value = parse_hex_codepoint(1, 6);
     789        if (!accept('}')) ParseFailure("Malformed hex escape sequence");
     790        return cp_value;
     791    } else if (accept('U')) {
     792        return parse_hex_codepoint(8,8);  // ICU compatibility
     793    } else {
     794        if (((*mCursor >= 'A') && (*mCursor <= 'Z')) || ((*mCursor >= 'a') && (*mCursor <= 'z'))){
     795            //Escape unknown letter will be parse as normal letter
     796            return parse_literal_codepoint();
     797            //ParseFailure("Undefined or unsupported escape sequence");
     798        }
     799        else if ((*mCursor < 0x20) || (*mCursor >= 0x7F))
     800            ParseFailure("Illegal escape sequence");
     801        else return static_cast<codepoint_t>(*mCursor++);
    1034802    }
    1035803}
Note: See TracChangeset for help on using the changeset viewer.