1 16 19 package org.apache.xpath.compiler; 20 21 import javax.xml.transform.ErrorListener ; 22 import javax.xml.transform.TransformerException ; 23 24 import org.apache.xalan.res.XSLMessages; 25 import org.apache.xml.utils.PrefixResolver; 26 import org.apache.xpath.XPathProcessorException; 27 import org.apache.xpath.objects.XNumber; 28 import org.apache.xpath.objects.XString; 29 import org.apache.xpath.res.XPATHErrorResources; 30 31 36 public class XPathParser 37 { 38 static public final String CONTINUE_AFTER_FATAL_ERROR="CONTINUE_AFTER_FATAL_ERROR"; 42 43 46 private OpMap m_ops; 47 48 51 transient String m_token; 52 53 58 transient char m_tokenChar = 0; 59 60 63 int m_queueMark = 0; 64 65 68 protected final static int FILTER_MATCH_FAILED = 0; 69 protected final static int FILTER_MATCH_PRIMARY = 1; 70 protected final static int FILTER_MATCH_PREDICATES = 2; 71 72 75 public XPathParser(ErrorListener errorListener, javax.xml.transform.SourceLocator sourceLocator) 76 { 77 m_errorListener = errorListener; 78 m_sourceLocator = sourceLocator; 79 } 80 81 84 PrefixResolver m_namespaceContext; 85 86 98 public void initXPath( 99 Compiler compiler, String expression, PrefixResolver namespaceContext) 100 throws javax.xml.transform.TransformerException 101 { 102 103 m_ops = compiler; 104 m_namespaceContext = namespaceContext; 105 106 Lexer lexer = new Lexer(compiler, namespaceContext, this); 107 108 lexer.tokenize(expression); 109 110 m_ops.setOp(0,OpCodes.OP_XPATH); 111 m_ops.setOp(OpMap.MAPINDEX_LENGTH,2); 112 113 114 try { 123 124 nextToken(); 125 Expr(); 126 127 if (null != m_token) 128 { 129 String extraTokens = ""; 130 131 while (null != m_token) 132 { 133 extraTokens += "'" + m_token + "'"; 134 135 nextToken(); 136 137 if (null != m_token) 138 extraTokens += ", "; 139 } 140 141 error(XPATHErrorResources.ER_EXTRA_ILLEGAL_TOKENS, 142 new Object []{ extraTokens }); } 144 145 } 146 catch (org.apache.xpath.XPathProcessorException e) 147 { 148 if(CONTINUE_AFTER_FATAL_ERROR.equals(e.getMessage())) 149 { 150 initXPath(compiler, "/..", namespaceContext); 154 } 155 else 156 throw e; 157 } 158 159 compiler.shrink(); 160 } 161 162 173 public void initMatchPattern( 174 Compiler compiler, String expression, PrefixResolver namespaceContext) 175 throws javax.xml.transform.TransformerException 176 { 177 178 m_ops = compiler; 179 m_namespaceContext = namespaceContext; 180 181 Lexer lexer = new Lexer(compiler, namespaceContext, this); 182 183 lexer.tokenize(expression); 184 185 m_ops.setOp(0, OpCodes.OP_MATCHPATTERN); 186 m_ops.setOp(OpMap.MAPINDEX_LENGTH, 2); 187 188 nextToken(); 189 Pattern(); 190 191 if (null != m_token) 192 { 193 String extraTokens = ""; 194 195 while (null != m_token) 196 { 197 extraTokens += "'" + m_token + "'"; 198 199 nextToken(); 200 201 if (null != m_token) 202 extraTokens += ", "; 203 } 204 205 error(XPATHErrorResources.ER_EXTRA_ILLEGAL_TOKENS, 206 new Object []{ extraTokens }); } 208 209 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP); 211 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH)+1); 212 213 m_ops.shrink(); 214 } 215 216 218 private ErrorListener m_errorListener; 219 220 221 javax.xml.transform.SourceLocator m_sourceLocator; 222 223 231 public void setErrorHandler(ErrorListener handler) 232 { 233 m_errorListener = handler; 234 } 235 236 241 public ErrorListener getErrorListener() 242 { 243 return m_errorListener; 244 } 245 246 254 final boolean tokenIs(String s) 255 { 256 return (m_token != null) ? (m_token.equals(s)) : (s == null); 257 } 258 259 267 final boolean tokenIs(char c) 268 { 269 return (m_token != null) ? (m_tokenChar == c) : false; 270 } 271 272 282 final boolean lookahead(char c, int n) 283 { 284 285 int pos = (m_queueMark + n); 286 boolean b; 287 288 if ((pos <= m_ops.getTokenQueueSize()) && (pos > 0) 289 && (m_ops.getTokenQueueSize() != 0)) 290 { 291 String tok = ((String ) m_ops.m_tokenQueue.elementAt(pos - 1)); 292 293 b = (tok.length() == 1) ? (tok.charAt(0) == c) : false; 294 } 295 else 296 { 297 b = false; 298 } 299 300 return b; 301 } 302 303 317 private final boolean lookbehind(char c, int n) 318 { 319 320 boolean isToken; 321 int lookBehindPos = m_queueMark - (n + 1); 322 323 if (lookBehindPos >= 0) 324 { 325 String lookbehind = (String ) m_ops.m_tokenQueue.elementAt(lookBehindPos); 326 327 if (lookbehind.length() == 1) 328 { 329 char c0 = (lookbehind == null) ? '|' : lookbehind.charAt(0); 330 331 isToken = (c0 == '|') ? false : (c0 == c); 332 } 333 else 334 { 335 isToken = false; 336 } 337 } 338 else 339 { 340 isToken = false; 341 } 342 343 return isToken; 344 } 345 346 358 private final boolean lookbehindHasToken(int n) 359 { 360 361 boolean hasToken; 362 363 if ((m_queueMark - n) > 0) 364 { 365 String lookbehind = (String ) m_ops.m_tokenQueue.elementAt(m_queueMark - (n - 1)); 366 char c0 = (lookbehind == null) ? '|' : lookbehind.charAt(0); 367 368 hasToken = (c0 == '|') ? false : true; 369 } 370 else 371 { 372 hasToken = false; 373 } 374 375 return hasToken; 376 } 377 378 389 private final boolean lookahead(String s, int n) 390 { 391 392 boolean isToken; 393 394 if ((m_queueMark + n) <= m_ops.getTokenQueueSize()) 395 { 396 String lookahead = (String ) m_ops.m_tokenQueue.elementAt(m_queueMark + (n - 1)); 397 398 isToken = (lookahead != null) ? lookahead.equals(s) : (s == null); 399 } 400 else 401 { 402 isToken = (null == s); 403 } 404 405 return isToken; 406 } 407 408 412 private final void nextToken() 413 { 414 415 if (m_queueMark < m_ops.getTokenQueueSize()) 416 { 417 m_token = (String ) m_ops.m_tokenQueue.elementAt(m_queueMark++); 418 m_tokenChar = m_token.charAt(0); 419 } 420 else 421 { 422 m_token = null; 423 m_tokenChar = 0; 424 } 425 } 426 427 435 private final String getTokenRelative(int i) 436 { 437 438 String tok; 439 int relative = m_queueMark + i; 440 441 if ((relative > 0) && (relative < m_ops.getTokenQueueSize())) 442 { 443 tok = (String ) m_ops.m_tokenQueue.elementAt(relative); 444 } 445 else 446 { 447 tok = null; 448 } 449 450 return tok; 451 } 452 453 457 private final void prevToken() 458 { 459 460 if (m_queueMark > 0) 461 { 462 m_queueMark--; 463 464 m_token = (String ) m_ops.m_tokenQueue.elementAt(m_queueMark); 465 m_tokenChar = m_token.charAt(0); 466 } 467 else 468 { 469 m_token = null; 470 m_tokenChar = 0; 471 } 472 } 473 474 482 private final void consumeExpected(String expected) 483 throws javax.xml.transform.TransformerException 484 { 485 486 if (tokenIs(expected)) 487 { 488 nextToken(); 489 } 490 else 491 { 492 error(XPATHErrorResources.ER_EXPECTED_BUT_FOUND, new Object []{ expected, 493 m_token }); 495 throw new XPathProcessorException(CONTINUE_AFTER_FATAL_ERROR); 499 } 500 } 501 502 510 private final void consumeExpected(char expected) 511 throws javax.xml.transform.TransformerException 512 { 513 514 if (tokenIs(expected)) 515 { 516 nextToken(); 517 } 518 else 519 { 520 error(XPATHErrorResources.ER_EXPECTED_BUT_FOUND, 521 new Object []{ String.valueOf(expected), 522 m_token }); 524 throw new XPathProcessorException(CONTINUE_AFTER_FATAL_ERROR); 528 } 529 } 530 531 543 void warn(String msg, Object [] args) throws TransformerException 544 { 545 546 String fmsg = XSLMessages.createXPATHWarning(msg, args); 547 ErrorListener ehandler = this.getErrorListener(); 548 549 if (null != ehandler) 550 { 551 ehandler.warning(new TransformerException (fmsg, m_sourceLocator)); 553 } 554 else 555 { 556 System.err.println(fmsg); 558 } 559 } 560 561 570 private void assertion(boolean b, String msg) 571 { 572 573 if (!b) 574 { 575 String fMsg = XSLMessages.createXPATHMessage( 576 XPATHErrorResources.ER_INCORRECT_PROGRAMMER_ASSERTION, 577 new Object []{ msg }); 578 579 throw new RuntimeException (fMsg); 580 } 581 } 582 583 596 void error(String msg, Object [] args) throws TransformerException 597 { 598 599 String fmsg = XSLMessages.createXPATHMessage(msg, args); 600 ErrorListener ehandler = this.getErrorListener(); 601 602 TransformerException te = new TransformerException (fmsg, m_sourceLocator); 603 if (null != ehandler) 604 { 605 ehandler.fatalError(te); 607 } 608 else 609 { 610 throw te; 612 } 613 } 614 615 622 protected String dumpRemainingTokenQueue() 623 { 624 625 int q = m_queueMark; 626 String returnMsg; 627 628 if (q < m_ops.getTokenQueueSize()) 629 { 630 String msg = "\n Remaining tokens: ("; 631 632 while (q < m_ops.getTokenQueueSize()) 633 { 634 String t = (String ) m_ops.m_tokenQueue.elementAt(q++); 635 636 msg += (" '" + t + "'"); 637 } 638 639 returnMsg = msg + ")"; 640 } 641 else 642 { 643 returnMsg = ""; 644 } 645 646 return returnMsg; 647 } 648 649 658 final int getFunctionToken(String key) 659 { 660 661 int tok; 662 663 try 664 { 665 tok = ((Integer ) (Keywords.m_functions.get(key))).intValue(); 666 } 667 catch (NullPointerException npe) 668 { 669 tok = -1; 670 } 671 catch (ClassCastException cce) 672 { 673 tok = -1; 674 } 675 676 return tok; 677 } 678 679 688 void insertOp(int pos, int length, int op) 689 { 690 691 int totalLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 692 693 for (int i = totalLen - 1; i >= pos; i--) 694 { 695 m_ops.setOp(i + length, m_ops.getOp(i)); 696 } 697 698 m_ops.setOp(pos,op); 699 m_ops.setOp(OpMap.MAPINDEX_LENGTH,totalLen + length); 700 } 701 702 710 void appendOp(int length, int op) 711 { 712 713 int totalLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 714 715 m_ops.setOp(totalLen, op); 716 m_ops.setOp(totalLen + OpMap.MAPINDEX_LENGTH, length); 717 m_ops.setOp(OpMap.MAPINDEX_LENGTH, totalLen + length); 718 } 719 720 722 730 protected void Expr() throws javax.xml.transform.TransformerException 731 { 732 OrExpr(); 733 } 734 735 744 protected void OrExpr() throws javax.xml.transform.TransformerException 745 { 746 747 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 748 749 AndExpr(); 750 751 if ((null != m_token) && tokenIs("or")) 752 { 753 nextToken(); 754 insertOp(opPos, 2, OpCodes.OP_OR); 755 OrExpr(); 756 757 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 758 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 759 } 760 } 761 762 771 protected void AndExpr() throws javax.xml.transform.TransformerException 772 { 773 774 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 775 776 EqualityExpr(-1); 777 778 if ((null != m_token) && tokenIs("and")) 779 { 780 nextToken(); 781 insertOp(opPos, 2, OpCodes.OP_AND); 782 AndExpr(); 783 784 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 785 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 786 } 787 } 788 789 804 protected int EqualityExpr(int addPos) throws javax.xml.transform.TransformerException 805 { 806 807 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 808 809 if (-1 == addPos) 810 addPos = opPos; 811 812 RelationalExpr(-1); 813 814 if (null != m_token) 815 { 816 if (tokenIs('!') && lookahead('=', 1)) 817 { 818 nextToken(); 819 nextToken(); 820 insertOp(addPos, 2, OpCodes.OP_NOTEQUALS); 821 822 int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos; 823 824 addPos = EqualityExpr(addPos); 825 m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH, 826 m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); 827 addPos += 2; 828 } 829 else if (tokenIs('=')) 830 { 831 nextToken(); 832 insertOp(addPos, 2, OpCodes.OP_EQUALS); 833 834 int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos; 835 836 addPos = EqualityExpr(addPos); 837 m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH, 838 m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); 839 addPos += 2; 840 } 841 } 842 843 return addPos; 844 } 845 846 864 protected int RelationalExpr(int addPos) throws javax.xml.transform.TransformerException 865 { 866 867 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 868 869 if (-1 == addPos) 870 addPos = opPos; 871 872 AdditiveExpr(-1); 873 874 if (null != m_token) 875 { 876 if (tokenIs('<')) 877 { 878 nextToken(); 879 880 if (tokenIs('=')) 881 { 882 nextToken(); 883 insertOp(addPos, 2, OpCodes.OP_LTE); 884 } 885 else 886 { 887 insertOp(addPos, 2, OpCodes.OP_LT); 888 } 889 890 int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos; 891 892 addPos = RelationalExpr(addPos); 893 m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH, 894 m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); 895 addPos += 2; 896 } 897 else if (tokenIs('>')) 898 { 899 nextToken(); 900 901 if (tokenIs('=')) 902 { 903 nextToken(); 904 insertOp(addPos, 2, OpCodes.OP_GTE); 905 } 906 else 907 { 908 insertOp(addPos, 2, OpCodes.OP_GT); 909 } 910 911 int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos; 912 913 addPos = RelationalExpr(addPos); 914 m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH, 915 m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); 916 addPos += 2; 917 } 918 } 919 920 return addPos; 921 } 922 923 939 protected int AdditiveExpr(int addPos) throws javax.xml.transform.TransformerException 940 { 941 942 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 943 944 if (-1 == addPos) 945 addPos = opPos; 946 947 MultiplicativeExpr(-1); 948 949 if (null != m_token) 950 { 951 if (tokenIs('+')) 952 { 953 nextToken(); 954 insertOp(addPos, 2, OpCodes.OP_PLUS); 955 956 int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos; 957 958 addPos = AdditiveExpr(addPos); 959 m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH, 960 m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); 961 addPos += 2; 962 } 963 else if (tokenIs('-')) 964 { 965 nextToken(); 966 insertOp(addPos, 2, OpCodes.OP_MINUS); 967 968 int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos; 969 970 addPos = AdditiveExpr(addPos); 971 m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH, 972 m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); 973 addPos += 2; 974 } 975 } 976 977 return addPos; 978 } 979 980 997 protected int MultiplicativeExpr(int addPos) throws javax.xml.transform.TransformerException 998 { 999 1000 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1001 1002 if (-1 == addPos) 1003 addPos = opPos; 1004 1005 UnaryExpr(); 1006 1007 if (null != m_token) 1008 { 1009 if (tokenIs('*')) 1010 { 1011 nextToken(); 1012 insertOp(addPos, 2, OpCodes.OP_MULT); 1013 1014 int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos; 1015 1016 addPos = MultiplicativeExpr(addPos); 1017 m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH, 1018 m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); 1019 addPos += 2; 1020 } 1021 else if (tokenIs("div")) 1022 { 1023 nextToken(); 1024 insertOp(addPos, 2, OpCodes.OP_DIV); 1025 1026 int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos; 1027 1028 addPos = MultiplicativeExpr(addPos); 1029 m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH, 1030 m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); 1031 addPos += 2; 1032 } 1033 else if (tokenIs("mod")) 1034 { 1035 nextToken(); 1036 insertOp(addPos, 2, OpCodes.OP_MOD); 1037 1038 int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos; 1039 1040 addPos = MultiplicativeExpr(addPos); 1041 m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH, 1042 m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); 1043 addPos += 2; 1044 } 1045 else if (tokenIs("quo")) 1046 { 1047 nextToken(); 1048 insertOp(addPos, 2, OpCodes.OP_QUO); 1049 1050 int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos; 1051 1052 addPos = MultiplicativeExpr(addPos); 1053 m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH, 1054 m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); 1055 addPos += 2; 1056 } 1057 } 1058 1059 return addPos; 1060 } 1061 1062 1070 protected void UnaryExpr() throws javax.xml.transform.TransformerException 1071 { 1072 1073 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1074 boolean isNeg = false; 1075 1076 if (m_tokenChar == '-') 1077 { 1078 nextToken(); 1079 appendOp(2, OpCodes.OP_NEG); 1080 1081 isNeg = true; 1082 } 1083 1084 UnionExpr(); 1085 1086 if (isNeg) 1087 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 1088 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1089 } 1090 1091 1098 protected void StringExpr() throws javax.xml.transform.TransformerException 1099 { 1100 1101 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1102 1103 appendOp(2, OpCodes.OP_STRING); 1104 Expr(); 1105 1106 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 1107 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1108 } 1109 1110 1118 protected void BooleanExpr() throws javax.xml.transform.TransformerException 1119 { 1120 1121 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1122 1123 appendOp(2, OpCodes.OP_BOOL); 1124 Expr(); 1125 1126 int opLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos; 1127 1128 if (opLen == 2) 1129 { 1130 error(XPATHErrorResources.ER_BOOLEAN_ARG_NO_LONGER_OPTIONAL, null); } 1132 1133 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, opLen); 1134 } 1135 1136 1144 protected void NumberExpr() throws javax.xml.transform.TransformerException 1145 { 1146 1147 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1148 1149 appendOp(2, OpCodes.OP_NUMBER); 1150 Expr(); 1151 1152 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 1153 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1154 } 1155 1156 1169 protected void UnionExpr() throws javax.xml.transform.TransformerException 1170 { 1171 1172 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1173 boolean continueOrLoop = true; 1174 boolean foundUnion = false; 1175 1176 do 1177 { 1178 PathExpr(); 1179 1180 if (tokenIs('|')) 1181 { 1182 if (false == foundUnion) 1183 { 1184 foundUnion = true; 1185 1186 insertOp(opPos, 2, OpCodes.OP_UNION); 1187 } 1188 1189 nextToken(); 1190 } 1191 else 1192 { 1193 break; 1194 } 1195 1196 } 1198 while (continueOrLoop); 1199 1200 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 1201 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1202 } 1203 1204 1215 protected void PathExpr() throws javax.xml.transform.TransformerException 1216 { 1217 1218 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1219 1220 int filterExprMatch = FilterExpr(); 1221 1222 if (filterExprMatch != FILTER_MATCH_FAILED) 1223 { 1224 boolean locationPathStarted = (filterExprMatch==FILTER_MATCH_PREDICATES); 1227 1228 if (tokenIs('/')) 1229 { 1230 nextToken(); 1231 1232 if (!locationPathStarted) 1233 { 1234 insertOp(opPos, 2, OpCodes.OP_LOCATIONPATH); 1236 1237 locationPathStarted = true; 1238 } 1239 1240 if (!RelativeLocationPath()) 1241 { 1242 error(XPATHErrorResources.ER_EXPECTED_REL_LOC_PATH, null); 1244 } 1245 1246 } 1247 1248 if (locationPathStarted) 1250 { 1251 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP); 1252 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1253 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 1254 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1255 } 1256 } 1257 else 1258 { 1259 LocationPath(); 1260 } 1261 } 1262 1263 1280 protected int FilterExpr() throws javax.xml.transform.TransformerException 1281 { 1282 1283 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1284 1285 int filterMatch; 1286 1287 if (PrimaryExpr()) 1288 { 1289 if (tokenIs('[')) 1290 { 1291 1292 insertOp(opPos, 2, OpCodes.OP_LOCATIONPATH); 1294 1295 while (tokenIs('[')) 1296 { 1297 Predicate(); 1298 } 1299 1300 filterMatch = FILTER_MATCH_PREDICATES; 1301 } 1302 else 1303 { 1304 filterMatch = FILTER_MATCH_PRIMARY; 1305 } 1306 } 1307 else 1308 { 1309 filterMatch = FILTER_MATCH_FAILED; 1310 } 1311 1312 return filterMatch; 1313 1314 1321 } 1322 1323 1336 protected boolean PrimaryExpr() throws javax.xml.transform.TransformerException 1337 { 1338 1339 boolean matchFound; 1340 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1341 1342 if ((m_tokenChar == '\'') || (m_tokenChar == '"')) 1343 { 1344 appendOp(2, OpCodes.OP_LITERAL); 1345 Literal(); 1346 1347 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 1348 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1349 1350 matchFound = true; 1351 } 1352 else if (m_tokenChar == '$') 1353 { 1354 nextToken(); appendOp(2, OpCodes.OP_VARIABLE); 1356 QName(); 1357 1358 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 1359 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1360 1361 matchFound = true; 1362 } 1363 else if (m_tokenChar == '(') 1364 { 1365 nextToken(); 1366 appendOp(2, OpCodes.OP_GROUP); 1367 Expr(); 1368 consumeExpected(')'); 1369 1370 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 1371 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1372 1373 matchFound = true; 1374 } 1375 else if ((null != m_token) && ((('.' == m_tokenChar) && (m_token.length() > 1) && Character.isDigit( 1376 m_token.charAt(1))) || Character.isDigit(m_tokenChar))) 1377 { 1378 appendOp(2, OpCodes.OP_NUMBERLIT); 1379 Number(); 1380 1381 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 1382 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1383 1384 matchFound = true; 1385 } 1386 else if (lookahead('(', 1) || (lookahead(':', 1) && lookahead('(', 3))) 1387 { 1388 matchFound = FunctionCall(); 1389 } 1390 else 1391 { 1392 matchFound = false; 1393 } 1394 1395 return matchFound; 1396 } 1397 1398 1405 protected void Argument() throws javax.xml.transform.TransformerException 1406 { 1407 1408 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1409 1410 appendOp(2, OpCodes.OP_ARGUMENT); 1411 Expr(); 1412 1413 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 1414 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1415 } 1416 1417 1425 protected boolean FunctionCall() throws javax.xml.transform.TransformerException 1426 { 1427 1428 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1429 1430 if (lookahead(':', 1)) 1431 { 1432 appendOp(4, OpCodes.OP_EXTFUNCTION); 1433 1434 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1, m_queueMark - 1); 1435 1436 nextToken(); 1437 consumeExpected(':'); 1438 1439 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 2, m_queueMark - 1); 1440 1441 nextToken(); 1442 } 1443 else 1444 { 1445 int funcTok = getFunctionToken(m_token); 1446 1447 if (-1 == funcTok) 1448 { 1449 error(XPATHErrorResources.ER_COULDNOT_FIND_FUNCTION, 1450 new Object []{ m_token }); } 1452 1453 switch (funcTok) 1454 { 1455 case OpCodes.NODETYPE_PI : 1456 case OpCodes.NODETYPE_COMMENT : 1457 case OpCodes.NODETYPE_TEXT : 1458 case OpCodes.NODETYPE_NODE : 1459 return false; 1461 default : 1462 appendOp(3, OpCodes.OP_FUNCTION); 1463 1464 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1, funcTok); 1465 } 1466 1467 nextToken(); 1468 } 1469 1470 consumeExpected('('); 1471 1472 while (!tokenIs(')') && m_token != null) 1473 { 1474 if (tokenIs(',')) 1475 { 1476 error(XPATHErrorResources.ER_FOUND_COMMA_BUT_NO_PRECEDING_ARG, null); } 1478 1479 Argument(); 1480 1481 if (!tokenIs(')')) 1482 { 1483 consumeExpected(','); 1484 1485 if (tokenIs(')')) 1486 { 1487 error(XPATHErrorResources.ER_FOUND_COMMA_BUT_NO_FOLLOWING_ARG, 1488 null); } 1490 } 1491 } 1492 1493 consumeExpected(')'); 1494 1495 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP); 1497 m_ops.setOp(OpMap.MAPINDEX_LENGTH,m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1498 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 1499 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1500 1501 return true; 1502 } 1503 1504 1506 1514 protected void LocationPath() throws javax.xml.transform.TransformerException 1515 { 1516 1517 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1518 1519 appendOp(2, OpCodes.OP_LOCATIONPATH); 1521 1522 boolean seenSlash = tokenIs('/'); 1523 1524 if (seenSlash) 1525 { 1526 appendOp(4, OpCodes.FROM_ROOT); 1527 1528 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 2, 4); 1530 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 1, OpCodes.NODETYPE_ROOT); 1531 1532 nextToken(); 1533 } 1534 1535 if (m_token != null) 1536 { 1537 if (!RelativeLocationPath() && !seenSlash) 1538 { 1539 error(XPATHErrorResources.ER_EXPECTED_LOC_PATH, 1542 new Object [] {m_token}); 1543 } 1544 } 1545 1546 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP); 1548 m_ops.setOp(OpMap.MAPINDEX_LENGTH,m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1549 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 1550 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1551 } 1552 1553 1563 protected boolean RelativeLocationPath() 1564 throws javax.xml.transform.TransformerException 1565 { 1566 if (!Step()) 1567 { 1568 return false; 1569 } 1570 1571 while (tokenIs('/')) 1572 { 1573 nextToken(); 1574 1575 if (!Step()) 1576 { 1577 error(XPATHErrorResources.ER_EXPECTED_LOC_STEP, null); 1580 } 1581 } 1582 1583 return true; 1584 } 1585 1586 1595 protected boolean Step() throws javax.xml.transform.TransformerException 1596 { 1597 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1598 1599 boolean doubleSlash = tokenIs('/'); 1600 1601 if (doubleSlash) 1605 { 1606 nextToken(); 1607 1608 appendOp(2, OpCodes.FROM_DESCENDANTS_OR_SELF); 1609 1610 1615 m_ops.setOp(OpMap.MAPINDEX_LENGTH,m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1617 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.NODETYPE_NODE); 1618 m_ops.setOp(OpMap.MAPINDEX_LENGTH,m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1619 1620 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1, 1622 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1623 1624 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 1626 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1627 1628 opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1629 } 1630 1631 if (tokenIs(".")) 1632 { 1633 nextToken(); 1634 1635 if (tokenIs('[')) 1636 { 1637 error(XPATHErrorResources.ER_PREDICATE_ILLEGAL_SYNTAX, null); } 1639 1640 appendOp(4, OpCodes.FROM_SELF); 1641 1642 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 2,4); 1644 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 1, OpCodes.NODETYPE_NODE); 1645 } 1646 else if (tokenIs("..")) 1647 { 1648 nextToken(); 1649 appendOp(4, OpCodes.FROM_PARENT); 1650 1651 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 2,4); 1653 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 1, OpCodes.NODETYPE_NODE); 1654 } 1655 1656 else if (tokenIs('*') || tokenIs('@') || tokenIs('_') 1660 || (m_token!= null && Character.isLetter(m_token.charAt(0)))) 1661 { 1662 Basis(); 1663 1664 while (tokenIs('[')) 1665 { 1666 Predicate(); 1667 } 1668 1669 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 1671 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1672 } 1673 else 1674 { 1675 if (doubleSlash) 1677 { 1678 error(XPATHErrorResources.ER_EXPECTED_LOC_STEP, null); 1680 } 1681 1682 return false; 1683 } 1684 1685 return true; 1686 } 1687 1688 1695 protected void Basis() throws javax.xml.transform.TransformerException 1696 { 1697 1698 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1699 int axesType; 1700 1701 if (lookahead("::", 1)) 1703 { 1704 axesType = AxisName(); 1705 1706 nextToken(); 1707 nextToken(); 1708 } 1709 else if (tokenIs('@')) 1710 { 1711 axesType = OpCodes.FROM_ATTRIBUTES; 1712 1713 appendOp(2, axesType); 1714 nextToken(); 1715 } 1716 else 1717 { 1718 axesType = OpCodes.FROM_CHILDREN; 1719 1720 appendOp(2, axesType); 1721 } 1722 1723 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1725 1726 NodeTest(axesType); 1727 1728 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1, 1730 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1731 } 1732 1733 1742 protected int AxisName() throws javax.xml.transform.TransformerException 1743 { 1744 1745 Object val = Keywords.m_axisnames.get(m_token); 1746 1747 if (null == val) 1748 { 1749 error(XPATHErrorResources.ER_ILLEGAL_AXIS_NAME, 1750 new Object []{ m_token }); } 1752 1753 int axesType = ((Integer ) val).intValue(); 1754 1755 appendOp(2, axesType); 1756 1757 return axesType; 1758 } 1759 1760 1770 protected void NodeTest(int axesType) throws javax.xml.transform.TransformerException 1771 { 1772 1773 if (lookahead('(', 1)) 1774 { 1775 Object nodeTestOp = Keywords.m_nodetypes.get(m_token); 1776 1777 if (null == nodeTestOp) 1778 { 1779 error(XPATHErrorResources.ER_UNKNOWN_NODETYPE, 1780 new Object []{ m_token }); } 1782 else 1783 { 1784 nextToken(); 1785 1786 int nt = ((Integer ) nodeTestOp).intValue(); 1787 1788 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), nt); 1789 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1790 1791 consumeExpected('('); 1792 1793 if (OpCodes.NODETYPE_PI == nt) 1794 { 1795 if (!tokenIs(')')) 1796 { 1797 Literal(); 1798 } 1799 } 1800 1801 consumeExpected(')'); 1802 } 1803 } 1804 else 1805 { 1806 1807 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.NODENAME); 1809 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1810 1811 if (lookahead(':', 1)) 1812 { 1813 if (tokenIs('*')) 1814 { 1815 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ELEMWILDCARD); 1816 } 1817 else 1818 { 1819 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1); 1820 1821 if (!Character.isLetter(m_tokenChar) && !tokenIs('_')) 1824 { 1825 error(XPATHErrorResources.ER_EXPECTED_NODE_TEST, null); 1827 } 1828 } 1829 1830 nextToken(); 1831 consumeExpected(':'); 1832 } 1833 else 1834 { 1835 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.EMPTY); 1836 } 1837 1838 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1839 1840 if (tokenIs('*')) 1841 { 1842 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ELEMWILDCARD); 1843 } 1844 else 1845 { 1846 if (OpCodes.FROM_NAMESPACE == axesType) 1847 { 1848 String prefix = (String ) this.m_ops.m_tokenQueue.elementAt(m_queueMark - 1); 1849 String namespace = 1850 ((PrefixResolver) m_namespaceContext).getNamespaceForPrefix( 1851 prefix); 1852 1853 this.m_ops.m_tokenQueue.setElementAt(namespace,m_queueMark - 1); 1854 } 1855 1856 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1); 1857 1858 if (!Character.isLetter(m_tokenChar) && !tokenIs('_')) 1861 { 1862 error(XPATHErrorResources.ER_EXPECTED_NODE_TEST, null); 1864 } 1865 } 1866 1867 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1868 1869 nextToken(); 1870 } 1871 } 1872 1873 1880 protected void Predicate() throws javax.xml.transform.TransformerException 1881 { 1882 1883 if (tokenIs('[')) 1884 { 1885 nextToken(); 1886 PredicateExpr(); 1887 consumeExpected(']'); 1888 } 1889 } 1890 1891 1898 protected void PredicateExpr() throws javax.xml.transform.TransformerException 1899 { 1900 1901 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 1902 1903 appendOp(2, OpCodes.OP_PREDICATE); 1904 Expr(); 1905 1906 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP); 1908 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1909 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 1910 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 1911 } 1912 1913 1920 protected void QName() throws javax.xml.transform.TransformerException 1921 { 1922 if(lookahead(':', 1)) 1924 { 1925 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1); 1926 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1927 1928 nextToken(); 1929 consumeExpected(':'); 1930 } 1931 else 1932 { 1933 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.EMPTY); 1934 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1935 } 1936 1937 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1); 1939 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1940 1941 nextToken(); 1942 } 1943 1944 1948 protected void NCName() 1949 { 1950 1951 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1); 1952 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1953 1954 nextToken(); 1955 } 1956 1957 1967 protected void Literal() throws javax.xml.transform.TransformerException 1968 { 1969 1970 int last = m_token.length() - 1; 1971 char c0 = m_tokenChar; 1972 char cX = m_token.charAt(last); 1973 1974 if (((c0 == '\"') && (cX == '\"')) || ((c0 == '\'') && (cX == '\''))) 1975 { 1976 1977 int tokenQueuePos = m_queueMark - 1; 1980 1981 m_ops.m_tokenQueue.setElementAt(null,tokenQueuePos); 1982 1983 Object obj = new XString(m_token.substring(1, last)); 1984 1985 m_ops.m_tokenQueue.setElementAt(obj,tokenQueuePos); 1986 1987 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), tokenQueuePos); 1989 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 1990 1991 nextToken(); 1992 } 1993 else 1994 { 1995 error(XPATHErrorResources.ER_PATTERN_LITERAL_NEEDS_BE_QUOTED, 1996 new Object []{ m_token }); } 1998 } 1999 2000 2007 protected void Number() throws javax.xml.transform.TransformerException 2008 { 2009 2010 if (null != m_token) 2011 { 2012 2013 double num; 2016 2017 try 2018 { 2019 if ((m_token.indexOf('e') > -1)||(m_token.indexOf('E') > -1)) 2021 throw new NumberFormatException (); 2022 num = Double.valueOf(m_token).doubleValue(); 2023 } 2024 catch (NumberFormatException nfe) 2025 { 2026 num = 0.0; 2028 error(XPATHErrorResources.ER_COULDNOT_BE_FORMATTED_TO_NUMBER, 2029 new Object []{ m_token }); } 2031 2032 m_ops.m_tokenQueue.setElementAt(new XNumber(num),m_queueMark - 1); 2033 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1); 2034 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 2035 2036 nextToken(); 2037 } 2038 } 2039 2040 2042 2050 protected void Pattern() throws javax.xml.transform.TransformerException 2051 { 2052 2053 while (true) 2054 { 2055 LocationPathPattern(); 2056 2057 if (tokenIs('|')) 2058 { 2059 nextToken(); 2060 } 2061 else 2062 { 2063 break; 2064 } 2065 } 2066 } 2067 2068 2078 protected void LocationPathPattern() throws javax.xml.transform.TransformerException 2079 { 2080 2081 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 2082 2083 final int RELATIVE_PATH_NOT_PERMITTED = 0; 2084 final int RELATIVE_PATH_PERMITTED = 1; 2085 final int RELATIVE_PATH_REQUIRED = 2; 2086 2087 int relativePathStatus = RELATIVE_PATH_NOT_PERMITTED; 2088 2089 appendOp(2, OpCodes.OP_LOCATIONPATHPATTERN); 2090 2091 if (lookahead('(', 1) 2092 && (tokenIs(Keywords.FUNC_ID_STRING) 2093 || tokenIs(Keywords.FUNC_KEY_STRING))) 2094 { 2095 IdKeyPattern(); 2096 2097 if (tokenIs('/')) 2098 { 2099 nextToken(); 2100 2101 if (tokenIs('/')) 2102 { 2103 appendOp(4, OpCodes.MATCH_ANY_ANCESTOR); 2104 2105 nextToken(); 2106 } 2107 else 2108 { 2109 appendOp(4, OpCodes.MATCH_IMMEDIATE_ANCESTOR); 2110 } 2111 2112 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 2, 4); 2114 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 1, OpCodes.NODETYPE_FUNCTEST); 2115 2116 relativePathStatus = RELATIVE_PATH_REQUIRED; 2117 } 2118 } 2119 else if (tokenIs('/')) 2120 { 2121 if (lookahead('/', 1)) 2122 { 2123 appendOp(4, OpCodes.MATCH_ANY_ANCESTOR); 2124 2125 nextToken(); 2130 2131 relativePathStatus = RELATIVE_PATH_REQUIRED; 2132 } 2133 else 2134 { 2135 appendOp(4, OpCodes.FROM_ROOT); 2136 2137 relativePathStatus = RELATIVE_PATH_PERMITTED; 2138 } 2139 2140 2141 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 2, 4); 2143 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 1, OpCodes.NODETYPE_ROOT); 2144 2145 nextToken(); 2146 } 2147 else 2148 { 2149 relativePathStatus = RELATIVE_PATH_REQUIRED; 2150 } 2151 2152 if (relativePathStatus != RELATIVE_PATH_NOT_PERMITTED) 2153 { 2154 if (!tokenIs('|') && (null != m_token)) 2155 { 2156 RelativePathPattern(); 2157 } 2158 else if (relativePathStatus == RELATIVE_PATH_REQUIRED) 2159 { 2160 error(XPATHErrorResources.ER_EXPECTED_REL_PATH_PATTERN, null); 2162 } 2163 } 2164 2165 m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP); 2167 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 2168 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 2169 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 2170 } 2171 2172 2181 protected void IdKeyPattern() throws javax.xml.transform.TransformerException 2182 { 2183 FunctionCall(); 2184 } 2185 2186 2194 protected void RelativePathPattern() 2195 throws javax.xml.transform.TransformerException 2196 { 2197 2198 boolean trailingSlashConsumed = StepPattern(false); 2201 2202 while (tokenIs('/')) 2203 { 2204 nextToken(); 2205 2206 trailingSlashConsumed = StepPattern(!trailingSlashConsumed); 2210 } 2211 } 2212 2213 2224 protected boolean StepPattern(boolean isLeadingSlashPermitted) 2225 throws javax.xml.transform.TransformerException 2226 { 2227 return AbbreviatedNodeTestStep(isLeadingSlashPermitted); 2228 } 2229 2230 2241 protected boolean AbbreviatedNodeTestStep(boolean isLeadingSlashPermitted) 2242 throws javax.xml.transform.TransformerException 2243 { 2244 2245 int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 2246 int axesType; 2247 2248 int matchTypePos = -1; 2250 2251 if (tokenIs('@')) 2252 { 2253 axesType = OpCodes.MATCH_ATTRIBUTE; 2254 2255 appendOp(2, axesType); 2256 nextToken(); 2257 } 2258 else if (this.lookahead("::", 1)) 2259 { 2260 if (tokenIs("attribute")) 2261 { 2262 axesType = OpCodes.MATCH_ATTRIBUTE; 2263 2264 appendOp(2, axesType); 2265 } 2266 else if (tokenIs("child")) 2267 { 2268 matchTypePos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 2269 axesType = OpCodes.MATCH_IMMEDIATE_ANCESTOR; 2270 2271 appendOp(2, axesType); 2272 } 2273 else 2274 { 2275 axesType = -1; 2276 2277 this.error(XPATHErrorResources.ER_AXES_NOT_ALLOWED, 2278 new Object []{ this.m_token }); 2279 } 2280 2281 nextToken(); 2282 nextToken(); 2283 } 2284 else if (tokenIs('/')) 2285 { 2286 if (!isLeadingSlashPermitted) 2287 { 2288 error(XPATHErrorResources.ER_EXPECTED_STEP_PATTERN, null); 2290 } 2291 axesType = OpCodes.MATCH_ANY_ANCESTOR; 2292 2293 appendOp(2, axesType); 2294 nextToken(); 2295 } 2296 else 2297 { 2298 matchTypePos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); 2299 axesType = OpCodes.MATCH_IMMEDIATE_ANCESTOR; 2300 2301 appendOp(2, axesType); 2302 } 2303 2304 m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); 2306 2307 NodeTest(axesType); 2308 2309 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1, 2311 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 2312 2313 while (tokenIs('[')) 2314 { 2315 Predicate(); 2316 } 2317 2318 boolean trailingSlashConsumed; 2319 2320 if ((matchTypePos > -1) && tokenIs('/') && lookahead('/', 1)) 2333 { 2334 m_ops.setOp(matchTypePos, OpCodes.MATCH_ANY_ANCESTOR); 2335 2336 nextToken(); 2337 2338 trailingSlashConsumed = true; 2339 } 2340 else 2341 { 2342 trailingSlashConsumed = false; 2343 } 2344 2345 m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 2347 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); 2348 2349 return trailingSlashConsumed; 2350 } 2351} 2352 | Popular Tags |