Changeset 4310


Ignore:
Timestamp:
Nov 22, 2014, 9:47:19 PM (4 years ago)
Author:
cameron
Message:

Clean indentation

File:
1 edited

Legend:

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

    r4309 r4310  
    103103                throw NothingToRepeat();
    104104            case ']': case '}':
    105                                 if (LEGACY_UNESCAPED_RBRAK_RBRACE_ALLOWED) {
    106                                         return parse_literal();
    107                                 }
    108                                 else throw ParseFailure("Use  \\] or \\} for literal ] or }.");
     105                if (LEGACY_UNESCAPED_RBRAK_RBRACE_ALLOWED) {
     106                    return parse_literal();
     107                }
     108                else throw ParseFailure("Use  \\] or \\} for literal ] or }.");
    109109            case '[':
    110                 *_cursor++;
     110                *_cursor++;
    111111                return parse_charset();
    112112            case '.': // the 'any' metacharacter
    113113                return parse_any_character();
    114                         case '\\':  // escape processing
     114            case '\\':  // escape processing
    115115                ++_cursor;
    116116                return parse_escaped();
     
    252252
    253253RE * RE_Parser::parse_escaped_set() {
    254         bool complemented = false;
    255         RE * s;
     254    bool complemented = false;
     255    RE * s;
    256256    switch (*_cursor) {
    257                 case 'd':
    258                         ++_cursor;
    259                         return makeDigitSet();
    260                 case 'D':
    261                         ++_cursor;
    262                         return makeComplement(makeDigitSet());
    263                 case 's':
    264                         ++_cursor;
    265                         return makeWhitespaceSet();
    266                 case 'S':
    267                         ++_cursor;
    268                         return makeComplement(makeWhitespaceSet());
    269                 case 'w':
    270                         ++_cursor;
    271                         return makeWordSet();
    272                 case 'W':
    273                         ++_cursor;
    274                         return makeComplement(makeWordSet());
     257        case 'd':
     258            ++_cursor;
     259            return makeDigitSet();
     260        case 'D':
     261            ++_cursor;
     262            return makeComplement(makeDigitSet());
     263        case 's':
     264            ++_cursor;
     265            return makeWhitespaceSet();
     266        case 'S':
     267            ++_cursor;
     268            return makeComplement(makeWhitespaceSet());
     269        case 'w':
     270            ++_cursor;
     271            return makeWordSet();
     272        case 'W':
     273            ++_cursor;
     274            return makeComplement(makeWordSet());
    275275        case 'P':
    276276            complemented = true;
    277277        case 'p':
    278                         ++_cursor;
    279                         if (_cursor == _end || *_cursor != '{') throw ParseFailure("Malformed property expression");
    280                         ++_cursor;
    281                         s = parse_property_expression();
    282                         if (_cursor == _end || *_cursor != '}') throw ParseFailure("Malformed property expression");
    283                         ++_cursor;
    284                         if (complemented) return makeComplement(s);
    285                         else return s;
    286                 default:
    287                         throw ParseFailure("Internal error");
     278            ++_cursor;
     279            if (_cursor == _end || *_cursor != '{') throw ParseFailure("Malformed property expression");
     280            ++_cursor;
     281            s = parse_property_expression();
     282            if (_cursor == _end || *_cursor != '}') throw ParseFailure("Malformed property expression");
     283            ++_cursor;
     284            if (complemented) return makeComplement(s);
     285            else return s;
     286        default:
     287            throw ParseFailure("Internal error");
    288288    }
    289289}
     
    333333Name * RE_Parser::parse_property_expression() {
    334334    const cursor_t start = _cursor;
    335         while (_cursor != _end && *_cursor != '}' and *_cursor != ':') {
    336                 _cursor++;
    337         }
    338         return makeName(std::string(start, _cursor), Name::Type::UnicodeCategory);
    339 }
    340        
     335    while (_cursor != _end && *_cursor != '}' and *_cursor != ':') {
     336        _cursor++;
     337    }
     338    return makeName(std::string(start, _cursor), Name::Type::UnicodeCategory);
     339}
     340   
    341341CharsetOperatorKind RE_Parser::getCharsetOperator() {
    342342    throw_incomplete_expression_error_if_end_of_stream();
    343         switch (*_cursor) {
    344                 case '&':
    345                         ++_cursor;
    346                         if (_cursor != _end && *_cursor == '&') {
    347                                 ++_cursor;
    348                                 return intersectOp;
    349                         }
    350                         else if (_cursor != _end && *_cursor == '[') {
    351                                 // Short-hand for intersectOp when a set follows
    352                                 return intersectOp;
    353                         }
    354                         else return ampChar;
    355                 case '-':
    356                         ++_cursor;
    357                         if (_cursor != _end && *_cursor == '-') {
    358                                 ++_cursor;
    359                                 return setDiffOp;
    360                         }
    361                         else if (_cursor != _end && *_cursor == '[') {
    362                                 return setDiffOp;
    363                         }
    364                         else if (_cursor != _end && *_cursor == ']') {
    365                                 return hyphenChar;
    366                         }
    367                         else return rangeHyphen;
    368                 case '[':
    369                         ++_cursor;
    370                         if (_cursor != _end && *_cursor == ':') {
    371                                 ++_cursor;
    372                                 return posixPropertyOpener;
    373                         }
    374                         else return setOpener;
    375                 case ']':
    376                         ++_cursor;
    377                         return setCloser;
    378                 case '\\':
    379                         ++_cursor;
    380                         return backSlash;
    381                 default:
    382                         return emptyOperator;
    383         }
    384 }                       
    385        
     343    switch (*_cursor) {
     344        case '&':
     345            ++_cursor;
     346            if (_cursor != _end && *_cursor == '&') {
     347                ++_cursor;
     348                return intersectOp;
     349            }
     350            else if (_cursor != _end && *_cursor == '[') {
     351                // Short-hand for intersectOp when a set follows
     352                return intersectOp;
     353            }
     354            else return ampChar;
     355        case '-':
     356            ++_cursor;
     357            if (_cursor != _end && *_cursor == '-') {
     358                ++_cursor;
     359                return setDiffOp;
     360            }
     361            else if (_cursor != _end && *_cursor == '[') {
     362                return setDiffOp;
     363            }
     364            else if (_cursor != _end && *_cursor == ']') {
     365                return hyphenChar;
     366            }
     367            else return rangeHyphen;
     368        case '[':
     369            ++_cursor;
     370            if (_cursor != _end && *_cursor == ':') {
     371                ++_cursor;
     372                return posixPropertyOpener;
     373            }
     374            else return setOpener;
     375        case ']':
     376            ++_cursor;
     377            return setCloser;
     378        case '\\':
     379            ++_cursor;
     380            return backSlash;
     381        default:
     382            return emptyOperator;
     383    }
     384}           
     385   
    386386// Precondition: cursor is immediately after opening '[' character
    387387RE * RE_Parser::parse_charset() {
    388         // Sets are accumulated using two variables:
    389         // subexprs accumulates set expressions such as \p{Lu}, [\w && \p{Greek}]
    390         // cc accumulates the literal and calculated codepoints and ranges
    391         std::vector<RE *> subexprs;
     388    // Sets are accumulated using two variables:
     389    // subexprs accumulates set expressions such as \p{Lu}, [\w && \p{Greek}]
     390    // cc accumulates the literal and calculated codepoints and ranges
     391    std::vector<RE *> subexprs;
    392392    CC * cc = makeCC();
    393         // When the last item deal with is a single literal charcacter or calculated codepoint,
    394         // a following hyphen can indicate a range.   When the last item is a set subexpression,
    395         // a following hyphen can indicate set subtraction.
    396         enum {NoItem, CodepointItem, RangeItem, SetItem, BrackettedSetItem} lastItemKind = NoItem;
    397         unsigned lastCodepointItem;
    398        
    399         bool havePendingOperation = false;
    400         CharsetOperatorKind pendingOperationKind;
    401         RE * pendingOperand;
    402        
     393    // When the last item deal with is a single literal charcacter or calculated codepoint,
     394    // a following hyphen can indicate a range.   When the last item is a set subexpression,
     395    // a following hyphen can indicate set subtraction.
     396    enum {NoItem, CodepointItem, RangeItem, SetItem, BrackettedSetItem} lastItemKind = NoItem;
     397    unsigned lastCodepointItem;
     398   
     399    bool havePendingOperation = false;
     400    CharsetOperatorKind pendingOperationKind;
     401    RE * pendingOperand;
     402   
    403403    // If the first character after the [ is a ^ (caret) then the matching character class is complemented.
    404404    bool negated = false;
     
    408408    }
    409409    throw_incomplete_expression_error_if_end_of_stream();
    410         // Legacy rule: an unescaped ] may appear as a literal set character
    411         // if and only if it appears immediately after the opening [ or [^
     410    // Legacy rule: an unescaped ] may appear as a literal set character
     411    // if and only if it appears immediately after the opening [ or [^
    412412    if ( *_cursor == ']' && LEGACY_UNESCAPED_RBRAK_RBRACE_ALLOWED) {
    413                 cc->insert(']');
    414                 lastItemKind = CodepointItem;
    415                 lastCodepointItem = static_cast<unsigned> (']');
    416                 ++_cursor;
     413        cc->insert(']');
     414        lastItemKind = CodepointItem;
     415        lastCodepointItem = static_cast<unsigned> (']');
     416        ++_cursor;
    417417    }
    418418    else if ( *_cursor == '-' && LEGACY_UNESCAPED_HYPHEN_ALLOWED) {
    419                 ++_cursor;
    420                 cc->insert('-');
    421                 lastItemKind = CodepointItem;
    422                 lastCodepointItem = static_cast<unsigned> ('-');
     419        ++_cursor;
     420        cc->insert('-');
     421        lastItemKind = CodepointItem;
     422        lastCodepointItem = static_cast<unsigned> ('-');
    423423                if (*_cursor == '-') throw ParseFailure("Set operator has no left operand.");
    424424    }
    425425    while (_cursor != _end) {
    426                 CharsetOperatorKind op = getCharsetOperator();
    427                 switch (op) {
    428                         case intersectOp: case setDiffOp: {
    429                                 if (lastItemKind == NoItem) throw ParseFailure("Set operator has no left operand.");
    430                                 if (cc->begin() != cc->end()) subexprs.push_back(cc);
    431                                 RE * newOperand = makeAlt(subexprs.begin(), subexprs.end());
    432                                 subexprs.clear();
    433                                 cc = makeCC();
    434                                 if (havePendingOperation) {
    435                                         if (pendingOperationKind == intersectOp) {
    436                                                 pendingOperand = makeIntersect(pendingOperand, newOperand);
    437                                         }
    438                                         else {
    439                                                 pendingOperand = makeDiff(pendingOperand, newOperand);
    440                                         }
    441                                 }
    442                                 else {
    443                                         pendingOperand = newOperand;
    444                                 }
    445                                 havePendingOperation = true;
    446                                 pendingOperationKind = op;
    447                                 lastItemKind = NoItem;
    448                         }
    449                         break;
    450                         case setCloser: {
    451                                 if (lastItemKind == NoItem) throw ParseFailure("Set operator has no right operand.");
    452                                 if (cc->begin() != cc->end()) subexprs.push_back(cc);
    453                                 RE * newOperand = makeAlt(subexprs.begin(), subexprs.end());
    454                                 if (havePendingOperation) {
    455                                         if (pendingOperationKind == intersectOp) {
    456                                                 newOperand = makeIntersect(pendingOperand, newOperand);
    457                                         }
    458                                         else {
    459                                                 newOperand = makeDiff(pendingOperand, newOperand);
    460                                         }
    461                                 }
    462                                 if (negated) return makeComplement(newOperand);
    463                                 else return newOperand;
    464                         }
    465                         case setOpener: case posixPropertyOpener: {
    466                                 if (lastItemKind != NoItem) {
    467                                         if (cc->begin() != cc->end()) subexprs.push_back(cc);
    468                                         RE * newOperand = makeAlt(subexprs.begin(), subexprs.end());
    469                                         subexprs.clear();
    470                                         cc = makeCC();
    471                                         if (havePendingOperation) {
    472                                                 if (pendingOperationKind == intersectOp) {
    473                                                         pendingOperand = makeIntersect(pendingOperand, newOperand);
    474                                                 }
    475                                                 else {
    476                                                         pendingOperand = makeDiff(pendingOperand, newOperand);
    477                                                 }
    478                                         }
    479                                         else {
    480                                                 pendingOperand = newOperand;
    481                                         }
    482                                         subexprs.push_back(pendingOperand);
    483                                         havePendingOperation = false;
    484                                 }
    485                                 if (op == setOpener) {
    486                                         subexprs.push_back(parse_charset());
    487                                         lastItemKind = SetItem;
    488                                 }
    489                                 else if (op == posixPropertyOpener) {
    490                                         bool negated = false;
    491                                         if (*_cursor == '^') {
    492                                                 negated = true;
    493                                                 _cursor++;
    494                                         }
    495                                         RE * posixSet = parse_property_expression();
    496                                         if (negated) posixSet = makeComplement(posixSet);
    497                                         subexprs.push_back(posixSet);
    498                                         lastItemKind = BrackettedSetItem;
    499                                         if (_cursor == _end || *_cursor++ != ':' || _cursor == _end || *_cursor++ != ']')
    500                                                 throw ParseFailure("Posix set expression improperly terminated.");
    501                                 }
    502                         }
    503                         break;
    504                         case rangeHyphen:
    505                                 if (lastItemKind != CodepointItem) throw ParseFailure("Range operator - has illegal left operand.");
    506                                 cc->insert_range(lastCodepointItem, parse_codepoint());
    507                                 lastItemKind = RangeItem;
    508                                 break;
    509                         case hyphenChar:
    510                                 cc->insert('-'); 
    511                                 lastItemKind = CodepointItem;
    512                                 lastCodepointItem = static_cast<unsigned> ('-');
    513                                 break;
    514                         case ampChar:
    515                                 cc->insert('&');
    516                                 lastItemKind = CodepointItem;
    517                                 lastCodepointItem = static_cast<unsigned> ('&');
    518                                 break;
    519                         case backSlash:
    520                                 throw_incomplete_expression_error_if_end_of_stream();
    521                                 if (isSetEscapeChar(*_cursor)) {
    522                                         subexprs.push_back(parse_escaped_set());
    523                                         lastItemKind = SetItem;
    524                                 }
    525                                 else {
    526                                         lastCodepointItem = parse_escaped_codepoint();
    527                                         cc->insert(lastCodepointItem);
    528                                         lastItemKind = CodepointItem;
    529                                 }
    530                                 break;
    531                         case emptyOperator:
    532                                 lastCodepointItem = parse_utf8_codepoint();
    533                                 cc->insert(lastCodepointItem);
    534                                 lastItemKind = CodepointItem;
    535                                 break;
    536                 }
    537         }
    538         throw ParseFailure("Set expression not properly terminated.");
     426        CharsetOperatorKind op = getCharsetOperator();
     427        switch (op) {
     428            case intersectOp: case setDiffOp: {
     429                if (lastItemKind == NoItem) throw ParseFailure("Set operator has no left operand.");
     430                if (cc->begin() != cc->end()) subexprs.push_back(cc);
     431                RE * newOperand = makeAlt(subexprs.begin(), subexprs.end());
     432                subexprs.clear();
     433                cc = makeCC();
     434                if (havePendingOperation) {
     435                    if (pendingOperationKind == intersectOp) {
     436                        pendingOperand = makeIntersect(pendingOperand, newOperand);
     437                    }
     438                    else {
     439                        pendingOperand = makeDiff(pendingOperand, newOperand);
     440                    }
     441                }
     442                else {
     443                    pendingOperand = newOperand;
     444                }
     445                havePendingOperation = true;
     446                pendingOperationKind = op;
     447                lastItemKind = NoItem;
     448            }
     449            break;
     450            case setCloser: {
     451                if (lastItemKind == NoItem) throw ParseFailure("Set operator has no right operand.");
     452                if (cc->begin() != cc->end()) subexprs.push_back(cc);
     453                RE * newOperand = makeAlt(subexprs.begin(), subexprs.end());
     454                if (havePendingOperation) {
     455                    if (pendingOperationKind == intersectOp) {
     456                        newOperand = makeIntersect(pendingOperand, newOperand);
     457                    }
     458                    else {
     459                        newOperand = makeDiff(pendingOperand, newOperand);
     460                    }
     461                }
     462                if (negated) return makeComplement(newOperand);
     463                else return newOperand;
     464            }
     465            case setOpener: case posixPropertyOpener: {
     466                if (lastItemKind != NoItem) {
     467                    if (cc->begin() != cc->end()) subexprs.push_back(cc);
     468                    RE * newOperand = makeAlt(subexprs.begin(), subexprs.end());
     469                    subexprs.clear();
     470                    cc = makeCC();
     471                    if (havePendingOperation) {
     472                        if (pendingOperationKind == intersectOp) {
     473                            pendingOperand = makeIntersect(pendingOperand, newOperand);
     474                        }
     475                        else {
     476                            pendingOperand = makeDiff(pendingOperand, newOperand);
     477                        }
     478                    }
     479                    else {
     480                        pendingOperand = newOperand;
     481                    }
     482                    subexprs.push_back(pendingOperand);
     483                    havePendingOperation = false;
     484                }
     485                if (op == setOpener) {
     486                    subexprs.push_back(parse_charset());
     487                    lastItemKind = SetItem;
     488                }
     489                else if (op == posixPropertyOpener) {
     490                    bool negated = false;
     491                    if (*_cursor == '^') {
     492                        negated = true;
     493                        _cursor++;
     494                    }
     495                    RE * posixSet = parse_property_expression();
     496                    if (negated) posixSet = makeComplement(posixSet);
     497                    subexprs.push_back(posixSet);
     498                    lastItemKind = BrackettedSetItem;
     499                    if (_cursor == _end || *_cursor++ != ':' || _cursor == _end || *_cursor++ != ']')
     500                        throw ParseFailure("Posix set expression improperly terminated.");
     501                }
     502            }
     503            break;
     504            case rangeHyphen:
     505                if (lastItemKind != CodepointItem) throw ParseFailure("Range operator - has illegal left operand.");
     506                cc->insert_range(lastCodepointItem, parse_codepoint());
     507                lastItemKind = RangeItem;
     508                break;
     509            case hyphenChar:
     510                cc->insert('-'); 
     511                lastItemKind = CodepointItem;
     512                lastCodepointItem = static_cast<unsigned> ('-');
     513                break;
     514            case ampChar:
     515                cc->insert('&');
     516                lastItemKind = CodepointItem;
     517                lastCodepointItem = static_cast<unsigned> ('&');
     518                break;
     519            case backSlash:
     520                throw_incomplete_expression_error_if_end_of_stream();
     521                if (isSetEscapeChar(*_cursor)) {
     522                    subexprs.push_back(parse_escaped_set());
     523                    lastItemKind = SetItem;
     524                }
     525                else {
     526                    lastCodepointItem = parse_escaped_codepoint();
     527                    cc->insert(lastCodepointItem);
     528                    lastItemKind = CodepointItem;
     529                }
     530                break;
     531            case emptyOperator:
     532                lastCodepointItem = parse_utf8_codepoint();
     533                cc->insert(lastCodepointItem);
     534                lastItemKind = CodepointItem;
     535                break;
     536        }
     537    }
     538    throw ParseFailure("Set expression not properly terminated.");
    539539}
    540540
     
    563563
    564564unsigned RE_Parser::parse_escaped_codepoint() {
    565         unsigned cp_value;
    566         throw_incomplete_expression_error_if_end_of_stream();
    567         switch (*_cursor) {
    568                 case 'a': ++_cursor; return 0x07; // BEL
    569                 case 'b': ++_cursor; return 0x08; // BS
    570                 case 'e': ++_cursor; return 0x1B; // ESC
    571                 case 'f': ++_cursor; return 0x0C; // FF
    572                 case 'n': ++_cursor; return 0x0A; // LF
    573                 case 'r': ++_cursor; return 0x0D; // CR
    574                 case 't': ++_cursor; return 0x09; // HT
    575                 case 'v': ++_cursor; return 0x0B; // VT
    576                 case 'c': // Control-escape based on next char
    577                         ++_cursor;
    578                         throw_incomplete_expression_error_if_end_of_stream();
    579                         // \c@, \cA, ... \c_, or \ca, ..., \cz
    580                         if (((*_cursor >= '@') && (*_cursor <= '_')) || ((*_cursor >= 'a') && (*_cursor <= 'z'))) {
    581                                 cp_value = static_cast<unsigned>(*_cursor & 0x1F);
    582                                 _cursor++;
    583                                 return cp_value;
    584                         }
    585                         else if (*_cursor++ == '?') return 0x7F;  // \c? ==> DEL
    586                         else throw("Illegal \\c escape sequence");
    587                 case '0': // Octal escape:  0 - 0377
    588                         ++_cursor;
    589                         return parse_octal_codepoint(0,3);
    590                 case 'o':
    591                         ++_cursor;
    592                         throw_incomplete_expression_error_if_end_of_stream();
    593                         if (*_cursor == '{') {
    594                                 ++_cursor;
    595                                 cp_value = parse_octal_codepoint(1, 7);
    596                                 if (_cursor == _end || *_cursor++ != '}') throw ParseFailure("Malformed octal escape sequence");
    597                                 return cp_value;
    598                         }
    599                         else {
    600                                 throw ParseFailure("Malformed octal escape sequence");
    601                         }
    602                 case 'x':
    603                         ++_cursor;
    604                         throw_incomplete_expression_error_if_end_of_stream();
    605                         if (*_cursor == '{') {
    606                           ++_cursor;
    607                           cp_value = parse_hex_codepoint(1, 6);
    608                           if (_cursor == _end || *_cursor++ != '}') throw ParseFailure("Malformed hex escape sequence");
    609                           return cp_value;
    610                         }
    611                         else {
    612                                 return parse_hex_codepoint(1,2);  // ICU compatibility
    613                         }
    614                 case 'u':
    615                         ++_cursor;
    616                         throw_incomplete_expression_error_if_end_of_stream();
    617                         if (*_cursor == '{') {
    618                                 ++_cursor;
    619                                 cp_value = parse_hex_codepoint(1, 6);
    620                                 if (_cursor == _end || *_cursor++ != '}') throw ParseFailure("Malformed hex escape sequence");
    621                                 return cp_value;
    622                         }
    623                         else {
    624                                 return parse_hex_codepoint(4,4);  // ICU compatibility
    625                         }
    626                 case 'U':
    627                         ++_cursor;
    628                         return parse_hex_codepoint(8,8);  // ICU compatibility
    629                 case 'N':
    630                         ++_cursor;
    631                         throw ParseFailure("\\N{...} character name syntax not yet supported.");
    632 
    633                 default:
    634                         // Escaped letters should be reserved for special functions.
    635                         if (((*_cursor >= 'A') && (*_cursor <= 'Z')) || ((*_cursor >= 'a') && (*_cursor <= 'z')))
    636                                 throw ParseFailure("Undefined or unsupported escape sequence");
    637                         else if ((*_cursor < 0x20) || (*_cursor >= 0x7F))
    638                                 throw ParseFailure("Illegal escape sequence");
    639                         else return static_cast<unsigned>(*_cursor++);
    640         }
     565    unsigned cp_value;
     566    throw_incomplete_expression_error_if_end_of_stream();
     567    switch (*_cursor) {
     568        case 'a': ++_cursor; return 0x07; // BEL
     569        case 'b': ++_cursor; return 0x08; // BS
     570        case 'e': ++_cursor; return 0x1B; // ESC
     571        case 'f': ++_cursor; return 0x0C; // FF
     572        case 'n': ++_cursor; return 0x0A; // LF
     573        case 'r': ++_cursor; return 0x0D; // CR
     574        case 't': ++_cursor; return 0x09; // HT
     575        case 'v': ++_cursor; return 0x0B; // VT
     576        case 'c': // Control-escape based on next char
     577            ++_cursor;
     578            throw_incomplete_expression_error_if_end_of_stream();
     579            // \c@, \cA, ... \c_, or \ca, ..., \cz
     580            if (((*_cursor >= '@') && (*_cursor <= '_')) || ((*_cursor >= 'a') && (*_cursor <= 'z'))) {
     581                cp_value = static_cast<unsigned>(*_cursor & 0x1F);
     582                _cursor++;
     583                return cp_value;
     584            }
     585            else if (*_cursor++ == '?') return 0x7F;  // \c? ==> DEL
     586            else throw("Illegal \\c escape sequence");
     587        case '0': // Octal escape:  0 - 0377
     588            ++_cursor;
     589            return parse_octal_codepoint(0,3);
     590        case 'o':
     591            ++_cursor;
     592            throw_incomplete_expression_error_if_end_of_stream();
     593            if (*_cursor == '{') {
     594                ++_cursor;
     595                cp_value = parse_octal_codepoint(1, 7);
     596                if (_cursor == _end || *_cursor++ != '}') throw ParseFailure("Malformed octal escape sequence");
     597                return cp_value;
     598            }
     599            else {
     600                throw ParseFailure("Malformed octal escape sequence");
     601            }
     602        case 'x':
     603            ++_cursor;
     604            throw_incomplete_expression_error_if_end_of_stream();
     605            if (*_cursor == '{') {
     606              ++_cursor;
     607              cp_value = parse_hex_codepoint(1, 6);
     608              if (_cursor == _end || *_cursor++ != '}') throw ParseFailure("Malformed hex escape sequence");
     609              return cp_value;
     610            }
     611            else {
     612                return parse_hex_codepoint(1,2);  // ICU compatibility
     613            }
     614        case 'u':
     615            ++_cursor;
     616            throw_incomplete_expression_error_if_end_of_stream();
     617            if (*_cursor == '{') {
     618                ++_cursor;
     619                cp_value = parse_hex_codepoint(1, 6);
     620                if (_cursor == _end || *_cursor++ != '}') throw ParseFailure("Malformed hex escape sequence");
     621                return cp_value;
     622            }
     623            else {
     624                return parse_hex_codepoint(4,4);  // ICU compatibility
     625            }
     626        case 'U':
     627            ++_cursor;
     628            return parse_hex_codepoint(8,8);  // ICU compatibility
     629        case 'N':
     630            ++_cursor;
     631            throw ParseFailure("\\N{...} character name syntax not yet supported.");
     632
     633        default:
     634            // Escaped letters should be reserved for special functions.
     635            if (((*_cursor >= 'A') && (*_cursor <= 'Z')) || ((*_cursor >= 'a') && (*_cursor <= 'z')))
     636                throw ParseFailure("Undefined or unsupported escape sequence");
     637            else if ((*_cursor < 0x20) || (*_cursor >= 0x7F))
     638                throw ParseFailure("Illegal escape sequence");
     639            else return static_cast<unsigned>(*_cursor++);
     640    }
    641641}
    642642
    643643
    644644unsigned RE_Parser::parse_octal_codepoint(int mindigits, int maxdigits) {
    645         unsigned value = 0;
    646         int count = 0;
    647         while (_cursor != _end && count < maxdigits) {
    648                 const char t = *_cursor;
    649                 if (t < '0' || t > '7') {
    650                         break;
    651                 }
    652                 value = value * 8 | (t - '0');
    653                 ++_cursor;
    654                 ++count;
    655         }
    656         if (count < mindigits) throw ParseFailure("Octal sequence has too few digits");
    657         if (value > CC::UNICODE_MAX) throw ParseFailure("Octal value too large");
    658         return value;
     645    unsigned value = 0;
     646    int count = 0;
     647    while (_cursor != _end && count < maxdigits) {
     648        const char t = *_cursor;
     649        if (t < '0' || t > '7') {
     650            break;
     651        }
     652        value = value * 8 | (t - '0');
     653        ++_cursor;
     654        ++count;
     655    }
     656    if (count < mindigits) throw ParseFailure("Octal sequence has too few digits");
     657    if (value > CC::UNICODE_MAX) throw ParseFailure("Octal value too large");
     658    return value;
    659659}
    660660
    661661unsigned RE_Parser::parse_hex_codepoint(int mindigits, int maxdigits) {
    662         unsigned value = 0;
    663         int count = 0;
    664         while (_cursor != _end && isxdigit(*_cursor) && count < maxdigits) {
    665                 const char t = *_cursor;
    666                 if (isdigit(t)) {
    667                         value = (value * 16) | (t - '0');
    668                 }
    669                 else { 
    670                         value = (value * 16) | ((t | 32) - 'a') + 10;
    671                 }
    672                 ++_cursor;
    673                 ++count;
    674         }
    675         if (count < mindigits) throw ParseFailure("Hexadecimal sequence has too few digits");
    676         if (value > CC::UNICODE_MAX) throw ParseFailure("Hexadecimal value too large");
    677         return value;
     662    unsigned value = 0;
     663    int count = 0;
     664    while (_cursor != _end && isxdigit(*_cursor) && count < maxdigits) {
     665        const char t = *_cursor;
     666        if (isdigit(t)) {
     667            value = (value * 16) | (t - '0');
     668        }
     669        else {   
     670            value = (value * 16) | ((t | 32) - 'a') + 10;
     671        }
     672        ++_cursor;
     673        ++count;
     674    }
     675    if (count < mindigits) throw ParseFailure("Hexadecimal sequence has too few digits");
     676    if (value > CC::UNICODE_MAX) throw ParseFailure("Hexadecimal value too large");
     677    return value;
    678678}
    679679
Note: See TracChangeset for help on using the changeset viewer.