]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/regexcmp.cpp
ICU-8.11.tar.gz
[apple/icu.git] / icuSources / i18n / regexcmp.cpp
index f126adb449f21b437e1aff19eef376a93602c0ea..5d71d29ffbd6ee0e794813b298ead253fbc12379 100644 (file)
@@ -2,7 +2,7 @@
 //
 //  file:  regexcmp.cpp
 //
-//  Copyright (C) 2002-2004 International Business Machines Corporation and others.
+//  Copyright (C) 2002-2006 International Business Machines Corporation and others.
 //  All Rights Reserved.
 //
 //  This file contains the ICU regular expression compiler, which is responsible
@@ -43,11 +43,11 @@ U_NAMESPACE_BEGIN
 
 
 
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //  Constructor.
 //
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 RegexCompile::RegexCompile(RegexPattern *rxp, UErrorCode &status) : fParenStack(status)
 {
     fStatus           = &status;
@@ -60,7 +60,7 @@ RegexCompile::RegexCompile(RegexPattern *rxp, UErrorCode &status) : fParenStack(
     fCharNum          = 0;
     fQuoteMode        = FALSE;
     fInBackslashQuote = FALSE;
-    fModeFlags        = fRXPat->fFlags;
+    fModeFlags        = fRXPat->fFlags | 0x80000000;
     fEOLComments      = TRUE;
 
     fMatchOpenParen   = -1;
@@ -74,22 +74,22 @@ RegexCompile::RegexCompile(RegexPattern *rxp, UErrorCode &status) : fParenStack(
 
 
 
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //  Destructor
 //
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 RegexCompile::~RegexCompile() {
 }
 
-//---------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //  Compile regex pattern.   The state machine for rexexp pattern parsing is here.
 //                           The state tables are hand-written in the file regexcst.txt,
 //                           and converted to the form used here by a perl
 //                           script regexcst.pl
 //
-//---------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 void    RegexCompile::compile(
                          const UnicodeString &pat,   // Source pat to be compiled.
                          UParseError &pp,            // Error position info
@@ -311,7 +311,7 @@ void    RegexCompile::compile(
 
 
 
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //  doParseAction        Do some action during regex pattern parsing.
 //                       Called by the parse state machine.
@@ -320,7 +320,7 @@ void    RegexCompile::compile(
 //                       in functions called from the parse actions defined here.
 //
 //
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 UBool RegexCompile::doParseActions(EParseAction action)
 {
     UBool   returnVal = TRUE;
@@ -339,11 +339,10 @@ UBool RegexCompile::doParseActions(EParseAction action)
         fRXPat->fCompiledPat->addElement(URX_BUILD(URX_STATE_SAVE, 2), *fStatus);
         fRXPat->fCompiledPat->addElement(URX_BUILD(URX_JMP,  3), *fStatus);
         fRXPat->fCompiledPat->addElement(URX_BUILD(URX_FAIL, 0), *fStatus);
-        fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP,  0), *fStatus);
-        fRXPat->fCompiledPat->addElement(URX_BUILD(URX_NOP,  0), *fStatus);
 
-        fParenStack.push(-1, *fStatus);     // Begin a Paren Stack Frame
-        fParenStack.push( 3, *fStatus);     // Push location of first NOP
+        // Standard open nonCapture paren action emits the two NOPs and
+        //   sets up the paren stack frame.
+        doParseActions((EParseAction)doOpenNonCaptureParen);
         break;
 
     case doPatFinish:
@@ -1333,6 +1332,7 @@ UBool RegexCompile::doParseActions(EParseAction action)
     case doSetMatchMode:
         // We've got a (?i) or similar.  The match mode is being changed, but
         //   the change is not scoped to a parenthesized block.
+        U_ASSERT(fNewModeFlags < 0);
         fModeFlags = fNewModeFlags;
 
         // Prevent any string from spanning across the change of match mode.
@@ -1363,6 +1363,7 @@ UBool RegexCompile::doParseActions(EParseAction action)
             fParenStack.push(fRXPat->fCompiledPat->size()-1, *fStatus);   // The second NOP
 
             // Set the current mode flags to the new values.
+            U_ASSERT(fNewModeFlags < 0);
             fModeFlags = fNewModeFlags;
         }
         break;
@@ -1391,7 +1392,7 @@ UBool RegexCompile::doParseActions(EParseAction action)
     }
 
     return returnVal;
-};
+}
 
 
 
