Ignore:
Timestamp:
Nov 23, 2014, 9:49:55 AM (5 years ago)
Author:
cameron
Message:

Parsing support for lookahead/behind assertions, mode flags

File:
1 edited

Legend:

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

    r4310 r4311  
    3030RE * RE_Parser::parse(const std::string & regular_expression) {
    3131    RE_Parser parser(regular_expression);
    32     RE * re = parser.parse_alt(false);
     32    RE * re = parser.parse_alt();
    3333    if (re == nullptr) {
    3434        throw ParseFailure("An unexpected parsing error occurred!");
     
    4444}
    4545
    46 RE * RE_Parser::parse_alt(const bool subexpression) {
     46RE * makeLookAheadAssertion(RE * r) {
     47    throw ParseFailure("Lookahead assertion not supported.");
     48}
     49
     50RE * makeNegativeLookAheadAssertion(RE * r) {
     51    throw ParseFailure("Lookahead assertion not supported.");
     52}
     53
     54RE * makeLookBehindAssertion(RE * r) {
     55    throw ParseFailure("Lookbehind assertion not supported.");
     56}
     57
     58RE * makeNegativeLookBehindAssertion(RE * r) {
     59    throw ParseFailure("Lookbehind assertion not supported.");
     60}
     61
     62RE * makeAtomicGroup(RE * r) {
     63    throw ParseFailure("Atomic grouping not supported.");
     64}
     65
     66RE * makeBranchResetGroup(RE * r) {
     67    // Branch reset groups only affect submatch numbering, but
     68    // this has no effect in icgrep.
     69    return r;
     70}
     71   
     72RE * RE_Parser::parse_RE() {
     73    RE * r = parse_alt();
     74    if (_cursor != _end) {
     75        throw ParseFailure("Unrecognized junk remaining at end of regexp");
     76    }
     77    return r;
     78}
     79
     80RE * RE_Parser::parse_alt() {
    4781    std::vector<RE *> alt;
    4882    for (;;) {
     
    5791        throw NoRegularExpressionFound();
    5892    }
    59     else if (subexpression) {
    60         if (_cursor == _end || *_cursor != ')') {
    61             throw ParseFailure("Parenthesization error!");
    62         }
    63         ++_cursor;
    64     }
    65     else if (_cursor != _end) { // !subexpression
    66         throw ParseFailure("Cannot fully parse statement!");
    67     }
    6893    return makeAlt(alt.begin(), alt.end());
    6994}
     
    7297    std::vector<RE *> seq;
    7398    for (;;) {
    74         RE * re = parse_next_token();
     99        RE * re = parse_next_item();
    75100        if (re == nullptr) {
    76101            break;
     
    85110}
    86111
    87 RE * RE_Parser::parse_next_token() {
     112RE * RE_Parser::parse_next_item() {
    88113    RE * re = nullptr;
    89114    if (_cursor != _end) {
     
    91116            case '(':
    92117                ++_cursor;
    93                 return parse_alt(true);
     118                return parse_group();
    94119            case '^':
    95120                ++_cursor;
     
    104129            case ']': case '}':
    105130                if (LEGACY_UNESCAPED_RBRAK_RBRACE_ALLOWED) {
    106                     return parse_literal();
     131                    return makeCC(parse_utf8_codepoint());
    107132                }
    108133                else throw ParseFailure("Use  \\] or \\} for literal ] or }.");
    109134            case '[':
    110                 *_cursor++;
     135                _cursor++;
    111136                return parse_charset();
    112137            case '.': // the 'any' metacharacter
    113                 return parse_any_character();
     138                _cursor++;
     139                return makeAny();
    114140            case '\\':  // escape processing
    115141                ++_cursor;
    116142                return parse_escaped();
    117143            default:
    118                 return parse_literal();
     144                return makeCC(parse_utf8_codepoint());
    119145        }
    120146    }
    121147    return re;
    122148}
    123 
    124 Any * RE_Parser::parse_any_character() {
    125     ++_cursor;
    126     return makeAny();
    127 }
    128 
     149   
     150   
     151// Parse some kind of parenthesized group.  Input precondition: _cursor
     152// after the (
     153RE * RE_Parser::parse_group() {
     154    RE * subexpr;
     155    RE * group_expr;
     156    throw_incomplete_expression_error_if_end_of_stream();
     157    if (*_cursor == '?') {
     158        ++_cursor;
     159        throw_incomplete_expression_error_if_end_of_stream();
     160        switch (*_cursor) {
     161            case '#':  // comment
     162                ++_cursor;
     163                while (_cursor != _end && *_cursor != ')') {
     164                    ++_cursor;
     165                }
     166                throw_incomplete_expression_error_if_end_of_stream();
     167                ++_cursor;
     168                return parse_next_item();
     169            case ':':  // Non-capturing paren
     170                ++_cursor;
     171                group_expr = parse_alt();
     172                break;
     173            case '=':
     174                ++_cursor;
     175                subexpr = parse_alt();
     176                group_expr = makeLookAheadAssertion(subexpr);
     177                break;
     178            case '!':
     179                ++_cursor;
     180                subexpr = parse_alt();
     181                group_expr = makeNegativeLookAheadAssertion(subexpr);
     182                break;
     183            case '>':
     184                ++_cursor;
     185                subexpr = parse_alt();
     186                group_expr = makeAtomicGroup(subexpr);
     187                break;
     188            case '|':
     189                ++_cursor;
     190                subexpr = parse_alt();
     191                group_expr = makeBranchResetGroup(subexpr);
     192                break;
     193            case '<':
     194                ++_cursor;
     195                throw_incomplete_expression_error_if_end_of_stream();
     196                if (*_cursor == '=') {
     197                    subexpr = parse_alt();
     198                    group_expr = makeLookBehindAssertion(subexpr);
     199                }
     200                else if (*_cursor == '!') {
     201                    subexpr = parse_alt();
     202                    group_expr = makeNegativeLookBehindAssertion(subexpr);
     203                }
     204                else {
     205                    throw ParseFailure("Illegal lookbehind assertion syntax.");
     206                }
     207                break;
     208            case '-': case 'd' : case 'i': case 'm': case 's': case 'x': {
     209                bool negateMode = false;
     210                unsigned modeBit;
     211                unsigned newModeFlags;
     212                while (_cursor != _end && *_cursor != ')' && *_cursor != ':') {
     213                    if (*_cursor == '-') {
     214                        negateMode = true;
     215                        _cursor++;
     216                        throw_incomplete_expression_error_if_end_of_stream();
     217                    }
     218                    switch (*_cursor++) {
     219                        case 'i': modeBit = CASE_INSENSITIVE_MODE_FLAG; break;
     220                        case 'm': modeBit = MULTILINE_MODE_FLAG; break;
     221                        case 's': modeBit = DOTALL_MODE_FLAG; break;
     222                        case 'x': modeBit = IGNORE_SPACE_MODE_FLAG; break;
     223                        case 'd': modeBit = UNIX_LINES_MODE_FLAG; break;
     224                        default: throw ParseFailure("Unrecognized mode flag.");
     225                    }
     226                    if (negateMode) {
     227                        newModeFlags &= ~modeBit;
     228                        negateMode = false;  // for next flag
     229                    }
     230                    else newModeFlags |= modeBit;
     231                }
     232                throw_incomplete_expression_error_if_end_of_stream();
     233                std::cerr << "newModeFlags " << newModeFlags << " ignored.\n";
     234                if (*_cursor == ':') {
     235                    ++_cursor;
     236                    group_expr = parse_alt();
     237                }
     238                else {  // if *_cursor == ')'
     239                    ++_cursor;
     240                    return parse_next_item();
     241                }
     242                break;
     243            }
     244            default:
     245                throw ParseFailure("Illegal (? syntax.");
     246        }
     247    }
     248    else {
     249        // Capturing paren group, but ignore capture in icgrep.
     250        group_expr = parse_alt();
     251    }
     252    if (_cursor == _end || *_cursor++ != ')')
     253        throw ParseFailure("Closing paren required.");
     254    return group_expr;
     255}
     256   
    129257RE * RE_Parser::extend_item(RE * re) {
    130258    int lower_bound, upper_bound;
     
    216344}
    217345
    218 inline RE * RE_Parser::parse_literal() {
    219     return makeCC(parse_utf8_codepoint());
    220 }
    221346
    222347#define bit40(x) (1ULL << ((x) - 0x40))
     
    289414}
    290415
    291 unsigned RE_Parser::parse_utf8_codepoint() {
    292     unsigned c = static_cast<unsigned>(*_cursor++);
     416codepoint_t RE_Parser::parse_utf8_codepoint() {
     417    codepoint_t c = static_cast<codepoint_t>(*_cursor++);
    293418    if (c > 0x80) { // if non-ascii
    294419        if (c < 0xC2) {
     
    313438                    throw InvalidUTF8Encoding();
    314439                }
    315                 c = (c << 6) | static_cast<unsigned>(*_cursor & 0x3F);
     440                c = (c << 6) | static_cast<codepoint_t>(*_cursor & 0x3F);
    316441                // It is an error if a 3-byte sequence is used to encode a codepoint < 0x800
    317442                // or a 4-byte sequence is used to encode a codepoint < 0x10000.
     
    395520    // a following hyphen can indicate set subtraction.
    396521    enum {NoItem, CodepointItem, RangeItem, SetItem, BrackettedSetItem} lastItemKind = NoItem;
    397     unsigned lastCodepointItem;
     522    codepoint_t lastCodepointItem;
    398523   
    399524    bool havePendingOperation = false;
     
    413538        cc->insert(']');
    414539        lastItemKind = CodepointItem;
    415         lastCodepointItem = static_cast<unsigned> (']');
     540        lastCodepointItem = static_cast<codepoint_t> (']');
    416541        ++_cursor;
    417542    }
     
    420545        cc->insert('-');
    421546        lastItemKind = CodepointItem;
    422         lastCodepointItem = static_cast<unsigned> ('-');
     547        lastCodepointItem = static_cast<codepoint_t> ('-');
    423548                if (*_cursor == '-') throw ParseFailure("Set operator has no left operand.");
    424549    }
     
    510635                cc->insert('-'); 
    511636                lastItemKind = CodepointItem;
    512                 lastCodepointItem = static_cast<unsigned> ('-');
     637                lastCodepointItem = static_cast<codepoint_t> ('-');
    513638                break;
    514639            case ampChar:
    515640                cc->insert('&');
    516641                lastItemKind = CodepointItem;
    517                 lastCodepointItem = static_cast<unsigned> ('&');
     642                lastCodepointItem = static_cast<codepoint_t> ('&');
    518643                break;
    519644            case backSlash:
     
    540665
    541666
    542 unsigned RE_Parser::parse_codepoint() {
     667codepoint_t RE_Parser::parse_codepoint() {
    543668    if (_cursor != _end && *_cursor == '\\') {
    544669        _cursor++;
     
    562687// 7. An escaped ASCII symbol, standing for itself
    563688
    564 unsigned RE_Parser::parse_escaped_codepoint() {
    565     unsigned cp_value;
     689codepoint_t RE_Parser::parse_escaped_codepoint() {
     690    codepoint_t cp_value;
    566691    throw_incomplete_expression_error_if_end_of_stream();
    567692    switch (*_cursor) {
     
    579704            // \c@, \cA, ... \c_, or \ca, ..., \cz
    580705            if (((*_cursor >= '@') && (*_cursor <= '_')) || ((*_cursor >= 'a') && (*_cursor <= 'z'))) {
    581                 cp_value = static_cast<unsigned>(*_cursor & 0x1F);
     706                cp_value = static_cast<codepoint_t>(*_cursor & 0x1F);
    582707                _cursor++;
    583708                return cp_value;
     
    637762            else if ((*_cursor < 0x20) || (*_cursor >= 0x7F))
    638763                throw ParseFailure("Illegal escape sequence");
    639             else return static_cast<unsigned>(*_cursor++);
    640     }
    641 }
    642 
    643 
    644 unsigned RE_Parser::parse_octal_codepoint(int mindigits, int maxdigits) {
    645     unsigned value = 0;
     764            else return static_cast<codepoint_t>(*_cursor++);
     765    }
     766}
     767
     768
     769codepoint_t RE_Parser::parse_octal_codepoint(int mindigits, int maxdigits) {
     770    codepoint_t value = 0;
    646771    int count = 0;
    647772    while (_cursor != _end && count < maxdigits) {
     
    659784}
    660785
    661 unsigned RE_Parser::parse_hex_codepoint(int mindigits, int maxdigits) {
    662     unsigned value = 0;
     786codepoint_t RE_Parser::parse_hex_codepoint(int mindigits, int maxdigits) {
     787    codepoint_t value = 0;
    663788    int count = 0;
    664789    while (_cursor != _end && isxdigit(*_cursor) && count < maxdigits) {
Note: See TracChangeset for help on using the changeset viewer.