1 57 58 package org.enhydra.apache.xerces.validators.schema.identity; 59 60 import org.enhydra.apache.xerces.utils.NamespacesScope; 61 import org.enhydra.apache.xerces.utils.QName; 62 import org.enhydra.apache.xerces.utils.StringPool; 63 import org.enhydra.apache.xerces.utils.XMLCharacterProperties; 64 65 71 public class XPath { 72 73 77 private static final boolean DEBUG_ALL = false; 78 79 private static final boolean DEBUG_XPATH_PARSE = DEBUG_ALL || false; 80 81 private static final boolean DEBUG_ANY = DEBUG_XPATH_PARSE; 82 83 87 88 protected String fExpression; 89 90 91 92 94 95 protected StringPool fStringPool; 96 97 101 102 public XPath(String xpath, StringPool stringPool, 103 NamespacesScope context) 104 throws XPathException { 105 XMLCharacterProperties.initCharFlags(); 106 fExpression = xpath; 107 fStringPool = stringPool; 108 parseExpression(context); 109 } 111 115 116 public LocationPath getLocationPath() { 117 return (LocationPath)fLocationPaths[0].clone(); 118 } 120 124 125 public String toString() { 126 StringBuffer buf=new StringBuffer (); 127 for (int i=0;i<fLocationPaths.length;i++){ 128 if (i>0){ 129 buf.append("|"); 130 } 131 buf.append(fLocationPaths[i].toString()); 132 } 133 return buf.toString(); 134 } 136 140 144 private void parseExpression(final NamespacesScope context) 145 throws XPathException { 146 147 final XPath.Tokens xtokens = new XPath.Tokens(fStringPool); 149 150 XPath.Scanner scanner = new XPath.Scanner(fStringPool) { 152 protected void addToken(XPath.Tokens tokens, int token) 153 throws XPathException { 154 if ( 155 token == XPath.Tokens.EXPRTOKEN_ATSIGN || 156 token == XPath.Tokens.EXPRTOKEN_AXISNAME_ATTRIBUTE || 157 token == XPath.Tokens.EXPRTOKEN_AXISNAME_CHILD || 158 token == XPath.Tokens.EXPRTOKEN_DOUBLE_COLON || 160 token == XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME || 162 token == XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH || 164 token == XPath.Tokens.EXPRTOKEN_PERIOD || 165 token == XPath.Tokens.EXPRTOKEN_NAMETEST_ANY || 167 token == XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE || 168 token == XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH || 169 token == XPath.Tokens.EXPRTOKEN_OPERATOR_UNION 170 ) { 172 super.addToken(tokens, token); 173 return; 174 } 175 StringBuffer str = new StringBuffer (); 176 str.append("token not supported: "); 177 String tokenName = tokens.getTokenName(token); 178 if (tokenName != null) { 179 str.append('"'); 180 str.append(tokenName); 181 str.append('"'); 182 } 183 else { 184 str.append('('); 185 str.append(token); 186 str.append(')'); 187 } 188 String message = str.toString(); 189 throw new XPathException(message); 190 } 191 }; 192 193 int length = fExpression.length(); 194 195 boolean success = scanner.scanExpr(fStringPool, 196 xtokens, fExpression, 0, length); 197 java.util.Vector stepsVector = new java.util.Vector (); 199 java.util.Vector locationPathsVector= new java.util.Vector (); 200 int tokenCount = xtokens.getTokenCount(); 201 boolean firstTokenOfLocationPath=true; 202 203 for (int i = 0; i < tokenCount; i++) { 204 int token = xtokens.getToken(i); 205 boolean isNamespace=false; 206 207 switch (token) { 208 case XPath.Tokens.EXPRTOKEN_OPERATOR_UNION :{ 209 if (i == 0) { 210 throw new XPathException("not allowed to have '|' at the beginning of an xpath value"); 211 } 212 213 int size = stepsVector.size(); 214 if (size == 0) { 215 throw new XPathException("not allowed to have '||'"); 216 } 217 Step[] steps = new Step[size]; 218 stepsVector.copyInto(steps); 219 locationPathsVector.addElement(new LocationPath(steps)); 221 stepsVector.removeAllElements(); 223 firstTokenOfLocationPath=true; 224 break; 225 } 226 227 case XPath.Tokens.EXPRTOKEN_AXISNAME_ATTRIBUTE: { 228 i++; 230 } 231 case XPath.Tokens.EXPRTOKEN_ATSIGN: { 232 if (i == tokenCount - 1) { 234 throw new XPathException("missing attribute name"); 235 } 236 token = xtokens.getToken(++i); 237 238 if (token != XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME 239 && token!= XPath.Tokens.EXPRTOKEN_NAMETEST_ANY 240 && token!= XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE) { 241 throw new XPathException("expected \""+xtokens.getTokenName(XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME)+ 242 "\" or \""+xtokens.getTokenName( XPath.Tokens.EXPRTOKEN_NAMETEST_ANY)+ 243 "\" or \""+xtokens.getTokenName( XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE)+ 244 "\", found "+xtokens.getTokenName(token)); 245 } 246 boolean isNamespaceAtt=false; 247 switch (token) 248 { 249 case XPath.Tokens.EXPRTOKEN_NAMETEST_ANY:{ 250 Axis axis = new Axis(Axis.ATTRIBUTE); 251 NodeTest nodeTest = new NodeTest(NodeTest.WILDCARD); 252 Step step = new Step(axis, nodeTest); 253 stepsVector.addElement(step); 254 break; 255 } 256 case XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE:{ 257 isNamespaceAtt=true; 258 } 259 case XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME:{ 260 261 token = xtokens.getToken(++i); 262 int prefix = xtokens.getTokenString(token); 263 int uri = StringPool.EMPTY_STRING; 264 if (context != null && prefix != -1) { 265 uri = context.getNamespaceForPrefix(prefix); 266 } 267 if (prefix != -1 && context != null && uri == StringPool.EMPTY_STRING) { 268 throw new XPathException("prefix "+fStringPool.toString(prefix)+" not bound to namespace URI"); 269 } 270 271 if (isNamespaceAtt) 272 { 273 Axis axis = new Axis(Axis.ATTRIBUTE); 275 NodeTest nodeTest=new NodeTest(fStringPool,prefix,uri); 276 Step step = new Step(axis, nodeTest); 277 stepsVector.addElement(step); 278 break; 279 } 280 281 token = xtokens.getToken(++i); 282 int localpart = xtokens.getTokenString(token); 283 int rawname = prefix != -1 284 ? fStringPool.addSymbol(fStringPool.toString(prefix) + ':' + fStringPool.toString(localpart)) 285 : localpart; 286 287 Axis axis = new Axis(Axis.ATTRIBUTE); 289 NodeTest nodeTest = new NodeTest(fStringPool, new QName(prefix, localpart, rawname, uri)); 290 Step step = new Step(axis, nodeTest); 291 stepsVector.addElement(step); 292 break; 293 } 294 } 295 firstTokenOfLocationPath=false; 296 break; 297 } 298 303 case XPath.Tokens.EXPRTOKEN_DOUBLE_COLON: { 304 throw new XPathException("Not allowed to have double colon here"); 306 } 307 312 case XPath.Tokens.EXPRTOKEN_AXISNAME_CHILD: { 313 314 i++; 316 if (i == tokenCount - 1) { 317 throw new XPathException("expected step following '" 318 +xtokens.getTokenName(XPath.Tokens.EXPRTOKEN_AXISNAME_CHILD)+"::'"); 319 } 320 firstTokenOfLocationPath=false; 321 break; 322 } 323 case XPath.Tokens.EXPRTOKEN_NAMETEST_ANY:{ 324 Axis axis = new Axis(Axis.CHILD); 325 NodeTest nodeTest = new NodeTest(NodeTest.WILDCARD); 326 Step step = new Step(axis, nodeTest); 327 stepsVector.addElement(step); 328 firstTokenOfLocationPath=false; 329 break; 330 } 331 332 case XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE:{ 333 isNamespace=true; 334 } 335 case XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME: { 336 token = xtokens.getToken(++i); 338 int prefix = xtokens.getTokenString(token); 339 int uri = StringPool.EMPTY_STRING; 340 if (context != null && prefix != -1) { 341 uri = context.getNamespaceForPrefix(prefix); 342 } 343 if (prefix != -1 && context != null && 344 uri == StringPool.EMPTY_STRING) { 345 throw new XPathException("prefix "+fStringPool.toString(prefix)+" not bound to namespace URI"); 346 } 347 348 if (isNamespace) 349 { 350 Axis axis = new Axis(Axis.CHILD); 352 NodeTest nodeTest=new NodeTest(fStringPool,prefix,uri); 353 Step step = new Step(axis, nodeTest); 354 stepsVector.addElement(step); 355 break; 356 } 357 358 token = xtokens.getToken(++i); 359 int localpart = xtokens.getTokenString(token); 360 int rawname = prefix != -1 361 ? fStringPool.addSymbol(fStringPool.toString(prefix) + ':' + fStringPool.toString(localpart)) 362 : localpart; 363 364 Axis axis = new Axis(Axis.CHILD); 366 NodeTest nodeTest = new NodeTest(fStringPool, new QName(prefix, localpart, rawname, uri)); 367 Step step = new Step(axis, nodeTest); 368 stepsVector.addElement(step); 369 firstTokenOfLocationPath=false; 370 break; 371 } 372 377 378 379 case XPath.Tokens.EXPRTOKEN_PERIOD: { 380 Axis axis = new Axis(Axis.SELF); 382 NodeTest nodeTest = new NodeTest(NodeTest.NODE); 383 Step step = new Step(axis, nodeTest); 384 stepsVector.addElement(step); 385 386 if (firstTokenOfLocationPath && i+1<tokenCount){ 387 token=xtokens.getToken(i+1); 388 if (token == XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH){ 389 i++; 390 if (i == tokenCount - 1) { 391 throw new XPathException("expected step following '//'"); 392 } 393 if (i+1<tokenCount) { 394 token=xtokens.getToken(i+1); 395 if (token==XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH) 396 throw new XPathException("'/' not allowed after '//'"); 397 } 398 axis = new Axis(Axis.DESCENDANT); 400 nodeTest = new NodeTest(NodeTest.NODE); 401 step = new Step(axis, nodeTest); 402 stepsVector.addElement(step); 403 } 404 } 405 firstTokenOfLocationPath=false; 406 break; 407 } 408 409 case XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH:{ 410 throw new XPathException("'//' only allowed after '.' at the beginning of an xpath"); 411 } 412 case XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH: { 413 if (i == 0) { 414 throw new XPathException("not allowed to have '/' at the beginning of an xpath value"); 415 } 416 if (firstTokenOfLocationPath) { 418 throw new XPathException("not allowed to select the root"); 419 } 420 if (i == tokenCount - 1) { 421 throw new XPathException("expected step following '/'"); 422 } 423 firstTokenOfLocationPath=false; 424 break; 425 } 426 default: 427 firstTokenOfLocationPath=false; 428 } 429 } 430 431 int size = stepsVector.size(); 432 if (size == 0) { 433 if (locationPathsVector.size()==0) 434 throw new XPathException("empty xpath expression"); 435 else 436 throw new XPathException("xpath cannot end with '|'"); 437 } 438 Step[] steps = new Step[size]; 439 stepsVector.copyInto(steps); 440 locationPathsVector.addElement(new LocationPath(steps)); 441 442 fLocationPaths=new LocationPath[locationPathsVector.size()]; 444 locationPathsVector.copyInto(fLocationPaths); 445 446 447 if (DEBUG_XPATH_PARSE) { 448 System.out.println(">>> "+fLocationPaths); 449 } 450 451 } 453 457 459 464 public static class LocationPath 465 implements Cloneable { 466 467 471 472 public Step[] steps; 473 474 478 479 public LocationPath(Step[] steps) { 480 this.steps = steps; 481 } 483 484 protected LocationPath(LocationPath path) { 485 steps = new Step[path.steps.length]; 486 for (int i = 0; i < steps.length; i++) { 487 steps[i] = (Step)path.steps[i].clone(); 488 } 489 } 491 495 496 public String toString() { 497 StringBuffer str = new StringBuffer (); 498 for (int i = 0; i < steps.length; i++) { 499 if (i > 0 && (steps[i-1].axis.type!=Axis.DESCENDANT 500 && steps[i].axis.type!=Axis.DESCENDANT) ){ 501 str.append('/'); 502 } 503 str.append(steps[i].toString()); 504 } 505 if (false) { 509 str.append('['); 510 String s = super.toString(); 511 str.append(s.substring(s.indexOf('@'))); 512 str.append(']'); 513 } 514 return str.toString(); 515 } 517 518 public Object clone() { 519 return new LocationPath(this); 520 } 522 } 524 529 public static class Step 530 implements Cloneable { 531 532 536 537 public Axis axis; 538 539 540 public NodeTest nodeTest; 541 542 546 547 public Step(Axis axis, NodeTest nodeTest) { 548 this.axis = axis; 549 this.nodeTest = nodeTest; 550 } 552 553 protected Step(Step step) { 554 axis = (Axis)step.axis.clone(); 555 nodeTest = (NodeTest)step.nodeTest.clone(); 556 } 558 562 563 public String toString() { 564 567 if (axis.type == Axis.SELF) { 568 return "."; 569 } 570 if (axis.type == Axis.ATTRIBUTE) { 571 return "@" + nodeTest.toString(); 572 } 573 if (axis.type == Axis.CHILD) { 574 return nodeTest.toString(); 575 } 576 if (axis.type == Axis.DESCENDANT) { 577 return "//"; 578 } 579 return "??? ("+axis.type+')'; 580 581 } 583 584 public Object clone() { 585 return new Step(this); 586 } 588 } 590 595 public static class Axis 596 implements Cloneable { 597 598 602 603 public static final short CHILD = 1; 604 605 606 public static final short ATTRIBUTE = 2; 607 608 609 public static final short SELF = 3; 610 611 612 613 public static final short DESCENDANT = 4; 614 618 619 public short type; 620 621 625 626 public Axis(short type) { 627 this.type = type; 628 } 630 631 protected Axis(Axis axis) { 632 type = axis.type; 633 } 635 639 640 public String toString() { 641 switch (type) { 642 case CHILD: return "child"; 643 case ATTRIBUTE: return "attribute"; 644 case SELF: return "self"; 645 case DESCENDANT: return "descendant"; 646 } 647 return "???"; 648 } 650 651 public Object clone() { 652 return new Axis(this); 653 } 655 } 657 662 public static class NodeTest 663 implements Cloneable { 664 665 669 670 public static final short QNAME = 1; 671 672 673 public static final short WILDCARD = 2; 674 675 676 public static final short NODE = 3; 677 678 679 public static final short NAMESPACE= 4; 680 681 685 686 protected StringPool fStringPool; 687 688 689 public short type; 690 691 692 public final QName name = new QName(); 693 694 698 699 public NodeTest(short type) { 700 this.type = type; 701 } 703 704 public NodeTest(StringPool stringPool, QName name) { 705 fStringPool = stringPool; 706 this.type = QNAME; 707 this.name.setValues(name); 708 } 710 public NodeTest(StringPool stringPool, int prefix, int uri) { 711 fStringPool = stringPool; 712 this.type = NAMESPACE; 713 this.name.setValues(prefix,-1,-1,uri); 714 } 715 716 717 public NodeTest(NodeTest nodeTest) { 718 fStringPool = nodeTest.fStringPool; 719 type = nodeTest.type; 720 name.setValues(nodeTest.name); 721 } 723 727 728 public String toString() { 729 730 switch (type) { 731 case QNAME: { 732 if (name.prefix != -1) { 733 if (name.uri == StringPool.EMPTY_STRING) { 734 return fStringPool.toString(name.prefix) + ':' + fStringPool.toString(name.localpart); 735 } 736 return "{" + fStringPool.toString(name.uri) + '}' + fStringPool.toString(name.prefix) + ':' + fStringPool.toString(name.localpart); 737 } 738 return fStringPool.toString(name.localpart); 739 } 740 case NAMESPACE: { 741 if (name.prefix!=-1) { 742 if (name.uri == StringPool.EMPTY_STRING) { 743 return fStringPool.toString(name.prefix) + ":*"; 744 } 745 return "{" + fStringPool.toString(name.uri) + '}' + fStringPool.toString(name.prefix) + ":*"; 746 } 747 return "???:*"; 748 } 749 case WILDCARD: { 750 return "*"; 751 } 752 case NODE: { 753 return "node()"; 754 } 755 } 756 return "???"; 757 758 } 760 761 public Object clone() { 762 return new NodeTest(this); 763 } 765 } 767 769 775 781 private static final class Tokens { 782 783 static final boolean DUMP_TOKENS = false; 784 785 790 public static final int 791 EXPRTOKEN_OPEN_PAREN = 0, 792 EXPRTOKEN_CLOSE_PAREN = 1, 793 EXPRTOKEN_OPEN_BRACKET = 2, 794 EXPRTOKEN_CLOSE_BRACKET = 3, 795 EXPRTOKEN_PERIOD = 4, 796 EXPRTOKEN_DOUBLE_PERIOD = 5, 797 EXPRTOKEN_ATSIGN = 6, 798 EXPRTOKEN_COMMA = 7, 799 EXPRTOKEN_DOUBLE_COLON = 8, 800 EXPRTOKEN_NAMETEST_ANY = 9, 806 EXPRTOKEN_NAMETEST_NAMESPACE = 10, 807 EXPRTOKEN_NAMETEST_QNAME = 11, 808 EXPRTOKEN_NODETYPE_COMMENT = 12, 812 EXPRTOKEN_NODETYPE_TEXT = 13, 813 EXPRTOKEN_NODETYPE_PI = 14, 814 EXPRTOKEN_NODETYPE_NODE = 15, 815 EXPRTOKEN_OPERATOR_AND = 16, 823 EXPRTOKEN_OPERATOR_OR = 17, 824 EXPRTOKEN_OPERATOR_MOD = 18, 825 EXPRTOKEN_OPERATOR_DIV = 19, 826 EXPRTOKEN_OPERATOR_MULT = 20, 827 EXPRTOKEN_OPERATOR_SLASH = 21, 828 EXPRTOKEN_OPERATOR_DOUBLE_SLASH = 22, 829 EXPRTOKEN_OPERATOR_UNION = 23, 830 EXPRTOKEN_OPERATOR_PLUS = 24, 831 EXPRTOKEN_OPERATOR_MINUS = 25, 832 EXPRTOKEN_OPERATOR_EQUAL = 26, 833 EXPRTOKEN_OPERATOR_NOT_EQUAL = 27, 834 EXPRTOKEN_OPERATOR_LESS = 28, 835 EXPRTOKEN_OPERATOR_LESS_EQUAL = 29, 836 EXPRTOKEN_OPERATOR_GREATER = 30, 837 EXPRTOKEN_OPERATOR_GREATER_EQUAL = 31, 838 839 842 EXPRTOKEN_FUNCTION_NAME = 32, 848 EXPRTOKEN_AXISNAME_ANCESTOR = 33, 860 EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF = 34, 861 EXPRTOKEN_AXISNAME_ATTRIBUTE = 35, 862 EXPRTOKEN_AXISNAME_CHILD = 36, 863 EXPRTOKEN_AXISNAME_DESCENDANT = 37, 864 EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF = 38, 865 EXPRTOKEN_AXISNAME_FOLLOWING = 39, 866 EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING = 40, 867 EXPRTOKEN_AXISNAME_NAMESPACE = 41, 868 EXPRTOKEN_AXISNAME_PARENT = 42, 869 EXPRTOKEN_AXISNAME_PRECEDING = 43, 870 EXPRTOKEN_AXISNAME_PRECEDING_SIBLING = 44, 871 EXPRTOKEN_AXISNAME_SELF = 45, 872 EXPRTOKEN_LITERAL = 46, 878 EXPRTOKEN_NUMBER = 47, 885 EXPRTOKEN_VARIABLE_REFERENCE = 48; 891 892 public static final String [] fgTokenNames = { 893 "EXPRTOKEN_OPEN_PAREN", 894 "EXPRTOKEN_CLOSE_PAREN", 895 "EXPRTOKEN_OPEN_BRACKET", 896 "EXPRTOKEN_CLOSE_BRACKET", 897 "EXPRTOKEN_PERIOD", 898 "EXPRTOKEN_DOUBLE_PERIOD", 899 "EXPRTOKEN_ATSIGN", 900 "EXPRTOKEN_COMMA", 901 "EXPRTOKEN_DOUBLE_COLON", 902 "EXPRTOKEN_NAMETEST_ANY", 903 "EXPRTOKEN_NAMETEST_NAMESPACE", 904 "EXPRTOKEN_NAMETEST_QNAME", 905 "EXPRTOKEN_NODETYPE_COMMENT", 906 "EXPRTOKEN_NODETYPE_TEXT", 907 "EXPRTOKEN_NODETYPE_PI", 908 "EXPRTOKEN_NODETYPE_NODE", 909 "EXPRTOKEN_OPERATOR_AND", 910 "EXPRTOKEN_OPERATOR_OR", 911 "EXPRTOKEN_OPERATOR_MOD", 912 "EXPRTOKEN_OPERATOR_DIV", 913 "EXPRTOKEN_OPERATOR_MULT", 914 "EXPRTOKEN_OPERATOR_SLASH", 915 "EXPRTOKEN_OPERATOR_DOUBLE_SLASH", 916 "EXPRTOKEN_OPERATOR_UNION", 917 "EXPRTOKEN_OPERATOR_PLUS", 918 "EXPRTOKEN_OPERATOR_MINUS", 919 "EXPRTOKEN_OPERATOR_EQUAL", 920 "EXPRTOKEN_OPERATOR_NOT_EQUAL", 921 "EXPRTOKEN_OPERATOR_LESS", 922 "EXPRTOKEN_OPERATOR_LESS_EQUAL", 923 "EXPRTOKEN_OPERATOR_GREATER", 924 "EXPRTOKEN_OPERATOR_GREATER_EQUAL", 925 "EXPRTOKEN_FUNCTION_NAME", 926 "EXPRTOKEN_AXISNAME_ANCESTOR", 927 "EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF", 928 "EXPRTOKEN_AXISNAME_ATTRIBUTE", 929 "EXPRTOKEN_AXISNAME_CHILD", 930 "EXPRTOKEN_AXISNAME_DESCENDANT", 931 "EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF", 932 "EXPRTOKEN_AXISNAME_FOLLOWING", 933 "EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING", 934 "EXPRTOKEN_AXISNAME_NAMESPACE", 935 "EXPRTOKEN_AXISNAME_PARENT", 936 "EXPRTOKEN_AXISNAME_PRECEDING", 937 "EXPRTOKEN_AXISNAME_PRECEDING_SIBLING", 938 "EXPRTOKEN_AXISNAME_SELF", 939 "EXPRTOKEN_LITERAL", 940 "EXPRTOKEN_NUMBER", 941 "EXPRTOKEN_VARIABLE_REFERENCE" 942 }; 943 944 947 private static final int INITIAL_TOKEN_COUNT = 1 << 8; 948 private int[] fTokens = new int[INITIAL_TOKEN_COUNT]; 949 private int fTokenCount = 0; 951 private StringPool fStringPool; 952 953 956 959 963 968 public Tokens(StringPool stringPool) { 969 fStringPool = stringPool; 970 1032 } 1033 1034 1035 1039 1045 1046 public String getTokenName(int token) { 1047 if (token < 0 || token >= fgTokenNames.length) 1048 return null; 1049 return fgTokenNames[token]; 1050 } 1051 1052 public int getTokenString(int token) { 1053 return token; 1054 } 1055 1056 public void addToken(int token) { 1057 try { 1058 fTokens[fTokenCount] = token; 1059 } catch (ArrayIndexOutOfBoundsException ex) { 1060 int[] oldList = fTokens; 1061 fTokens = new int[fTokenCount << 1]; 1062 System.arraycopy(oldList, 0, fTokens, 0, fTokenCount); 1063 fTokens[fTokenCount] = token; 1064 } 1065 fTokenCount++; 1066 } 1067 public int getTokenCount() { 1068 return fTokenCount; 1069 } 1070 public int getToken(int tokenIndex) { 1071 return fTokens[tokenIndex]; 1072 } 1073 public void dumpTokens() { 1074 for (int i = 0; i < fTokenCount; i++) { 1076 switch (fTokens[i]) { 1077 case EXPRTOKEN_OPEN_PAREN: 1078 System.out.print("<OPEN_PAREN/>"); 1079 break; 1080 case EXPRTOKEN_CLOSE_PAREN: 1081 System.out.print("<CLOSE_PAREN/>"); 1082 break; 1083 case EXPRTOKEN_OPEN_BRACKET: 1084 System.out.print("<OPEN_BRACKET/>"); 1085 break; 1086 case EXPRTOKEN_CLOSE_BRACKET: 1087 System.out.print("<CLOSE_BRACKET/>"); 1088 break; 1089 case EXPRTOKEN_PERIOD: 1090 System.out.print("<PERIOD/>"); 1091 break; 1092 case EXPRTOKEN_DOUBLE_PERIOD: 1093 System.out.print("<DOUBLE_PERIOD/>"); 1094 break; 1095 case EXPRTOKEN_ATSIGN: 1096 System.out.print("<ATSIGN/>"); 1097 break; 1098 case EXPRTOKEN_COMMA: 1099 System.out.print("<COMMA/>"); 1100 break; 1101 case EXPRTOKEN_DOUBLE_COLON: 1102 System.out.print("<DOUBLE_COLON/>"); 1103 break; 1104 case EXPRTOKEN_NAMETEST_ANY: 1105 System.out.print("<NAMETEST_ANY/>"); 1106 break; 1107 case EXPRTOKEN_NAMETEST_NAMESPACE: 1108 System.out.print("<NAMETEST_NAMESPACE"); 1109 1112 System.out.print(" prefix=\"" + getTokenString(fTokens[++i]) + "\""); 1113 1114 System.out.print("/>"); 1115 break; 1116 case EXPRTOKEN_NAMETEST_QNAME: 1117 System.out.print("<NAMETEST_QNAME"); 1118 if (fTokens[++i] != -1) 1119 1122 System.out.print(" prefix=\"" + getTokenString(fTokens[i]) + "\""); 1123 1124 1127 System.out.print(" localpart=\"" + getTokenString(fTokens[++i]) + "\""); 1128 1129 System.out.print("/>"); 1130 break; 1131 case EXPRTOKEN_NODETYPE_COMMENT: 1132 System.out.print("<NODETYPE_COMMENT/>"); 1133 break; 1134 case EXPRTOKEN_NODETYPE_TEXT: 1135 System.out.print("<NODETYPE_TEXT/>"); 1136 break; 1137 case EXPRTOKEN_NODETYPE_PI: 1138 System.out.print("<NODETYPE_PI/>"); 1139 break; 1140 case EXPRTOKEN_NODETYPE_NODE: 1141 System.out.print("<NODETYPE_NODE/>"); 1142 break; 1143 case EXPRTOKEN_OPERATOR_AND: 1144 System.out.print("<OPERATOR_AND/>"); 1145 break; 1146 case EXPRTOKEN_OPERATOR_OR: 1147 System.out.print("<OPERATOR_OR/>"); 1148 break; 1149 case EXPRTOKEN_OPERATOR_MOD: 1150 System.out.print("<OPERATOR_MOD/>"); 1151 break; 1152 case EXPRTOKEN_OPERATOR_DIV: 1153 System.out.print("<OPERATOR_DIV/>"); 1154 break; 1155 case EXPRTOKEN_OPERATOR_MULT: 1156 System.out.print("<OPERATOR_MULT/>"); 1157 break; 1158 case EXPRTOKEN_OPERATOR_SLASH: 1159 System.out.print("<OPERATOR_SLASH/>"); 1160 if (i + 1 < fTokenCount) { 1161 System.out.println(); 1162 System.out.print(" "); 1163 } 1164 break; 1165 case EXPRTOKEN_OPERATOR_DOUBLE_SLASH: 1166 System.out.print("<OPERATOR_DOUBLE_SLASH/>"); 1167 break; 1168 case EXPRTOKEN_OPERATOR_UNION: 1169 System.out.print("<OPERATOR_UNION/>"); 1170 break; 1171 case EXPRTOKEN_OPERATOR_PLUS: 1172 System.out.print("<OPERATOR_PLUS/>"); 1173 break; 1174 case EXPRTOKEN_OPERATOR_MINUS: 1175 System.out.print("<OPERATOR_MINUS/>"); 1176 break; 1177 case EXPRTOKEN_OPERATOR_EQUAL: 1178 System.out.print("<OPERATOR_EQUAL/>"); 1179 break; 1180 case EXPRTOKEN_OPERATOR_NOT_EQUAL: 1181 System.out.print("<OPERATOR_NOT_EQUAL/>"); 1182 break; 1183 case EXPRTOKEN_OPERATOR_LESS: 1184 System.out.print("<OPERATOR_LESS/>"); 1185 break; 1186 case EXPRTOKEN_OPERATOR_LESS_EQUAL: 1187 System.out.print("<OPERATOR_LESS_EQUAL/>"); 1188 break; 1189 case EXPRTOKEN_OPERATOR_GREATER: 1190 System.out.print("<OPERATOR_GREATER/>"); 1191 break; 1192 case EXPRTOKEN_OPERATOR_GREATER_EQUAL: 1193 System.out.print("<OPERATOR_GREATER_EQUAL/>"); 1194 break; 1195 case EXPRTOKEN_FUNCTION_NAME: 1196 System.out.print("<FUNCTION_NAME"); 1197 if (fTokens[++i] != -1) 1198 1201 System.out.print(" prefix=\"" + getTokenString(fTokens[i]) + "\""); 1202 1203 1206 System.out.print(" localpart=\"" + getTokenString(fTokens[++i]) + "\""); 1207 1208 System.out.print("/>"); 1209 break; 1210 case EXPRTOKEN_AXISNAME_ANCESTOR: 1211 System.out.print("<AXISNAME_ANCESTOR/>"); 1212 break; 1213 case EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF: 1214 System.out.print("<AXISNAME_ANCESTOR_OR_SELF/>"); 1215 break; 1216 case EXPRTOKEN_AXISNAME_ATTRIBUTE: 1217 System.out.print("<AXISNAME_ATTRIBUTE/>"); 1218 break; 1219 case EXPRTOKEN_AXISNAME_CHILD: 1220 System.out.print("<AXISNAME_CHILD/>"); 1221 break; 1222 case EXPRTOKEN_AXISNAME_DESCENDANT: 1223 System.out.print("<AXISNAME_DESCENDANT/>"); 1224 break; 1225 case EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF: 1226 System.out.print("<AXISNAME_DESCENDANT_OR_SELF/>"); 1227 break; 1228 case EXPRTOKEN_AXISNAME_FOLLOWING: 1229 System.out.print("<AXISNAME_FOLLOWING/>"); 1230 break; 1231 case EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING: 1232 System.out.print("<AXISNAME_FOLLOWING_SIBLING/>"); 1233 break; 1234 case EXPRTOKEN_AXISNAME_NAMESPACE: 1235 System.out.print("<AXISNAME_NAMESPACE/>"); 1236 break; 1237 case EXPRTOKEN_AXISNAME_PARENT: 1238 System.out.print("<AXISNAME_PARENT/>"); 1239 break; 1240 case EXPRTOKEN_AXISNAME_PRECEDING: 1241 System.out.print("<AXISNAME_PRECEDING/>"); 1242 break; 1243 case EXPRTOKEN_AXISNAME_PRECEDING_SIBLING: 1244 System.out.print("<AXISNAME_PRECEDING_SIBLING/>"); 1245 break; 1246 case EXPRTOKEN_AXISNAME_SELF: 1247 System.out.print("<AXISNAME_SELF/>"); 1248 break; 1249 case EXPRTOKEN_LITERAL: 1250 System.out.print("<LITERAL"); 1251 1254 System.out.print(" value=\"" + getTokenString(fTokens[++i]) + "\""); 1255 1256 System.out.print("/>"); 1257 break; 1258 case EXPRTOKEN_NUMBER: 1259 System.out.print("<NUMBER"); 1260 System.out.print(" whole=\"" + getTokenString(fTokens[++i]) + "\""); 1261 System.out.print(" part=\"" + getTokenString(fTokens[++i]) + "\""); 1262 System.out.print("/>"); 1263 break; 1264 case EXPRTOKEN_VARIABLE_REFERENCE: 1265 System.out.print("<VARIABLE_REFERENCE"); 1266 if (fTokens[++i] != -1) 1267 1270 System.out.print(" prefix=\"" + getTokenString(fTokens[i]) + "\""); 1271 1272 1275 System.out.print(" localpart=\"" + getTokenString(fTokens[++i]) + "\""); 1276 1277 System.out.print("/>"); 1278 break; 1279 default: 1280 System.out.println("<???/>"); 1281 } 1282 } 1283 System.out.println(); 1284 } 1286 1287 } 1289 1295 private static class Scanner { 1296 1297 1310 private static final byte 1311 CHARTYPE_INVALID = 0, CHARTYPE_OTHER = 1, CHARTYPE_WHITESPACE = 2, CHARTYPE_EXCLAMATION = 3, CHARTYPE_QUOTE = 4, CHARTYPE_DOLLAR = 5, CHARTYPE_OPEN_PAREN = 6, CHARTYPE_CLOSE_PAREN = 7, CHARTYPE_STAR = 8, CHARTYPE_PLUS = 9, CHARTYPE_COMMA = 10, CHARTYPE_MINUS = 11, CHARTYPE_PERIOD = 12, CHARTYPE_SLASH = 13, CHARTYPE_DIGIT = 14, CHARTYPE_COLON = 15, CHARTYPE_LESS = 16, CHARTYPE_EQUAL = 17, CHARTYPE_GREATER = 18, CHARTYPE_ATSIGN = 19, CHARTYPE_LETTER = 20, CHARTYPE_OPEN_BRACKET = 21, CHARTYPE_CLOSE_BRACKET = 22, CHARTYPE_UNDERSCORE = 23, CHARTYPE_UNION = 24, CHARTYPE_NONASCII = 25; 1338 private static byte[] fASCIICharMap = { 1339 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 0, 0, 1340 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1341 2, 3, 4, 1, 5, 1, 1, 4, 6, 7, 8, 9, 10, 11, 12, 13, 1342 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 1, 16, 17, 18, 1, 1343 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 1344 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 1, 22, 1, 23, 1345 1, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 1346 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 1, 24, 1, 1, 1 1347 }; 1348 1349 1352 1403 1404 1408 1409 private StringPool fStringPool; 1410 1411 1413 private int fAndSymbol; 1414 private int fOrSymbol; 1415 private int fModSymbol; 1416 private int fDivSymbol; 1417 1418 private int fCommentSymbol; 1419 private int fTextSymbol; 1420 private int fPISymbol; 1421 private int fNodeSymbol; 1422 1423 private int fAncestorSymbol; 1424 private int fAncestorOrSelfSymbol; 1425 private int fAttributeSymbol; 1426 private int fChildSymbol; 1427 private int fDescendantSymbol; 1428 private int fDescendantOrSelfSymbol; 1429 private int fFollowingSymbol; 1430 private int fFollowingSiblingSymbol; 1431 private int fNamespaceSymbol; 1432 private int fParentSymbol; 1433 private int fPrecedingSymbol; 1434 private int fPrecedingSiblingSymbol; 1435 private int fSelfSymbol; 1436 1437 1441 1442 public Scanner(StringPool stringPool) { 1443 1444 fStringPool = stringPool; 1446 1447 fAndSymbol = fStringPool.addSymbol("and"); 1449 fOrSymbol = fStringPool.addSymbol("or"); 1450 fModSymbol = fStringPool.addSymbol("mod"); 1451 fDivSymbol = fStringPool.addSymbol("div"); 1452 fCommentSymbol = fStringPool.addSymbol("comment"); 1453 fTextSymbol = fStringPool.addSymbol("text"); 1454 fPISymbol = fStringPool.addSymbol("processing-instruction"); 1455 fNodeSymbol = fStringPool.addSymbol("node"); 1456 fAncestorSymbol = fStringPool.addSymbol("ancestor"); 1457 fAncestorOrSelfSymbol = fStringPool.addSymbol("ancestor-or-self"); 1458 fAttributeSymbol = fStringPool.addSymbol("attribute"); 1459 fChildSymbol = fStringPool.addSymbol("child"); 1460 fDescendantSymbol = fStringPool.addSymbol("descendant"); 1461 fDescendantOrSelfSymbol = fStringPool.addSymbol("descendant-or-self"); 1462 fFollowingSymbol = fStringPool.addSymbol("following"); 1463 fFollowingSiblingSymbol = fStringPool.addSymbol("following-sibling"); 1464 fNamespaceSymbol = fStringPool.addSymbol("namespace"); 1465 fParentSymbol = fStringPool.addSymbol("parent"); 1466 fPrecedingSymbol = fStringPool.addSymbol("preceding"); 1467 fPrecedingSiblingSymbol = fStringPool.addSymbol("preceding-sibling"); 1468 fSelfSymbol = fStringPool.addSymbol("self"); 1469 1470 } 1472 1475 public boolean scanExpr(StringPool stringPool, 1476 XPath.Tokens tokens, String data, 1477 int currentOffset, int endOffset) 1478 throws XPathException { 1479 1480 int nameOffset; 1481 int nameHandle, prefixHandle; 1482 boolean starIsMultiplyOperator = false; 1483 int ch; 1484 1485 1493 while (true) { 1494 if (currentOffset == endOffset) { 1495 break; 1496 } 1497 1500 ch = data.charAt(currentOffset); 1501 1502 while (ch == ' ' || ch == 0x0A || ch == 0x09 || ch == 0x0D) { 1506 if (++currentOffset == endOffset) { 1507 break; 1508 } 1509 1512 ch = data.charAt(currentOffset); 1513 1514 } 1515 if (currentOffset == endOffset) { 1516 break; 1517 } 1518 byte chartype = (ch >= 0x80) ? CHARTYPE_NONASCII : fASCIICharMap[ch]; 1524 switch (chartype) { 1525 case CHARTYPE_OPEN_PAREN: addToken(tokens, XPath.Tokens.EXPRTOKEN_OPEN_PAREN); 1527 starIsMultiplyOperator = false; 1528 if (++currentOffset == endOffset) { 1529 break; 1530 } 1531 break; 1532 case CHARTYPE_CLOSE_PAREN: addToken(tokens, XPath.Tokens.EXPRTOKEN_CLOSE_PAREN); 1534 starIsMultiplyOperator = true; 1535 if (++currentOffset == endOffset) { 1536 break; 1537 } 1538 break; 1539 case CHARTYPE_OPEN_BRACKET: addToken(tokens, XPath.Tokens.EXPRTOKEN_OPEN_BRACKET); 1541 starIsMultiplyOperator = false; 1542 if (++currentOffset == endOffset) { 1543 break; 1544 } 1545 break; 1546 case CHARTYPE_CLOSE_BRACKET: addToken(tokens, XPath.Tokens.EXPRTOKEN_CLOSE_BRACKET); 1548 starIsMultiplyOperator = true; 1549 if (++currentOffset == endOffset) { 1550 break; 1551 } 1552 break; 1553 case CHARTYPE_PERIOD: if (currentOffset + 1 == endOffset) { 1559 addToken(tokens, XPath.Tokens.EXPRTOKEN_PERIOD); 1560 starIsMultiplyOperator = true; 1561 currentOffset++; 1562 break; 1563 } 1564 1567 ch = data.charAt(currentOffset + 1); 1568 1569 if (ch == '.') { addToken(tokens, XPath.Tokens.EXPRTOKEN_DOUBLE_PERIOD); 1571 starIsMultiplyOperator = true; 1572 currentOffset += 2; 1573 } else if (ch >= '0' && ch <= '9') { 1574 addToken(tokens, XPath.Tokens.EXPRTOKEN_NUMBER); 1575 starIsMultiplyOperator = true; 1576 currentOffset = scanNumber(tokens, data, endOffset, currentOffset); 1577 } else if (ch == '/') { 1578 addToken(tokens, XPath.Tokens.EXPRTOKEN_PERIOD); 1579 starIsMultiplyOperator = true; 1580 currentOffset++; 1581 } else { throw new XPathException ("Invalid character following '.'"); 1583 } 1584 if (currentOffset == endOffset) { 1585 break; 1586 } 1587 break; 1588 case CHARTYPE_ATSIGN: addToken(tokens, XPath.Tokens.EXPRTOKEN_ATSIGN); 1590 starIsMultiplyOperator = false; 1591 if (++currentOffset == endOffset) { 1592 break; 1593 } 1594 break; 1595 case CHARTYPE_COMMA: addToken(tokens, XPath.Tokens.EXPRTOKEN_COMMA); 1597 starIsMultiplyOperator = false; 1598 if (++currentOffset == endOffset) { 1599 break; 1600 } 1601 break; 1602 case CHARTYPE_COLON: if (++currentOffset == endOffset) { 1604 return false; } 1607 1610 ch = data.charAt(currentOffset); 1611 1612 if (ch != ':') { 1613 return false; } 1616 addToken(tokens, XPath.Tokens.EXPRTOKEN_DOUBLE_COLON); 1617 starIsMultiplyOperator = false; 1618 if (++currentOffset == endOffset) { 1619 break; 1620 } 1621 break; 1622 case CHARTYPE_SLASH: if (++currentOffset == endOffset) { 1624 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH); 1625 starIsMultiplyOperator = false; 1626 break; 1627 } 1628 1631 ch = data.charAt(currentOffset); 1632 1633 if (ch == '/') { addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH); 1635 starIsMultiplyOperator = false; 1636 if (++currentOffset == endOffset) { 1637 break; 1638 } 1639 } else { 1640 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH); 1641 starIsMultiplyOperator = false; 1642 } 1643 break; 1644 case CHARTYPE_UNION: addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_UNION); 1646 starIsMultiplyOperator = false; 1647 if (++currentOffset == endOffset) { 1648 break; 1649 } 1650 break; 1651 case CHARTYPE_PLUS: addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_PLUS); 1653 starIsMultiplyOperator = false; 1654 if (++currentOffset == endOffset) { 1655 break; 1656 } 1657 break; 1658 case CHARTYPE_MINUS: addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_MINUS); 1660 starIsMultiplyOperator = false; 1661 if (++currentOffset == endOffset) { 1662 break; 1663 } 1664 break; 1665 case CHARTYPE_EQUAL: addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_EQUAL); 1667 starIsMultiplyOperator = false; 1668 if (++currentOffset == endOffset) { 1669 break; 1670 } 1671 break; 1672 case CHARTYPE_EXCLAMATION: if (++currentOffset == endOffset) { 1674 return false; } 1677 1680 ch = data.charAt(currentOffset); 1681 1682 if (ch != '=') { 1683 return false; } 1686 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_NOT_EQUAL); 1687 starIsMultiplyOperator = false; 1688 if (++currentOffset == endOffset) { 1689 break; 1690 } 1691 break; 1692 case CHARTYPE_LESS: if (++currentOffset == endOffset) { 1694 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_LESS); 1695 starIsMultiplyOperator = false; 1696 break; 1697 } 1698 1701 ch = data.charAt(currentOffset); 1702 1703 if (ch == '=') { addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_LESS_EQUAL); 1705 starIsMultiplyOperator = false; 1706 if (++currentOffset == endOffset) { 1707 break; 1708 } 1709 } else { 1710 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_LESS); 1711 starIsMultiplyOperator = false; 1712 } 1713 break; 1714 case CHARTYPE_GREATER: if (++currentOffset == endOffset) { 1716 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_GREATER); 1717 starIsMultiplyOperator = false; 1718 break; 1719 } 1720 1723 ch = data.charAt(currentOffset); 1724 1725 if (ch == '=') { addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_GREATER_EQUAL); 1727 starIsMultiplyOperator = false; 1728 if (++currentOffset == endOffset) { 1729 break; 1730 } 1731 } else { 1732 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_GREATER); 1733 starIsMultiplyOperator = false; 1734 } 1735 break; 1736 case CHARTYPE_QUOTE: int qchar = ch; 1741 if (++currentOffset == endOffset) { 1742 return false; } 1745 1748 ch = data.charAt(currentOffset); 1749 1750 int litOffset = currentOffset; 1751 while (ch != qchar) { 1752 if (++currentOffset == endOffset) { 1753 return false; } 1756 1759 ch = data.charAt(currentOffset); 1760 1761 } 1762 int litLength = currentOffset - litOffset; 1763 addToken(tokens, XPath.Tokens.EXPRTOKEN_LITERAL); 1764 starIsMultiplyOperator = true; 1765 1768 tokens.addToken(stringPool.addSymbol(data.substring(litOffset, litOffset + litLength))); 1769 1770 if (++currentOffset == endOffset) { 1771 break; 1772 } 1773 break; 1774 case CHARTYPE_DIGIT: 1779 addToken(tokens, XPath.Tokens.EXPRTOKEN_NUMBER); 1780 starIsMultiplyOperator = true; 1781 currentOffset = scanNumber(tokens, data, endOffset, currentOffset); 1782 break; 1783 case CHARTYPE_DOLLAR: 1787 if (++currentOffset == endOffset) { 1788 return false; } 1791 nameOffset = currentOffset; 1792 currentOffset = scanNCName(data, endOffset, currentOffset); 1793 if (currentOffset == nameOffset) { 1794 return false; } 1797 if (currentOffset < endOffset) { 1798 ch = data.charAt(currentOffset); 1799 } 1800 else { 1801 ch = -1; 1802 } 1803 1806 nameHandle = stringPool.addSymbol(data.substring(nameOffset, currentOffset)); 1807 1808 if (ch != ':') { 1809 prefixHandle = -1; 1810 } else { 1811 prefixHandle = nameHandle; 1812 if (++currentOffset == endOffset) { 1813 return false; } 1816 nameOffset = currentOffset; 1817 currentOffset = scanNCName(data, endOffset, currentOffset); 1818 if (currentOffset == nameOffset) { 1819 return false; } 1822 if (currentOffset < endOffset) { 1823 ch = data.charAt(currentOffset); 1824 } 1825 else { 1826 ch = -1; 1827 } 1828 1831 nameHandle = stringPool.addSymbol(data.substring(nameOffset, currentOffset)); 1832 1833 } 1834 addToken(tokens, XPath.Tokens.EXPRTOKEN_VARIABLE_REFERENCE); 1835 starIsMultiplyOperator = true; 1836 tokens.addToken(prefixHandle); 1837 tokens.addToken(nameHandle); 1838 break; 1839 case CHARTYPE_STAR: if (starIsMultiplyOperator) { 1853 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_MULT); 1854 starIsMultiplyOperator = false; 1855 } else { 1856 addToken(tokens, XPath.Tokens.EXPRTOKEN_NAMETEST_ANY); 1857 starIsMultiplyOperator = true; 1858 } 1859 if (++currentOffset == endOffset) { 1860 break; 1861 } 1862 break; 1863 case CHARTYPE_NONASCII: case CHARTYPE_LETTER: 1868 case CHARTYPE_UNDERSCORE: 1869 nameOffset = currentOffset; 1897 currentOffset = scanNCName(data, endOffset, currentOffset); 1898 if (currentOffset == nameOffset) { 1899 return false; } 1902 if (currentOffset < endOffset) { 1903 ch = data.charAt(currentOffset); 1904 } 1905 else { 1906 ch = -1; 1907 } 1908 1911 nameHandle = stringPool.addSymbol(data.substring(nameOffset, currentOffset)); 1912 1913 boolean isNameTestNCName = false; 1914 boolean isAxisName = false; 1915 prefixHandle = -1; 1916 if (ch == ':') { 1917 if (++currentOffset == endOffset) { 1918 return false; } 1921 1924 ch = data.charAt(currentOffset); 1925 1926 if (ch == '*') { 1927 if (++currentOffset < endOffset) { 1928 1931 ch = data.charAt(currentOffset); 1932 1933 } 1934 isNameTestNCName = true; 1935 } else if (ch == ':') { 1936 if (++currentOffset < endOffset) { 1937 1940 ch = data.charAt(currentOffset); 1941 1942 } 1943 isAxisName = true; 1944 } else { 1945 prefixHandle = nameHandle; 1946 nameOffset = currentOffset; 1947 currentOffset = scanNCName(data, endOffset, currentOffset); 1948 if (currentOffset == nameOffset) { 1949 return false; } 1952 if (currentOffset < endOffset) { 1953 ch = data.charAt(currentOffset); 1954 } 1955 else { 1956 ch = -1; 1957 } 1958 1961 nameHandle = stringPool.addSymbol(data.substring(nameOffset, currentOffset)); 1962 1963 } 1964 } 1965 while (ch == ' ' || ch == 0x0A || ch == 0x09 || ch == 0x0D) { 1969 if (++currentOffset == endOffset) { 1970 break; 1971 } 1972 1975 ch = data.charAt(currentOffset); 1976 1977 } 1978 if (starIsMultiplyOperator) { 1983 if (nameHandle == fAndSymbol) { 1984 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_AND); 1985 starIsMultiplyOperator = false; 1986 } else if (nameHandle == fOrSymbol) { 1987 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_OR); 1988 starIsMultiplyOperator = false; 1989 } else if (nameHandle == fModSymbol) { 1990 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_MOD); 1991 starIsMultiplyOperator = false; 1992 } else if (nameHandle == fDivSymbol) { 1993 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_DIV); 1994 starIsMultiplyOperator = false; 1995 } else { 1996 return false; } 1999 if (isNameTestNCName) { 2000 return false; } else if (isAxisName) { 2003 return false; } 2006 break; 2007 } 2008 if (ch == '(' && !isNameTestNCName && !isAxisName) { 2013 if (nameHandle == fCommentSymbol) { 2014 addToken(tokens, XPath.Tokens.EXPRTOKEN_NODETYPE_COMMENT); 2015 } else if (nameHandle == fTextSymbol) { 2016 addToken(tokens, XPath.Tokens.EXPRTOKEN_NODETYPE_TEXT); 2017 } else if (nameHandle == fPISymbol) { 2018 addToken(tokens, XPath.Tokens.EXPRTOKEN_NODETYPE_PI); 2019 } else if (nameHandle == fNodeSymbol) { 2020 addToken(tokens, XPath.Tokens.EXPRTOKEN_NODETYPE_NODE); 2021 } else { 2022 addToken(tokens, XPath.Tokens.EXPRTOKEN_FUNCTION_NAME); 2023 tokens.addToken(prefixHandle); 2024 tokens.addToken(nameHandle); 2025 } 2026 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPEN_PAREN); 2027 starIsMultiplyOperator = false; 2028 if (++currentOffset == endOffset) { 2029 break; 2030 } 2031 break; 2032 } 2033 if (isAxisName || 2038 (ch == ':' && currentOffset + 1 < endOffset && 2039 2042 data.charAt(currentOffset + 1) == ':')) { 2043 2044 if (nameHandle == fAncestorSymbol) { 2045 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_ANCESTOR); 2046 } else if (nameHandle == fAncestorOrSelfSymbol) { 2047 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF); 2048 } else if (nameHandle == fAttributeSymbol) { 2049 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_ATTRIBUTE); 2050 } else if (nameHandle == fChildSymbol) { 2051 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_CHILD); 2052 } else if (nameHandle == fDescendantSymbol) { 2053 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_DESCENDANT); 2054 } else if (nameHandle == fDescendantOrSelfSymbol) { 2055 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF); 2056 } else if (nameHandle == fFollowingSymbol) { 2057 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_FOLLOWING); 2058 } else if (nameHandle == fFollowingSiblingSymbol) { 2059 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING); 2060 } else if (nameHandle == fNamespaceSymbol) { 2061 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_NAMESPACE); 2062 } else if (nameHandle == fParentSymbol) { 2063 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_PARENT); 2064 } else if (nameHandle == fPrecedingSymbol) { 2065 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_PRECEDING); 2066 } else if (nameHandle == fPrecedingSiblingSymbol) { 2067 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_PRECEDING_SIBLING); 2068 } else if (nameHandle == fSelfSymbol) { 2069 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_SELF); 2070 } else { 2071 return false; } 2074 if (isNameTestNCName) { 2075 return false; } 2078 addToken(tokens, XPath.Tokens.EXPRTOKEN_DOUBLE_COLON); 2079 starIsMultiplyOperator = false; 2080 if (!isAxisName) { 2081 currentOffset++; 2082 if (++currentOffset == endOffset) { 2083 break; 2084 } 2085 } 2086 break; 2087 } 2088 if (isNameTestNCName) { 2093 addToken(tokens, XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE); 2094 starIsMultiplyOperator = true; 2095 tokens.addToken(nameHandle); 2096 } else { 2097 addToken(tokens, XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME); 2098 starIsMultiplyOperator = true; 2099 tokens.addToken(prefixHandle); 2100 tokens.addToken(nameHandle); 2101 } 2102 break; 2103 } 2104 } 2105 if (XPath.Tokens.DUMP_TOKENS) { 2106 tokens.dumpTokens(); 2107 } 2108 return true; 2109 } 2110 int scanNCName(String data, int endOffset, int currentOffset) { 2115 int ch = data.charAt(currentOffset); 2116 if (ch >= 0x80) { 2117 if ((XMLCharacterProperties.fgCharFlags[ch] & 2118 XMLCharacterProperties.E_InitialNameCharFlag) == 0) 2119 { 2120 return currentOffset; 2121 } 2122 } 2123 else { 2124 byte chartype = fASCIICharMap[ch]; 2125 if (chartype != CHARTYPE_LETTER && chartype != CHARTYPE_UNDERSCORE) { 2126 return currentOffset; 2127 } 2128 } 2129 while (++currentOffset < endOffset) { 2130 ch = data.charAt(currentOffset); 2131 if (ch >= 0x80) { 2132 if ((XMLCharacterProperties.fgCharFlags[ch] & 2133 XMLCharacterProperties.E_NameCharFlag) == 0) 2134 { 2135 break; 2136 } 2137 } 2138 else { 2139 byte chartype = fASCIICharMap[ch]; 2140 if (chartype != CHARTYPE_LETTER && chartype != CHARTYPE_DIGIT && 2141 chartype != CHARTYPE_PERIOD && chartype != CHARTYPE_MINUS && 2142 chartype != CHARTYPE_UNDERSCORE) 2143 { 2144 break; 2145 } 2146 } 2147 } 2148 return currentOffset; 2149 } 2150 2203 private int scanNumber(XPath.Tokens tokens, String data, int endOffset, int currentOffset) { 2208 2211 int ch = data.charAt(currentOffset); 2212 2213 int whole = 0; 2214 int part = 0; 2215 while (ch >= '0' && ch <= '9') { 2216 whole = (whole * 10) + (ch - '0'); 2217 if (++currentOffset == endOffset) { 2218 break; 2219 } 2220 2223 ch = data.charAt(currentOffset); 2224 2225 } 2226 if (ch == '.') { 2227 if (++currentOffset < endOffset) { 2228 int start = currentOffset; 2229 2232 ch = data.charAt(currentOffset); 2233 2234 while (ch >= '0' && ch <= '9') { 2235 part = (part * 10) + (ch - '0'); 2236 if (++currentOffset == endOffset) { 2237 break; 2238 } 2239 2242 ch = data.charAt(currentOffset); 2243 2244 } 2245 if (part != 0) { 2246 2249 throw new RuntimeException ("find a solution!"); 2250 2252 } 2253 } 2254 } 2255 tokens.addToken(whole); 2256 tokens.addToken(part); 2257 return currentOffset; 2258 } 2259 2260 2327 2328 2332 2340 protected void addToken(XPath.Tokens tokens, int token) 2341 throws XPathException { 2342 tokens.addToken(token); 2343 } 2345 } 2347 2353 3796 3797 3801 3802 public static void main(String [] argv) throws Exception { 3803 3804 for (int i = 0; i < argv.length; i++) { 3805 final String expression = argv[i]; 3806 System.out.println("# XPath expression: \""+expression+'"'); 3807 try { 3808 StringPool stringPool = new StringPool(); 3809 XPath xpath = new XPath(expression, stringPool, 3810 null); 3811 System.out.println("expanded xpath: \""+xpath.toString()+'"'); 3812 } 3813 catch (XPathException e) { 3814 System.out.println("error: "+e.getMessage()); 3815 } 3816 } 3817 3818 } 3820 3821 protected LocationPath[] fLocationPaths; 3825 3828 public LocationPath[] getLocationPaths() { 3829 LocationPath[] ret=new LocationPath[fLocationPaths.length]; 3830 for (int i=0;i<fLocationPaths.length;i++){ 3831 ret[i]=(LocationPath)fLocationPaths[i].clone(); 3832 } 3833 return ret; 3834 } } | Popular Tags |