Ignore:
Timestamp:
Feb 24, 2018, 9:33:57 AM (14 months ago)
Author:
cameron
Message:

Grapheme cluster support: represent B{g} using Seq{} - b{g}; parser cleanups

File:
1 edited

Legend:

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

    r5835 r5880  
    11/*
    2  *  Copyright (c) 2017 International Characters.
     2 *  Copyright (c) 2018 International Characters.
    33 *  This software is licensed to the public under the Open Software License 3.0.
    44 *  icgrep is a trademark of International Characters.
     
    350350   
    351351RE * RE_Parser::parseEscapedSet() {
    352     bool complemented = false;
     352    bool complemented = atany("BDSWQP");
     353    char escapeCh = get1();
     354    if (complemented) escapeCh = tolower(escapeCh);
    353355    RE * re = nullptr;
    354     switch (*mCursor) {
    355         case 'B': complemented = true;
     356    switch (escapeCh) {
    356357        case 'b':
    357             if (*++mCursor != '{') {
     358            if (accept('{')) {
     359                if (accept("g}")) {
     360                    re = makeZeroWidth("\\b{g}");
     361                    return complemented ? makeZerowidthComplement(re) : re;
     362                } else if (accept("w}")) {
     363                    ParseFailure("\\b{w} not yet supported.");
     364                    //return complemented ? makeZerowidthComplement(re) : re;
     365                } else if (accept("l}")) {
     366                    ParseFailure("\\b{l} not yet supported.");
     367                    //return complemented ? makeZerowidthComplement(re) : re;
     368                } else if (accept("s}")) {
     369                    ParseFailure("\\b{s} not yet supported.");
     370                    //return complemented ? makeZerowidthComplement(re) : re;
     371                } else {
     372                    re = parsePropertyExpression();
     373                    require('}');
     374                    return complemented ? makeReNonBoundary(re) : makeReBoundary(re);
     375                }
     376            } else {
    358377                return complemented ? makeWordNonBoundary() : makeWordBoundary();
    359             } else {
    360                 ++mCursor;
    361                 if (isCharAhead('}')) {
    362                     switch (*mCursor) {
    363                         case 'g':
    364                             re = complemented ? makeZeroWidth("\\B{g}") : makeZeroWidth("\\b{g}");
    365                             ++mCursor;
    366                             ++mCursor;
    367                             break;
    368                         case 'w': ParseFailure("\\b{w} not yet supported.");
    369                         case 'l': ParseFailure("\\b{l} not yet supported.");
    370                         case 's': ParseFailure("\\b{s} not yet supported.");
    371 //                        default: ParseFailure("Unrecognized boundary assertion");
    372                     }
    373                 }
    374                 if (!re) {
    375                     auto propExpr = parsePropertyExpression();
    376                     if (*mCursor++ != '}') {
    377                         ParseFailure("Malformed boundary assertion");
    378                     }
    379                     re = complemented ? makeReNonBoundary(propExpr) : makeReBoundary(propExpr);
    380                 }
    381                 return re;
    382378            }
    383379        case 'd':
    384             ++mCursor;
    385             return makeDigitSet();
    386         case 'D':
    387             ++mCursor;
    388             return makeComplement(makeDigitSet());
     380            re = makeDigitSet();
     381            return complemented ? makeComplement(re) : re;
    389382        case 's':
    390             ++mCursor;
    391             return makeWhitespaceSet();
    392         case 'S':
    393             ++mCursor;
    394             return makeComplement(makeWhitespaceSet());
     383            re = makeWhitespaceSet();
     384            return complemented ? makeComplement(re) : re;
    395385        case 'w':
    396             ++mCursor;
    397             return makeWordSet();
    398         case 'W':
    399             ++mCursor;
    400             return makeComplement(makeWordSet());
    401         case 'Q':
    402             complemented = true;
     386            re = makeWordSet();
     387            return complemented ? makeComplement(re) : re;
    403388        case 'q':
    404             if (*++mCursor != '{') {
    405                 ParseFailure("Malformed grapheme cluster expression");
    406             }
    407             ++mCursor;
     389            require('{');
    408390            ParseFailure("Literal grapheme cluster expressions not yet supported.");
    409             if (*mCursor != '}') {
    410                 ParseFailure("Malformed grapheme cluster expression");
    411             }
    412             ++mCursor;
     391            require('}');
    413392            return complemented ? makeComplement(re) : re;
    414         case 'P':
    415             complemented = true;
    416393        case 'p':
    417             if (*++mCursor != '{') {
    418                 ParseFailure("Malformed property expression");
    419             }
    420             ++mCursor;
     394            require('{');
    421395            re = parsePropertyExpression();
    422             if (*mCursor != '}') {
    423                 ParseFailure("Malformed property expression");
    424             }
    425             ++mCursor;
     396            require('}');
    426397            return complemented ? makeComplement(re) : re;
    427         case 'X':
     398        case 'X': {
    428399            // \X is equivalent to ".+?\b{g}"; proceed the minimal number of characters (but at least one)
    429400            // to get to the next extended grapheme cluster boundary.
    430             ++mCursor;
    431             return makeSeq({makeAny(), makeRep(makeSeq({makeZeroWidth("\\B{g}"), makeAny()}), 0, Rep::UNBOUNDED_REP), makeZeroWidth("\\b{g}")});
     401            RE * GCB = makeZeroWidth("\\b{g}");
     402            return makeSeq({makeAny(), makeRep(makeSeq({makeZerowidthComplement(GCB), makeAny()}), 0, Rep::UNBOUNDED_REP), GCB});
     403        }
    432404        case 'N':
    433             ++mCursor;
    434405            re = parseNamePatternExpression();
    435406            assert (re);
    436407            return re;
    437408        case '<':
    438             ++mCursor;
    439409            return makeWordBegin();
    440410        case '>':
    441             ++mCursor;
    442411            return makeWordEnd();
    443412        default:
     
    507476    }
    508477    return s.str();
    509 }
    510 
    511 bool RE_Parser::isCharAhead(char c) {
    512     if (mCursor.remaining() < 2) {
    513         return false;
    514     }
    515     auto nextCursor = mCursor.pos() + 1;
    516     return *nextCursor == c;
    517478}
    518479
     
    811772}
    812773
     774RE * RE_Parser::makeZerowidthComplement(RE * s) {
     775    return makeDiff(makeSeq({}), s);
     776}
     777
    813778RE * RE_Parser::makeWordBoundary() {
    814779    Name * wordC = makeWordSet();
Note: See TracChangeset for help on using the changeset viewer.