@@ -1620,6 +1621,7 @@ void   RegexCompile::insertOp(int32_t where) {
     //  the compiled pattern.   (Negative values are frame boundaries, and don't need fixing.)
     for (loc=0; loc<fParenStack.size(); loc++) {
         int32_t x = fParenStack.elementAti(loc);
+        U_ASSERT(x < code->size());
         if (x>where) {
             x++;
             fParenStack.setElementAt(x, loc);
@@ -1691,7 +1693,7 @@ int32_t   RegexCompile::blockTopLoc(UBool reserveLoc) {
 //                          This function is called both when encountering a
 //                          real ) and at the end of the pattern.
 //
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 void  RegexCompile::handleCloseParen() {
     int32_t   patIdx;
     int32_t   patOp;
@@ -1726,6 +1728,7 @@ void  RegexCompile::handleCloseParen() {
     //  the value they had at the open paren.  Saved value is
     //  at the top of the paren stack.  
     fModeFlags = fParenStack.popi();
+    U_ASSERT(fModeFlags < 0);
     
     // DO any additional fixups, depending on the specific kind of
     // parentesized grouping this is
@@ -1877,12 +1880,12 @@ void  RegexCompile::handleCloseParen() {
 
 
 
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //   compileSet       Compile the pattern operations for a reference to a
 //                    UnicodeSet.
 //
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 void        RegexCompile::compileSet(UnicodeSet *theSet)
 {
     if (theSet == NULL) {
@@ -1929,7 +1932,7 @@ void        RegexCompile::compileSet(UnicodeSet *theSet)
 }
 
 
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //   compileInterval    Generate the code for a {min, max} style interval quantifier.
 //                      Except for the specific opcodes used, the code is the same
@@ -1945,7 +1948,7 @@ void        RegexCompile::compileSet(UnicodeSet *theSet)
 //                         5  CTR_LOOP   
 //    
 //                       In                                 
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 void        RegexCompile::compileInterval(int32_t InitOp,  int32_t LoopOp)
 {
     // The CTR_INIT op at the top of the block with the {n,m} quantifier takes
@@ -2049,7 +2052,7 @@ UBool RegexCompile::compileInlineInterval() {
 
 
 
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //   matchStartType    Determine how a match can start.
 //                     Used to optimize find() operations.
@@ -2059,7 +2062,7 @@ UBool RegexCompile::compileInlineInterval() {
 //                     op where the min match coming in is zero, add that ops possible
 //                     starting matches to the possible starts for the overall pattern.
 //
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 void   RegexCompile::matchStartType() {
     if (U_FAILURE(*fStatus)) {
         return;
@@ -2240,7 +2243,7 @@ void   RegexCompile::matchStartType() {
                     // character may have distinct cased forms.  Add all of them
                     //   to the set of possible starting match chars.
                     UnicodeSet s(c, c);
-                    s.closeOver(USET_CASE);
+                    s.closeOver(USET_CASE_INSENSITIVE);
                     fRXPat->fInitialChars->addAll(s);
                 } else {
                     // Char has no case variants.  Just add it as-is to the
@@ -2366,7 +2369,7 @@ void   RegexCompile::matchStartType() {
                     int32_t stringStartIdx = URX_VAL(op);
                     UChar32  c = fRXPat->fLiteralText.char32At(stringStartIdx);
                     UnicodeSet s(c, c);
-                    s.closeOver(USET_CASE);
+                    s.closeOver(USET_CASE_INSENSITIVE);
                     fRXPat->fInitialChars->addAll(s);
                     numInitialStrings += 2;  // Matching on an initial string not possible.
                 }
@@ -2519,7 +2522,7 @@ void   RegexCompile::matchStartType() {
 
 
 
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //   minMatchLength    Calculate the length of the shortest string that could
 //                     match the specified pattern.   
@@ -2532,7 +2535,7 @@ void   RegexCompile::matchStartType() {
 //                     start and end are the range of p-code operations to be
 //                     examined.  The endpoints are included in the range.
 //
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 int32_t   RegexCompile::minMatchLength(int32_t start, int32_t end) {
     if (U_FAILURE(*fStatus)) {
         return 0;
@@ -2771,7 +2774,7 @@ int32_t   RegexCompile::minMatchLength(int32_t start, int32_t end) {
 
 
 
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //   maxMatchLength    Calculate the length of the longest string that could
 //                     match the specified pattern.   
@@ -2781,7 +2784,7 @@ int32_t   RegexCompile::minMatchLength(int32_t start, int32_t end) {
 //                     value may be longer than the actual maximum; it must
 //                     never be shorter.
 //
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 int32_t   RegexCompile::maxMatchLength(int32_t start, int32_t end) {
     if (U_FAILURE(*fStatus)) {
         return 0;
@@ -2958,8 +2961,8 @@ int32_t   RegexCompile::maxMatchLength(int32_t start, int32_t end) {
             
             // End of look-ahead ops should always be consumed by the processing at
             //  the URX_LA_START op.
-            U_ASSERT(FALSE);
-            break;
+            // U_ASSERT(FALSE);
+            // break;
             
         case URX_LB_START:
             {
@@ -3000,14 +3003,14 @@ int32_t   RegexCompile::maxMatchLength(int32_t start, int32_t end) {
 }
 
 
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //   stripNOPs    Remove any NOP operations from the compiled pattern code.
 //                Extra NOPs are inserted for some constructs during the initial
 //                code generation to provide locations that may be patched later.
 //                Many end up unneeded, and are removed by this function.
 //
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 void RegexCompile::stripNOPs() {
 
     if (U_FAILURE(*fStatus)) {
@@ -3125,7 +3128,7 @@ void RegexCompile::stripNOPs() {
 
 
 
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //   OptDotStar       Optimize patterns that end with a '.*' or '.+' to
 //                    just advance the input to the end.
@@ -3142,7 +3145,7 @@ void RegexCompile::stripNOPs() {
 //            [NOP | END_CAPTURE | DOLLAR | BACKSLASH_Z]*
 //            END
 //
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 void RegexCompile::OptDotStar() {
     // Scan backwards in the pattern, looking for a JMP_SAV near the end.
     int32_t  jmpLoc;
@@ -3202,12 +3205,12 @@ void RegexCompile::OptDotStar() {
 }
 
 
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //  Error         Report a rule parse error.
 //                Only report it if no previous error has been recorded.
 //
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 void RegexCompile::error(UErrorCode e) {
     if (U_SUCCESS(*fStatus)) {
         *fStatus = e;
@@ -3235,27 +3238,24 @@ static const UChar      chCR        = 0x0d;      // New lines, for terminating c
 static const UChar      chLF        = 0x0a;
 static const UChar      chNEL       = 0x85;      //    NEL newline variant
 static const UChar      chLS        = 0x2028;    //    Unicode Line Separator
-static const UChar      chApos      = 0x27;      //  single quote, for quoted chars.
 static const UChar      chPound     = 0x23;      // '#', introduces a comment.
 static const UChar      chE         = 0x45;      // 'E'
+static const UChar      chUpperN    = 0x4E;
+static const UChar      chLowerP    = 0x70;
+static const UChar      chUpperP    = 0x50;
 static const UChar      chBackSlash = 0x5c;      // '\'  introduces a char escape
-static const UChar      chLParen    = 0x28;
-static const UChar      chRParen    = 0x29;
 static const UChar      chLBracket  = 0x5b;
 static const UChar      chRBracket  = 0x5d;
 static const UChar      chRBrace    = 0x7d;
-static const UChar      chUpperN    = 0x4E;
-static const UChar      chLowerP    = 0x70;
-static const UChar      chUpperP    = 0x50;
 
 
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //  nextCharLL    Low Level Next Char from the regex pattern.
 //                Get a char from the string, keep track of input position
 //                     for error reporting.
 //
-//----------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 UChar32  RegexCompile::nextCharLL() {
     UChar32       ch;
     UnicodeString &pattern = fRXPat->fPattern;
@@ -3295,12 +3295,12 @@ UChar32  RegexCompile::nextCharLL() {
     return ch;
 }
 
-//---------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //   peekCharLL    Low Level Character Scanning, sneak a peek at the next
 //                 character without actually getting it.
 //
-//---------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 UChar32  RegexCompile::peekCharLL() {
     if (fPeekChar == -1) {
         fPeekChar = nextCharLL();
@@ -3309,13 +3309,13 @@ UChar32  RegexCompile::peekCharLL() {
 }
 
 
-//---------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //   nextChar     for pattern scanning.  At this level, we handle stripping
 //                out comments and processing some backslash character escapes.
 //                The rest of the pattern grammar is handled at the next level up.
 //
-//---------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 void RegexCompile::nextChar(RegexPatternChar &c) {
 
     fScanIndex = fNextIndex;
@@ -3411,7 +3411,7 @@ void RegexCompile::nextChar(RegexPatternChar &c) {
 
 
 
-//---------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //  scanSet    Construct a UnicodeSet from the text at the current scan
 //             position.  Advance the scan position to the first character
@@ -3421,11 +3421,10 @@ void RegexCompile::nextChar(RegexPatternChar &c) {
 //             that controls pattern parsing.  UnicodeSets, however, are parsed by
 //             the UnicodeSet constructor, not by the Regex pattern parser.
 //
-//---------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 UnicodeSet *RegexCompile::scanSet() {
     UnicodeSet    *uset = NULL;
     ParsePosition  pos;
-    int            startPos;
     int            i;
 
     if (U_FAILURE(*fStatus)) {
@@ -3433,7 +3432,6 @@ UnicodeSet *RegexCompile::scanSet() {
     }
 
     pos.setIndex(fScanIndex);
-    startPos = fScanIndex;
     UErrorCode localStatus = U_ZERO_ERROR;
     uint32_t   usetFlags = 0;
     if (fModeFlags & UREGEX_CASE_INSENSITIVE) {
@@ -3466,10 +3464,10 @@ UnicodeSet *RegexCompile::scanSet() {
     }
 
     return uset;
-};
+}
 
 
-//---------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //  scanProp   Construct a UnicodeSet from the text at the current scan
 //             position, which will be of the form \p{whaterver}
@@ -3480,7 +3478,7 @@ UnicodeSet *RegexCompile::scanSet() {
 //             Return a UnicodeSet, constructed from the \P pattern,
 //             or NULL if the pattern is invalid.
 //
-//---------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 UnicodeSet *RegexCompile::scanProp() {
     UnicodeSet    *uset = NULL;
 
@@ -3525,7 +3523,8 @@ UnicodeSet *RegexCompile::scanProp() {
 
     nextChar(fC);      // Continue overall regex pattern processing with char after the '}'
     return uset;
-};
+}
 
 U_NAMESPACE_END
 #endif  // !UCONFIG_NO_REGULAR_EXPRESSIONS
+