RegxParser.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:39k
源码类别:

词法分析

开发平台:

Visual C++

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