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

词法分析

开发平台:

Visual 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: Token.cpp,v $
  58.  * Revision 1.5  2002/11/21 14:56:35  gareth
  59.  * Fixed bug in Token::analyzeFirstCharacter so that . matches new line with head character optimisation enabled. As per discussion Jennifer Schachter had with Khaled.
  60.  *
  61.  * Revision 1.4  2002/11/04 15:17:00  tng
  62.  * C++ Namespace Support.
  63.  *
  64.  * Revision 1.3  2002/10/15 18:11:02  knoaman
  65.  * [Bug 13489]: missing 'return' in Token.cpp
  66.  *
  67.  * Revision 1.2  2002/03/18 19:29:53  knoaman
  68.  * Change constant names to eliminate possible conflict with user defined ones.
  69.  *
  70.  * Revision 1.1.1.1  2002/02/01 22:22:31  peiyongz
  71.  * sane_include
  72.  *
  73.  * Revision 1.3  2001/05/11 13:26:50  tng
  74.  * Copyright update.
  75.  *
  76.  * Revision 1.2  2001/05/03 18:17:49  knoaman
  77.  * Some design changes:
  78.  * o Changed the TokenFactory from a single static instance, to a
  79.  *    normal class. Each RegularExpression object will have its own
  80.  *    instance of TokenFactory, and that instance will be passed to
  81.  *    other classes that need to use a TokenFactory to create Token
  82.  *    objects (with the exception of RangeTokenMap).
  83.  * o Added a new class RangeTokenMap to map a the different ranges
  84.  *    in a given category to a specific RangeFactory object. In the old
  85.  *    design RangeFactory had dual functionality (act as a Map, and as
  86.  *    a factory for creating RangeToken(s)). The RangeTokenMap will
  87.  *    have its own copy of the TokenFactory. There will be only one
  88.  *    instance of the RangeTokenMap class, and that instance will be
  89.  *    lazily deleted when XPlatformUtils::Terminate is called.
  90.  *
  91.  * Revision 1.1  2001/03/02 19:22:58  knoaman
  92.  * Schema: Regular expression handling part I
  93.  *
  94.  */
  95. // ---------------------------------------------------------------------------
  96. //  Includes
  97. // ---------------------------------------------------------------------------
  98. #include <xercesc/util/regx/RangeToken.hpp>
  99. #include <xercesc/util/regx/ModifierToken.hpp>
  100. #include <xercesc/util/regx/RegularExpression.hpp>
  101. #include <xercesc/util/regx/RegxUtil.hpp>
  102. XERCES_CPP_NAMESPACE_BEGIN
  103. // ---------------------------------------------------------------------------
  104. //  Static member data initialization
  105. // ---------------------------------------------------------------------------
  106. const XMLInt32  Token::UTF16_MAX = 0x10FFFF;
  107. const unsigned short Token::FC_CONTINUE = 0;
  108. const unsigned short Token::FC_TERMINAL = 1;
  109. const unsigned short Token::FC_ANY = 2;
  110. // ---------------------------------------------------------------------------
  111. //  Token: Constructors and Destructors
  112. // ---------------------------------------------------------------------------
  113. Token::Token(const unsigned short tokType) : fTokenType(tokType) {
  114. }
  115. Token::~Token() {
  116. }
  117. // ---------------------------------------------------------------------------
  118. //  Token: Getter mthods
  119. // ---------------------------------------------------------------------------
  120. int Token::getMinLength() const {
  121. switch (fTokenType) {
  122. case T_CONCAT:
  123.         {
  124.             int sum = 0;
  125.             unsigned int childSize = size();
  126.             for (unsigned int i=0; i<childSize; i++) {
  127.                 sum += getChild(i)->getMinLength();
  128.             }
  129.             return sum;
  130.         }
  131. case T_CONDITION:
  132. case T_UNION:
  133.         {
  134. unsigned int childSize = size();
  135.             if (childSize == 0) {
  136.                 return 0;
  137.             }
  138. int ret = getChild(0)->getMinLength();
  139.             for (unsigned int i=1; i < childSize; i++) {
  140.                 int min = getChild(i)->getMinLength();
  141.                 if (min < ret)
  142.                     ret = min;
  143.             }
  144. return ret;
  145.         }
  146. case T_CLOSURE:
  147. case T_NONGREEDYCLOSURE:
  148.         if (getMin() >= 0)
  149.             return getMin() * getChild(0)->getMinLength();
  150. return 0;
  151. case T_EMPTY:
  152. case T_ANCHOR:
  153. return 0;
  154. case T_DOT:
  155. case T_CHAR:
  156. case T_RANGE:
  157. case T_NRANGE:
  158. return 1;
  159. case T_INDEPENDENT:
  160. case T_PAREN:
  161. case T_MODIFIERGROUP:
  162. return getChild(0)->getMinLength();
  163. case T_BACKREFERENCE:
  164. return 0; // *****  - REVISIT
  165. case T_STRING:
  166. return XMLString::stringLen(getString());
  167. case T_LOOKAHEAD:
  168. case T_NEGATIVELOOKAHEAD:
  169. case T_LOOKBEHIND:
  170. case T_NEGATIVELOOKBEHIND:
  171. return 0; // *****  - REVIST
  172. // default:
  173. // throw;
  174. }
  175. // We should not get here, but we have it to make some compilers happy
  176. return -1;
  177. }
  178. int Token::getMaxLength() const {
  179. switch (fTokenType) {
  180. case T_CONCAT:
  181.         {
  182.             int sum = 0;
  183.             unsigned int childSize = size();
  184.             for (unsigned int i=0; i<childSize; i++) {
  185.                 int val = getChild(i)->getMaxLength();
  186. if (val < 0){
  187. return -1;
  188. }
  189.                 sum += val;
  190.             }
  191.             return sum;
  192.         }
  193.     case T_CONDITION:
  194.     case T_UNION:
  195.         {
  196.             unsigned int childSize = size();
  197. if (childSize == 0)
  198.                 return 0;
  199.             int ret = getChild(0)->getMaxLength();
  200.             for (unsigned i = 1; ret > 0 && i < childSize; i++) {
  201.                 int max = getChild(i)->getMaxLength();
  202.                 if (max < 0) {
  203.                     ret = -1;
  204.                     break;
  205.                 }
  206.                 if (max > ret)
  207.                     ret = max;
  208.             }
  209. return ret;
  210.         }
  211.     case T_CLOSURE:
  212.     case T_NONGREEDYCLOSURE:
  213.         if (getMax() >= 0) {
  214.             return getMax() * getChild(0)->getMaxLength();
  215. }
  216. return -1;
  217.     case T_EMPTY:
  218.     case T_ANCHOR:
  219.         return 0;
  220.     case T_CHAR:
  221.         return 1;
  222.     case T_DOT:
  223.     case T_RANGE:
  224.     case T_NRANGE:
  225.         return 2;
  226.     case T_INDEPENDENT:
  227.     case T_PAREN:
  228.     case T_MODIFIERGROUP:
  229.         return getChild(0)->getMaxLength();
  230.     case T_BACKREFERENCE:
  231. return -1; // REVISIT
  232.     case T_STRING:
  233.         return XMLString::stringLen(getString());
  234.     case T_LOOKAHEAD:
  235.     case T_NEGATIVELOOKAHEAD:
  236.     case T_LOOKBEHIND:
  237.     case T_NEGATIVELOOKBEHIND:
  238. return 0; // REVISIT
  239. //    default:
  240. // throw; //ThrowXML(RuntimeException, ...)
  241.     } // end switch
  242. return -1;
  243. }
  244. // ---------------------------------------------------------------------------
  245. //  Token: Helper mthods
  246. // ---------------------------------------------------------------------------
  247. int Token::analyzeFirstCharacter(RangeToken* const rangeTok,
  248.  const int options,
  249.                                  TokenFactory* const tokFactory)
  250. {
  251. switch(fTokenType) {
  252. case T_CONCAT:
  253. {
  254. int ret = FC_CONTINUE;
  255. for (int i=0; i<size(); i++) {
  256. Token* tok = getChild(i);
  257. if (tok
  258. && (ret=tok->analyzeFirstCharacter(rangeTok,
  259.                                     options, tokFactory))!= FC_CONTINUE)
  260. break;
  261. }
  262. return ret;
  263. }
  264. case T_UNION:
  265. {
  266. unsigned int childSize = size();
  267.             if (childSize == 0)
  268.                 return FC_CONTINUE;
  269.             int ret = FC_CONTINUE;
  270. bool hasEmpty = false;
  271. for (unsigned int i=0; i < childSize; i++) {
  272.                 ret = getChild(i)->analyzeFirstCharacter(rangeTok, options, tokFactory);
  273. if (ret == FC_ANY)
  274. break;
  275. else
  276. hasEmpty = true;
  277. }
  278. return hasEmpty ? FC_CONTINUE : ret;
  279. }
  280. case T_CONDITION:
  281. {
  282.             int ret1 = getChild(0)->analyzeFirstCharacter(rangeTok, options, tokFactory);
  283.             if (size() == 1)
  284.                 return FC_CONTINUE;
  285. int ret2;
  286. if (ret1 != FC_ANY) {
  287.     ret2 = getChild(1)->analyzeFirstCharacter(rangeTok, options, tokFactory);
  288. }
  289. if (ret1 == FC_ANY || ret2 == FC_ANY)
  290. return FC_ANY;
  291. if (ret1 == FC_CONTINUE || ret2 == FC_CONTINUE)
  292. return FC_CONTINUE;
  293. return FC_TERMINAL;
  294. }
  295. case T_CLOSURE:
  296. case T_NONGREEDYCLOSURE:
  297. {
  298. Token* tok = getChild(0);
  299. if (tok)
  300. tok->analyzeFirstCharacter(rangeTok, options, tokFactory);
  301. return FC_CONTINUE;
  302. }
  303. case T_DOT:
  304.     return FC_ANY;
  305. case T_EMPTY:
  306. case T_ANCHOR:
  307. return FC_CONTINUE;
  308. case T_CHAR:
  309. {
  310.             XMLInt32 ch = getChar();
  311. rangeTok->addRange(ch, ch);
  312. if (ch < 0x1000 && isSet(options,RegularExpression::IGNORE_CASE)) {
  313. //REVISIT
  314. }
  315. }
  316. return FC_TERMINAL;
  317. case T_RANGE:
  318. {
  319. if (isSet(options, RegularExpression::IGNORE_CASE)) {
  320.                 rangeTok->mergeRanges(((RangeToken*)
  321.                                          this)->getCaseInsensitiveToken(tokFactory));
  322. }
  323. else {
  324. rangeTok->mergeRanges(this);
  325. }
  326. return FC_TERMINAL;
  327. }
  328. case T_NRANGE:
  329. {
  330. if (isSet(options, RegularExpression::IGNORE_CASE)) {
  331. RangeToken* caseITok = (((RangeToken*)
  332.                        this)->getCaseInsensitiveToken(tokFactory));
  333. rangeTok->mergeRanges(RangeToken::complementRanges(caseITok, tokFactory));
  334. }
  335. else {
  336. rangeTok->mergeRanges(
  337. RangeToken::complementRanges((RangeToken*) this, tokFactory));
  338. }
  339. }
  340. case T_INDEPENDENT:
  341. case T_PAREN:
  342. {
  343. Token* tok = getChild(0);
  344. if (tok)
  345. return tok->analyzeFirstCharacter(rangeTok,options, tokFactory);
  346. }
  347. case T_MODIFIERGROUP:
  348. case T_BACKREFERENCE:
  349. rangeTok->addRange(0, UTF16_MAX);
  350. return FC_ANY;
  351. case T_STRING:
  352. {
  353. const XMLCh* str = getString();
  354.             XMLInt32 ch = str[0];
  355. if (RegxUtil::isHighSurrogate((XMLCh) ch)) {
  356. }
  357.     rangeTok->addRange(ch, ch);
  358.     if (ch<0x10000 && isSet(options,RegularExpression::IGNORE_CASE)) {
  359.                 //REVISIT
  360.             }
  361. }
  362. return FC_TERMINAL;
  363. case T_LOOKAHEAD:
  364. case T_NEGATIVELOOKAHEAD:
  365. case T_LOOKBEHIND:
  366. case T_NEGATIVELOOKBEHIND:
  367. return FC_CONTINUE;
  368. // default:
  369. // throw;
  370. }
  371. return 0;
  372. }
  373. Token* Token::findFixedString(int options, int& outOptions) {
  374.     switch(fTokenType) {
  375.     case T_CHAR:
  376. return 0;
  377.     case T_STRING:
  378. outOptions = options;
  379. return this;
  380.     case T_UNION:
  381.     case T_CLOSURE:
  382.     case T_NONGREEDYCLOSURE:
  383.     case T_EMPTY:
  384.     case T_ANCHOR:
  385.     case T_RANGE:
  386.     case T_NRANGE:
  387.     case T_DOT:
  388.     case T_BACKREFERENCE:
  389.     case T_LOOKAHEAD:
  390.     case T_NEGATIVELOOKAHEAD:
  391.     case T_LOOKBEHIND:
  392.     case T_NEGATIVELOOKBEHIND:
  393.     case T_CONDITION:
  394. return 0;
  395.     case T_INDEPENDENT:
  396.     case T_PAREN:
  397. return getChild(0)->findFixedString(options, outOptions);
  398.     case T_CONCAT:
  399.         {
  400.             Token* prevTok = 0;
  401.             int prevOptions = 0;
  402.             for (int i=0; i<size(); i++) {
  403.                 Token* tok = getChild(i)->findFixedString(options, outOptions);
  404.                 if (prevTok == 0 || prevTok->isShorterThan(tok)) {
  405.                     prevTok = tok;
  406. prevOptions = outOptions;
  407.                 }
  408.             }
  409. outOptions = prevOptions;
  410.             return prevTok;
  411.         }
  412.     case T_MODIFIERGROUP:
  413.         {
  414.             options |= ((ModifierToken *) this)->getOptions();
  415.             options &= ~((ModifierToken *) this)->getOptionsMask();
  416.             return getChild(0)->findFixedString(options, outOptions);
  417.         }
  418.     } // end switch
  419.     return 0;
  420. }
  421. bool Token::isShorterThan(Token* const tok) {
  422. if (tok == 0)
  423. return false;
  424. if (getTokenType() != T_STRING && tok->getTokenType() != T_STRING)
  425. return false; //Should we throw an exception?
  426.     int length = XMLString::stringLen(getString());
  427.     int tokLength = XMLString::stringLen(tok->getString());
  428. return length < tokLength;
  429. }
  430. XERCES_CPP_NAMESPACE_END
  431. /**
  432.   * End of file Token.cpp
  433.   */