RegxParser.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:37k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 2001 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 2001, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Log: RegxParser.cpp,v $
  58.  * Revision 1.10  2001/11/20 20:48:10  knoaman
  59.  * Fix for invalid repeating quantifier check.
  60.  *
  61.  * Revision 1.9  2001/11/16 15:56:37  knoaman
  62.  * Add check for invalid repeating quantifier.
  63.  *
  64.  * Revision 1.8  2001/09/20 13:11:42  knoaman
  65.  * Regx  + misc. fixes
  66.  *
  67.  * Revision 1.7  2001/08/31 16:53:41  knoaman
  68.  * Misc. fixes.
  69.  *
  70.  * Revision 1.6  2001/07/26 12:46:48  knoaman
  71.  * Fix for bug 2815.
  72.  *
  73.  * Revision 1.5  2001/06/06 13:49:27  jberry
  74.  * Fix two improper NULL tests
  75.  *
  76.  * Revision 1.4  2001/05/11 21:51:01  knoaman
  77.  * Schema updates and fixes.
  78.  *
  79.  * Revision 1.3  2001/05/11 13:26:48  tng
  80.  * Copyright update.
  81.  *
  82.  * Revision 1.2  2001/05/03 18:17:45  knoaman
  83.  * Some design changes:
  84.  * o Changed the TokenFactory from a single static instance, to a
  85.  *    normal class. Each RegularExpression object will have its own
  86.  *    instance of TokenFactory, and that instance will be passed to
  87.  *    other classes that need to use a TokenFactory to create Token
  88.  *    objects (with the exception of RangeTokenMap).
  89.  * o Added a new class RangeTokenMap to map a the different ranges
  90.  *    in a given category to a specific RangeFactory object. In the old
  91.  *    design RangeFactory had dual functionality (act as a Map, and as
  92.  *    a factory for creating RangeToken(s)). The RangeTokenMap will
  93.  *    have its own copy of the TokenFactory. There will be only one
  94.  *    instance of the RangeTokenMap class, and that instance will be
  95.  *    lazily deleted when XPlatformUtils::Terminate is called.
  96.  *
  97.  * Revision 1.1  2001/03/02 19:22:54  knoaman
  98.  * Schema: Regular expression handling part I
  99.  *
  100.  */
  101. // ---------------------------------------------------------------------------
  102. //  Includes
  103. // ---------------------------------------------------------------------------
  104. #include <util/regx/RegxParser.hpp>
  105. #include <util/PlatformUtils.hpp>
  106. #include <util/XMLString.hpp>
  107. #include <util/regx/RegularExpression.hpp>
  108. #include <util/regx/RegxUtil.hpp>
  109. #include <util/regx/RegxDefs.hpp>
  110. #include <util/regx/TokenInc.hpp>
  111. #include <framework/XMLErrorCodes.hpp>
  112. #include <util/ParseException.hpp>
  113. // ---------------------------------------------------------------------------
  114. //  Static member data initialization
  115. // ---------------------------------------------------------------------------
  116. const unsigned short RegxParser::S_NORMAL = 0;
  117. const unsigned short RegxParser::S_INBRACKETS = 1;
  118. const unsigned short RegxParser::S_INXBRACKETS = 2;
  119. // ---------------------------------------------------------------------------
  120. //  RegxParser::ReferencePostion: Constructors and Destructor
  121. // ---------------------------------------------------------------------------
  122. RegxParser::ReferencePosition::ReferencePosition(const int refNo,
  123.  const int position)
  124. :fReferenceNo(refNo)
  125. , fPosition(position)
  126. {
  127. }
  128. // ---------------------------------------------------------------------------
  129. //  RegxParser: Constructors and Destructors
  130. // ---------------------------------------------------------------------------
  131. RegxParser::RegxParser()
  132.     :fHasBackReferences(false),
  133.      fOptions(0),
  134.      fOffset(0),
  135.      fNoGroups(1),
  136.      fParseContext(S_NORMAL),
  137.      fStringLen(0),
  138.      fState(0),
  139.      fCharData(0),
  140.      fString(0),
  141.      fReferences(0),
  142.      fTokenFactory(0)
  143. {
  144. }
  145. RegxParser::~RegxParser() {
  146. delete [] fString;
  147. delete fReferences;
  148. }
  149. // ---------------------------------------------------------------------------
  150. //  RegxParser: Parsing methods
  151. // ---------------------------------------------------------------------------
  152. Token* RegxParser::parse(const XMLCh* const regxStr, const int options) {
  153.     // if TokenFactory is not set do nothing.
  154.     // REVISIT - should we throw an exception
  155.     if (fTokenFactory == 0) {
  156.         return 0;
  157.     }
  158. XMLMutexLock lockInit(&fMutex);
  159. fOptions = options;
  160. fOffset = 0;
  161. fNoGroups = 1;
  162. fHasBackReferences = false;
  163. setParseContext(S_NORMAL);
  164. delete [] fString;
  165. fString = XMLString::replicate(regxStr);
  166. if (isSet(RegularExpression::EXTENDED_COMMENT)) {
  167.         delete [] fString;
  168. fString = RegxUtil::stripExtendedComment(regxStr);
  169.     }
  170.     fStringLen = XMLString::stringLen(fString);
  171.     processNext();
  172.     Token* retTok = parseRegx();
  173. if (fOffset != fStringLen) {
  174.         ThrowXML(ParseException,XMLExcepts::Parser_Parse1);
  175.     }
  176.     if (fReferences != 0) {
  177. unsigned int refSize = fReferences->size();
  178.         for (unsigned int i = 0; i < refSize; i++) {
  179. if (fNoGroups <= fReferences->elementAt(i)->fReferenceNo) {
  180.                 ThrowXML(ParseException,XMLExcepts::Parser_Parse2);
  181.             }
  182.         }
  183. fReferences->removeAllElements();
  184.     }
  185.     return retTok;
  186. }
  187. void RegxParser::processNext() {
  188.     if (fOffset >= fStringLen) {
  189.         fCharData = -1;
  190.         fState = T_EOF;
  191.         return;
  192. }
  193.     unsigned short nextState;
  194. XMLCh ch = fString[fOffset++];
  195. fCharData = ch;
  196.     if (fParseContext == S_INBRACKETS) {
  197. switch (ch) {
  198.         case chBackSlash:
  199.             nextState = T_BACKSOLIDUS;
  200. if (fOffset >= fStringLen) {
  201. ThrowXML(ParseException,XMLExcepts::Parser_Next1);
  202. }
  203. fCharData = fString[fOffset++];
  204. break;
  205. case chDash:
  206.             if (isSet(RegularExpression::XMLSCHEMA_MODE)
  207.                 && fOffset < fStringLen && fString[fOffset] == chOpenSquare) {
  208.                 fOffset++;
  209.                 nextState = T_XMLSCHEMA_CC_SUBTRACTION;
  210.             }
  211.             else {
  212.                 nextState = T_CHAR;
  213.             }
  214.             break;
  215.         case chOpenSquare:
  216.             if (!isSet(RegularExpression::XMLSCHEMA_MODE)
  217.                 && fOffset < fStringLen && fString[fOffset] == chColon) {
  218.                 fOffset++;
  219.                 nextState = T_POSIX_CHARCLASS_START;
  220.                 break;
  221. } // Through down
  222.         default:
  223.             if (RegxUtil::isHighSurrogate(ch) && fOffset < fStringLen) {
  224.                 XMLCh lowCh = fString[fOffset];
  225.                 if (RegxUtil::isLowSurrogate(lowCh)) {
  226.                     fCharData = RegxUtil::composeFromSurrogate(ch, lowCh);
  227. fOffset++;
  228.                 }
  229. else {
  230.                     throw XMLErrs::Expected2ndSurrogateChar;
  231.                 }
  232.             }
  233. nextState = T_CHAR;
  234.         }
  235.         fState = nextState;
  236.         return;
  237.     }
  238.     switch (ch) {
  239.     case chPipe:
  240.         nextState = T_OR;
  241.         break;
  242.     case chAsterisk:
  243.         nextState = T_STAR;
  244.         break;
  245.     case chPlus:
  246.         nextState = T_PLUS;
  247.         break;
  248.     case chQuestion:
  249. nextState = T_QUESTION;
  250. break;
  251.     case chCloseParen:
  252.         nextState = T_RPAREN;
  253.         break;
  254.     case chPeriod:
  255. nextState = T_DOT;
  256. break;
  257.     case chOpenSquare:
  258.         nextState = T_LBRACKET;
  259.         break;
  260.     case chCaret:
  261.         nextState = T_CARET;
  262.         break;
  263.     case chDollarSign:
  264. nextState = T_DOLLAR;
  265. break;
  266. case chOpenParen:
  267.         {
  268.     nextState = T_LPAREN;
  269.             if (fOffset >= fStringLen)
  270.                 break;
  271. if (fString[fOffset] != chQuestion)
  272.                 break;
  273.             if (++fOffset >= fStringLen)
  274.                 ThrowXML(ParseException,XMLExcepts::Parser_Next2);
  275.             ch = fString[fOffset++];
  276.             switch (ch) {
  277.             case chColon:
  278.                 nextState = T_LPAREN2;
  279.                 break;
  280. case chEqual:
  281.                 nextState = T_LOOKAHEAD;
  282.                 break;
  283.             case chBang:
  284.                 nextState = T_NEGATIVELOOKAHEAD;
  285.                 break;
  286.             case chOpenSquare:
  287.                 nextState = T_SET_OPERATIONS;
  288.                 break;
  289.             case chCloseAngle:
  290.                 nextState = T_INDEPENDENT;
  291. break;
  292.             case chOpenAngle:
  293. if (fOffset >= fStringLen)
  294. ThrowXML(ParseException,XMLExcepts::Parser_Next2);
  295. ch = fString[fOffset++];
  296. if (ch == chEqual) {
  297. nextState = T_LOOKBEHIND;
  298. }
  299. else if (ch == chBang) {
  300. nextState = T_NEGATIVELOOKBEHIND;
  301. }
  302. else {
  303. ThrowXML(ParseException,XMLExcepts::Parser_Next3);
  304. }
  305. break;
  306.             case chPound:
  307. while (fOffset < fStringLen) {
  308. ch = fString[fOffset++];
  309. if (ch == chCloseParen)
  310. break;
  311. }
  312. if (ch != chCloseParen)
  313. ThrowXML(ParseException,XMLExcepts::Parser_Next4);
  314. nextState = T_COMMENT;
  315. break;
  316.             default:
  317. if (ch == chDash || chLatin_a <= ch && ch <= chLatin_z
  318.                     || chLatin_A <= ch && ch <= chLatin_Z) { // Options
  319.                     fOffset--;
  320.                     nextState = T_MODIFIERS;
  321.                     break;
  322.                 }
  323.                 else if (ch == chOpenParen) {
  324.                     nextState = T_CONDITION;
  325.                     break;
  326.                 }
  327.                 ThrowXML(ParseException,XMLExcepts::Parser_Next2);
  328.             }
  329.         }
  330. break;
  331. case chBackSlash:
  332.         nextState = T_BACKSOLIDUS;
  333.         if (fOffset >= fStringLen) {
  334. ThrowXML(ParseException,XMLExcepts::Parser_Next1);
  335.         }
  336.         fCharData = fString[fOffset++];
  337.         break;
  338. default:
  339. nextState = T_CHAR;
  340. if (RegxUtil::isHighSurrogate(ch) && fOffset < fStringLen) {
  341.                 XMLCh lowCh = fString[fOffset];
  342.                 if (RegxUtil::isLowSurrogate(lowCh)) {
  343.                     fCharData = RegxUtil::composeFromSurrogate(ch, lowCh);
  344. fOffset++;
  345.                 }
  346. else {
  347.                     throw XMLErrs::Expected2ndSurrogateChar;
  348.                 }
  349.             }
  350. }
  351. fState = nextState;
  352. }
  353. Token* RegxParser::parseRegx() {
  354.     Token* tok = parseTerm();
  355.     Token* parentTok = 0;
  356.     while (fState == T_OR) {
  357.         processNext();
  358.         if (parentTok == 0) {
  359.             parentTok = fTokenFactory->createUnion();
  360.     parentTok->addChild(tok, fTokenFactory);
  361.             tok = parentTok;
  362.         }
  363.         tok->addChild(parseTerm(), fTokenFactory);
  364.     }
  365.     return tok;
  366. }
  367. Token* RegxParser::parseTerm() {
  368.     unsigned short state = fState;
  369.     if (state == T_OR || state == T_RPAREN || state == T_EOF) {
  370.         return fTokenFactory->createToken(Token::EMPTY);
  371.     }
  372.     else {
  373. Token* tok = parseFactor();
  374. Token* concatTok = 0;
  375. while ((state = fState) != T_OR && state != T_RPAREN && state != T_EOF)
  376.         {
  377.             if (concatTok == 0) {
  378.                 concatTok = fTokenFactory->createUnion(true);
  379.                 concatTok->addChild(tok, fTokenFactory);
  380.                 tok = concatTok;
  381.             }
  382.             concatTok->addChild(parseFactor(), fTokenFactory);
  383.         }
  384.         return tok;
  385.     }
  386. }
  387. Token* RegxParser::processCaret() {
  388.     processNext();
  389. return fTokenFactory->getLineBegin();
  390. }
  391. Token* RegxParser::processDollar() {
  392.     processNext();
  393.     return fTokenFactory->getLineEnd();
  394. }
  395. Token* RegxParser::processLook(const unsigned short tokType) {
  396.     processNext();
  397. Token* tok = fTokenFactory->createLook(tokType, parseRegx());
  398.     if (fState != T_RPAREN) {
  399.         ThrowXML(ParseException,XMLExcepts::Parser_Factor1);
  400.     }
  401.     processNext();
  402.     return tok;
  403. }
  404. Token* RegxParser::processBacksolidus_A() {
  405.     processNext();
  406. return fTokenFactory->getStringBegin();
  407. }
  408. Token* RegxParser::processBacksolidus_Z() {
  409.     processNext();
  410.     return fTokenFactory->getStringEnd2();
  411. }
  412. Token* RegxParser::processBacksolidus_z() {
  413.     processNext();
  414.     return fTokenFactory->getStringEnd();
  415. }
  416. Token* RegxParser::processBacksolidus_b() {
  417.     processNext();
  418.     return fTokenFactory->getWordEdge();
  419. }
  420. Token* RegxParser::processBacksolidus_B() {
  421.     processNext();
  422.     return fTokenFactory->getNotWordEdge();
  423. }
  424. Token* RegxParser::processBacksolidus_lt() {
  425.     processNext();
  426.     return fTokenFactory->getWordBegin();
  427. }
  428. Token* RegxParser::processBacksolidus_gt() {
  429.     processNext();
  430.     return fTokenFactory->getWordEnd();
  431. }
  432. Token* RegxParser::processStar(Token* const tok) {
  433.     processNext();
  434.     if (fState == T_QUESTION) {
  435.         processNext();
  436.         return fTokenFactory->createClosure(tok, true);
  437.     }
  438.     return fTokenFactory->createClosure(tok);
  439. }
  440. Token* RegxParser::processPlus(Token* const tok) {
  441.     processNext();
  442.     if (fState == T_QUESTION) {
  443. processNext();
  444. return fTokenFactory->createConcat(tok,
  445.                fTokenFactory->createClosure(tok,true));
  446.     }
  447.     return fTokenFactory->createConcat(tok,
  448.                         fTokenFactory->createClosure(tok));
  449. }
  450. Token* RegxParser::processQuestion(Token* const tok) {
  451.     processNext();
  452.     Token* parentTok = fTokenFactory->createUnion();
  453.     if (fState == T_QUESTION) {
  454.         processNext();
  455.         parentTok->addChild(fTokenFactory->createToken(Token::EMPTY), fTokenFactory);
  456.         parentTok->addChild(tok, fTokenFactory);
  457.     }
  458.     else {
  459.         parentTok->addChild(tok, fTokenFactory);
  460.         parentTok->addChild(fTokenFactory->createToken(Token::EMPTY), fTokenFactory);
  461.     }
  462.     return parentTok;
  463. }
  464. Token* RegxParser::processParen() {
  465.     processNext();
  466.     int num = fNoGroups++;
  467.     Token* tok = fTokenFactory->createParenthesis(parseRegx(),num);
  468.     if (fState != T_RPAREN)
  469.         ThrowXML(ParseException,XMLExcepts::Parser_Factor1);
  470.     processNext();
  471.     return tok;
  472. }
  473. Token* RegxParser::processParen2() {
  474.     processNext();
  475.     Token* tok = fTokenFactory->createParenthesis(parseRegx(), 0);
  476.     if (fState != T_RPAREN)
  477.         ThrowXML(ParseException,XMLExcepts::Parser_Factor1);
  478.     processNext();
  479.     return tok;
  480. }
  481. Token* RegxParser::processCondition() {
  482.     if (fOffset + 1 >= fStringLen)
  483. ThrowXML(ParseException,XMLExcepts::Parser_Factor4);
  484.     int refNo = -1;
  485. Token* conditionTok = 0;
  486. XMLInt32 ch = fString[fOffset];
  487.     if (chDigit_1 <= ch && ch <= chDigit_9) {
  488.         refNo = ch - chDigit_0;
  489.         fHasBackReferences =  true;
  490.         if (fReferences == 0) {
  491.             this->fReferences = new RefVectorOf<ReferencePosition>(8, true);
  492.         }
  493.         fReferences->addElement(new ReferencePosition(refNo, fOffset));
  494.         fOffset++;
  495.         if (fString[fOffset] != chCloseParen)
  496.             ThrowXML(ParseException,XMLExcepts::Parser_Factor1);
  497.         fOffset++;
  498.     }
  499.     else {
  500.         if (ch == chQuestion) {
  501.             fOffset--;
  502.         }
  503.         processNext();
  504.         conditionTok = parseFactor();
  505.         switch(conditionTok->getTokenType()) {
  506.         case Token::LOOKAHEAD:
  507.         case Token::NEGATIVELOOKAHEAD:
  508.         case Token::LOOKBEHIND:
  509.         case Token::NEGATIVELOOKBEHIND:
  510.             break;
  511.         case Token::ANCHOR:
  512.             if (fState != T_RPAREN)
  513. ThrowXML(ParseException,XMLExcepts::Parser_Factor1);
  514. break;
  515.         default:
  516. ThrowXML(ParseException,XMLExcepts::Parser_Factor5);
  517.         }
  518.     }
  519.     processNext();
  520.     Token* yesPattern = parseRegx();
  521.     Token* noPattern = 0;
  522.     if (yesPattern->getTokenType() == Token::UNION) {
  523.         if (yesPattern->size() != 2)
  524.             ThrowXML(ParseException,XMLExcepts::Parser_Factor6);
  525.         noPattern = yesPattern->getChild(1);
  526.         yesPattern = yesPattern->getChild(0);
  527.     }
  528.     if (fState != T_RPAREN)
  529.         ThrowXML(ParseException,XMLExcepts::Parser_Factor1);
  530. processNext();
  531. return fTokenFactory->createCondition(refNo,conditionTok,
  532.                                              yesPattern,noPattern);
  533. }
  534. Token* RegxParser::processModifiers() {
  535.     // fOffset points to the next '?'.
  536. // modifiers ::= [imsw]* ('-' [imsw]*)? ':'
  537.     int add = 0;
  538.     int mask = 0;
  539.     XMLInt32 ch = -1;
  540.     while (fOffset < fStringLen) {
  541.         int v = RegularExpression::getOptionValue(fString[fOffset]);
  542.         ch = fString[fOffset];
  543.         if (v == 0)
  544.             break;
  545.         add |= v;
  546.         fOffset++;
  547.     } // end while
  548.     if (fOffset >= fStringLen)
  549.         ThrowXML(ParseException,XMLExcepts::Parser_Factor2);
  550.     if (ch == chDash) {
  551.         fOffset++;
  552.         while(fOffset < fStringLen) {
  553.             int v = RegularExpression::getOptionValue(fString[fOffset]);
  554.             ch = fString[fOffset];
  555.             if (v == 0)
  556.                 break;
  557.             mask |= v;
  558.             fOffset++;
  559.         }
  560.         if (fOffset >= fStringLen)
  561.             ThrowXML(ParseException,XMLExcepts::Parser_Factor2);
  562.     }
  563.     Token* tok = 0;
  564.     if (ch == chColon) {
  565.         fOffset++;
  566. processNext();
  567.         tok = fTokenFactory->createModifierGroup(parseRegx(),add,mask);
  568.         if (fState != T_RPAREN)
  569.             ThrowXML(ParseException,XMLExcepts::Parser_Factor1);
  570.         processNext();
  571.     }
  572.     else if (ch == chCloseParen) {
  573.         fOffset++;
  574.         processNext();
  575.         tok = fTokenFactory->createModifierGroup(parseRegx(),add,mask);
  576.     }
  577.     else {
  578.         ThrowXML(ParseException,XMLExcepts::Parser_Factor3);
  579. }
  580. return tok;
  581. }
  582. Token* RegxParser::processIndependent() {
  583.     processNext();
  584. Token* tok = fTokenFactory->createLook(Token::INDEPENDENT,
  585.                                               parseRegx());
  586. if (fState != T_RPAREN)
  587. ThrowXML(ParseException,XMLExcepts::Parser_Factor1);
  588.     processNext();
  589.     return tok;
  590. }
  591. Token* RegxParser::processBacksolidus_c() {
  592.     XMLCh ch; //Must be in 0x0040-0x005F
  593.     if (fOffset >= fStringLen
  594.         || ((ch = fString[fOffset++]) & 0xFFE0) != 0x0040)
  595.         ThrowXML(ParseException,XMLExcepts::Parser_Atom1);
  596.     processNext();
  597. return fTokenFactory->createChar(ch - 0x40);
  598. }
  599. Token* RegxParser::processBacksolidus_C() {
  600. // REVISIT - Do we throw an exception - we do not want to throw too
  601. // many exceptions
  602.     return 0;
  603. }
  604. Token* RegxParser::processBacksolidus_i() {
  605.     processNext();
  606. return fTokenFactory->createChar(chLatin_i);
  607. }
  608. Token* RegxParser::processBacksolidus_I() {
  609. //Ditto
  610.     return 0;
  611. }
  612. Token* RegxParser::processBacksolidus_g() {
  613.     processNext();
  614.     return fTokenFactory->getGraphemePattern();
  615. }
  616. Token* RegxParser::processBacksolidus_X() {
  617.     processNext();
  618.     return fTokenFactory->getCombiningCharacterSequence();
  619. }
  620. Token* RegxParser::processBackReference() {
  621.     int refNo = fCharData - chDigit_0;
  622.     Token* tok = fTokenFactory->createBackReference(refNo);
  623.     fHasBackReferences = true;
  624.     if (fReferences == 0) {
  625.         fReferences = new RefVectorOf<ReferencePosition>(8, true);
  626.     }
  627.     fReferences->addElement(new ReferencePosition(refNo, fOffset - 2));
  628.     processNext();
  629.     return tok;
  630. }
  631. Token* RegxParser::parseFactor() {
  632.     switch (fState) {
  633.     case T_CARET:
  634.         return processCaret();
  635.     case T_DOLLAR:
  636.         return processDollar();
  637.     case T_LOOKAHEAD:
  638.         return processLook(Token::LOOKAHEAD);
  639.     case T_NEGATIVELOOKAHEAD:
  640.         return processLook(Token::NEGATIVELOOKAHEAD);
  641.     case T_LOOKBEHIND:
  642.         return processLook(Token::LOOKBEHIND);
  643.     case T_NEGATIVELOOKBEHIND:
  644.         return processLook(Token::NEGATIVELOOKBEHIND);
  645.     case T_COMMENT:
  646.         processNext();
  647.         return fTokenFactory->createToken(Token::EMPTY);
  648.     case T_BACKSOLIDUS:
  649.         switch(fCharData) {
  650.         case chLatin_A:
  651.             return processBacksolidus_A();
  652.         case chLatin_Z:
  653.             return processBacksolidus_Z();
  654.         case chLatin_z:
  655.             return processBacksolidus_z();
  656.         case chLatin_b:
  657.             return processBacksolidus_B();
  658.         case chLatin_B:
  659.             return processBacksolidus_B();
  660.         case chOpenAngle:
  661.             return processBacksolidus_lt();
  662.         case chCloseAngle:
  663.             return processBacksolidus_gt();
  664. }
  665.     }
  666. Token* tok = parseAtom();
  667. switch(fState) {
  668.     case T_STAR:
  669.         return processStar(tok);
  670.     case T_PLUS:
  671.         return processPlus(tok);
  672.     case T_QUESTION:
  673.         return processQuestion(tok);
  674.     case T_CHAR:
  675. if (fCharData == chOpenCurly) {
  676.             int offset = fOffset;
  677.             int min = 0;
  678.             int max = -1;
  679.             bool minExist = false;
  680.             if (offset >= fStringLen)
  681.                 break;
  682.             XMLInt32 ch = fString[offset++];
  683.             if (ch != chComma && (ch < chDigit_0 || ch > chDigit_9))
  684.                 ThrowXML1(ParseException, XMLExcepts::Regex_InvalidQuantifier, fString);
  685.             if (ch != chComma) {
  686.                 minExist = true;
  687.                 min = ch - chDigit_0;
  688.                 while (offset < fStringLen
  689.                        && (ch = fString[offset++]) >= chDigit_0
  690.                        && ch <= chDigit_9) {
  691.                     min = min*10 + ch - chDigit_0;
  692.                     ch = -1;
  693.                 }
  694.             }
  695.             max = min;
  696.             if (ch != chCloseCurly && ch != chComma)  {
  697.                 ThrowXML1(ParseException, XMLExcepts::Regex_InvalidQuantifier, fString);
  698.             }
  699.             if (ch == chComma) {
  700.                 if (offset >= fStringLen)
  701.                     break;
  702.                 if (((ch = fString[offset++]) < chDigit_0 || ch > chDigit_9)
  703.                     && ch != chCloseCurly)
  704.                     ThrowXML1(ParseException, XMLExcepts::Regex_InvalidQuantifier, fString);
  705.                 if (ch == chCloseCurly) {
  706.                     if (minExist)
  707.                         max = -1;
  708.                     else
  709.                         ThrowXML1(ParseException, XMLExcepts::Regex_InvalidQuantifier, fString);
  710.                 }
  711.                 else {
  712.                     max = ch - chDigit_0;
  713.                     while (offset < fStringLen
  714.                            && (ch = fString[offset++]) >= chDigit_0
  715.                            && ch <= chDigit_9) {
  716.                         max = max*10 + ch - chDigit_0;
  717.                         ch = -1;
  718.                     }
  719.                     if (ch != chCloseCurly)  {
  720.                         ThrowXML1(ParseException, XMLExcepts::Regex_InvalidQuantifier, fString);
  721.                     }
  722.                 }
  723.             } // end if ch = chComma
  724.             if (checkQuestion(offset)) {
  725.                 tok = fTokenFactory->createClosure(tok, true);
  726.                 fOffset = offset + 1;
  727.             }
  728.             else {
  729.                 tok = fTokenFactory->createClosure(tok);
  730.                 fOffset = offset;
  731.             }
  732.             tok->setMin(min);
  733.             tok->setMax(max);
  734.             processNext();
  735. }
  736. }
  737. return tok;
  738. }
  739. Token* RegxParser::parseAtom() {
  740.     Token* tok = 0;
  741.     switch(fState) {
  742.     case T_LPAREN:
  743.         return processParen();
  744.     case T_LPAREN2:
  745.         return processParen2();
  746.     case T_CONDITION:
  747.         return processCondition();
  748.     case T_MODIFIERS:
  749.         return processModifiers();
  750.     case T_INDEPENDENT:
  751.         return processIndependent();
  752.     case T_DOT:
  753.         processNext();
  754.         tok = fTokenFactory->getDot();
  755.         break;
  756.     case T_LBRACKET:
  757.         return parseCharacterClass(true);
  758.     case T_SET_OPERATIONS:
  759.         return parseSetOperations();
  760.     case T_BACKSOLIDUS:
  761. switch(fCharData) {
  762.         case chLatin_d:
  763.         case chLatin_D:
  764.         case chLatin_w:
  765.         case chLatin_W:
  766.         case chLatin_s:
  767.         case chLatin_S:
  768.             tok = getTokenForShorthand(fCharData);
  769.             processNext();
  770.             return tok;
  771.         case chLatin_e:
  772.         case chLatin_f:
  773.         case chLatin_n:
  774.         case chLatin_r:
  775.         case chLatin_t:
  776.         case chLatin_u:
  777.         case chLatin_v:
  778.         case chLatin_x:
  779. {
  780.                 XMLInt32 ch = decodeEscaped();
  781.                 if (ch < 0x10000) {
  782.                     tok = fTokenFactory->createChar(ch);
  783.                 }
  784.                 else {
  785.                     XMLCh* surrogateStr = RegxUtil::decomposeToSurrogates(ch);
  786.     ArrayJanitor<XMLCh> janSurrogate(surrogateStr);
  787.     tok = fTokenFactory->createString(surrogateStr);
  788.                 }
  789.             }
  790. break;
  791.         case chLatin_c:
  792.             return processBacksolidus_c();
  793.         case chLatin_C:
  794.             return processBacksolidus_C();
  795.         case chLatin_i:
  796.             return processBacksolidus_i();
  797.         case chLatin_I:
  798.             return processBacksolidus_I();
  799.         case chLatin_g:
  800.             return processBacksolidus_g();
  801.         case chLatin_X:
  802.             return processBacksolidus_X();
  803.         case chDigit_0:
  804.         case chDigit_1:
  805.         case chDigit_2:
  806.         case chDigit_3:
  807.         case chDigit_4:
  808.         case chDigit_5:
  809.         case chDigit_6:
  810.         case chDigit_7:
  811.         case chDigit_8:
  812.         case chDigit_9:
  813.             return processBackReference();
  814.         case chLatin_p:
  815.         case chLatin_P:
  816. {
  817. int start = fOffset;
  818. tok = processBacksolidus_pP(fCharData);
  819. if (tok == 0) {
  820. ThrowXML(ParseException,XMLExcepts::Parser_Atom5);
  821. }
  822. }
  823.             break;
  824.         default:
  825.             tok = fTokenFactory->createChar(fCharData);
  826. } // end switch
  827.         processNext();
  828.         break;
  829.     case T_CHAR:
  830.         tok = fTokenFactory->createChar(fCharData);
  831.         processNext();
  832.         break;
  833.     default:
  834.         ThrowXML(ParseException,XMLExcepts::Parser_Atom4);
  835.     } //end switch
  836.     return tok;
  837. }
  838. RangeToken* RegxParser::processBacksolidus_pP(const XMLInt32 ch) {
  839.     bool positive = (ch == chLatin_p);
  840.     processNext();
  841. if (fState != T_CHAR)
  842. ThrowXML(ParseException,XMLExcepts::Parser_Atom2);
  843.     RangeToken* tok = 0;
  844. switch(fCharData) {
  845.     case chLatin_L:
  846. tok = fTokenFactory->getRange(fgUniLetter, !positive);
  847. break;
  848.     case chLatin_M:
  849. tok = fTokenFactory->getRange(fgUniMark, !positive);
  850. break;
  851.     case chLatin_N:
  852. tok = fTokenFactory->getRange(fgUniNumber, !positive);
  853. break;
  854.     case chLatin_Z:
  855. tok = fTokenFactory->getRange(fgUniSeparator, !positive);
  856. break;
  857.     case chLatin_C:
  858. tok = fTokenFactory->getRange(fgUniControl, !positive);
  859. break;
  860.     case chLatin_P:
  861. tok = fTokenFactory->getRange(fgUniPunctuation, !positive);
  862. break;
  863.     case chLatin_S:
  864. tok = fTokenFactory->getRange(fgUniSymbol, !positive);
  865. break;
  866.     case chOpenCurly:
  867. {
  868. int nameStart = fOffset;
  869. int nameEnd = XMLString::indexOf(fString,chCloseCurly,nameStart);
  870. if (nameEnd < 0)
  871. ThrowXML(ParseException,XMLExcepts::Parser_Atom3);
  872. fOffset = nameEnd + 1;
  873. XMLCh* rangeName = new XMLCh[(nameEnd - nameStart) + 1];
  874. ArrayJanitor<XMLCh> janRangeName(rangeName);
  875. XMLString::subString(rangeName, fString, nameStart, nameEnd);
  876. tok = fTokenFactory->getRange(rangeName, !positive);
  877. }
  878. break;
  879. default:
  880. ThrowXML(ParseException,XMLExcepts::Parser_Atom2);
  881. }
  882.     return tok;
  883. }
  884. XMLInt32 RegxParser::processCInCharacterClass(RangeToken* const tok,
  885.                                               const XMLInt32 ch) {
  886. return decodeEscaped();
  887. }
  888. RangeToken* RegxParser::parseCharacterClass(const bool useNRange) {
  889.     setParseContext(S_INBRACKETS);
  890. processNext();
  891.     RangeToken* base = 0;
  892.     RangeToken* tok = 0;
  893.     bool nRange = false;
  894. if (fState == T_CHAR && fCharData == chCaret) {
  895.         nRange = true;
  896.         processNext();
  897. if (useNRange) {
  898.             tok = fTokenFactory->createRange(true);
  899.         }
  900.         else {
  901. base = fTokenFactory->createRange();
  902.             base->addRange(0, Token::UTF16_MAX);
  903.             tok = fTokenFactory->createRange();
  904.         }
  905.     }
  906.     else {
  907.         tok = fTokenFactory->createRange();
  908.     }
  909.     bool firstLoop = true;
  910.     while (fState != T_EOF) {
  911.         if (fState == T_CHAR && fCharData == chCloseSquare && !firstLoop)
  912. break;
  913.         bool end = false;
  914.         XMLInt32 ch = fCharData;
  915.         firstLoop = false;
  916.         if (fState == T_BACKSOLIDUS) {
  917.             switch(ch) {
  918.             case chLatin_d:
  919.             case chLatin_D:
  920.             case chLatin_w:
  921.             case chLatin_W:
  922.             case chLatin_s:
  923.             case chLatin_S:
  924.                 tok->mergeRanges(getTokenForShorthand(ch));
  925.                 end = true;
  926. break;
  927.             case chLatin_i:
  928.             case chLatin_I:
  929.             case chLatin_c:
  930.             case chLatin_C:
  931.                 ch = processCInCharacterClass(tok, ch);
  932. if (ch < 0){
  933.     end = true;
  934.                 }
  935.                 break;
  936.             case chLatin_p:
  937.             case chLatin_P:
  938. {
  939. int pStart = fOffset;
  940. RangeToken* tok2 = processBacksolidus_pP(ch);
  941. if (tok2 == 0) {
  942. ThrowXML(ParseException,XMLExcepts::Parser_Atom5);
  943. }
  944. tok->mergeRanges(tok2);
  945. end = true;
  946. }
  947.                 break;
  948.             default:
  949.                 ch = decodeEscaped();
  950. }
  951.         } // end if T_BACKSOLIDUS
  952.         else if (fState == T_POSIX_CHARCLASS_START) {
  953.             int nameEnd = XMLString::indexOf(fString, chColon, fOffset);
  954.             if (nameEnd < 0) {
  955. ThrowXML(ParseException,XMLExcepts::Parser_CC1);
  956. }
  957.             bool positive = true;
  958.             if (fString[fOffset] == chCaret) {
  959.                 fOffset++;
  960.                 positive = false;
  961.             }
  962. XMLCh* name = new XMLCh[(nameEnd - fOffset) + 1];
  963. ArrayJanitor<XMLCh> janName(name);
  964. XMLString::subString(name, fString, fOffset, nameEnd);
  965.             RangeToken* rangeTok = fTokenFactory->getRange(name, !positive);
  966.             if (rangeTok == 0) {
  967. ThrowXML(ParseException,XMLExcepts::Parser_CC3);
  968.             }
  969. tok->mergeRanges(rangeTok);
  970. end = true;
  971. if (nameEnd+1 >= fStringLen || fString[nameEnd+1] != chCloseSquare) {
  972. ThrowXML(ParseException,XMLExcepts::Parser_CC1);
  973. }
  974. fOffset = nameEnd + 2;
  975.         }
  976.         processNext();
  977. if (!end) {
  978.             if (fState != T_CHAR || fCharData != chDash) {
  979.                 tok->addRange(ch, ch);
  980.             }
  981.             else {
  982.                 processNext();
  983.                 if (fState == T_EOF)
  984.                     ThrowXML(ParseException,XMLExcepts::Parser_CC2);
  985.                 if (fState == T_CHAR && fCharData == chCloseSquare) {
  986.                     tok->addRange(ch, ch);
  987.                     tok->addRange(chDash, chDash);
  988.                 }
  989.                 else {
  990.                     XMLInt32 rangeEnd = fCharData;
  991.                     if (fState == T_BACKSOLIDUS) {
  992.                         rangeEnd = decodeEscaped();
  993.                     }
  994.                     processNext();
  995.                     tok->addRange(ch, rangeEnd);
  996.                 }
  997.             }
  998.         }
  999.         if (isSet(RegularExpression::SPECIAL_COMMA)
  1000.             && fState == T_CHAR && fCharData == chComma) {
  1001.             processNext();
  1002.         }
  1003.     } // end while fState
  1004. if (fState == T_EOF) {
  1005.         ThrowXML(ParseException,XMLExcepts::Parser_CC2);
  1006. }
  1007.     if (!useNRange && nRange) {
  1008.         base->subtractRanges(tok);
  1009.         tok = base;
  1010.     }
  1011.     tok->sortRanges();
  1012.     tok->compactRanges();
  1013.     setParseContext(S_NORMAL);
  1014.     processNext();
  1015.     return tok;
  1016. }
  1017. RangeToken* RegxParser::parseSetOperations() {
  1018.     RangeToken* tok = parseCharacterClass(false);
  1019.     while (fState != T_RPAREN) {
  1020. if (fState == T_CHAR
  1021.             && (fCharData == chDash || fCharData == chAmpersand)
  1022.             || fState == T_PLUS) {
  1023.             processNext();
  1024.             if (fState != T_LBRACKET)
  1025.                 ThrowXML(ParseException,XMLExcepts::Parser_Ope1);
  1026.             RangeToken* tok2 = parseCharacterClass(false);
  1027.             if (fState == T_PLUS) {
  1028.                 tok->mergeRanges(tok2);
  1029.             }
  1030.             else if (fCharData == chDash) {
  1031.                 tok->subtractRanges(tok2);
  1032.             }
  1033.             else if (fCharData == chAmpersand) {
  1034.                 tok->intersectRanges(tok2);
  1035.             }
  1036.             else {
  1037.                 throw 0; // ThrowXML(RuntimeException, "ASSERT")
  1038.             }
  1039.         }
  1040.         else {
  1041. ThrowXML(ParseException,XMLExcepts::Parser_Ope2);
  1042. }
  1043.     }
  1044.     processNext();
  1045.     return tok;
  1046. }
  1047. Token* RegxParser::getTokenForShorthand(const XMLInt32 ch) {
  1048.     Token* tok = 0;
  1049.     bool useUnicode = isSet(RegularExpression::USE_UNICODE_CATEGORY);
  1050. switch (ch) {
  1051. case chLatin_d:
  1052. tok = useUnicode ? fTokenFactory->getRange(fgUniDecimalDigit)
  1053.  : fTokenFactory->getRange(fgASCIIDigit);
  1054. break;
  1055. case chLatin_D:
  1056. tok = useUnicode ? fTokenFactory->getRange(fgUniDecimalDigit, true)
  1057.  : fTokenFactory->getRange(fgASCIIDigit, true);
  1058. break;
  1059. case chLatin_w:
  1060. tok = useUnicode ? fTokenFactory->getRange(fgUniIsWord)
  1061.  : fTokenFactory->getRange(fgASCIIWord);
  1062. break;
  1063. case chLatin_W:
  1064. tok = useUnicode ? fTokenFactory->getRange(fgUniIsWord, true)
  1065.  : fTokenFactory->getRange(fgASCIIWord, true);
  1066. break;
  1067. case chLatin_s:
  1068. tok = useUnicode ? fTokenFactory->getRange(fgUniIsSpace)
  1069.  : fTokenFactory->getRange(fgASCIISpace);
  1070. break;
  1071. case chLatin_S:
  1072. tok = useUnicode ? fTokenFactory->getRange(fgUniIsSpace, true)
  1073.  : fTokenFactory->getRange(fgASCIISpace, true);
  1074. // default:
  1075. // ThrowXML(RuntimeException, "Invalid shorthand {0}", chAsString)
  1076. }
  1077.     return tok;
  1078. }
  1079. XMLInt32 RegxParser::decodeEscaped() {
  1080.     if (fState != T_BACKSOLIDUS)
  1081. ThrowXML(ParseException,XMLExcepts::Parser_Next1);
  1082.     XMLInt32 ch = fCharData;
  1083. switch (ch) {
  1084. case chLatin_e:
  1085. ch = 0x1B; // Escape
  1086. break;
  1087. case chLatin_f:
  1088. ch = chFF;
  1089. break;
  1090. case chLatin_n:
  1091. ch = chLF;
  1092. break;
  1093. case chLatin_r:
  1094. ch = chCR;
  1095. break;
  1096. case chLatin_t:
  1097. ch = chHTab;
  1098. break;
  1099. case chLatin_x:
  1100. {
  1101. processNext();
  1102. if (fState != T_CHAR) {
  1103. ThrowXML(ParseException,XMLExcepts::Parser_Descape1);
  1104. }
  1105. if (fCharData == chOpenCurly) {
  1106. int v1 = 0;
  1107. XMLInt32 uv = 0;
  1108. do {
  1109. processNext();
  1110. if (fState != T_CHAR)
  1111. ThrowXML(ParseException,XMLExcepts::Parser_Descape1);
  1112. if ((v1 = hexChar(fCharData)) < 0)
  1113. break;
  1114. uv = uv*16 + v1;
  1115. } while (true);
  1116. if (fCharData != chCloseCurly)
  1117. ThrowXML(ParseException,XMLExcepts::Parser_Descape3);
  1118. if (uv > Token::UTF16_MAX)
  1119. ThrowXML(ParseException,XMLExcepts::Parser_Descape4);
  1120. ch = uv;
  1121. }
  1122. else {
  1123. int v1 = 0;
  1124. if (fState != T_CHAR || (v1 = hexChar(fCharData)) < 0)
  1125. ThrowXML(ParseException,XMLExcepts::Parser_Descape1);
  1126. int uv = v1;
  1127. processNext();
  1128. if (fState != T_CHAR || (v1 = hexChar(fCharData)) < 0)
  1129. ThrowXML(ParseException,XMLExcepts::Parser_Descape1);
  1130. ch = uv*16 + v1;
  1131. }
  1132. }
  1133. break;
  1134. case chLatin_u:
  1135. {
  1136. int v1 = 0;
  1137. int uv = 0;
  1138. for (int i=0; i< 4; i++) {
  1139. processNext();
  1140. if (fState != T_CHAR || (v1 = hexChar(fCharData)) < 0)
  1141. ThrowXML(ParseException,XMLExcepts::Parser_Descape1);
  1142. uv = (i == 0) ? v1 : uv*16 + v1;
  1143. }
  1144. ch = uv;
  1145. }
  1146. break;
  1147. case chLatin_v:
  1148. {
  1149. int v1 = 0;
  1150. int uv = 0;
  1151. for (int i=0; i< 6; i++) {
  1152. processNext();
  1153. if (fState != T_CHAR || (v1 = hexChar(fCharData)) < 0)
  1154. ThrowXML(ParseException,XMLExcepts::Parser_Descape1);
  1155. uv = (i == 0) ? v1 : uv*16 + v1;
  1156. }
  1157. if (uv > Token::UTF16_MAX)
  1158. ThrowXML(ParseException,XMLExcepts::Parser_Descape1);
  1159. ch = uv;
  1160. }
  1161. break;
  1162. case chLatin_A:
  1163. case chLatin_Z:
  1164. case chLatin_z:
  1165. ThrowXML(ParseException,XMLExcepts::Parser_Descape5);
  1166. } // end switch
  1167.     return ch;
  1168. }
  1169. // ---------------------------------------------------------------------------
  1170. //  RegxParser: Helper Methods
  1171. // ---------------------------------------------------------------------------
  1172. bool RegxParser::checkQuestion(const int off) {
  1173.     return ((off < fStringLen) && fString[off] == chQuestion);
  1174. }
  1175. /**
  1176.   * End file RegxParser.cpp
  1177.   */