1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 // Class header file...
20 #include "XPathProcessorImpl.hpp"
21
22
23
24 #include <xercesc/sax/Locator.hpp>
25
26
27
28 #include <xalanc/PlatformSupport/DOMStringHelper.hpp>
29 #include <xalanc/PlatformSupport/DOMStringPrintWriter.hpp>
30 #include <xalanc/PlatformSupport/DoubleSupport.hpp>
31 #include <xalanc/PlatformSupport/PrefixResolver.hpp>
32 #include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
33 #include <xalanc/PlatformSupport/XalanUnicode.hpp>
34 #include <xalanc/PlatformSupport/XalanXMLChar.hpp>
35
36
37
38 #include <xalanc/DOMSupport/DOMServices.hpp>
39
40
41
42 #include "XalanQName.hpp"
43 #include "XPathEnvSupport.hpp"
44 #include "XPathFunctionTable.hpp"
45 #include "XPathConstructionContext.hpp"
46 #include "XPathExecutionContext.hpp"
47 #include "XPathParserException.hpp"
48
49
50
51 namespace XALAN_CPP_NAMESPACE {
52
53
54
XPathProcessorImpl(MemoryManager & theManager)55 XPathProcessorImpl::XPathProcessorImpl(MemoryManager& theManager) :
56 m_token(theManager),
57 m_tokenChar(0),
58 m_xpath(0),
59 m_constructionContext(0),
60 m_expression(0),
61 m_prefixResolver(0),
62 m_requireLiterals(false),
63 m_isMatchPattern(false),
64 m_positionPredicateStack(theManager),
65 m_namespaces(theManager),
66 m_allowVariableReferences(true),
67 m_allowKeyFunction(true)
68 {
69 }
70
71
72
73 XPathProcessorImpl*
create(MemoryManager & theManager)74 XPathProcessorImpl::create(MemoryManager& theManager)
75 {
76 typedef XPathProcessorImpl ThisType;
77
78 XalanAllocationGuard theGuard(theManager, theManager.allocate(sizeof(ThisType)));
79
80 ThisType* const theResult =
81 new (theGuard.get()) ThisType(theManager);
82
83 theGuard.release();
84
85 return theResult;
86 }
87
88
89
~XPathProcessorImpl()90 XPathProcessorImpl::~XPathProcessorImpl()
91 {
92 }
93
94
95
96 void
initXPath(XPath & pathObj,XPathConstructionContext & constructionContext,const XalanDOMString & expression,const PrefixResolver & resolver,const Locator * locator,bool allowVariableReferences,bool allowKeyFunction)97 XPathProcessorImpl::initXPath(
98 XPath& pathObj,
99 XPathConstructionContext& constructionContext,
100 const XalanDOMString& expression,
101 const PrefixResolver& resolver,
102 const Locator* locator,
103 bool allowVariableReferences,
104 bool allowKeyFunction)
105 {
106 m_isMatchPattern = false;
107
108 m_requireLiterals = false;
109
110 m_allowVariableReferences = allowVariableReferences;
111
112 m_allowKeyFunction = allowKeyFunction;
113
114 m_xpath = &pathObj;
115
116 m_constructionContext = &constructionContext;
117
118 m_expression = &m_xpath->getExpression();
119
120 m_prefixResolver = &resolver;
121
122 m_locator = locator;
123
124 m_expression->reset();
125
126 tokenize(expression);
127
128 m_expression->appendOpCode(XPathExpression::eOP_XPATH);
129
130 nextToken();
131
132 Expr();
133
134 if (m_token.empty() == false)
135 {
136 error(XalanMessages::ExtraIllegalTokens);
137 }
138
139 m_xpath = 0;
140 m_constructionContext = 0;
141 m_expression = 0;
142 m_prefixResolver = 0;
143 m_locator = 0;
144 m_positionPredicateStack.clear();
145 m_namespaces.clear();
146 }
147
148
149
150 void
initMatchPattern(XPath & pathObj,XPathConstructionContext & constructionContext,const XalanDOMString & expression,const PrefixResolver & resolver,const Locator * locator,bool allowVariableReferences,bool allowKeyFunction)151 XPathProcessorImpl::initMatchPattern(
152 XPath& pathObj,
153 XPathConstructionContext& constructionContext,
154 const XalanDOMString& expression,
155 const PrefixResolver& resolver,
156 const Locator* locator,
157 bool allowVariableReferences,
158 bool allowKeyFunction)
159 {
160 m_isMatchPattern = true;
161
162 m_allowVariableReferences = allowVariableReferences;
163
164 m_allowKeyFunction = allowKeyFunction;
165
166 m_xpath = &pathObj;
167
168 m_constructionContext = &constructionContext;
169
170 m_expression = &m_xpath->getExpression();
171
172 m_prefixResolver = &resolver;
173
174 m_locator = locator;
175
176 m_expression->reset();
177
178 tokenize(expression);
179
180 m_expression->appendOpCode(XPathExpression::eOP_MATCHPATTERN);
181
182 nextToken();
183
184 Pattern();
185
186 if (m_token.empty() == false)
187 {
188 error(XalanMessages::ExtraIllegalTokens);
189 }
190
191 // Terminate for safety.
192 m_expression->appendOpCode(XPathExpression::eENDOP);
193
194 m_expression->shrink();
195
196 m_xpath = 0;
197 m_constructionContext = 0;
198 m_expression = 0;
199 m_prefixResolver = 0;
200 m_locator = 0;
201 m_positionPredicateStack.clear();
202 m_namespaces.clear();
203 }
204
205
206
207 void
tokenize(const XalanDOMString & pat)208 XPathProcessorImpl::tokenize(const XalanDOMString& pat)
209 {
210 assert(m_xpath != 0);
211 assert(m_expression != 0);
212 assert(m_constructionContext != 0);
213
214 m_expression->setCurrentPattern(m_constructionContext->getPooledString(pat));
215
216 const t_size_type nChars = pat.length();
217
218 t_size_type startSubstring = XalanDOMString::npos;
219 t_size_type posOfNSSep = XalanDOMString::npos;
220
221 const XPathConstructionContext::GetCachedString theGuard(*m_constructionContext);
222
223 XalanDOMString& theToken = theGuard.get();
224
225 for(t_size_type i = 0; i < nChars; i++)
226 {
227 XalanDOMChar c = pat[i];
228
229 switch(c)
230 {
231 case XalanUnicode::charQuoteMark:
232 {
233 if(startSubstring != XalanDOMString::npos)
234 {
235 if(XalanDOMString::npos != posOfNSSep)
236 {
237 posOfNSSep = mapNSTokens(pat, startSubstring, posOfNSSep, i);
238 }
239 else
240 {
241 substring(pat, theToken, startSubstring, i);
242
243 addToTokenQueue(theToken);
244 }
245 }
246
247 startSubstring = i;
248
249 for(++i; i < nChars && (c = pat[i]) != XalanUnicode::charQuoteMark; ++i);
250
251 if(c == XalanUnicode::charQuoteMark && i < nChars)
252 {
253 substring(pat, theToken, startSubstring, i + 1);
254
255 addToTokenQueue(theToken);
256
257 startSubstring = XalanDOMString::npos;
258 }
259 else
260 {
261 error(XalanMessages::UnterminatedStringLiteral);
262 }
263 }
264 break;
265
266 case XalanUnicode::charApostrophe:
267 {
268 if(startSubstring != XalanDOMString::npos)
269 {
270 if(XalanDOMString::npos != posOfNSSep)
271 {
272 posOfNSSep = mapNSTokens(pat, startSubstring, posOfNSSep, i);
273 }
274 else
275 {
276 substring(pat, theToken, startSubstring, i);
277
278 addToTokenQueue(theToken);
279 }
280 }
281
282 startSubstring = i;
283
284 for(++i; i < nChars && (c = pat[i]) != XalanUnicode::charApostrophe; ++i);
285
286 if(c == XalanUnicode::charApostrophe && i < nChars)
287 {
288 substring(pat, theToken, startSubstring, i + 1);
289
290 addToTokenQueue(theToken);
291
292 startSubstring = XalanDOMString::npos;
293 }
294 else
295 {
296 error(XalanMessages::UnterminatedStringLiteral);
297 }
298 }
299 break;
300
301 case XalanUnicode::charLF:
302 case XalanUnicode::charCR:
303 case XalanUnicode::charSpace:
304 case XalanUnicode::charHTab:
305 {
306 if(startSubstring != XalanDOMString::npos)
307 {
308 if(XalanDOMString::npos != posOfNSSep)
309 {
310 posOfNSSep = mapNSTokens(pat, startSubstring, posOfNSSep, i);
311 }
312 else
313 {
314 substring(pat, theToken, startSubstring, i);
315
316 addToTokenQueue(theToken);
317 }
318
319 startSubstring = XalanDOMString::npos;
320 }
321 }
322 break;
323
324 case XalanUnicode::charHyphenMinus:
325 {
326 if(!(startSubstring == XalanDOMString::npos))
327 {
328 break;
329 }
330 }
331 // fall-through on purpose
332
333 case XalanUnicode::charCommercialAt:
334 case XalanUnicode::charLeftParenthesis:
335 case XalanUnicode::charLeftSquareBracket:
336 case XalanUnicode::charRightParenthesis:
337 case XalanUnicode::charRightSquareBracket:
338 case XalanUnicode::charVerticalLine:
339 case XalanUnicode::charSolidus:
340 case XalanUnicode::charAsterisk:
341 case XalanUnicode::charPlusSign:
342 case XalanUnicode::charEqualsSign:
343 case XalanUnicode::charComma:
344 case XalanUnicode::charReverseSolidus: // Unused at the moment
345 case XalanUnicode::charCircumflexAccent: // Unused at the moment
346 case XalanUnicode::charExclamationMark: // Unused at the moment
347 case XalanUnicode::charDollarSign:
348 case XalanUnicode::charLessThanSign:
349 case XalanUnicode::charGreaterThanSign:
350 {
351 if(startSubstring != XalanDOMString::npos)
352 {
353 if(XalanDOMString::npos != posOfNSSep)
354 {
355 posOfNSSep = mapNSTokens(pat, startSubstring, posOfNSSep, i);
356 }
357 else
358 {
359 substring(pat, theToken, startSubstring, i);
360
361 addToTokenQueue(theToken);
362 }
363
364 startSubstring = XalanDOMString::npos;
365 }
366
367 substring(pat, theToken, i, i + 1);
368
369 addToTokenQueue(theToken);
370 }
371 break;
372
373 case XalanUnicode::charColon:
374 {
375 if(posOfNSSep == i - 1 && i > 0)
376 {
377 if(startSubstring != XalanDOMString::npos)
378 {
379 if (startSubstring < i - 1)
380 {
381 substring(pat, theToken, startSubstring, i - 1);
382
383 addToTokenQueue(theToken);
384 }
385 }
386
387 startSubstring = XalanDOMString::npos;
388 posOfNSSep = XalanDOMString::npos;
389
390 substring(pat, theToken, i - 1, i + 1);
391
392 addToTokenQueue(theToken);
393 break;
394 }
395 else
396 {
397 posOfNSSep = i;
398 }
399 }
400 // fall through on purpose
401
402
403 default:
404 {
405 if(XalanDOMString::npos == startSubstring)
406 {
407 startSubstring = i;
408
409 if (XalanXMLChar::isDigit(c) == true)
410 {
411 bool gotFullStop = false;
412
413 while(i < nChars - 1)
414 {
415 ++i;
416
417 const XalanDOMChar currentChar = pat[i];
418
419 if (currentChar == XalanUnicode::charFullStop)
420 {
421 if (gotFullStop == false)
422 {
423 gotFullStop = true;
424 }
425 else
426 {
427 --i;
428
429 break;
430 }
431 }
432 else if (XalanXMLChar::isDigit(currentChar) == false)
433 {
434 --i;
435
436 break;
437 }
438 }
439
440 substring(pat, theToken, startSubstring, i + 1);
441
442 addToTokenQueue(theToken);
443
444 startSubstring = XalanDOMString::npos;
445 }
446 }
447 }
448 }
449 }
450
451 if(startSubstring != XalanDOMString::npos)
452 {
453 if(XalanDOMString::npos != posOfNSSep)
454 {
455 posOfNSSep = mapNSTokens(pat, startSubstring, posOfNSSep, nChars);
456 }
457 else
458 {
459 substring(pat, theToken, startSubstring, nChars);
460
461 addToTokenQueue(theToken);
462 }
463 }
464
465 if (0 == m_expression->tokenQueueSize())
466 {
467 error(XalanMessages::EmptyExpression);
468
469 }
470
471 m_expression->resetTokenPosition();
472 }
473
474
475
476 void
addToTokenQueue(const XalanDOMString & s) const477 XPathProcessorImpl::addToTokenQueue(const XalanDOMString& s) const
478 {
479 assert(m_xpath != 0);
480 assert(m_expression != 0);
481
482 m_expression->pushToken(m_constructionContext->getPooledString(s));
483 }
484
485
486
487 void
replaceTokenWithNamespaceToken() const488 XPathProcessorImpl::replaceTokenWithNamespaceToken() const
489 {
490 assert(m_xpath != 0);
491 assert(m_expression != 0);
492 assert(m_token.empty() == false);
493
494 StringToStringMapType::const_iterator i = m_namespaces.find(m_token);
495 assert(i != m_namespaces.end());
496
497 const XalanDOMString* const theNamespaceURI = (*i).second;
498 assert(theNamespaceURI != 0 && theNamespaceURI->empty() == false);
499
500 m_expression->replaceRelativeToken(
501 1,
502 XPathExpression::eRelativeBackward,
503 m_constructionContext->getPooledString(*theNamespaceURI));
504 }
505
506
507
508 XPathProcessorImpl::t_size_type
mapNSTokens(const XalanDOMString & pat,t_size_type startSubstring,t_size_type posOfNSSep,t_size_type posOfScan)509 XPathProcessorImpl::mapNSTokens(
510 const XalanDOMString& pat,
511 t_size_type startSubstring,
512 t_size_type posOfNSSep,
513 t_size_type posOfScan)
514 {
515 assert(m_prefixResolver != 0);
516
517 const XPathConstructionContext::GetCachedString theGuard(*m_constructionContext);
518
519 XalanDOMString& scratchString = theGuard.get();
520
521 // Get the prefix of the QName...
522 scratchString.assign(pat, startSubstring, posOfNSSep - startSubstring);
523
524 if (XalanQName::isValidNCName(scratchString) == false)
525 {
526 error(
527 XalanMessages::IsNotValidNCName_1Param,
528 scratchString);
529
530 }
531
532 const XalanDOMString* const uName =
533 m_prefixResolver->getNamespaceForPrefix(scratchString);
534
535 if(uName == 0)
536 {
537 error(
538 XalanMessages::PrefixIsNotDeclared_1Param,
539 scratchString);
540 }
541 else if (uName->empty() == true)
542 {
543 error(
544 XalanMessages::PrefixIsBoundToZeroLengthURI_1Param,
545 scratchString);
546 }
547 else
548 {
549 m_namespaces[scratchString] = uName;
550
551 addToTokenQueue(scratchString);
552
553 addToTokenQueue(DOMServices::s_XMLNamespaceSeparatorString);
554
555 // If there's no local part, then don't bother. We need to check
556 // this because '*' tokenizes separately, which means "ns:*" tokenizes
557 // differently from "ns:foo". In the first case, '*' will be tokenized
558 // _after_ this code, in the second 'ns:foo' will be split into tokens
559 // here...
560 if(posOfNSSep + 1 < posOfScan)
561 {
562 scratchString.assign(pat, posOfNSSep + 1, posOfScan - (posOfNSSep + 1));
563
564 assert(scratchString.empty() == false);
565
566 if (XalanQName::isValidNCName(scratchString) == false)
567 {
568 error(
569 XalanMessages::NotValidNCName_1Param,
570 scratchString);
571 }
572 else
573 {
574 addToTokenQueue(scratchString);
575 }
576 }
577 }
578
579 return XalanDOMString::npos;
580 }
581
582
583
584 bool
tokenIs(const XalanDOMString & s) const585 XPathProcessorImpl::tokenIs(const XalanDOMString& s) const
586 {
587 return equals(m_token, s);
588 }
589
590
591
592 bool
tokenIs(const XalanDOMChar * s) const593 XPathProcessorImpl::tokenIs(const XalanDOMChar* s) const
594 {
595 return equals(m_token, s);
596 }
597
598
599
600 bool
tokenIs(XalanDOMChar c) const601 XPathProcessorImpl::tokenIs(XalanDOMChar c) const
602 {
603 return m_tokenChar == c ? true : false;
604 }
605
606
607
608 bool
lookahead(XalanDOMChar c,int n) const609 XPathProcessorImpl::lookahead(
610 XalanDOMChar c,
611 int n) const
612 {
613 const XalanDOMString& tok =
614 getTokenRelative(n - 1);
615
616 if (tok.length() == 1 &&
617 tok[0] == c)
618 {
619 return true;
620 }
621 else
622 {
623 return false;
624 }
625 }
626
627
628
629 bool
lookahead(const XalanDOMChar * s,int n) const630 XPathProcessorImpl::lookahead(
631 const XalanDOMChar* s,
632 int n) const
633 {
634 assert(s != 0);
635
636 const XalanDOMString& tok =
637 getTokenRelative(n - 1);
638
639 return equals(tok, s);
640 }
641
642
643
644 bool
lookahead(const XalanDOMString & s,int n) const645 XPathProcessorImpl::lookahead(
646 const XalanDOMString& s,
647 int n) const
648 {
649 const XalanDOMString& tok =
650 getTokenRelative(n - 1);
651
652 return equals(tok, s);
653 }
654
655
656
657 bool
lookbehind(char c,int n) const658 XPathProcessorImpl::lookbehind(
659 char c,
660 int n) const
661 {
662 const XalanDOMString& tok =
663 getTokenRelative(-(n + 1));
664
665 if (tok.length() == 1 &&
666 tok[0] == c)
667 {
668 return true;
669 }
670 else
671 {
672 return false;
673 }
674 }
675
676
677
678 bool
lookbehindHasToken(int n) const679 XPathProcessorImpl::lookbehindHasToken(int n) const
680 {
681 const XalanDOMString& tok =
682 getTokenRelative(-(n + 1));
683
684 const XalanDOMChar c0 = tok.length() == 0 ?
685 XalanUnicode::charVerticalLine : tok[0];
686
687 return c0 == XalanUnicode::charVerticalLine ? false : true;
688 }
689
690
691
692 bool
nextToken()693 XPathProcessorImpl::nextToken()
694 {
695 assert(m_expression != 0);
696
697 const XToken* const theNextToken =
698 m_expression->getNextToken();
699
700 if (theNextToken == 0)
701 {
702 m_token.clear();
703 }
704 else
705 {
706 m_token = theNextToken->str();
707 }
708
709 if(m_token.empty() == false)
710 {
711 m_tokenChar = m_token[0];
712
713 return true;
714 }
715 else
716 {
717 m_tokenChar = 0;
718
719 return false;
720 }
721 }
722
723
724
725 void
prevToken()726 XPathProcessorImpl::prevToken()
727 {
728 assert(m_expression != 0);
729
730 const XToken* const thePreviousToken =
731 m_expression->getPreviousToken();
732
733 m_token = thePreviousToken == 0 ? s_emptyString : thePreviousToken->str();
734
735 if(m_token.empty() == false)
736 {
737 m_tokenChar = m_token[0];
738 }
739 else
740 {
741 m_tokenChar = 0;
742 }
743 }
744
745
746
747 const XalanDOMString&
getTokenRelative(int theOffset) const748 XPathProcessorImpl::getTokenRelative(int theOffset) const
749 {
750 assert(m_expression != 0);
751
752 const XToken* theToken = 0;
753
754 if (theOffset < 0)
755 {
756 theToken =
757 m_expression->getRelativeToken(
758 XPathExpression::TokenQueueSizeType(-theOffset),
759 XPathExpression::eRelativeBackward);
760 }
761 else
762 {
763 theToken =
764 m_expression->getRelativeToken(
765 XPathExpression::TokenQueueSizeType(theOffset),
766 XPathExpression::eRelativeForward);
767 }
768
769 return theToken == 0 ? s_emptyString : theToken->str();
770 }
771
772
773
774 void
consumeExpected(XalanDOMChar expected)775 XPathProcessorImpl::consumeExpected(XalanDOMChar expected)
776 {
777 if(tokenIs(expected) == true)
778 {
779 nextToken();
780 }
781 else
782 {
783 error(
784 XalanMessages::NotFoundWhatExpected_2Param,
785 expected,
786 m_token);
787 }
788 }
789
790
791
792 typedef XPathConstructionContext::GetCachedString GetCachedString;
793
794
795
796 void
error(const XalanDOMString & msg) const797 XPathProcessorImpl::error(const XalanDOMString& msg) const
798 {
799 assert(m_constructionContext != 0);
800
801 const GetCachedString theGuard(*m_constructionContext);
802
803 XalanDOMString& emsg = theGuard.get();
804
805 if (m_expression == 0)
806 {
807 emsg = msg;
808 }
809 else
810 {
811 const XalanDOMString& theCurrentPattern =
812 m_expression->getCurrentPattern();
813
814 DOMStringPrintWriter thePrintWriter(emsg);
815
816 thePrintWriter.print(msg);
817
818 thePrintWriter.println();
819
820 if (theCurrentPattern.empty() == false)
821 {
822 const GetCachedString theGuard(*m_constructionContext);
823
824 XalanDOMString& theResult = theGuard.get();
825
826 const XalanMessages::Codes theCode =
827 m_isMatchPattern == true ?
828 XalanMessages::PatternIs_1Param :
829 XalanMessages::ExpressionIs_1Param;
830
831 thePrintWriter.print(
832 XalanMessageLoader::getMessage(
833 theResult,
834 theCode,
835 theCurrentPattern));
836 }
837
838 // Back up one token, since we've consumed one...
839 m_expression->getPreviousToken();
840
841 // Ask the expression to dump the remaining tokens...
842 m_expression->dumpRemainingTokenQueue(thePrintWriter);
843 }
844
845 m_constructionContext->problem(
846 XPathConstructionContext::eXPath,
847 XPathConstructionContext::eError,
848 emsg,
849 m_locator,
850 0);
851
852 throw XPathParserException(
853 emsg,
854 m_constructionContext->getMemoryManager(),
855 m_locator);
856 }
857
858
859
860 void
error(XalanMessages::Codes theCode) const861 XPathProcessorImpl::error(XalanMessages::Codes theCode) const
862 {
863 assert(m_constructionContext != 0);
864
865 const GetCachedString theGuard(*m_constructionContext);
866
867 error(
868 XalanMessageLoader::getMessage(
869 theGuard.get(),
870 theCode));
871 }
872
873
874
875 void
error(XalanMessages::Codes theCode,const XalanDOMString & theToken) const876 XPathProcessorImpl::error(
877 XalanMessages::Codes theCode,
878 const XalanDOMString& theToken) const
879 {
880 assert(m_constructionContext != 0);
881
882 const GetCachedString theGuard(*m_constructionContext);
883
884 error(
885 XalanMessageLoader::getMessage(
886 theGuard.get(),
887 theCode,
888 theToken));
889 }
890
891
892
893 void
error(XalanMessages::Codes theCode,const XalanDOMChar * theToken) const894 XPathProcessorImpl::error(
895 XalanMessages::Codes theCode,
896 const XalanDOMChar* theToken) const
897 {
898 assert(m_constructionContext != 0);
899
900 const GetCachedString theGuard(*m_constructionContext);
901
902 error(
903 XalanMessageLoader::getMessage(
904 theGuard.get(),
905 theCode,
906 theToken));
907 }
908
909
910
911 void
error(XalanMessages::Codes theCode,XalanDOMChar theToken1,const XalanDOMString & theToken2) const912 XPathProcessorImpl::error(
913 XalanMessages::Codes theCode,
914 XalanDOMChar theToken1,
915 const XalanDOMString& theToken2) const
916 {
917 assert(m_constructionContext != 0);
918
919 const GetCachedString theGuard(*m_constructionContext);
920
921 XalanDOMString& theResult = theGuard.get();
922
923 error(
924 XalanMessageLoader::getMessage(
925 theResult,
926 theCode,
927 XalanDOMString(1, theToken1, theResult.getMemoryManager()),
928 theToken2));
929 }
930
931
932
933 void
Expr()934 XPathProcessorImpl::Expr()
935 {
936 OrExpr();
937 }
938
939
940
941 void
OrExpr()942 XPathProcessorImpl::OrExpr()
943 {
944 const int opPos = m_expression->opCodeMapLength();
945
946 AndExpr();
947
948 if(tokenIs(s_orString) == true)
949 {
950 if (nextToken() == false)
951 {
952 error(XalanMessages::ExpectedToken);
953 }
954 else
955 {
956 m_expression->insertOpCode(
957 XPathExpression::eOP_OR,
958 opPos);
959
960 OrExpr();
961
962 m_expression->updateOpCodeLength(
963 XPathExpression::eOP_OR,
964 opPos);
965 }
966 }
967 }
968
969
970
971 void
AndExpr()972 XPathProcessorImpl::AndExpr()
973 {
974 const int opPos = m_expression->opCodeMapLength();
975
976 EqualityExpr();
977
978 if(tokenIs(s_andString) == true)
979 {
980 if (nextToken() == false)
981 {
982 error(XalanMessages::ExpectedToken);
983 }
984 else
985 {
986 m_expression->insertOpCode(
987 XPathExpression::eOP_AND,
988 opPos);
989
990 AndExpr();
991
992 m_expression->updateOpCodeLength(
993 XPathExpression::eOP_AND,
994 opPos);
995 }
996 }
997 }
998
999
1000
1001 int
EqualityExpr(int opCodePos)1002 XPathProcessorImpl::EqualityExpr(int opCodePos)
1003 {
1004 int theOpDisplacement = 0;
1005
1006 const int opPos = opCodePos != -1 ? opCodePos : m_expression->opCodeMapLength();
1007
1008 RelationalExpr();
1009
1010 XPathExpression::eOpCodes theOpCode =
1011 XPathExpression::eENDOP;
1012
1013 bool foundToken = false;
1014
1015 if(tokenIs(XalanUnicode::charExclamationMark) &&
1016 lookahead(XalanUnicode::charEqualsSign, 1))
1017 {
1018 nextToken();
1019
1020 foundToken = nextToken();
1021
1022 theOpCode = XPathExpression::eOP_NOTEQUALS;
1023 }
1024 else if(tokenIs(XalanUnicode::charEqualsSign))
1025 {
1026 foundToken = nextToken();
1027
1028 theOpCode = XPathExpression::eOP_EQUALS;
1029 }
1030
1031 if (theOpCode != XPathExpression::eENDOP)
1032 {
1033 if (foundToken == false)
1034 {
1035 error(XalanMessages::ExpectedToken);
1036 }
1037 else
1038 {
1039 // Save the number of bytes we inserted
1040 // into the map.
1041 const int theLocalDisplacement =
1042 m_expression->insertOpCode(theOpCode,
1043 opPos);
1044
1045 // Update the length
1046 m_expression->updateOpCodeLength(theOpCode,
1047 opPos);
1048
1049 // Do the right term of the expression.
1050 theOpDisplacement += EqualityExpr(opPos);
1051
1052 // If there's any displacement from the right
1053 // term, update the length for a shift. Otherwise,
1054 // just update the length.
1055 if (theOpDisplacement > 0)
1056 {
1057 m_expression->updateShiftedOpCodeLength(
1058 theOpCode,
1059 opPos,
1060 opPos + theOpDisplacement);
1061 }
1062 else
1063 {
1064 m_expression->updateOpCodeLength(
1065 theOpCode,
1066 opPos);
1067 }
1068
1069 // Accumulate the displacement.
1070 theOpDisplacement += theLocalDisplacement;
1071 }
1072 }
1073
1074 return theOpDisplacement;
1075 }
1076
1077
1078
1079 int
RelationalExpr(int opCodePos)1080 XPathProcessorImpl::RelationalExpr(int opCodePos)
1081 {
1082 int theOpDisplacement = 0;
1083
1084 const int opPos = opCodePos != -1 ? opCodePos : m_expression->opCodeMapLength();
1085
1086 AdditiveExpr();
1087
1088 if(m_token.empty() == false)
1089 {
1090 bool foundToken = false;
1091
1092 XPathExpression::eOpCodes theOpCode =
1093 XPathExpression::eENDOP;
1094
1095 if(tokenIs(XalanUnicode::charLessThanSign) == true)
1096 {
1097 foundToken = nextToken();
1098
1099 if(tokenIs(XalanUnicode::charEqualsSign) == true)
1100 {
1101 foundToken = nextToken();
1102
1103 theOpCode = XPathExpression::eOP_LTE;
1104 }
1105 else
1106 {
1107 theOpCode = XPathExpression::eOP_LT;
1108 }
1109 }
1110 else if(tokenIs(XalanUnicode::charGreaterThanSign) == true)
1111 {
1112 foundToken = nextToken();
1113
1114 if(tokenIs(XalanUnicode::charEqualsSign) == true)
1115 {
1116 foundToken = nextToken();
1117
1118 theOpCode = XPathExpression::eOP_GTE;
1119 }
1120 else
1121 {
1122 theOpCode = XPathExpression::eOP_GT;
1123 }
1124 }
1125
1126 if (theOpCode != XPathExpression::eENDOP)
1127 {
1128 if (foundToken == false)
1129 {
1130 error(XalanMessages::ExpectedToken);
1131 }
1132 else
1133 {
1134 // Save the number of bytes we inserted
1135 // into the map.
1136 const int theLocalDisplacement =
1137 m_expression->insertOpCode(theOpCode,
1138 opPos);
1139
1140 // Update the length
1141 m_expression->updateOpCodeLength(theOpCode,
1142 opPos);
1143
1144 // Do the right term of the expression.
1145 theOpDisplacement += RelationalExpr(opPos);
1146
1147 // If there's any displacement from the right
1148 // term, update the length for a shift. Otherwise,
1149 // just update the length.
1150 if (theOpDisplacement > 0)
1151 {
1152 m_expression->updateShiftedOpCodeLength(
1153 theOpCode,
1154 opPos,
1155 opPos + theOpDisplacement);
1156 }
1157 else
1158 {
1159 m_expression->updateOpCodeLength(
1160 theOpCode,
1161 opPos);
1162 }
1163
1164 // Accumulate the displacement.
1165 theOpDisplacement += theLocalDisplacement;
1166 }
1167 }
1168 }
1169
1170 return theOpDisplacement;
1171 }
1172
1173
1174
1175 int
AdditiveExpr(int opCodePos)1176 XPathProcessorImpl::AdditiveExpr(int opCodePos)
1177 {
1178 int theOpDisplacement = 0;
1179
1180 const int opPos = opCodePos != -1 ? opCodePos : m_expression->opCodeMapLength();
1181
1182 MultiplicativeExpr();
1183
1184 if(m_token.empty() == false)
1185 {
1186 XPathExpression::eOpCodes theOpCode =
1187 XPathExpression::eENDOP;
1188
1189 if(tokenIs(XalanUnicode::charPlusSign) == true)
1190 {
1191 theOpCode = XPathExpression::eOP_PLUS;
1192 }
1193 else if(tokenIs(XalanUnicode::charHyphenMinus) == true)
1194 {
1195 theOpCode = XPathExpression::eOP_MINUS;
1196 }
1197
1198 if (theOpCode != XPathExpression::eENDOP)
1199 {
1200 if (nextToken() == false)
1201 {
1202 error(XalanMessages::ExpectedToken);
1203 }
1204 else
1205 {
1206 // Save the number of bytes we inserted
1207 // into the map.
1208 const int theLocalDisplacement =
1209 m_expression->insertOpCode(theOpCode,
1210 opPos);
1211
1212 // Update the length
1213 m_expression->updateOpCodeLength(theOpCode,
1214 opPos);
1215
1216 // Do the right term of the expression.
1217 theOpDisplacement += AdditiveExpr(opPos);
1218
1219 // If there's any displacement from the right
1220 // term, update the length for a shift. Otherwise,
1221 // just update the length.
1222 if (theOpDisplacement > 0)
1223 {
1224 m_expression->updateShiftedOpCodeLength(
1225 theOpCode,
1226 opPos,
1227 opPos + theOpDisplacement);
1228 }
1229 else
1230 {
1231 m_expression->updateOpCodeLength(
1232 theOpCode,
1233 opPos);
1234 }
1235
1236 // Accumulate the displacement.
1237 theOpDisplacement += theLocalDisplacement;
1238 }
1239 }
1240 }
1241
1242 return theOpDisplacement;
1243 }
1244
1245
1246
1247 int
MultiplicativeExpr(int opCodePos)1248 XPathProcessorImpl::MultiplicativeExpr(int opCodePos)
1249 {
1250 int theOpDisplacement = 0;
1251
1252 const int opPos = opCodePos != -1 ? opCodePos : m_expression->opCodeMapLength();
1253
1254 UnaryExpr();
1255
1256 if(m_token.empty() == false)
1257 {
1258 XPathExpression::eOpCodes theOpCode =
1259 XPathExpression::eENDOP;
1260
1261 if(tokenIs(XalanUnicode::charAsterisk) == true)
1262 {
1263 theOpCode = XPathExpression::eOP_MULT;
1264 }
1265 else if(tokenIs(s_divString) == true)
1266 {
1267 theOpCode = XPathExpression::eOP_DIV;
1268 }
1269 else if(tokenIs(s_modString) == true)
1270 {
1271 theOpCode = XPathExpression::eOP_MOD;
1272 }
1273
1274 if (theOpCode != XPathExpression::eENDOP)
1275 {
1276 if (nextToken() == false)
1277 {
1278 error(XalanMessages::ExpectedToken);
1279 }
1280 else
1281 {
1282 // Save the number of bytes we inserted
1283 // into the map.
1284 const int theLocalDisplacement =
1285 m_expression->insertOpCode(theOpCode,
1286 opPos);
1287
1288 // Update the length
1289 m_expression->updateOpCodeLength(theOpCode,
1290 opPos);
1291
1292 // Do the right term of the expression.
1293 theOpDisplacement += MultiplicativeExpr(opPos);
1294
1295 // If there's any displacement from the right
1296 // term, update the length for a shift. Otherwise,
1297 // just update the length.
1298 if (theOpDisplacement > 0)
1299 {
1300 m_expression->updateShiftedOpCodeLength(
1301 theOpCode,
1302 opPos,
1303 opPos + theOpDisplacement);
1304 }
1305 else
1306 {
1307 m_expression->updateOpCodeLength(
1308 theOpCode,
1309 opPos);
1310 }
1311
1312 // Accumulate the displacement.
1313 theOpDisplacement += theLocalDisplacement;
1314 }
1315 }
1316 }
1317
1318 return theOpDisplacement;
1319 }
1320
1321
1322
1323 void
UnaryExpr()1324 XPathProcessorImpl::UnaryExpr()
1325 {
1326 const int opPos = m_expression->opCodeMapLength();
1327
1328 bool isNeg = false;
1329
1330 if(tokenIs(XalanUnicode::charHyphenMinus) == true)
1331 {
1332 nextToken();
1333
1334 m_expression->insertOpCode(XPathExpression::eOP_NEG,
1335 opPos);
1336
1337 isNeg = true;
1338 }
1339
1340 UnionExpr();
1341
1342 if(isNeg == true)
1343 {
1344 m_expression->updateOpCodeLength(XPathExpression::eOP_NEG,
1345 opPos);
1346 }
1347 }
1348
1349
1350
1351 void
UnionExpr()1352 XPathProcessorImpl::UnionExpr()
1353 {
1354 const int opPos = m_expression->opCodeMapLength();
1355
1356 bool continueOrLoop = true;
1357 bool foundUnion = false;
1358
1359 do
1360 {
1361 PathExpr();
1362
1363 if(tokenIs(XalanUnicode::charVerticalLine) == true)
1364 {
1365 if(false == foundUnion)
1366 {
1367 foundUnion = true;
1368
1369 m_expression->insertOpCode(XPathExpression::eOP_UNION,
1370 opPos);
1371 }
1372
1373 nextToken();
1374 }
1375 else
1376 {
1377 if (foundUnion == true)
1378 {
1379 // Terminate for safety.
1380 m_expression->appendOpCode(XPathExpression::eENDOP);
1381 }
1382
1383 break;
1384 }
1385 }
1386 while(continueOrLoop == true);
1387
1388 m_expression->updateOpCodeLength(opPos);
1389 }
1390
1391
1392
1393 void
PathExpr()1394 XPathProcessorImpl::PathExpr()
1395 {
1396 assert(m_expression != 0);
1397
1398 const int opPos = m_expression->opCodeMapLength();
1399
1400 FilterExpr();
1401
1402 if(tokenIs(XalanUnicode::charSolidus) == true)
1403 {
1404 nextToken();
1405
1406 m_expression->insertOpCode(
1407 XPathExpression::eOP_LOCATIONPATH,
1408 opPos);
1409
1410 RelativeLocationPath();
1411
1412 m_expression->appendOpCode(XPathExpression::eENDOP);
1413
1414 m_expression->updateOpCodeLength(
1415 XPathExpression::eOP_LOCATIONPATH,
1416 opPos);
1417 }
1418 }
1419
1420
1421
1422 void
FilterExpr()1423 XPathProcessorImpl::FilterExpr()
1424 {
1425 assert(m_expression != 0);
1426
1427 const int opPos = m_expression->opCodeMapLength();
1428
1429 // const bool isFunc = lookahead(XalanUnicode::charLeftParenthesis, 1);
1430
1431 PrimaryExpr();
1432
1433 if(tokenIs(XalanUnicode::charLeftSquareBracket) == true)
1434 {
1435 m_expression->insertOpCode(XPathExpression::eOP_LOCATIONPATH,
1436 opPos);
1437
1438 while(tokenIs(XalanUnicode::charLeftSquareBracket) == true)
1439 {
1440 Predicate();
1441 }
1442
1443 if(tokenIs(XalanUnicode::charSolidus) == true)
1444 {
1445 nextToken();
1446
1447 RelativeLocationPath();
1448 }
1449
1450 // Terminate for safety.
1451 m_expression->appendOpCode(XPathExpression::eENDOP);
1452
1453 m_expression->updateOpCodeLength(XPathExpression::eOP_LOCATIONPATH,
1454 opPos);
1455 }
1456 }
1457
1458
1459
1460 void
PrimaryExpr()1461 XPathProcessorImpl::PrimaryExpr()
1462 {
1463 assert(m_expression != 0);
1464
1465 const int opPos = m_expression->opCodeMapLength();
1466
1467 if(tokenIs(XalanUnicode::charApostrophe) == true ||
1468 tokenIs(XalanUnicode::charQuoteMark) == true)
1469 {
1470 m_expression->appendOpCode(XPathExpression::eOP_LITERAL);
1471
1472 Literal();
1473
1474 m_expression->updateOpCodeLength(
1475 XPathExpression::eOP_LITERAL,
1476 opPos);
1477 }
1478 else if(tokenIs(XalanUnicode::charDollarSign) == true)
1479 {
1480 nextToken(); // consume '$'
1481
1482 if (m_allowVariableReferences == false)
1483 {
1484 error(XalanMessages::VariableReferenceNotAllowed);
1485 }
1486 else
1487 {
1488 m_expression->appendOpCode(XPathExpression::eOP_VARIABLE);
1489
1490 QName();
1491
1492 m_expression->updateOpCodeLength(
1493 XPathExpression::eOP_VARIABLE,
1494 opPos);
1495 }
1496 }
1497 else if(tokenIs(XalanUnicode::charLeftParenthesis) == true)
1498 {
1499 nextToken();
1500
1501 m_expression->appendOpCode(XPathExpression::eOP_GROUP);
1502
1503 Expr();
1504
1505 consumeExpected(XalanUnicode::charRightParenthesis);
1506
1507 m_expression->updateOpCodeLength(
1508 XPathExpression::eOP_GROUP,
1509 opPos);
1510 }
1511 else if((tokenIs(XalanUnicode::charFullStop) == true &&
1512 m_token.length() > 1 &&
1513 XalanXMLChar::isDigit(m_token[1]) == true) ||
1514 XalanXMLChar::isDigit(m_tokenChar) == true)
1515 {
1516 m_expression->appendOpCode(XPathExpression::eOP_NUMBERLIT);
1517
1518 Number();
1519
1520 m_expression->updateOpCodeLength(
1521 XPathExpression::eOP_NUMBERLIT,
1522 opPos);
1523 }
1524 else if(lookahead(XalanUnicode::charLeftParenthesis, 1) == true ||
1525 (lookahead(XalanUnicode::charColon, 1) == true && lookahead(XalanUnicode::charLeftParenthesis, 3) == true))
1526 {
1527 FunctionCall();
1528 }
1529 else
1530 {
1531 LocationPath();
1532 }
1533 }
1534
1535
1536
1537 void
Argument()1538 XPathProcessorImpl::Argument()
1539 {
1540 assert(m_expression != 0);
1541
1542 if (m_requireLiterals == false ||
1543 isCurrentLiteral() == true)
1544 {
1545 Expr();
1546 }
1547 else
1548 {
1549 error(XalanMessages::LiteralArgumentIsRequired);
1550 }
1551 }
1552
1553
1554
1555 int
FunctionCallArguments()1556 XPathProcessorImpl::FunctionCallArguments()
1557 {
1558 int argCount = 0;
1559
1560 consumeExpected(XalanUnicode::charLeftParenthesis);
1561
1562 while(tokenIs(XalanUnicode::charRightParenthesis) == false &&
1563 m_token.empty() == false)
1564 {
1565 if(tokenIs(XalanUnicode::charComma) == true)
1566 {
1567 error(XalanMessages::NoPrecedingArgument);
1568 }
1569
1570 Argument();
1571
1572 ++argCount;
1573
1574 if(tokenIs(XalanUnicode::charRightParenthesis) == false)
1575 {
1576 consumeExpected(XalanUnicode::charComma);
1577
1578 if(tokenIs(XalanUnicode::charRightParenthesis) == true)
1579 {
1580 error(XalanMessages::NoFollowingArgument);
1581 }
1582 }
1583 }
1584
1585 consumeExpected(XalanUnicode::charRightParenthesis);
1586
1587 return argCount;
1588 }
1589
1590
1591
1592 void
FunctionCall()1593 XPathProcessorImpl::FunctionCall()
1594 {
1595 assert(m_expression != 0);
1596
1597 const int opPos = m_expression->opCodeMapLength();
1598
1599 if(lookahead(XalanUnicode::charColon, 1) == true)
1600 {
1601 m_expression->appendOpCode(XPathExpression::eOP_EXTFUNCTION);
1602
1603 XPathExpression::OpCodeMapValueVectorType theArgs(2, 0, m_constructionContext->getMemoryManager());
1604
1605 // Replace the token in the queue with the actual namespace URI...
1606 replaceTokenWithNamespaceToken();
1607
1608 theArgs[0] = m_expression->getTokenPosition() - 1;
1609
1610 nextToken();
1611
1612 consumeExpected(XalanUnicode::charColon);
1613
1614 theArgs[1] = m_expression->getTokenPosition() - 1;
1615
1616 m_expression->setOpCodeArgs(XPathExpression::eOP_EXTFUNCTION,
1617 opPos,
1618 theArgs);
1619
1620 nextToken();
1621
1622 FunctionCallArguments();
1623 }
1624 else
1625 {
1626 if (isValidFunction(m_token) == false)
1627 {
1628 error(
1629 XalanMessages::CouldNotFindFunction_1Param,
1630 m_token);
1631
1632 }
1633
1634 const XPathExpression::eOpCodes funcTok = getFunctionToken(m_token);
1635
1636 switch(funcTok)
1637 {
1638 case XPathExpression::eNODETYPE_PI:
1639 case XPathExpression::eNODETYPE_COMMENT:
1640 case XPathExpression::eNODETYPE_TEXT:
1641 case XPathExpression::eNODETYPE_NODE:
1642 LocationPath();
1643 // ************** Nasty return here!!! *********************** //
1644 return;
1645 break;
1646
1647 case XPathExpression::eOP_FUNCTION_POSITION:
1648 FunctionPosition();
1649 break;
1650
1651 case XPathExpression::eOP_FUNCTION_LAST:
1652 FunctionLast();
1653 break;
1654
1655 case XPathExpression::eOP_FUNCTION_COUNT:
1656 FunctionCount();
1657 break;
1658
1659 case XPathExpression::eOP_FUNCTION_NOT:
1660 FunctionNot();
1661 break;
1662
1663 case XPathExpression::eOP_FUNCTION_TRUE:
1664 FunctionTrue();
1665 break;
1666
1667 case XPathExpression::eOP_FUNCTION_FALSE:
1668 FunctionFalse();
1669 break;
1670
1671 case XPathExpression::eOP_FUNCTION_BOOLEAN:
1672 FunctionBoolean();
1673 break;
1674
1675 case XPathExpression::eOP_FUNCTION_NAME_0:
1676 FunctionName(opPos);
1677 break;
1678
1679 case XPathExpression::eOP_FUNCTION_LOCALNAME_0:
1680 FunctionLocalName(opPos);
1681 break;
1682
1683 case XPathExpression::eOP_FUNCTION_NUMBER_0:
1684 FunctionNumber(opPos);
1685 break;
1686
1687 case XPathExpression::eOP_FUNCTION_FLOOR:
1688 FunctionFloor();
1689 break;
1690
1691 case XPathExpression::eOP_FUNCTION_CEILING:
1692 FunctionCeiling();
1693 break;
1694
1695 case XPathExpression::eOP_FUNCTION_ROUND:
1696 FunctionRound();
1697 break;
1698
1699 case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0:
1700 FunctionStringLength(opPos);
1701 break;
1702
1703 case XPathExpression::eOP_FUNCTION_SUM:
1704 FunctionSum();
1705 break;
1706
1707 default:
1708 {
1709 // The position must be at least 1, since
1710 // we've looked at a token.
1711 assert(m_expression->getTokenPosition() > 0);
1712
1713 if (m_allowKeyFunction == false &&
1714 m_token == XPathFunctionTable::s_key)
1715 {
1716 error(XalanMessages::KeyFunctionNotAllowed);
1717 }
1718
1719 int theFunctionID =
1720 XPath::getFunctionTable().nameToID(m_token);
1721
1722 if ((equals(m_token, s_positionString) == true ||
1723 equals(m_token, s_lastString) == true) &&
1724 m_positionPredicateStack.empty() == false)
1725 {
1726 m_positionPredicateStack.back() = true;
1727 }
1728
1729 XPathExpression::OpCodeMapValueVectorType theArgs(2, 0, m_constructionContext->getMemoryManager());
1730
1731 theArgs[0] = theFunctionID;
1732 theArgs[1] = 0;
1733
1734 m_expression->appendOpCode(
1735 XPathExpression::eOP_FUNCTION,
1736 theArgs);
1737
1738 nextToken();
1739
1740 // Get the arguments, and the argument count...
1741 const int argCount = FunctionCallArguments();
1742
1743 assert(m_expression->getOpCodeMapValue(opPos + 3) == 0);
1744
1745 // update the arg count in the op map...
1746 m_expression->setOpCodeMapValue(opPos + 3, argCount);
1747 }
1748 }
1749 }
1750
1751 // Terminate for safety.
1752 m_expression->appendOpCode(XPathExpression::eENDOP);
1753
1754 m_expression->updateOpCodeLength(opPos);
1755 }
1756
1757
1758
1759 void
FunctionPosition()1760 XPathProcessorImpl::FunctionPosition()
1761 {
1762 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_POSITION);
1763
1764 // Consume the name...
1765 nextToken();
1766
1767 // Get the arguments, and the argument count...
1768 const int argCount = FunctionCallArguments();
1769
1770 if (argCount != 0)
1771 {
1772 XalanDOMString theResult(m_constructionContext->getMemoryManager());
1773
1774 error(
1775 XalanMessages::FunctionDoesNotAcceptAnyArguments_1Param,
1776 XPathFunctionTable::s_position);
1777 }
1778 else
1779 {
1780 if (m_positionPredicateStack.empty() == false)
1781 {
1782 m_positionPredicateStack.back() = true;
1783 }
1784 }
1785 }
1786
1787
1788
1789 void
FunctionLast()1790 XPathProcessorImpl::FunctionLast()
1791 {
1792 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_LAST);
1793
1794 // Consume the name...
1795 nextToken();
1796
1797 // Get the arguments, and the argument count...
1798 const int argCount = FunctionCallArguments();
1799
1800 if (argCount != 0)
1801 {
1802 error(
1803 XalanMessages::FunctionDoesNotAcceptAnyArguments_1Param,
1804 XPathFunctionTable::s_last);
1805 }
1806 else
1807 {
1808 if (m_positionPredicateStack.empty() == false)
1809 {
1810 m_positionPredicateStack.back() = true;
1811 }
1812 }
1813 }
1814
1815
1816
1817 void
FunctionCount()1818 XPathProcessorImpl::FunctionCount()
1819 {
1820 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_COUNT);
1821
1822 // Consume the name...
1823 nextToken();
1824
1825 // Get the arguments, and the argument count...
1826 const int argCount = FunctionCallArguments();
1827
1828 if (argCount != 1)
1829 {
1830 error(
1831 XalanMessages::FunctionAcceptsOneArgument_1Param,
1832 XPathFunctionTable::s_count);
1833 }
1834 }
1835
1836
1837
1838 void
FunctionNot()1839 XPathProcessorImpl::FunctionNot()
1840 {
1841 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_NOT);
1842
1843 // Consume the name...
1844 nextToken();
1845
1846 // Get the arguments, and the argument count...
1847 const int argCount = FunctionCallArguments();
1848
1849 if (argCount != 1)
1850 {
1851 error(
1852 XalanMessages::FunctionAcceptsOneArgument_1Param,
1853 XPathFunctionTable::s_not);
1854 }
1855 }
1856
1857
1858
1859 void
FunctionTrue()1860 XPathProcessorImpl::FunctionTrue()
1861 {
1862 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_TRUE);
1863
1864 // Consume the name...
1865 nextToken();
1866
1867 // Get the arguments, and the argument count...
1868 const int argCount = FunctionCallArguments();
1869
1870 if (argCount != 0)
1871 {
1872 error(
1873 XalanMessages::FunctionDoesNotAcceptAnyArguments_1Param,
1874 XPathFunctionTable::s_true);
1875 }
1876 }
1877
1878
1879
1880 void
FunctionFalse()1881 XPathProcessorImpl::FunctionFalse()
1882 {
1883 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_FALSE);
1884
1885 // Consume the name...
1886 nextToken();
1887
1888 // Get the arguments, and the argument count...
1889 const int argCount = FunctionCallArguments();
1890
1891 if (argCount != 0)
1892 {
1893 error(
1894 XalanMessages::FunctionDoesNotAcceptAnyArguments_1Param,
1895 XPathFunctionTable::s_false);
1896 }
1897 }
1898
1899
1900
1901 void
FunctionBoolean()1902 XPathProcessorImpl::FunctionBoolean()
1903 {
1904 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_BOOLEAN);
1905
1906 // Consume the name...
1907 nextToken();
1908
1909 // Get the arguments, and the argument count...
1910 const int argCount = FunctionCallArguments();
1911
1912 if (argCount != 1)
1913 {
1914 error(
1915 XalanMessages::FunctionAcceptsOneArgument_1Param,
1916 XPathFunctionTable::s_boolean);
1917 }
1918 }
1919
1920
1921
1922 void
FunctionName(int opPos)1923 XPathProcessorImpl::FunctionName(int opPos)
1924 {
1925 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_NAME_0);
1926
1927 // Consume the name...
1928 nextToken();
1929
1930 // Get the arguments, and the argument count...
1931 const int argCount = FunctionCallArguments();
1932
1933 if (argCount != 0)
1934 {
1935 if (argCount == 1)
1936 {
1937 m_expression->replaceOpCode(
1938 opPos,
1939 XPathExpression::eOP_FUNCTION_NAME_0,
1940 XPathExpression::eOP_FUNCTION_NAME_1);
1941 }
1942 else
1943 {
1944 error(
1945 XalanMessages::FunctionTakesZeroOrOneArg_1Param,
1946 XPathFunctionTable::s_name);
1947 }
1948 }
1949 }
1950
1951
1952
1953 void
FunctionLocalName(int opPos)1954 XPathProcessorImpl::FunctionLocalName(int opPos)
1955 {
1956 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_LOCALNAME_0);
1957
1958 // Consume the name...
1959 nextToken();
1960
1961 // Get the arguments, and the argument count...
1962 const int argCount = FunctionCallArguments();
1963
1964 if (argCount != 0)
1965 {
1966 if (argCount == 1)
1967 {
1968 m_expression->replaceOpCode(
1969 opPos,
1970 XPathExpression::eOP_FUNCTION_LOCALNAME_0,
1971 XPathExpression::eOP_FUNCTION_LOCALNAME_1);
1972 }
1973 else
1974 {
1975 error(
1976 XalanMessages::FunctionTakesZeroOrOneArg_1Param,
1977 XPathFunctionTable::s_localName);
1978 }
1979 }
1980 }
1981
1982
1983
1984 void
FunctionNumber(int opPos)1985 XPathProcessorImpl::FunctionNumber(int opPos)
1986 {
1987 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_NUMBER_0);
1988
1989 // Consume the name...
1990 nextToken();
1991
1992 // Get the arguments, and the argument count...
1993 const int argCount = FunctionCallArguments();
1994
1995 if (argCount != 0)
1996 {
1997 if (argCount == 1)
1998 {
1999 m_expression->replaceOpCode(
2000 opPos,
2001 XPathExpression::eOP_FUNCTION_NUMBER_0,
2002 XPathExpression::eOP_FUNCTION_NUMBER_1);
2003 }
2004 else
2005 {
2006 error(
2007 XalanMessages::FunctionTakesZeroOrOneArg_1Param,
2008 XPathFunctionTable::s_number);
2009 }
2010 }
2011 }
2012
2013
2014
2015 void
FunctionFloor()2016 XPathProcessorImpl::FunctionFloor()
2017 {
2018 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_FLOOR);
2019
2020 // Consume the name...
2021 nextToken();
2022
2023 // Get the arguments, and the argument count...
2024 const int argCount = FunctionCallArguments();
2025
2026 if (argCount != 1)
2027 {
2028 error(
2029 XalanMessages::FunctionAcceptsOneArgument_1Param,
2030 XPathFunctionTable::s_floor);
2031 }
2032 }
2033
2034
2035
2036 void
FunctionCeiling()2037 XPathProcessorImpl::FunctionCeiling()
2038 {
2039 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_CEILING);
2040
2041 // Consume the name...
2042 nextToken();
2043
2044 // Get the arguments, and the argument count...
2045 const int argCount = FunctionCallArguments();
2046
2047 if (argCount != 1)
2048 {
2049 error(
2050 XalanMessages::FunctionAcceptsOneArgument_1Param,
2051 XPathFunctionTable::s_ceiling);
2052 }
2053 }
2054
2055
2056
2057 void
FunctionRound()2058 XPathProcessorImpl::FunctionRound()
2059 {
2060 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_ROUND);
2061
2062 // Consume the name...
2063 nextToken();
2064
2065 // Get the arguments, and the argument count...
2066 const int argCount = FunctionCallArguments();
2067
2068 if (argCount != 1)
2069 {
2070 error(
2071 XalanMessages::FunctionAcceptsOneArgument_1Param,
2072 XPathFunctionTable::s_round);
2073 }
2074 }
2075
2076
2077
2078 void
FunctionString(int opPos)2079 XPathProcessorImpl::FunctionString(int opPos)
2080 {
2081 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_STRING_0);
2082
2083 // Consume the name...
2084 nextToken();
2085
2086 // Get the arguments, and the argument count...
2087 const int argCount = FunctionCallArguments();
2088
2089 if (argCount != 0)
2090 {
2091 if (argCount == 1)
2092 {
2093 m_expression->replaceOpCode(
2094 opPos,
2095 XPathExpression::eOP_FUNCTION_STRING_0,
2096 XPathExpression::eOP_FUNCTION_STRING_1);
2097 }
2098 else
2099 {
2100 error(
2101 XalanMessages::FunctionTakesZeroOrOneArg_1Param,
2102 XPathFunctionTable::s_string);
2103 }
2104 }
2105 }
2106
2107
2108
2109 void
FunctionSum()2110 XPathProcessorImpl::FunctionSum()
2111 {
2112 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_SUM);
2113
2114 // Consume the name...
2115 nextToken();
2116
2117 // Get the arguments, and the argument count...
2118 const int argCount = FunctionCallArguments();
2119
2120 if (argCount != 1)
2121 {
2122 error(
2123 XalanMessages::FunctionAcceptsOneArgument_1Param,
2124 XPathFunctionTable::s_sum);
2125 }
2126 }
2127
2128
2129
2130 void
FunctionStringLength(int opPos)2131 XPathProcessorImpl::FunctionStringLength(int opPos)
2132 {
2133 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_STRINGLENGTH_0);
2134
2135 // Consume the name...
2136 nextToken();
2137
2138 // Get the arguments, and the argument count...
2139 const int argCount = FunctionCallArguments();
2140
2141 if (argCount != 0)
2142 {
2143 if (argCount == 1)
2144 {
2145 m_expression->replaceOpCode(
2146 opPos,
2147 XPathExpression::eOP_FUNCTION_STRINGLENGTH_0,
2148 XPathExpression::eOP_FUNCTION_STRINGLENGTH_1);
2149 }
2150 else
2151 {
2152 error(
2153 XalanMessages::FunctionTakesZeroOrOneArg_1Param,
2154 XPathFunctionTable::s_stringLength);
2155 }
2156 }
2157 }
2158
2159
2160
2161 void
FunctionNamespaceURI(int opPos)2162 XPathProcessorImpl::FunctionNamespaceURI(int opPos)
2163 {
2164 m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_NAMESPACEURI_0);
2165
2166 // Consume the name...
2167 nextToken();
2168
2169 // Get the arguments, and the argument count...
2170 const int argCount = FunctionCallArguments();
2171
2172 if (argCount != 0)
2173 {
2174 if (argCount == 1)
2175 {
2176 m_expression->replaceOpCode(
2177 opPos,
2178 XPathExpression::eOP_FUNCTION_NAMESPACEURI_0,
2179 XPathExpression::eOP_FUNCTION_NAMESPACEURI_1);
2180 }
2181 else
2182 {
2183 error(
2184 XalanMessages::FunctionTakesZeroOrOneArg_1Param,
2185 XPathFunctionTable::s_namespaceUri);
2186 }
2187 }
2188 }
2189
2190
2191
2192 void
LocationPath()2193 XPathProcessorImpl::LocationPath()
2194 {
2195 const int opPos = m_expression->opCodeMapLength();
2196
2197 m_expression->appendOpCode(XPathExpression::eOP_LOCATIONPATH);
2198
2199 if(tokenIs(XalanUnicode::charSolidus) == true)
2200 {
2201 nextToken();
2202
2203 const int newOpPos = m_expression->opCodeMapLength();
2204
2205 // Tell how long the step is without the predicate
2206 const XPathExpression::OpCodeMapValueVectorType theArgs(1, 4, m_constructionContext->getMemoryManager());
2207
2208 m_expression->appendOpCode(
2209 XPathExpression::eFROM_ROOT,
2210 theArgs);
2211
2212 m_expression->appendOpCode(XPathExpression::eNODETYPE_ROOT);
2213
2214 // Tell how long the entire step is.
2215 m_expression->updateOpCodeLength(newOpPos);
2216 }
2217
2218 if(m_token.empty() == false)
2219 {
2220 RelativeLocationPath();
2221 }
2222
2223 // Terminate for safety.
2224 m_expression->appendOpCode(XPathExpression::eENDOP);
2225
2226 m_expression->updateOpCodeLength(XPathExpression::eOP_LOCATIONPATH,
2227 opPos);
2228 }
2229
2230
2231
2232 void
RelativeLocationPath()2233 XPathProcessorImpl::RelativeLocationPath()
2234 {
2235 Step();
2236
2237 while(tokenIs(XalanUnicode::charSolidus) == true)
2238 {
2239 nextToken();
2240
2241 Step();
2242 }
2243 }
2244
2245
2246
2247 void
Step()2248 XPathProcessorImpl::Step()
2249 {
2250 const int opPos = m_expression->opCodeMapLength();
2251
2252 if(m_token.empty() == true)
2253 {
2254 error(XalanMessages::ExpectedNodeTest);
2255 }
2256 else if(tokenIs(s_dotString) == true)
2257 {
2258 nextToken();
2259
2260 if(tokenIs(XalanUnicode::charLeftSquareBracket) == true)
2261 {
2262 error(XalanMessages::IllegalSyntaxOfPredicatesSelf);
2263 }
2264
2265 const XPathExpression::OpCodeMapValueVectorType theArgs(1, 4, m_constructionContext->getMemoryManager());
2266
2267 m_expression->appendOpCode(XPathExpression::eFROM_SELF,
2268 theArgs);
2269
2270 m_expression->appendOpCode(XPathExpression::eNODETYPE_NODE);
2271
2272 // Tell how long the entire step is.
2273 m_expression->updateOpCodeLength(opPos);
2274 }
2275 else if(tokenIs(s_dotDotString) == true)
2276 {
2277 nextToken();
2278
2279 if(tokenIs(XalanUnicode::charLeftSquareBracket) == true)
2280 {
2281 error(XalanMessages::IllegalSyntaxOfPredicatesParent);
2282 }
2283
2284 // Tell how long the step is without the predicate
2285 const XPathExpression::OpCodeMapValueVectorType theArgs(1, 4,m_constructionContext->getMemoryManager());
2286
2287 m_expression->appendOpCode(XPathExpression::eFROM_PARENT,
2288 theArgs);
2289
2290 m_expression->appendOpCode(XPathExpression::eNODETYPE_NODE);
2291
2292 // Tell how long the entire step is.
2293 m_expression->updateOpCodeLength(opPos);
2294 }
2295 else if (tokenIs(XalanUnicode::charAsterisk) ||
2296 tokenIs(XalanUnicode::charCommercialAt) ||
2297 tokenIs(XalanUnicode::charSolidus) ||
2298 (tokenIs(XalanUnicode::charLowLine) ||
2299 XalanXMLChar::isLetter(m_token[0])))
2300 {
2301 Basis();
2302
2303 while(tokenIs(XalanUnicode::charLeftSquareBracket) == true)
2304 {
2305 Predicate();
2306 }
2307
2308 // Tell how long the entire step is.
2309 m_expression->updateOpCodeLength(opPos);
2310 }
2311 else if (tokenIs(XalanUnicode::charRightParenthesis) == false)
2312 {
2313 error(
2314 XalanMessages::UnexpectedTokenFound_1Param,
2315 m_token);
2316 }
2317 }
2318
2319
2320
2321 void
Basis()2322 XPathProcessorImpl::Basis()
2323 {
2324 assert(m_xpath != 0);
2325 assert(m_expression != 0);
2326
2327 const int opPos = m_expression->opCodeMapLength();
2328
2329 XPathExpression::eOpCodes axisType = XPathExpression::eENDOP;
2330
2331 // The next blocks guarantee that a FROM_XXX will be added.
2332 if(lookahead(s_axisString, 1) == true)
2333 {
2334 axisType = AxisName();
2335
2336 nextToken();
2337 nextToken();
2338 }
2339 else if(tokenIs(XalanUnicode::charCommercialAt) == true)
2340 {
2341 axisType = XPathExpression::eFROM_ATTRIBUTES;
2342
2343 m_expression->appendOpCode(XPathExpression::eFROM_ATTRIBUTES);
2344
2345 nextToken();
2346 }
2347 else if(tokenIs(XalanUnicode::charSolidus) == true)
2348 {
2349 // Check the current token in the expression. It's
2350 // actually the next token in this context.
2351 //
2352 const XalanDOMString& theNextToken = getTokenRelative(0);
2353
2354 if (isAxis(theNextToken) == false && isNodeTest(theNextToken) == false)
2355 {
2356 nextToken();
2357
2358 error(XalanMessages::ExpectedAxis);
2359 }
2360 else
2361 {
2362 // Tell how long the step is without the predicate
2363 const XPathExpression::OpCodeMapValueVectorType theArgs(1, 4, m_constructionContext->getMemoryManager());
2364
2365 m_expression->appendOpCode(XPathExpression::eFROM_DESCENDANTS_OR_SELF,
2366 theArgs);
2367
2368 m_expression->appendOpCode(XPathExpression::eNODETYPE_NODE);
2369
2370 // Tell how long the step is without the predicate
2371 m_expression->updateOpCodeLengthAfterNodeTest(opPos);
2372
2373 return; // make a quick exit...
2374 }
2375 }
2376 else
2377 {
2378 axisType = XPathExpression::eFROM_CHILDREN;
2379
2380 m_expression->appendOpCode(XPathExpression::eFROM_CHILDREN);
2381 }
2382
2383 NodeTest();
2384
2385 // Tell how long the step is without the predicate
2386 m_expression->updateOpCodeLengthAfterNodeTest(opPos);
2387 }
2388
2389
2390
2391 XPathExpression::eOpCodes
AxisName()2392 XPathProcessorImpl::AxisName()
2393 {
2394 assert(m_xpath != 0);
2395 assert(m_expression != 0);
2396
2397 const XPathExpression::eOpCodes theOpCode =
2398 getAxisToken(m_token);
2399
2400 if (theOpCode == XPathExpression::eENDOP)
2401 {
2402 error(
2403 XalanMessages::IllegalAxisName_1Param,
2404 m_token);
2405 }
2406 else
2407 {
2408 m_expression->appendOpCode(theOpCode);
2409 }
2410
2411 return theOpCode;
2412 }
2413
2414
2415
2416 int
NodeTest()2417 XPathProcessorImpl::NodeTest()
2418 {
2419 assert(m_xpath != 0);
2420 assert(m_expression != 0);
2421
2422 int nodeTestPos = -1;
2423
2424 if (lookahead(XalanUnicode::charLeftParenthesis, 1) == true)
2425 {
2426 const XPathExpression::eOpCodes theOpCode = getNodeTypeToken(m_token);
2427
2428 if (theOpCode == XPathExpression::eENDOP)
2429 {
2430 error(
2431 XalanMessages::UnknownNodeType_1Param,
2432 m_token);
2433 }
2434 else
2435 {
2436 nextToken();
2437
2438 nodeTestPos = m_expression->appendOpCode(theOpCode);
2439
2440 consumeExpected(XalanUnicode::charLeftParenthesis);
2441
2442 if(XPathExpression::eNODETYPE_PI == theOpCode)
2443 {
2444 if(tokenIs(XalanUnicode::charRightParenthesis) == false)
2445 {
2446 Literal();
2447 }
2448 }
2449
2450 consumeExpected(XalanUnicode::charRightParenthesis);
2451 }
2452 }
2453 else
2454 {
2455 // Assume name of attribute or element.
2456 m_expression->appendOpCode(XPathExpression::eNODENAME);
2457
2458 if(lookahead(XalanUnicode::charColon, 1) == true)
2459 {
2460 if(tokenIs(XalanUnicode::charAsterisk) == true)
2461 {
2462 m_expression->appendOpCode(XPathExpression::eELEMWILDCARD);
2463 }
2464 else
2465 {
2466 // Replace the token in the queue with the actual namespace...
2467 replaceTokenWithNamespaceToken();
2468
2469 m_expression->pushCurrentTokenOnOpCodeMap();
2470 }
2471
2472 nextToken();
2473
2474 consumeExpected(XalanUnicode::charColon);
2475 }
2476 else
2477 {
2478 m_expression->appendOpCode(XPathExpression::eEMPTY);
2479 }
2480
2481 if (tokenIs(XalanUnicode::charAsterisk) == true)
2482 {
2483 m_expression->appendOpCode(XPathExpression::eELEMWILDCARD);
2484 }
2485 else if (isNodeTest(m_token) == false)
2486 {
2487 error(XalanMessages::ExpectedNodeTest);
2488 }
2489 else
2490 {
2491 m_expression->pushCurrentTokenOnOpCodeMap();
2492 }
2493
2494 nextToken();
2495 }
2496
2497 return nodeTestPos;
2498 }
2499
2500
2501
2502 void
Predicate()2503 XPathProcessorImpl::Predicate()
2504 {
2505 if(tokenIs(XalanUnicode::charLeftSquareBracket) == true)
2506 {
2507 nextToken();
2508
2509 PredicateExpr();
2510
2511 consumeExpected(XalanUnicode::charRightSquareBracket);
2512 }
2513 }
2514
2515
2516
2517 void
PredicateExpr()2518 XPathProcessorImpl::PredicateExpr()
2519 {
2520 assert(m_xpath != 0);
2521 assert(m_expression != 0);
2522
2523 const int opPos = m_expression->opCodeMapLength();
2524
2525 m_expression->appendOpCode(XPathExpression::eOP_PREDICATE);
2526
2527 m_positionPredicateStack.push_back(false);
2528
2529 Expr();
2530
2531 // Terminate for safety.
2532 m_expression->appendOpCode(XPathExpression::eENDOP);
2533
2534 m_expression->updateOpCodeLength(XPathExpression::eOP_PREDICATE,
2535 opPos);
2536
2537 assert(m_positionPredicateStack.empty() == false);
2538
2539 if (m_positionPredicateStack.back() == true)
2540 {
2541 m_expression->replaceOpCode(
2542 opPos,
2543 XPathExpression::eOP_PREDICATE,
2544 XPathExpression::eOP_PREDICATE_WITH_POSITION);
2545 }
2546
2547 m_positionPredicateStack.pop_back();
2548 }
2549
2550
2551
2552 void
QName()2553 XPathProcessorImpl::QName()
2554 {
2555 assert(m_xpath != 0);
2556 assert(m_expression != 0);
2557
2558 // If there is no prefix, we have to fake things out...
2559 if (lookahead(XalanUnicode::charColon, 1) == false)
2560 {
2561 m_expression->insertToken(s_emptyString);
2562
2563 m_expression->pushCurrentTokenOnOpCodeMap();
2564
2565 nextToken();
2566 }
2567 else
2568 {
2569 // Replace the token in the queue with the actual namespace...
2570 replaceTokenWithNamespaceToken();
2571
2572 m_expression->pushCurrentTokenOnOpCodeMap();
2573
2574 nextToken();
2575
2576 consumeExpected(XalanUnicode::charColon);
2577 }
2578
2579 m_expression->pushCurrentTokenOnOpCodeMap();
2580
2581 nextToken();
2582 }
2583
2584
2585
2586 void
NCName()2587 XPathProcessorImpl::NCName()
2588 {
2589 assert(m_xpath != 0);
2590 assert(m_expression != 0);
2591
2592 m_expression->pushCurrentTokenOnOpCodeMap();
2593
2594 nextToken();
2595 }
2596
2597
2598
2599 void
Literal()2600 XPathProcessorImpl::Literal()
2601 {
2602 assert(m_xpath != 0);
2603 assert(m_expression != 0);
2604
2605 if(isCurrentLiteral() == true)
2606 {
2607 m_expression->pushArgumentOnOpCodeMap(
2608 m_constructionContext->getPooledString(m_token.c_str() + 1, m_token.length() - 2));
2609
2610 nextToken();
2611 }
2612 else
2613 {
2614 error(XalanMessages::LiteralArgumentIsRequired);
2615 }
2616 }
2617
2618
2619
2620 void
Number()2621 XPathProcessorImpl::Number()
2622 {
2623 assert(m_xpath != 0);
2624 assert(m_expression != 0);
2625
2626 if(m_token.empty() == false)
2627 {
2628 const double num = DoubleSupport::toDouble(m_token, m_constructionContext->getMemoryManager());
2629
2630 const XPathConstructionContext::GetCachedString theGuard(*m_constructionContext);
2631
2632 XalanDOMString& theStringValue = theGuard.get();
2633
2634 NumberToDOMString(num, theStringValue);
2635
2636 m_expression->pushNumberLiteralOnOpCodeMap(num);
2637
2638 m_expression->pushArgumentOnOpCodeMap(num, m_constructionContext->getPooledString(theStringValue));
2639
2640 nextToken();
2641 }
2642 }
2643
2644
2645
2646 void
Pattern()2647 XPathProcessorImpl::Pattern()
2648 {
2649 while(true)
2650 {
2651 LocationPathPattern();
2652
2653 if(tokenIs(XalanUnicode::charVerticalLine) == true)
2654 {
2655 nextToken();
2656 }
2657 else
2658 {
2659 break;
2660 }
2661 }
2662 }
2663
2664
2665
2666 void
LocationPathPattern()2667 XPathProcessorImpl::LocationPathPattern()
2668 {
2669 assert(m_xpath != 0);
2670 assert(m_expression != 0);
2671
2672 const int opPos = m_expression->opCodeMapLength();
2673
2674 m_expression->appendOpCode(XPathExpression::eOP_LOCATIONPATHPATTERN);
2675
2676 if(lookahead(XalanUnicode::charLeftParenthesis, 1) == true &&
2677 (tokenIs(s_functionIDString) == true ||
2678 tokenIs(s_functionKeyString) == true))
2679 {
2680 IdKeyPattern();
2681
2682 if(tokenIs(XalanUnicode::charSolidus) == true && lookahead(XalanUnicode::charSolidus, 1) == true)
2683 {
2684 const int newOpPos = m_expression->opCodeMapLength();
2685
2686 // Tell how long the step is without the predicate
2687 const XPathExpression::OpCodeMapValueVectorType theArgs(1, 4, m_constructionContext->getMemoryManager());
2688
2689 m_expression->appendOpCode(XPathExpression::eMATCH_ANY_ANCESTOR_WITH_FUNCTION_CALL,
2690 theArgs);
2691
2692 m_expression->updateOpCodeLength(newOpPos);
2693
2694 nextToken();
2695 }
2696 }
2697 else if(tokenIs(XalanUnicode::charSolidus) == true)
2698 {
2699 const int newOpPos = m_expression->opCodeMapLength();
2700
2701 // Tell how long the step is without the predicate
2702 const XPathExpression::OpCodeMapValueVectorType theArgs(1, 4, m_constructionContext->getMemoryManager());
2703
2704 if(lookahead(XalanUnicode::charSolidus, 1) == true)
2705 {
2706 m_expression->appendOpCode(
2707 XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE,
2708 theArgs);
2709
2710 m_expression->appendOpCode(XPathExpression::eNODETYPE_NODE);
2711
2712 nextToken();
2713 }
2714 else
2715 {
2716 m_expression->appendOpCode(XPathExpression::eFROM_ROOT,
2717 theArgs);
2718
2719 m_expression->appendOpCode(XPathExpression::eNODETYPE_ROOT);
2720 }
2721
2722 m_expression->updateOpCodeLength(newOpPos);
2723
2724 nextToken();
2725 }
2726
2727 if(m_token.empty() == false)
2728 {
2729 if (!tokenIs(XalanUnicode::charVerticalLine) == true)
2730 {
2731 RelativePathPattern();
2732 }
2733 else if (lookahead(XalanUnicode::charVerticalLine, -1) == true)
2734 {
2735 error(
2736 XalanMessages::UnexpectedTokenFound_1Param,
2737 m_token);
2738 }
2739 }
2740
2741 // Terminate for safety.
2742 m_expression->appendOpCode(XPathExpression::eENDOP);
2743
2744 m_expression->updateOpCodeLength(XPathExpression::eOP_LOCATIONPATHPATTERN,
2745 opPos);
2746 }
2747
2748
2749
2750 void
IdKeyPattern()2751 XPathProcessorImpl::IdKeyPattern()
2752 {
2753 m_requireLiterals = true;
2754
2755 FunctionCall();
2756
2757 m_requireLiterals = false;
2758 }
2759
2760
2761
2762 void
RelativePathPattern()2763 XPathProcessorImpl::RelativePathPattern()
2764 {
2765 StepPattern();
2766
2767 while(tokenIs(XalanUnicode::charSolidus) == true)
2768 {
2769 nextToken();
2770
2771 StepPattern();
2772 }
2773 }
2774
2775
2776
2777 void
StepPattern()2778 XPathProcessorImpl::StepPattern()
2779 {
2780 AbbreviatedNodeTestStep();
2781 }
2782
2783
2784
2785 void
AbbreviatedNodeTestStep()2786 XPathProcessorImpl::AbbreviatedNodeTestStep()
2787 {
2788 assert(m_xpath != 0);
2789 assert(m_expression != 0);
2790
2791 const int opPos = m_expression->opCodeMapLength();
2792
2793 int matchTypePos = -1;
2794
2795 XPathExpression::eOpCodes axisType = XPathExpression::eENDOP;
2796
2797 // The next blocks guarantee that a MATCH_XXX will be added.
2798 if(tokenIs(XalanUnicode::charCommercialAt) == true)
2799 {
2800 axisType = XPathExpression::eMATCH_ATTRIBUTE;
2801
2802 m_expression->appendOpCode(axisType);
2803
2804 nextToken();
2805 }
2806 else if(lookahead(s_axisString, 1) == true)
2807 {
2808 if(tokenIs(s_attributeString) == true)
2809 {
2810 axisType = XPathExpression::eMATCH_ATTRIBUTE;
2811
2812 m_expression->appendOpCode(axisType);
2813 }
2814 else if(tokenIs(s_childString) == true)
2815 {
2816 matchTypePos = m_expression->opCodeMapLength();
2817
2818 axisType = XPathExpression::eMATCH_IMMEDIATE_ANCESTOR;
2819
2820 m_expression->appendOpCode(axisType);
2821 }
2822 else
2823 {
2824 error(XalanMessages::OnlyChildAndAttributeAxesAreAllowed);
2825 }
2826
2827 nextToken();
2828 nextToken();
2829 }
2830 else if(tokenIs(XalanUnicode::charSolidus) == true)
2831 {
2832 if(lookahead(s_axisString, 2) == false &&
2833 lookahead(XalanUnicode::charCommercialAt, 1) == false)
2834 {
2835 matchTypePos = m_expression->opCodeMapLength();
2836
2837 axisType = XPathExpression::eMATCH_IMMEDIATE_ANCESTOR;
2838
2839 m_expression->appendOpCode(axisType);
2840 }
2841 else
2842 {
2843 nextToken();
2844
2845 // This matches an abbreviated step "@foo"
2846 if (tokenIs(XalanUnicode::charCommercialAt) == true)
2847 {
2848 axisType = XPathExpression::eMATCH_ATTRIBUTE;
2849
2850 m_expression->appendOpCode(axisType);
2851 }
2852 else
2853 {
2854 // This matches the attribute or child axis: attribute::name or child::name.
2855 if(tokenIs(s_attributeString) == true)
2856 {
2857 axisType = XPathExpression::eMATCH_ATTRIBUTE;
2858
2859 m_expression->appendOpCode(axisType);
2860 }
2861 else if(tokenIs(s_childString) == true)
2862 {
2863 matchTypePos = m_expression->opCodeMapLength();
2864
2865 axisType = XPathExpression::eMATCH_IMMEDIATE_ANCESTOR;
2866
2867 m_expression->appendOpCode(axisType);
2868 }
2869 else
2870 {
2871 error(XalanMessages::OnlyChildAndAttributeAxesAreAllowed);
2872 }
2873
2874 nextToken();
2875 }
2876 }
2877
2878 nextToken();
2879 }
2880 else
2881 {
2882 if(tokenIs(XalanUnicode::charSolidus) == true)
2883 {
2884 nextToken();
2885 }
2886
2887 matchTypePos = m_expression->opCodeMapLength();
2888
2889 axisType = XPathExpression::eMATCH_IMMEDIATE_ANCESTOR;
2890
2891 m_expression->appendOpCode(axisType);
2892 }
2893
2894 // Make room for telling how long the step is without the predicate.
2895 // This will be replaced by the right value.
2896 m_expression->appendOpCode(XPathExpression::eENDOP);
2897
2898 NodeTest();
2899
2900 m_expression->updateOpCodeLengthAfterNodeTest(opPos);
2901
2902 while(tokenIs(XalanUnicode::charLeftSquareBracket) == true)
2903 {
2904 Predicate();
2905 }
2906
2907 if(matchTypePos > -1 && tokenIs(XalanUnicode::charSolidus) == true && lookahead(XalanUnicode::charSolidus, 1) == true)
2908 {
2909 assert(m_expression->opCodeMapLength() > matchTypePos);
2910
2911 m_expression->setOpCodeMapValue(matchTypePos, XPathExpression::eMATCH_ANY_ANCESTOR);
2912 }
2913
2914 m_expression->updateOpCodeLength(opPos);
2915 }
2916
2917
2918
2919 bool
isValidFunction(const XalanDOMString & key)2920 XPathProcessorImpl::isValidFunction(const XalanDOMString& key)
2921 {
2922 bool fResult = true;
2923
2924 if(XPath::isInstalledFunction(key) == false)
2925 {
2926 if (searchTable(s_functionTable, s_functionTableSize, key).m_opCode == XPathExpression::eENDOP)
2927 {
2928 fResult = false;
2929 }
2930 }
2931
2932 return fResult;
2933 }
2934
2935
2936
2937 bool
isCurrentLiteral() const2938 XPathProcessorImpl::isCurrentLiteral() const
2939 {
2940 const t_size_type theLength = m_token.length();
2941
2942 if (theLength <= 1)
2943 {
2944 return false;
2945 }
2946 else
2947 {
2948 const t_size_type last = theLength - 1;
2949
2950 const XalanDOMChar c0 = m_tokenChar;
2951 const XalanDOMChar cX = m_token[last];
2952
2953 if((c0 == XalanUnicode::charQuoteMark && cX == XalanUnicode::charQuoteMark) ||
2954 (c0 == XalanUnicode::charApostrophe && cX == XalanUnicode::charApostrophe))
2955 {
2956 return true;
2957 }
2958 else
2959 {
2960 return false;
2961 }
2962 }
2963 }
2964
2965
2966
2967 bool
isAxis(const XalanDOMString & theToken)2968 XPathProcessorImpl::isAxis(const XalanDOMString& theToken)
2969 {
2970 const XalanDOMString::size_type theLength =
2971 theToken.length();
2972
2973 if (theLength == 0)
2974 {
2975 return false;
2976 }
2977 else if (theLength == 1 &&
2978 theToken[0] == XalanUnicode::charCommercialAt)
2979 {
2980 return true;
2981 }
2982 else if (equals(theToken, s_dotString) == true ||
2983 equals(theToken, s_dotDotString) == true)
2984 {
2985 return true;
2986 }
2987 else
2988 {
2989 const XPathExpression::eOpCodes theOpCode =
2990 getAxisToken(theToken);
2991
2992 if (theOpCode != XPathExpression::eENDOP)
2993 {
2994 return true;
2995 }
2996 else
2997 {
2998 return false;
2999 }
3000 }
3001 }
3002
3003
3004
3005 bool
isNodeTest(const XalanDOMString & theToken)3006 XPathProcessorImpl::isNodeTest(const XalanDOMString& theToken)
3007 {
3008 const XalanDOMString::size_type theLength = theToken.length();
3009
3010 if (theLength == 0)
3011 {
3012 return false;
3013 }
3014 else if (theLength == 1 &&
3015 theToken[0] == XalanUnicode::charAsterisk)
3016 {
3017 return true;
3018 }
3019 else if (theToken[0] == XalanUnicode::charLowLine ||
3020 XalanXMLChar::isLetter(theToken[0]) == true)
3021 {
3022 return true;
3023 }
3024 else
3025 {
3026 return false;
3027 }
3028 }
3029
3030
3031
3032 const XPathProcessorImpl::TableEntry&
searchTable(const TableEntry theTable[],size_type theTableSize,const XalanDOMString & theString)3033 XPathProcessorImpl::searchTable(
3034 const TableEntry theTable[],
3035 size_type theTableSize,
3036 const XalanDOMString& theString)
3037 {
3038 const TableEntry* theFirst = theTable;
3039 const TableEntry* theLast = &theTable[theTableSize - 1];
3040
3041 while(theFirst <= theLast)
3042 {
3043 const TableEntry* theCurrent = theFirst + (theLast - theFirst) / 2;
3044 assert(theCurrent->m_string[0] != 0);
3045
3046 const int theResult = compare(theString.c_str(), theCurrent->m_string);
3047
3048 if (theResult < 0)
3049 {
3050 theLast = theCurrent - 1;
3051 }
3052 else if (theResult > 0)
3053 {
3054 theFirst = theCurrent + 1;
3055 }
3056 else
3057 {
3058 return *theCurrent;
3059 }
3060 }
3061
3062 return s_dummyEntry;
3063 }
3064
3065
3066
3067 const XalanDOMString XPathProcessorImpl::s_emptyString(XalanMemMgrs::getDummyMemMgr());
3068
3069
3070
3071 const XalanDOMChar XPathProcessorImpl::s_functionIDString[] =
3072 {
3073 XalanUnicode::charLetter_i,
3074 XalanUnicode::charLetter_d,
3075 0
3076 };
3077
3078 // This shouldn't really be here, since it's not part of the XPath standard,
3079 // but rather a part ofthe XSLT standard.
3080 const XalanDOMChar XPathProcessorImpl::s_functionKeyString[] =
3081 {
3082 XalanUnicode::charLetter_k,
3083 XalanUnicode::charLetter_e,
3084 XalanUnicode::charLetter_y,
3085 0
3086 };
3087
3088 const XalanDOMChar XPathProcessorImpl::s_orString[] =
3089 {
3090 XalanUnicode::charLetter_o,
3091 XalanUnicode::charLetter_r,
3092 0
3093 };
3094
3095 const XalanDOMChar XPathProcessorImpl::s_andString[] =
3096 {
3097 XalanUnicode::charLetter_a,
3098 XalanUnicode::charLetter_n,
3099 XalanUnicode::charLetter_d,
3100 0
3101 };
3102
3103 const XalanDOMChar XPathProcessorImpl::s_divString[] =
3104 {
3105 XalanUnicode::charLetter_d,
3106 XalanUnicode::charLetter_i,
3107 XalanUnicode::charLetter_v,
3108 0
3109 };
3110
3111 const XalanDOMChar XPathProcessorImpl::s_modString[] =
3112 {
3113 XalanUnicode::charLetter_m,
3114 XalanUnicode::charLetter_o,
3115 XalanUnicode::charLetter_d,
3116 0
3117 };
3118
3119 const XalanDOMChar XPathProcessorImpl::s_dotString[] =
3120 {
3121 XalanUnicode::charFullStop,
3122 0
3123 };
3124
3125 const XalanDOMChar XPathProcessorImpl::s_dotDotString[] =
3126 {
3127 XalanUnicode::charFullStop,
3128 XalanUnicode::charFullStop,
3129 0
3130 };
3131
3132 const XalanDOMChar XPathProcessorImpl::s_axisString[] =
3133 {
3134 XalanUnicode::charColon,
3135 XalanUnicode::charColon,
3136 0
3137 };
3138
3139 const XalanDOMChar XPathProcessorImpl::s_attributeString[] =
3140 {
3141 XalanUnicode::charLetter_a,
3142 XalanUnicode::charLetter_t,
3143 XalanUnicode::charLetter_t,
3144 XalanUnicode::charLetter_r,
3145 XalanUnicode::charLetter_i,
3146 XalanUnicode::charLetter_b,
3147 XalanUnicode::charLetter_u,
3148 XalanUnicode::charLetter_t,
3149 XalanUnicode::charLetter_e,
3150 0
3151 };
3152
3153 const XalanDOMChar XPathProcessorImpl::s_childString[] =
3154 {
3155 XalanUnicode::charLetter_c,
3156 XalanUnicode::charLetter_h,
3157 XalanUnicode::charLetter_i,
3158 XalanUnicode::charLetter_l,
3159 XalanUnicode::charLetter_d,
3160 0
3161 };
3162
3163 const XalanDOMChar XPathProcessorImpl::s_lastString[] =
3164 {
3165 XalanUnicode::charLetter_l,
3166 XalanUnicode::charLetter_a,
3167 XalanUnicode::charLetter_s,
3168 XalanUnicode::charLetter_t,
3169 0
3170 };
3171
3172 const XalanDOMChar XPathProcessorImpl::s_positionString[] =
3173 {
3174 XalanUnicode::charLetter_p,
3175 XalanUnicode::charLetter_o,
3176 XalanUnicode::charLetter_s,
3177 XalanUnicode::charLetter_i,
3178 XalanUnicode::charLetter_t,
3179 XalanUnicode::charLetter_i,
3180 XalanUnicode::charLetter_o,
3181 XalanUnicode::charLetter_n,
3182 0
3183 };
3184
3185 const XalanDOMChar XPathProcessorImpl::s_asteriskString[] =
3186 {
3187 XalanUnicode::charAsterisk,
3188 0
3189 };
3190
3191 const XalanDOMChar XPathProcessorImpl::s_commentString[] =
3192 {
3193 XalanUnicode::charLetter_c,
3194 XalanUnicode::charLetter_o,
3195 XalanUnicode::charLetter_m,
3196 XalanUnicode::charLetter_m,
3197 XalanUnicode::charLetter_e,
3198 XalanUnicode::charLetter_n,
3199 XalanUnicode::charLetter_t,
3200 0
3201 };
3202
3203 const XalanDOMChar XPathProcessorImpl::s_piString[] =
3204 {
3205 XalanUnicode::charLetter_p,
3206 XalanUnicode::charLetter_r,
3207 XalanUnicode::charLetter_o,
3208 XalanUnicode::charLetter_c,
3209 XalanUnicode::charLetter_e,
3210 XalanUnicode::charLetter_s,
3211 XalanUnicode::charLetter_s,
3212 XalanUnicode::charLetter_i,
3213 XalanUnicode::charLetter_n,
3214 XalanUnicode::charLetter_g,
3215 XalanUnicode::charHyphenMinus,
3216 XalanUnicode::charLetter_i,
3217 XalanUnicode::charLetter_n,
3218 XalanUnicode::charLetter_s,
3219 XalanUnicode::charLetter_t,
3220 XalanUnicode::charLetter_r,
3221 XalanUnicode::charLetter_u,
3222 XalanUnicode::charLetter_c,
3223 XalanUnicode::charLetter_t,
3224 XalanUnicode::charLetter_i,
3225 XalanUnicode::charLetter_o,
3226 XalanUnicode::charLetter_n,
3227 0
3228 };
3229
3230 const XalanDOMChar XPathProcessorImpl::s_nodeString[] =
3231 {
3232 XalanUnicode::charLetter_n,
3233 XalanUnicode::charLetter_o,
3234 XalanUnicode::charLetter_d,
3235 XalanUnicode::charLetter_e,
3236 0
3237 };
3238
3239 const XalanDOMChar XPathProcessorImpl::s_textString[] =
3240 {
3241 XalanUnicode::charLetter_t,
3242 XalanUnicode::charLetter_e,
3243 XalanUnicode::charLetter_x,
3244 XalanUnicode::charLetter_t,
3245 0
3246 };
3247
3248 const XalanDOMChar XPathProcessorImpl::s_ancestorString[] =
3249 {
3250 XalanUnicode::charLetter_a,
3251 XalanUnicode::charLetter_n,
3252 XalanUnicode::charLetter_c,
3253 XalanUnicode::charLetter_e,
3254 XalanUnicode::charLetter_s,
3255 XalanUnicode::charLetter_t,
3256 XalanUnicode::charLetter_o,
3257 XalanUnicode::charLetter_r,
3258 0
3259 };
3260
3261 const XalanDOMChar XPathProcessorImpl::s_ancestorOrSelfString[] =
3262 {
3263 XalanUnicode::charLetter_a,
3264 XalanUnicode::charLetter_n,
3265 XalanUnicode::charLetter_c,
3266 XalanUnicode::charLetter_e,
3267 XalanUnicode::charLetter_s,
3268 XalanUnicode::charLetter_t,
3269 XalanUnicode::charLetter_o,
3270 XalanUnicode::charLetter_r,
3271 XalanUnicode::charHyphenMinus,
3272 XalanUnicode::charLetter_o,
3273 XalanUnicode::charLetter_r,
3274 XalanUnicode::charHyphenMinus,
3275 XalanUnicode::charLetter_s,
3276 XalanUnicode::charLetter_e,
3277 XalanUnicode::charLetter_l,
3278 XalanUnicode::charLetter_f,
3279 0
3280 };
3281
3282 const XalanDOMChar XPathProcessorImpl::s_descendantString[] =
3283 {
3284 XalanUnicode::charLetter_d,
3285 XalanUnicode::charLetter_e,
3286 XalanUnicode::charLetter_s,
3287 XalanUnicode::charLetter_c,
3288 XalanUnicode::charLetter_e,
3289 XalanUnicode::charLetter_n,
3290 XalanUnicode::charLetter_d,
3291 XalanUnicode::charLetter_a,
3292 XalanUnicode::charLetter_n,
3293 XalanUnicode::charLetter_t,
3294 0
3295 };
3296
3297 const XalanDOMChar XPathProcessorImpl::s_descendantOrSelfString[] =
3298 {
3299 XalanUnicode::charLetter_d,
3300 XalanUnicode::charLetter_e,
3301 XalanUnicode::charLetter_s,
3302 XalanUnicode::charLetter_c,
3303 XalanUnicode::charLetter_e,
3304 XalanUnicode::charLetter_n,
3305 XalanUnicode::charLetter_d,
3306 XalanUnicode::charLetter_a,
3307 XalanUnicode::charLetter_n,
3308 XalanUnicode::charLetter_t,
3309 XalanUnicode::charHyphenMinus,
3310 XalanUnicode::charLetter_o,
3311 XalanUnicode::charLetter_r,
3312 XalanUnicode::charHyphenMinus,
3313 XalanUnicode::charLetter_s,
3314 XalanUnicode::charLetter_e,
3315 XalanUnicode::charLetter_l,
3316 XalanUnicode::charLetter_f,
3317 0
3318 };
3319
3320 const XalanDOMChar XPathProcessorImpl::s_followingString[] =
3321 {
3322 XalanUnicode::charLetter_f,
3323 XalanUnicode::charLetter_o,
3324 XalanUnicode::charLetter_l,
3325 XalanUnicode::charLetter_l,
3326 XalanUnicode::charLetter_o,
3327 XalanUnicode::charLetter_w,
3328 XalanUnicode::charLetter_i,
3329 XalanUnicode::charLetter_n,
3330 XalanUnicode::charLetter_g,
3331 0
3332 };
3333
3334 const XalanDOMChar XPathProcessorImpl::s_followingSiblingString[] =
3335 {
3336 XalanUnicode::charLetter_f,
3337 XalanUnicode::charLetter_o,
3338 XalanUnicode::charLetter_l,
3339 XalanUnicode::charLetter_l,
3340 XalanUnicode::charLetter_o,
3341 XalanUnicode::charLetter_w,
3342 XalanUnicode::charLetter_i,
3343 XalanUnicode::charLetter_n,
3344 XalanUnicode::charLetter_g,
3345 XalanUnicode::charHyphenMinus,
3346 XalanUnicode::charLetter_s,
3347 XalanUnicode::charLetter_i,
3348 XalanUnicode::charLetter_b,
3349 XalanUnicode::charLetter_l,
3350 XalanUnicode::charLetter_i,
3351 XalanUnicode::charLetter_n,
3352 XalanUnicode::charLetter_g,
3353 0
3354 };
3355
3356 const XalanDOMChar XPathProcessorImpl::s_parentString[] =
3357 {
3358 XalanUnicode::charLetter_p,
3359 XalanUnicode::charLetter_a,
3360 XalanUnicode::charLetter_r,
3361 XalanUnicode::charLetter_e,
3362 XalanUnicode::charLetter_n,
3363 XalanUnicode::charLetter_t,
3364 0
3365 };
3366
3367 const XalanDOMChar XPathProcessorImpl::s_precedingString[] =
3368 {
3369 XalanUnicode::charLetter_p,
3370 XalanUnicode::charLetter_r,
3371 XalanUnicode::charLetter_e,
3372 XalanUnicode::charLetter_c,
3373 XalanUnicode::charLetter_e,
3374 XalanUnicode::charLetter_d,
3375 XalanUnicode::charLetter_i,
3376 XalanUnicode::charLetter_n,
3377 XalanUnicode::charLetter_g,
3378 0
3379 };
3380
3381 const XalanDOMChar XPathProcessorImpl::s_precedingSiblingString[] =
3382 {
3383 XalanUnicode::charLetter_p,
3384 XalanUnicode::charLetter_r,
3385 XalanUnicode::charLetter_e,
3386 XalanUnicode::charLetter_c,
3387 XalanUnicode::charLetter_e,
3388 XalanUnicode::charLetter_d,
3389 XalanUnicode::charLetter_i,
3390 XalanUnicode::charLetter_n,
3391 XalanUnicode::charLetter_g,
3392 XalanUnicode::charHyphenMinus,
3393 XalanUnicode::charLetter_s,
3394 XalanUnicode::charLetter_i,
3395 XalanUnicode::charLetter_b,
3396 XalanUnicode::charLetter_l,
3397 XalanUnicode::charLetter_i,
3398 XalanUnicode::charLetter_n,
3399 XalanUnicode::charLetter_g,
3400 0
3401 };
3402
3403 const XalanDOMChar XPathProcessorImpl::s_selfString[] =
3404 {
3405 XalanUnicode::charLetter_s,
3406 XalanUnicode::charLetter_e,
3407 XalanUnicode::charLetter_l,
3408 XalanUnicode::charLetter_f,
3409 0
3410 };
3411
3412 const XalanDOMChar XPathProcessorImpl::s_namespaceString[] =
3413 {
3414 XalanUnicode::charLetter_n,
3415 XalanUnicode::charLetter_a,
3416 XalanUnicode::charLetter_m,
3417 XalanUnicode::charLetter_e,
3418 XalanUnicode::charLetter_s,
3419 XalanUnicode::charLetter_p,
3420 XalanUnicode::charLetter_a,
3421 XalanUnicode::charLetter_c,
3422 XalanUnicode::charLetter_e,
3423 0
3424 };
3425
3426
3427
3428 const XPathProcessorImpl::TableEntry XPathProcessorImpl::s_functionTable[] =
3429 {
3430 { XPathFunctionTable::s_not, XPathExpression::eOP_FUNCTION_NOT },
3431 { XPathFunctionTable::s_sum, XPathExpression::eOP_FUNCTION_SUM },
3432 { XPathProcessorImpl::s_lastString, XPathExpression::eOP_FUNCTION_LAST },
3433 { XPathFunctionTable::s_name, XPathExpression::eOP_FUNCTION_NAME_0 },
3434 { XPathProcessorImpl::s_nodeString, XPathExpression::eNODETYPE_NODE },
3435 { XPathProcessorImpl::s_textString, XPathExpression::eNODETYPE_TEXT },
3436 { XPathFunctionTable::s_true, XPathExpression::eOP_FUNCTION_TRUE },
3437 { XPathFunctionTable::s_count, XPathExpression::eOP_FUNCTION_COUNT },
3438 { XPathFunctionTable::s_false, XPathExpression::eOP_FUNCTION_FALSE },
3439 { XPathFunctionTable::s_floor, XPathExpression::eOP_FUNCTION_FLOOR },
3440 { XPathFunctionTable::s_round, XPathExpression::eOP_FUNCTION_ROUND },
3441 { XPathFunctionTable::s_number, XPathExpression::eOP_FUNCTION_NUMBER_0 },
3442 { XPathFunctionTable::s_boolean, XPathExpression::eOP_FUNCTION_BOOLEAN },
3443 { XPathFunctionTable::s_ceiling, XPathExpression::eOP_FUNCTION_CEILING },
3444 { XPathProcessorImpl::s_commentString, XPathExpression::eNODETYPE_COMMENT },
3445 { XPathProcessorImpl::s_positionString, XPathExpression::eOP_FUNCTION_POSITION },
3446 { XPathFunctionTable::s_localName, XPathExpression::eOP_FUNCTION_LOCALNAME_0 },
3447 { XPathFunctionTable::s_stringLength, XPathExpression::eOP_FUNCTION_STRINGLENGTH_0 },
3448 { XPathProcessorImpl::s_piString, XPathExpression::eNODETYPE_PI },
3449 };
3450
3451 const XPathProcessorImpl::size_type XPathProcessorImpl::s_functionTableSize =
3452 sizeof(s_functionTable) / sizeof(s_functionTable[0]);
3453
3454
3455
3456 const XPathProcessorImpl::TableEntry XPathProcessorImpl::s_nodeTypeTable[] =
3457 {
3458 { XPathProcessorImpl::s_asteriskString, XPathExpression::eNODETYPE_ANYELEMENT },
3459 { XPathProcessorImpl::s_nodeString, XPathExpression::eNODETYPE_NODE },
3460 { XPathProcessorImpl::s_textString, XPathExpression::eNODETYPE_TEXT },
3461 { XPathProcessorImpl::s_commentString, XPathExpression::eNODETYPE_COMMENT },
3462 { XPathProcessorImpl::s_piString, XPathExpression::eNODETYPE_PI },
3463 };
3464
3465 const XPathProcessorImpl::size_type XPathProcessorImpl::s_nodeTypeTableSize =
3466 sizeof(s_nodeTypeTable) / sizeof(s_nodeTypeTable[0]);
3467
3468
3469
3470 const XPathProcessorImpl::TableEntry XPathProcessorImpl::s_axisTable[] =
3471 {
3472 { XPathProcessorImpl::s_selfString, XPathExpression::eFROM_SELF },
3473 { XPathProcessorImpl::s_childString, XPathExpression::eFROM_CHILDREN },
3474 { XPathProcessorImpl::s_parentString, XPathExpression::eFROM_PARENT },
3475 { XPathProcessorImpl::s_ancestorString, XPathExpression::eFROM_ANCESTORS },
3476 { XPathProcessorImpl::s_attributeString, XPathExpression::eFROM_ATTRIBUTES },
3477 { XPathProcessorImpl::s_followingString, XPathExpression::eFROM_FOLLOWING },
3478 { XPathProcessorImpl::s_namespaceString, XPathExpression::eFROM_NAMESPACE },
3479 { XPathProcessorImpl::s_precedingString, XPathExpression::eFROM_PRECEDING },
3480 { XPathProcessorImpl::s_descendantString, XPathExpression::eFROM_DESCENDANTS },
3481 { XPathProcessorImpl::s_ancestorOrSelfString, XPathExpression::eFROM_ANCESTORS_OR_SELF },
3482 { XPathProcessorImpl::s_followingSiblingString, XPathExpression::eFROM_FOLLOWING_SIBLINGS },
3483 { XPathProcessorImpl::s_precedingSiblingString, XPathExpression::eFROM_PRECEDING_SIBLINGS },
3484 { XPathProcessorImpl::s_descendantOrSelfString, XPathExpression::eFROM_DESCENDANTS_OR_SELF },
3485 };
3486
3487 const XPathProcessorImpl::size_type XPathProcessorImpl::s_axisTableSize =
3488 sizeof(s_axisTable) / sizeof(s_axisTable[0]);
3489
3490
3491 const XPathProcessorImpl::TableEntry XPathProcessorImpl::s_dummyEntry =
3492 {
3493 0, XPathExpression::eENDOP
3494 };
3495
3496
3497
3498 }
3499