1 16 17 package org.apache.xerces.impl.xpath; 18 19 import java.util.Vector ; 20 21 import org.apache.xerces.util.SymbolTable; 22 import org.apache.xerces.util.XMLSymbols; 23 import org.apache.xerces.util.XMLChar; 24 import org.apache.xerces.xni.NamespaceContext; 25 import org.apache.xerces.xni.QName; 26 27 35 public class XPath { 36 37 41 private static final boolean DEBUG_ALL = false; 42 43 private static final boolean DEBUG_XPATH_PARSE = DEBUG_ALL || false; 44 45 private static final boolean DEBUG_ANY = DEBUG_XPATH_PARSE; 46 47 51 52 protected String fExpression; 53 54 55 protected SymbolTable fSymbolTable; 56 57 58 protected LocationPath[] fLocationPaths; 59 60 64 65 public XPath(String xpath, SymbolTable symbolTable, 66 NamespaceContext context) 67 throws XPathException { 68 fExpression = xpath; 69 fSymbolTable = symbolTable; 70 parseExpression(context); 71 } 73 77 81 public LocationPath[] getLocationPaths() { 82 LocationPath[] ret=new LocationPath[fLocationPaths.length]; 83 for (int i=0;i<fLocationPaths.length;i++){ 84 ret[i]=(LocationPath)fLocationPaths[i].clone(); 85 } 86 return ret; 87 } 89 90 public LocationPath getLocationPath() { 91 return (LocationPath)fLocationPaths[0].clone(); 92 } 94 98 99 public String toString() { 100 StringBuffer buf=new StringBuffer (); 101 for (int i=0;i<fLocationPaths.length;i++){ 102 if (i>0){ 103 buf.append("|"); 104 } 105 buf.append(fLocationPaths[i].toString()); 106 } 107 return buf.toString(); 108 } 110 114 121 private static void check( boolean b ) throws XPathException { 122 if(!b) throw new XPathException("c-general-xpath"); 123 } 124 125 130 private LocationPath buildLocationPath( Vector stepsVector ) throws XPathException { 131 int size = stepsVector.size(); 132 check(size!=0); 133 Step[] steps = new Step[size]; 134 stepsVector.copyInto(steps); 135 stepsVector.removeAllElements(); 136 137 return new LocationPath(steps); 138 } 139 140 144 private void parseExpression(final NamespaceContext context) 145 throws XPathException { 146 147 final XPath.Tokens xtokens = new XPath.Tokens(fSymbolTable); 149 150 XPath.Scanner scanner = new XPath.Scanner(fSymbolTable) { 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_NAMETEST_QNAME || 157 token == XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH || 158 token == XPath.Tokens.EXPRTOKEN_PERIOD || 159 token == XPath.Tokens.EXPRTOKEN_NAMETEST_ANY || 160 token == XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE || 161 token == XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH || 162 token == XPath.Tokens.EXPRTOKEN_OPERATOR_UNION 163 ) { 165 super.addToken(tokens, token); 166 return; 167 } 168 throw new XPathException("c-general-xpath"); 169 } 170 }; 171 172 int length = fExpression.length(); 173 174 boolean success = scanner.scanExpr(fSymbolTable, 175 xtokens, fExpression, 0, length); 176 if(!success) 177 throw new XPathException("c-general-xpath"); 178 179 Vector stepsVector = new Vector (); 181 Vector locationPathsVector= new Vector (); 182 183 boolean expectingStep = true; 190 191 while(xtokens.hasMore()) { 192 final int token = xtokens.nextToken(); 193 194 switch (token) { 195 case XPath.Tokens.EXPRTOKEN_OPERATOR_UNION :{ 196 check(!expectingStep); 197 locationPathsVector.addElement(buildLocationPath(stepsVector)); 198 expectingStep=true; 199 break; 200 } 201 202 case XPath.Tokens.EXPRTOKEN_ATSIGN: { 203 check(expectingStep); 204 Step step = new Step( 205 new Axis(Axis.ATTRIBUTE), 206 parseNodeTest(xtokens.nextToken(),xtokens,context)); 207 stepsVector.addElement(step); 208 expectingStep=false; 209 break; 210 } 211 case XPath.Tokens.EXPRTOKEN_NAMETEST_ANY: 212 case XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE: 213 case XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME: { 214 check(expectingStep); 215 Step step = new Step( 216 new Axis(Axis.CHILD), 217 parseNodeTest(token,xtokens,context)); 218 stepsVector.addElement(step); 219 expectingStep=false; 220 break; 221 } 222 223 case XPath.Tokens.EXPRTOKEN_PERIOD: { 224 check(expectingStep); 225 expectingStep=false; 226 227 if (stepsVector.size()==0) { 233 Axis axis = new Axis(Axis.SELF); 235 NodeTest nodeTest = new NodeTest(NodeTest.NODE); 236 Step step = new Step(axis, nodeTest); 237 stepsVector.addElement(step); 238 239 if( xtokens.hasMore() 240 && xtokens.peekToken() == XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH){ 241 xtokens.nextToken(); 243 244 axis = new Axis(Axis.DESCENDANT); 246 nodeTest = new NodeTest(NodeTest.NODE); 247 step = new Step(axis, nodeTest); 248 stepsVector.addElement(step); 249 expectingStep=true; 250 } 251 } 252 break; 253 } 254 255 case XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH:{ 256 throw new XPathException("c-general-xpath"); 260 } 261 case XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH: { 262 check(!expectingStep); 263 expectingStep=true; 264 break; 265 } 266 default: 267 throw new InternalError (); 269 } 270 } 271 272 check(!expectingStep); 273 274 locationPathsVector.addElement(buildLocationPath(stepsVector)); 275 276 fLocationPaths=new LocationPath[locationPathsVector.size()]; 278 locationPathsVector.copyInto(fLocationPaths); 279 280 281 if (DEBUG_XPATH_PARSE) { 282 System.out.println(">>> "+fLocationPaths); 283 } 284 285 } 287 291 private NodeTest parseNodeTest( int typeToken, Tokens xtokens, NamespaceContext context ) 292 throws XPathException { 293 switch(typeToken) { 294 case XPath.Tokens.EXPRTOKEN_NAMETEST_ANY: 295 return new NodeTest(NodeTest.WILDCARD); 296 297 case XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE: 298 case XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME: 299 String prefix = xtokens.nextTokenAsString(); 301 String uri = null; 302 if (context != null && prefix != XMLSymbols.EMPTY_STRING) { 303 uri = context.getURI(prefix); 304 } 305 if (prefix != XMLSymbols.EMPTY_STRING && context != null && uri == null) { 306 throw new XPathException("c-general-xpath-ns"); 307 } 308 309 if (typeToken==XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE) 310 return new NodeTest(prefix,uri); 311 312 String localpart = xtokens.nextTokenAsString(); 313 String rawname = prefix != XMLSymbols.EMPTY_STRING 314 ? fSymbolTable.addSymbol(prefix+':'+localpart) 315 : localpart; 316 317 return new NodeTest(new QName(prefix, localpart, rawname, uri)); 318 319 default: 320 throw new InternalError (); 322 } 323 } 324 325 326 330 332 339 public static class LocationPath 340 implements Cloneable { 341 342 346 347 public Step[] steps; 348 349 353 354 public LocationPath(Step[] steps) { 355 this.steps = steps; 356 } 358 359 protected LocationPath(LocationPath path) { 360 steps = new Step[path.steps.length]; 361 for (int i = 0; i < steps.length; i++) { 362 steps[i] = (Step)path.steps[i].clone(); 363 } 364 } 366 370 371 public String toString() { 372 StringBuffer str = new StringBuffer (); 373 for (int i = 0; i < steps.length; i++) { 374 if (i > 0 && (steps[i-1].axis.type!=Axis.DESCENDANT 375 && steps[i].axis.type!=Axis.DESCENDANT) ){ 376 str.append('/'); 377 } 378 str.append(steps[i].toString()); 379 } 380 if (false) { 384 str.append('['); 385 String s = super.toString(); 386 str.append(s.substring(s.indexOf('@'))); 387 str.append(']'); 388 } 389 return str.toString(); 390 } 392 393 public Object clone() { 394 return new LocationPath(this); 395 } 397 } 399 406 public static class Step 407 implements Cloneable { 408 409 413 414 public Axis axis; 415 416 417 public NodeTest nodeTest; 418 419 423 424 public Step(Axis axis, NodeTest nodeTest) { 425 this.axis = axis; 426 this.nodeTest = nodeTest; 427 } 429 430 protected Step(Step step) { 431 axis = (Axis)step.axis.clone(); 432 nodeTest = (NodeTest)step.nodeTest.clone(); 433 } 435 439 440 public String toString() { 441 if (axis.type == Axis.SELF) { 442 return "."; 443 } 444 if (axis.type == Axis.ATTRIBUTE) { 445 return "@" + nodeTest.toString(); 446 } 447 if (axis.type == Axis.CHILD) { 448 return nodeTest.toString(); 449 } 450 if (axis.type == Axis.DESCENDANT) { 451 return "//"; 452 } 453 return "??? ("+axis.type+')'; 454 } 456 457 public Object clone() { 458 return new Step(this); 459 } 461 } 463 470 public static class Axis 471 implements Cloneable { 472 473 477 478 public static final short CHILD = 1; 479 480 481 public static final short ATTRIBUTE = 2; 482 483 484 public static final short SELF = 3; 485 486 487 488 public static final short DESCENDANT = 4; 489 493 494 public short type; 495 496 500 501 public Axis(short type) { 502 this.type = type; 503 } 505 506 protected Axis(Axis axis) { 507 type = axis.type; 508 } 510 514 515 public String toString() { 516 switch (type) { 517 case CHILD: return "child"; 518 case ATTRIBUTE: return "attribute"; 519 case SELF: return "self"; 520 case DESCENDANT: return "descendant"; 521 } 522 return "???"; 523 } 525 526 public Object clone() { 527 return new Axis(this); 528 } 530 } 532 539 public static class NodeTest 540 implements Cloneable { 541 542 546 547 public static final short QNAME = 1; 548 549 550 public static final short WILDCARD = 2; 551 552 553 public static final short NODE = 3; 554 555 556 public static final short NAMESPACE= 4; 557 558 562 563 public short type; 564 565 566 public final QName name = new QName(); 567 568 572 573 public NodeTest(short type) { 574 this.type = type; 575 } 577 578 public NodeTest(QName name) { 579 this.type = QNAME; 580 this.name.setValues(name); 581 } 583 public NodeTest(String prefix, String uri) { 584 this.type = NAMESPACE; 585 this.name.setValues(prefix, null, null, uri); 586 } 588 589 public NodeTest(NodeTest nodeTest) { 590 type = nodeTest.type; 591 name.setValues(nodeTest.name); 592 } 594 598 599 public String toString() { 600 601 switch (type) { 602 case QNAME: { 603 if (name.prefix.length() !=0) { 604 if (name.uri != null) { 605 return name.prefix+':'+name.localpart; 606 } 607 return "{"+name.uri+'}'+name.prefix+':'+name.localpart; 608 } 609 return name.localpart; 610 } 611 case NAMESPACE: { 612 if (name.prefix.length() !=0) { 613 if (name.uri != null) { 614 return name.prefix+":*"; 615 } 616 return "{"+name.uri+'}'+name.prefix+":*"; 617 } 618 return "???:*"; 619 } 620 case WILDCARD: { 621 return "*"; 622 } 623 case NODE: { 624 return "node()"; 625 } 626 } 627 return "???"; 628 629 } 631 632 public Object clone() { 633 return new NodeTest(this); 634 } 636 } 638 640 646 656 private static final class Tokens { 657 658 static final boolean DUMP_TOKENS = false; 659 660 665 public static final int 666 EXPRTOKEN_OPEN_PAREN = 0, 667 EXPRTOKEN_CLOSE_PAREN = 1, 668 EXPRTOKEN_OPEN_BRACKET = 2, 669 EXPRTOKEN_CLOSE_BRACKET = 3, 670 EXPRTOKEN_PERIOD = 4, 671 EXPRTOKEN_DOUBLE_PERIOD = 5, 672 EXPRTOKEN_ATSIGN = 6, 673 EXPRTOKEN_COMMA = 7, 674 EXPRTOKEN_DOUBLE_COLON = 8, 675 EXPRTOKEN_NAMETEST_ANY = 9, 681 EXPRTOKEN_NAMETEST_NAMESPACE = 10, 682 EXPRTOKEN_NAMETEST_QNAME = 11, 683 EXPRTOKEN_NODETYPE_COMMENT = 12, 687 EXPRTOKEN_NODETYPE_TEXT = 13, 688 EXPRTOKEN_NODETYPE_PI = 14, 689 EXPRTOKEN_NODETYPE_NODE = 15, 690 EXPRTOKEN_OPERATOR_AND = 16, 698 EXPRTOKEN_OPERATOR_OR = 17, 699 EXPRTOKEN_OPERATOR_MOD = 18, 700 EXPRTOKEN_OPERATOR_DIV = 19, 701 EXPRTOKEN_OPERATOR_MULT = 20, 702 EXPRTOKEN_OPERATOR_SLASH = 21, 703 EXPRTOKEN_OPERATOR_DOUBLE_SLASH = 22, 704 EXPRTOKEN_OPERATOR_UNION = 23, 705 EXPRTOKEN_OPERATOR_PLUS = 24, 706 EXPRTOKEN_OPERATOR_MINUS = 25, 707 EXPRTOKEN_OPERATOR_EQUAL = 26, 708 EXPRTOKEN_OPERATOR_NOT_EQUAL = 27, 709 EXPRTOKEN_OPERATOR_LESS = 28, 710 EXPRTOKEN_OPERATOR_LESS_EQUAL = 29, 711 EXPRTOKEN_OPERATOR_GREATER = 30, 712 EXPRTOKEN_OPERATOR_GREATER_EQUAL = 31, 713 714 717 EXPRTOKEN_FUNCTION_NAME = 32, 723 EXPRTOKEN_AXISNAME_ANCESTOR = 33, 735 EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF = 34, 736 EXPRTOKEN_AXISNAME_ATTRIBUTE = 35, 737 EXPRTOKEN_AXISNAME_CHILD = 36, 738 EXPRTOKEN_AXISNAME_DESCENDANT = 37, 739 EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF = 38, 740 EXPRTOKEN_AXISNAME_FOLLOWING = 39, 741 EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING = 40, 742 EXPRTOKEN_AXISNAME_NAMESPACE = 41, 743 EXPRTOKEN_AXISNAME_PARENT = 42, 744 EXPRTOKEN_AXISNAME_PRECEDING = 43, 745 EXPRTOKEN_AXISNAME_PRECEDING_SIBLING = 44, 746 EXPRTOKEN_AXISNAME_SELF = 45, 747 EXPRTOKEN_LITERAL = 46, 753 EXPRTOKEN_NUMBER = 47, 760 EXPRTOKEN_VARIABLE_REFERENCE = 48; 766 767 private static final String [] fgTokenNames = { 768 "EXPRTOKEN_OPEN_PAREN", 769 "EXPRTOKEN_CLOSE_PAREN", 770 "EXPRTOKEN_OPEN_BRACKET", 771 "EXPRTOKEN_CLOSE_BRACKET", 772 "EXPRTOKEN_PERIOD", 773 "EXPRTOKEN_DOUBLE_PERIOD", 774 "EXPRTOKEN_ATSIGN", 775 "EXPRTOKEN_COMMA", 776 "EXPRTOKEN_DOUBLE_COLON", 777 "EXPRTOKEN_NAMETEST_ANY", 778 "EXPRTOKEN_NAMETEST_NAMESPACE", 779 "EXPRTOKEN_NAMETEST_QNAME", 780 "EXPRTOKEN_NODETYPE_COMMENT", 781 "EXPRTOKEN_NODETYPE_TEXT", 782 "EXPRTOKEN_NODETYPE_PI", 783 "EXPRTOKEN_NODETYPE_NODE", 784 "EXPRTOKEN_OPERATOR_AND", 785 "EXPRTOKEN_OPERATOR_OR", 786 "EXPRTOKEN_OPERATOR_MOD", 787 "EXPRTOKEN_OPERATOR_DIV", 788 "EXPRTOKEN_OPERATOR_MULT", 789 "EXPRTOKEN_OPERATOR_SLASH", 790 "EXPRTOKEN_OPERATOR_DOUBLE_SLASH", 791 "EXPRTOKEN_OPERATOR_UNION", 792 "EXPRTOKEN_OPERATOR_PLUS", 793 "EXPRTOKEN_OPERATOR_MINUS", 794 "EXPRTOKEN_OPERATOR_EQUAL", 795 "EXPRTOKEN_OPERATOR_NOT_EQUAL", 796 "EXPRTOKEN_OPERATOR_LESS", 797 "EXPRTOKEN_OPERATOR_LESS_EQUAL", 798 "EXPRTOKEN_OPERATOR_GREATER", 799 "EXPRTOKEN_OPERATOR_GREATER_EQUAL", 800 "EXPRTOKEN_FUNCTION_NAME", 801 "EXPRTOKEN_AXISNAME_ANCESTOR", 802 "EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF", 803 "EXPRTOKEN_AXISNAME_ATTRIBUTE", 804 "EXPRTOKEN_AXISNAME_CHILD", 805 "EXPRTOKEN_AXISNAME_DESCENDANT", 806 "EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF", 807 "EXPRTOKEN_AXISNAME_FOLLOWING", 808 "EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING", 809 "EXPRTOKEN_AXISNAME_NAMESPACE", 810 "EXPRTOKEN_AXISNAME_PARENT", 811 "EXPRTOKEN_AXISNAME_PRECEDING", 812 "EXPRTOKEN_AXISNAME_PRECEDING_SIBLING", 813 "EXPRTOKEN_AXISNAME_SELF", 814 "EXPRTOKEN_LITERAL", 815 "EXPRTOKEN_NUMBER", 816 "EXPRTOKEN_VARIABLE_REFERENCE" 817 }; 818 819 822 private static final int INITIAL_TOKEN_COUNT = 1 << 8; 823 private int[] fTokens = new int[INITIAL_TOKEN_COUNT]; 824 private int fTokenCount = 0; 826 private SymbolTable fSymbolTable; 827 828 private java.util.Hashtable fSymbolMapping = new java.util.Hashtable (); 830 831 private java.util.Hashtable fTokenNames = new java.util.Hashtable (); 833 834 837 private int fCurrentTokenIndex; 838 839 843 public Tokens(SymbolTable symbolTable) { 844 fSymbolTable = symbolTable; 845 final String [] symbols = { 846 "ancestor", "ancestor-or-self", "attribute", 847 "child", "descendant", "descendant-or-self", 848 "following", "following-sibling", "namespace", 849 "parent", "preceding", "preceding-sibling", 850 "self", 851 }; 852 for (int i = 0; i < symbols.length; i++) { 853 fSymbolMapping.put(fSymbolTable.addSymbol(symbols[i]), new Integer (i)); 854 } 855 fTokenNames.put(new Integer (EXPRTOKEN_OPEN_PAREN), "EXPRTOKEN_OPEN_PAREN"); 856 fTokenNames.put(new Integer (EXPRTOKEN_CLOSE_PAREN), "EXPRTOKEN_CLOSE_PAREN"); 857 fTokenNames.put(new Integer (EXPRTOKEN_OPEN_BRACKET), "EXPRTOKEN_OPEN_BRACKET"); 858 fTokenNames.put(new Integer (EXPRTOKEN_CLOSE_BRACKET), "EXPRTOKEN_CLOSE_BRACKET"); 859 fTokenNames.put(new Integer (EXPRTOKEN_PERIOD), "EXPRTOKEN_PERIOD"); 860 fTokenNames.put(new Integer (EXPRTOKEN_DOUBLE_PERIOD), "EXPRTOKEN_DOUBLE_PERIOD"); 861 fTokenNames.put(new Integer (EXPRTOKEN_ATSIGN), "EXPRTOKEN_ATSIGN"); 862 fTokenNames.put(new Integer (EXPRTOKEN_COMMA), "EXPRTOKEN_COMMA"); 863 fTokenNames.put(new Integer (EXPRTOKEN_DOUBLE_COLON), "EXPRTOKEN_DOUBLE_COLON"); 864 fTokenNames.put(new Integer (EXPRTOKEN_NAMETEST_ANY), "EXPRTOKEN_NAMETEST_ANY"); 865 fTokenNames.put(new Integer (EXPRTOKEN_NAMETEST_NAMESPACE), "EXPRTOKEN_NAMETEST_NAMESPACE"); 866 fTokenNames.put(new Integer (EXPRTOKEN_NAMETEST_QNAME), "EXPRTOKEN_NAMETEST_QNAME"); 867 fTokenNames.put(new Integer (EXPRTOKEN_NODETYPE_COMMENT), "EXPRTOKEN_NODETYPE_COMMENT"); 868 fTokenNames.put(new Integer (EXPRTOKEN_NODETYPE_TEXT), "EXPRTOKEN_NODETYPE_TEXT"); 869 fTokenNames.put(new Integer (EXPRTOKEN_NODETYPE_PI), "EXPRTOKEN_NODETYPE_PI"); 870 fTokenNames.put(new Integer (EXPRTOKEN_NODETYPE_NODE), "EXPRTOKEN_NODETYPE_NODE"); 871 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_AND), "EXPRTOKEN_OPERATOR_AND"); 872 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_OR), "EXPRTOKEN_OPERATOR_OR"); 873 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_MOD), "EXPRTOKEN_OPERATOR_MOD"); 874 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_DIV), "EXPRTOKEN_OPERATOR_DIV"); 875 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_MULT), "EXPRTOKEN_OPERATOR_MULT"); 876 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_SLASH), "EXPRTOKEN_OPERATOR_SLASH"); 877 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_DOUBLE_SLASH), "EXPRTOKEN_OPERATOR_DOUBLE_SLASH"); 878 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_UNION), "EXPRTOKEN_OPERATOR_UNION"); 879 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_PLUS), "EXPRTOKEN_OPERATOR_PLUS"); 880 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_MINUS), "EXPRTOKEN_OPERATOR_MINUS"); 881 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_EQUAL), "EXPRTOKEN_OPERATOR_EQUAL"); 882 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_NOT_EQUAL), "EXPRTOKEN_OPERATOR_NOT_EQUAL"); 883 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_LESS), "EXPRTOKEN_OPERATOR_LESS"); 884 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_LESS_EQUAL), "EXPRTOKEN_OPERATOR_LESS_EQUAL"); 885 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_GREATER), "EXPRTOKEN_OPERATOR_GREATER"); 886 fTokenNames.put(new Integer (EXPRTOKEN_OPERATOR_GREATER_EQUAL), "EXPRTOKEN_OPERATOR_GREATER_EQUAL"); 887 fTokenNames.put(new Integer (EXPRTOKEN_FUNCTION_NAME), "EXPRTOKEN_FUNCTION_NAME"); 888 fTokenNames.put(new Integer (EXPRTOKEN_AXISNAME_ANCESTOR), "EXPRTOKEN_AXISNAME_ANCESTOR"); 889 fTokenNames.put(new Integer (EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF), "EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF"); 890 fTokenNames.put(new Integer (EXPRTOKEN_AXISNAME_ATTRIBUTE), "EXPRTOKEN_AXISNAME_ATTRIBUTE"); 891 fTokenNames.put(new Integer (EXPRTOKEN_AXISNAME_CHILD), "EXPRTOKEN_AXISNAME_CHILD"); 892 fTokenNames.put(new Integer (EXPRTOKEN_AXISNAME_DESCENDANT), "EXPRTOKEN_AXISNAME_DESCENDANT"); 893 fTokenNames.put(new Integer (EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF), "EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF"); 894 fTokenNames.put(new Integer (EXPRTOKEN_AXISNAME_FOLLOWING), "EXPRTOKEN_AXISNAME_FOLLOWING"); 895 fTokenNames.put(new Integer (EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING), "EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING"); 896 fTokenNames.put(new Integer (EXPRTOKEN_AXISNAME_NAMESPACE), "EXPRTOKEN_AXISNAME_NAMESPACE"); 897 fTokenNames.put(new Integer (EXPRTOKEN_AXISNAME_PARENT), "EXPRTOKEN_AXISNAME_PARENT"); 898 fTokenNames.put(new Integer (EXPRTOKEN_AXISNAME_PRECEDING), "EXPRTOKEN_AXISNAME_PRECEDING"); 899 fTokenNames.put(new Integer (EXPRTOKEN_AXISNAME_PRECEDING_SIBLING), "EXPRTOKEN_AXISNAME_PRECEDING_SIBLING"); 900 fTokenNames.put(new Integer (EXPRTOKEN_AXISNAME_SELF), "EXPRTOKEN_AXISNAME_SELF"); 901 fTokenNames.put(new Integer (EXPRTOKEN_LITERAL), "EXPRTOKEN_LITERAL"); 902 fTokenNames.put(new Integer (EXPRTOKEN_NUMBER), "EXPRTOKEN_NUMBER"); 903 fTokenNames.put(new Integer (EXPRTOKEN_VARIABLE_REFERENCE), "EXPRTOKEN_VARIABLE_REFERENCE"); 904 } 905 906 910 public String getTokenString(int token) { 917 return (String )fTokenNames.get(new Integer (token)); 918 } 919 920 public void addToken(String tokenStr) { 921 Integer tokenInt = (Integer )fTokenNames.get(tokenStr); 922 if (tokenInt == null) { 923 tokenInt = new Integer (fTokenNames.size()); 924 fTokenNames.put(tokenInt, tokenStr); 925 } 926 addToken(tokenInt.intValue()); 927 } 928 929 public void addToken(int token) { 930 try { 931 fTokens[fTokenCount] = token; 932 } catch (ArrayIndexOutOfBoundsException ex) { 933 int[] oldList = fTokens; 934 fTokens = new int[fTokenCount << 1]; 935 System.arraycopy(oldList, 0, fTokens, 0, fTokenCount); 936 fTokens[fTokenCount] = token; 937 } 938 fTokenCount++; 939 } 940 947 950 public void rewind() { 951 fCurrentTokenIndex=0; 952 } 953 957 public boolean hasMore() { 958 return fCurrentTokenIndex<fTokenCount; 959 } 960 967 public int nextToken() throws XPathException { 968 if( fCurrentTokenIndex==fTokenCount ) 969 throw new XPathException("c-general-xpath"); 970 return fTokens[fCurrentTokenIndex++]; 971 } 972 979 public int peekToken() throws XPathException { 980 if( fCurrentTokenIndex==fTokenCount ) 981 throw new XPathException("c-general-xpath"); 982 return fTokens[fCurrentTokenIndex]; 983 } 984 991 public String nextTokenAsString() throws XPathException { 992 String s = getTokenString(nextToken()); 993 if(s==null) throw new XPathException("c-general-xpath"); 994 return s; 995 } 996 997 public void dumpTokens() { 998 for (int i = 0; i < fTokenCount; i++) { 1000 switch (fTokens[i]) { 1001 case EXPRTOKEN_OPEN_PAREN: 1002 System.out.print("<OPEN_PAREN/>"); 1003 break; 1004 case EXPRTOKEN_CLOSE_PAREN: 1005 System.out.print("<CLOSE_PAREN/>"); 1006 break; 1007 case EXPRTOKEN_OPEN_BRACKET: 1008 System.out.print("<OPEN_BRACKET/>"); 1009 break; 1010 case EXPRTOKEN_CLOSE_BRACKET: 1011 System.out.print("<CLOSE_BRACKET/>"); 1012 break; 1013 case EXPRTOKEN_PERIOD: 1014 System.out.print("<PERIOD/>"); 1015 break; 1016 case EXPRTOKEN_DOUBLE_PERIOD: 1017 System.out.print("<DOUBLE_PERIOD/>"); 1018 break; 1019 case EXPRTOKEN_ATSIGN: 1020 System.out.print("<ATSIGN/>"); 1021 break; 1022 case EXPRTOKEN_COMMA: 1023 System.out.print("<COMMA/>"); 1024 break; 1025 case EXPRTOKEN_DOUBLE_COLON: 1026 System.out.print("<DOUBLE_COLON/>"); 1027 break; 1028 case EXPRTOKEN_NAMETEST_ANY: 1029 System.out.print("<NAMETEST_ANY/>"); 1030 break; 1031 case EXPRTOKEN_NAMETEST_NAMESPACE: 1032 System.out.print("<NAMETEST_NAMESPACE"); 1033 System.out.print(" prefix=\"" + getTokenString(fTokens[++i]) + "\""); 1034 System.out.print("/>"); 1035 break; 1036 case EXPRTOKEN_NAMETEST_QNAME: 1037 System.out.print("<NAMETEST_QNAME"); 1038 if (fTokens[++i] != -1) 1039 System.out.print(" prefix=\"" + getTokenString(fTokens[i]) + "\""); 1040 System.out.print(" localpart=\"" + getTokenString(fTokens[++i]) + "\""); 1041 System.out.print("/>"); 1042 break; 1043 case EXPRTOKEN_NODETYPE_COMMENT: 1044 System.out.print("<NODETYPE_COMMENT/>"); 1045 break; 1046 case EXPRTOKEN_NODETYPE_TEXT: 1047 System.out.print("<NODETYPE_TEXT/>"); 1048 break; 1049 case EXPRTOKEN_NODETYPE_PI: 1050 System.out.print("<NODETYPE_PI/>"); 1051 break; 1052 case EXPRTOKEN_NODETYPE_NODE: 1053 System.out.print("<NODETYPE_NODE/>"); 1054 break; 1055 case EXPRTOKEN_OPERATOR_AND: 1056 System.out.print("<OPERATOR_AND/>"); 1057 break; 1058 case EXPRTOKEN_OPERATOR_OR: 1059 System.out.print("<OPERATOR_OR/>"); 1060 break; 1061 case EXPRTOKEN_OPERATOR_MOD: 1062 System.out.print("<OPERATOR_MOD/>"); 1063 break; 1064 case EXPRTOKEN_OPERATOR_DIV: 1065 System.out.print("<OPERATOR_DIV/>"); 1066 break; 1067 case EXPRTOKEN_OPERATOR_MULT: 1068 System.out.print("<OPERATOR_MULT/>"); 1069 break; 1070 case EXPRTOKEN_OPERATOR_SLASH: 1071 System.out.print("<OPERATOR_SLASH/>"); 1072 if (i + 1 < fTokenCount) { 1073 System.out.println(); 1074 System.out.print(" "); 1075 } 1076 break; 1077 case EXPRTOKEN_OPERATOR_DOUBLE_SLASH: 1078 System.out.print("<OPERATOR_DOUBLE_SLASH/>"); 1079 break; 1080 case EXPRTOKEN_OPERATOR_UNION: 1081 System.out.print("<OPERATOR_UNION/>"); 1082 break; 1083 case EXPRTOKEN_OPERATOR_PLUS: 1084 System.out.print("<OPERATOR_PLUS/>"); 1085 break; 1086 case EXPRTOKEN_OPERATOR_MINUS: 1087 System.out.print("<OPERATOR_MINUS/>"); 1088 break; 1089 case EXPRTOKEN_OPERATOR_EQUAL: 1090 System.out.print("<OPERATOR_EQUAL/>"); 1091 break; 1092 case EXPRTOKEN_OPERATOR_NOT_EQUAL: 1093 System.out.print("<OPERATOR_NOT_EQUAL/>"); 1094 break; 1095 case EXPRTOKEN_OPERATOR_LESS: 1096 System.out.print("<OPERATOR_LESS/>"); 1097 break; 1098 case EXPRTOKEN_OPERATOR_LESS_EQUAL: 1099 System.out.print("<OPERATOR_LESS_EQUAL/>"); 1100 break; 1101 case EXPRTOKEN_OPERATOR_GREATER: 1102 System.out.print("<OPERATOR_GREATER/>"); 1103 break; 1104 case EXPRTOKEN_OPERATOR_GREATER_EQUAL: 1105 System.out.print("<OPERATOR_GREATER_EQUAL/>"); 1106 break; 1107 case EXPRTOKEN_FUNCTION_NAME: 1108 System.out.print("<FUNCTION_NAME"); 1109 if (fTokens[++i] != -1) 1110 System.out.print(" prefix=\"" + getTokenString(fTokens[i]) + "\""); 1111 System.out.print(" localpart=\"" + getTokenString(fTokens[++i]) + "\""); 1112 System.out.print("/>"); 1113 break; 1114 case EXPRTOKEN_AXISNAME_ANCESTOR: 1115 System.out.print("<AXISNAME_ANCESTOR/>"); 1116 break; 1117 case EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF: 1118 System.out.print("<AXISNAME_ANCESTOR_OR_SELF/>"); 1119 break; 1120 case EXPRTOKEN_AXISNAME_ATTRIBUTE: 1121 System.out.print("<AXISNAME_ATTRIBUTE/>"); 1122 break; 1123 case EXPRTOKEN_AXISNAME_CHILD: 1124 System.out.print("<AXISNAME_CHILD/>"); 1125 break; 1126 case EXPRTOKEN_AXISNAME_DESCENDANT: 1127 System.out.print("<AXISNAME_DESCENDANT/>"); 1128 break; 1129 case EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF: 1130 System.out.print("<AXISNAME_DESCENDANT_OR_SELF/>"); 1131 break; 1132 case EXPRTOKEN_AXISNAME_FOLLOWING: 1133 System.out.print("<AXISNAME_FOLLOWING/>"); 1134 break; 1135 case EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING: 1136 System.out.print("<AXISNAME_FOLLOWING_SIBLING/>"); 1137 break; 1138 case EXPRTOKEN_AXISNAME_NAMESPACE: 1139 System.out.print("<AXISNAME_NAMESPACE/>"); 1140 break; 1141 case EXPRTOKEN_AXISNAME_PARENT: 1142 System.out.print("<AXISNAME_PARENT/>"); 1143 break; 1144 case EXPRTOKEN_AXISNAME_PRECEDING: 1145 System.out.print("<AXISNAME_PRECEDING/>"); 1146 break; 1147 case EXPRTOKEN_AXISNAME_PRECEDING_SIBLING: 1148 System.out.print("<AXISNAME_PRECEDING_SIBLING/>"); 1149 break; 1150 case EXPRTOKEN_AXISNAME_SELF: 1151 System.out.print("<AXISNAME_SELF/>"); 1152 break; 1153 case EXPRTOKEN_LITERAL: 1154 System.out.print("<LITERAL"); 1155 System.out.print(" value=\"" + getTokenString(fTokens[++i]) + "\""); 1156 System.out.print("/>"); 1157 break; 1158 case EXPRTOKEN_NUMBER: 1159 System.out.print("<NUMBER"); 1160 System.out.print(" whole=\"" + getTokenString(fTokens[++i]) + "\""); 1161 System.out.print(" part=\"" + getTokenString(fTokens[++i]) + "\""); 1162 System.out.print("/>"); 1163 break; 1164 case EXPRTOKEN_VARIABLE_REFERENCE: 1165 System.out.print("<VARIABLE_REFERENCE"); 1166 if (fTokens[++i] != -1) 1167 System.out.print(" prefix=\"" + getTokenString(fTokens[i]) + "\""); 1168 System.out.print(" localpart=\"" + getTokenString(fTokens[++i]) + "\""); 1169 System.out.print("/>"); 1170 break; 1171 default: 1172 System.out.println("<???/>"); 1173 } 1174 } 1175 System.out.println(); 1176 } 1178 1179 } 1181 1189 private static class Scanner { 1190 1191 1204 private static final byte 1205 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; 1232 private static final byte[] fASCIICharMap = { 1233 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 0, 0, 1234 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1235 2, 3, 4, 1, 5, 1, 1, 4, 6, 7, 8, 9, 10, 11, 12, 13, 1236 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 1, 16, 17, 18, 1, 1237 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 1238 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 1, 22, 1, 23, 1239 1, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 1240 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 1, 24, 1, 1, 1 1241 }; 1242 1243 1246 1247 1251 1252 private SymbolTable fSymbolTable; 1253 1254 1256 private static final String fAndSymbol = "and".intern(); 1257 private static final String fOrSymbol = "or".intern(); 1258 private static final String fModSymbol = "mod".intern(); 1259 private static final String fDivSymbol = "div".intern(); 1260 1261 private static final String fCommentSymbol = "comment".intern(); 1262 private static final String fTextSymbol = "text".intern(); 1263 private static final String fPISymbol = "processing-instruction".intern(); 1264 private static final String fNodeSymbol = "node".intern(); 1265 1266 private static final String fAncestorSymbol = "ancestor".intern(); 1267 private static final String fAncestorOrSelfSymbol = "ancestor-or-self".intern(); 1268 private static final String fAttributeSymbol = "attribute".intern(); 1269 private static final String fChildSymbol = "child".intern(); 1270 private static final String fDescendantSymbol = "descendant".intern(); 1271 private static final String fDescendantOrSelfSymbol = "descendant-or-self".intern(); 1272 private static final String fFollowingSymbol = "following".intern(); 1273 private static final String fFollowingSiblingSymbol = "following-sibling".intern(); 1274 private static final String fNamespaceSymbol = "namespace".intern(); 1275 private static final String fParentSymbol = "parent".intern(); 1276 private static final String fPrecedingSymbol = "preceding".intern(); 1277 private static final String fPrecedingSiblingSymbol = "preceding-sibling".intern(); 1278 private static final String fSelfSymbol = "self".intern(); 1279 1280 1284 1285 public Scanner(SymbolTable symbolTable) { 1286 1287 fSymbolTable = symbolTable; 1289 1290 } 1292 1295 public boolean scanExpr(SymbolTable symbolTable, 1296 XPath.Tokens tokens, String data, 1297 int currentOffset, int endOffset) 1298 throws XPathException { 1299 1300 int nameOffset; 1301 String nameHandle, prefixHandle; 1302 boolean starIsMultiplyOperator = false; 1303 int ch; 1304 1305 while (true) { 1306 if (currentOffset == endOffset) { 1307 break; 1308 } 1309 ch = data.charAt(currentOffset); 1310 while (ch == ' ' || ch == 0x0A || ch == 0x09 || ch == 0x0D) { 1314 if (++currentOffset == endOffset) { 1315 break; 1316 } 1317 ch = data.charAt(currentOffset); 1318 } 1319 if (currentOffset == endOffset) { 1320 break; 1321 } 1322 byte chartype = (ch >= 0x80) ? CHARTYPE_NONASCII : fASCIICharMap[ch]; 1328 switch (chartype) { 1329 case CHARTYPE_OPEN_PAREN: addToken(tokens, XPath.Tokens.EXPRTOKEN_OPEN_PAREN); 1331 starIsMultiplyOperator = false; 1332 if (++currentOffset == endOffset) { 1333 break; 1334 } 1335 break; 1336 case CHARTYPE_CLOSE_PAREN: addToken(tokens, XPath.Tokens.EXPRTOKEN_CLOSE_PAREN); 1338 starIsMultiplyOperator = true; 1339 if (++currentOffset == endOffset) { 1340 break; 1341 } 1342 break; 1343 case CHARTYPE_OPEN_BRACKET: addToken(tokens, XPath.Tokens.EXPRTOKEN_OPEN_BRACKET); 1345 starIsMultiplyOperator = false; 1346 if (++currentOffset == endOffset) { 1347 break; 1348 } 1349 break; 1350 case CHARTYPE_CLOSE_BRACKET: addToken(tokens, XPath.Tokens.EXPRTOKEN_CLOSE_BRACKET); 1352 starIsMultiplyOperator = true; 1353 if (++currentOffset == endOffset) { 1354 break; 1355 } 1356 break; 1357 case CHARTYPE_PERIOD: if (currentOffset + 1 == endOffset) { 1363 addToken(tokens, XPath.Tokens.EXPRTOKEN_PERIOD); 1364 starIsMultiplyOperator = true; 1365 currentOffset++; 1366 break; 1367 } 1368 ch = data.charAt(currentOffset + 1); 1369 if (ch == '.') { addToken(tokens, XPath.Tokens.EXPRTOKEN_DOUBLE_PERIOD); 1371 starIsMultiplyOperator = true; 1372 currentOffset += 2; 1373 } else if (ch >= '0' && ch <= '9') { 1374 addToken(tokens, XPath.Tokens.EXPRTOKEN_NUMBER); 1375 starIsMultiplyOperator = true; 1376 currentOffset = scanNumber(tokens, data, endOffset, currentOffset); 1377 } else if (ch == '/') { 1378 addToken(tokens, XPath.Tokens.EXPRTOKEN_PERIOD); 1379 starIsMultiplyOperator = true; 1380 currentOffset++; 1381 } else if (ch == '|') { 1382 addToken(tokens, XPath.Tokens.EXPRTOKEN_PERIOD); 1383 starIsMultiplyOperator = true; 1384 currentOffset++; 1385 break; 1386 } else if (ch == ' ' || ch == 0x0A || ch == 0x09 || ch == 0x0D) { 1387 do { 1389 if (++currentOffset == endOffset) { 1390 break; 1391 } 1392 ch = data.charAt(currentOffset); 1393 } while (ch == ' ' || ch == 0x0A || ch == 0x09 || ch == 0x0D); 1394 if (currentOffset == endOffset || ch == '|') { 1395 addToken(tokens, XPath.Tokens.EXPRTOKEN_PERIOD); 1396 starIsMultiplyOperator = true; 1397 break; 1398 } 1399 throw new XPathException ("c-general-xpath"); 1400 } else { throw new XPathException ("c-general-xpath"); 1402 } 1403 if (currentOffset == endOffset) { 1404 break; 1405 } 1406 break; 1407 case CHARTYPE_ATSIGN: addToken(tokens, XPath.Tokens.EXPRTOKEN_ATSIGN); 1409 starIsMultiplyOperator = false; 1410 if (++currentOffset == endOffset) { 1411 break; 1412 } 1413 break; 1414 case CHARTYPE_COMMA: addToken(tokens, XPath.Tokens.EXPRTOKEN_COMMA); 1416 starIsMultiplyOperator = false; 1417 if (++currentOffset == endOffset) { 1418 break; 1419 } 1420 break; 1421 case CHARTYPE_COLON: if (++currentOffset == endOffset) { 1423 return false; } 1426 ch = data.charAt(currentOffset); 1427 if (ch != ':') { 1428 return false; } 1431 addToken(tokens, XPath.Tokens.EXPRTOKEN_DOUBLE_COLON); 1432 starIsMultiplyOperator = false; 1433 if (++currentOffset == endOffset) { 1434 break; 1435 } 1436 break; 1437 case CHARTYPE_SLASH: if (++currentOffset == endOffset) { 1439 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH); 1440 starIsMultiplyOperator = false; 1441 break; 1442 } 1443 ch = data.charAt(currentOffset); 1444 if (ch == '/') { addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH); 1446 starIsMultiplyOperator = false; 1447 if (++currentOffset == endOffset) { 1448 break; 1449 } 1450 } else { 1451 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH); 1452 starIsMultiplyOperator = false; 1453 } 1454 break; 1455 case CHARTYPE_UNION: addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_UNION); 1457 starIsMultiplyOperator = false; 1458 if (++currentOffset == endOffset) { 1459 break; 1460 } 1461 break; 1462 case CHARTYPE_PLUS: addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_PLUS); 1464 starIsMultiplyOperator = false; 1465 if (++currentOffset == endOffset) { 1466 break; 1467 } 1468 break; 1469 case CHARTYPE_MINUS: addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_MINUS); 1471 starIsMultiplyOperator = false; 1472 if (++currentOffset == endOffset) { 1473 break; 1474 } 1475 break; 1476 case CHARTYPE_EQUAL: addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_EQUAL); 1478 starIsMultiplyOperator = false; 1479 if (++currentOffset == endOffset) { 1480 break; 1481 } 1482 break; 1483 case CHARTYPE_EXCLAMATION: if (++currentOffset == endOffset) { 1485 return false; } 1488 ch = data.charAt(currentOffset); 1489 if (ch != '=') { 1490 return false; } 1493 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_NOT_EQUAL); 1494 starIsMultiplyOperator = false; 1495 if (++currentOffset == endOffset) { 1496 break; 1497 } 1498 break; 1499 case CHARTYPE_LESS: if (++currentOffset == endOffset) { 1501 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_LESS); 1502 starIsMultiplyOperator = false; 1503 break; 1504 } 1505 ch = data.charAt(currentOffset); 1506 if (ch == '=') { addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_LESS_EQUAL); 1508 starIsMultiplyOperator = false; 1509 if (++currentOffset == endOffset) { 1510 break; 1511 } 1512 } else { 1513 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_LESS); 1514 starIsMultiplyOperator = false; 1515 } 1516 break; 1517 case CHARTYPE_GREATER: if (++currentOffset == endOffset) { 1519 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_GREATER); 1520 starIsMultiplyOperator = false; 1521 break; 1522 } 1523 ch = data.charAt(currentOffset); 1524 if (ch == '=') { addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_GREATER_EQUAL); 1526 starIsMultiplyOperator = false; 1527 if (++currentOffset == endOffset) { 1528 break; 1529 } 1530 } else { 1531 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_GREATER); 1532 starIsMultiplyOperator = false; 1533 } 1534 break; 1535 case CHARTYPE_QUOTE: int qchar = ch; 1540 if (++currentOffset == endOffset) { 1541 return false; } 1544 ch = data.charAt(currentOffset); 1545 int litOffset = currentOffset; 1546 while (ch != qchar) { 1547 if (++currentOffset == endOffset) { 1548 return false; } 1551 ch = data.charAt(currentOffset); 1552 } 1553 int litLength = currentOffset - litOffset; 1554 addToken(tokens, XPath.Tokens.EXPRTOKEN_LITERAL); 1555 starIsMultiplyOperator = true; 1556 tokens.addToken(symbolTable.addSymbol(data.substring(litOffset, litOffset + litLength))); 1557 if (++currentOffset == endOffset) { 1558 break; 1559 } 1560 break; 1561 case CHARTYPE_DIGIT: 1566 addToken(tokens, XPath.Tokens.EXPRTOKEN_NUMBER); 1567 starIsMultiplyOperator = true; 1568 currentOffset = scanNumber(tokens, data, endOffset, currentOffset); 1569 break; 1570 case CHARTYPE_DOLLAR: 1574 if (++currentOffset == endOffset) { 1575 return false; } 1578 nameOffset = currentOffset; 1579 currentOffset = scanNCName(data, endOffset, currentOffset); 1580 if (currentOffset == nameOffset) { 1581 return false; } 1584 if (currentOffset < endOffset) { 1585 ch = data.charAt(currentOffset); 1586 } 1587 else { 1588 ch = -1; 1589 } 1590 nameHandle = symbolTable.addSymbol(data.substring(nameOffset, currentOffset)); 1591 if (ch != ':') { 1592 prefixHandle = XMLSymbols.EMPTY_STRING; 1593 } else { 1594 prefixHandle = nameHandle; 1595 if (++currentOffset == endOffset) { 1596 return false; } 1599 nameOffset = currentOffset; 1600 currentOffset = scanNCName(data, endOffset, currentOffset); 1601 if (currentOffset == nameOffset) { 1602 return false; } 1605 if (currentOffset < endOffset) { 1606 ch = data.charAt(currentOffset); 1607 } 1608 else { 1609 ch = -1; 1610 } 1611 nameHandle = symbolTable.addSymbol(data.substring(nameOffset, currentOffset)); 1612 } 1613 addToken(tokens, XPath.Tokens.EXPRTOKEN_VARIABLE_REFERENCE); 1614 starIsMultiplyOperator = true; 1615 tokens.addToken(prefixHandle); 1616 tokens.addToken(nameHandle); 1617 break; 1618 case CHARTYPE_STAR: if (starIsMultiplyOperator) { 1632 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_MULT); 1633 starIsMultiplyOperator = false; 1634 } else { 1635 addToken(tokens, XPath.Tokens.EXPRTOKEN_NAMETEST_ANY); 1636 starIsMultiplyOperator = true; 1637 } 1638 if (++currentOffset == endOffset) { 1639 break; 1640 } 1641 break; 1642 case CHARTYPE_NONASCII: case CHARTYPE_LETTER: 1647 case CHARTYPE_UNDERSCORE: 1648 nameOffset = currentOffset; 1676 currentOffset = scanNCName(data, endOffset, currentOffset); 1677 if (currentOffset == nameOffset) { 1678 return false; } 1681 if (currentOffset < endOffset) { 1682 ch = data.charAt(currentOffset); 1683 } 1684 else { 1685 ch = -1; 1686 } 1687 nameHandle = symbolTable.addSymbol(data.substring(nameOffset, currentOffset)); 1688 boolean isNameTestNCName = false; 1689 boolean isAxisName = false; 1690 prefixHandle = XMLSymbols.EMPTY_STRING; 1691 if (ch == ':') { 1692 if (++currentOffset == endOffset) { 1693 return false; } 1696 ch = data.charAt(currentOffset); 1697 if (ch == '*') { 1698 if (++currentOffset < endOffset) { 1699 ch = data.charAt(currentOffset); 1700 } 1701 isNameTestNCName = true; 1702 } else if (ch == ':') { 1703 if (++currentOffset < endOffset) { 1704 ch = data.charAt(currentOffset); 1705 } 1706 isAxisName = true; 1707 } else { 1708 prefixHandle = nameHandle; 1709 nameOffset = currentOffset; 1710 currentOffset = scanNCName(data, endOffset, currentOffset); 1711 if (currentOffset == nameOffset) { 1712 return false; } 1715 if (currentOffset < endOffset) { 1716 ch = data.charAt(currentOffset); 1717 } 1718 else { 1719 ch = -1; 1720 } 1721 nameHandle = symbolTable.addSymbol(data.substring(nameOffset, currentOffset)); 1722 } 1723 } 1724 while (ch == ' ' || ch == 0x0A || ch == 0x09 || ch == 0x0D) { 1728 if (++currentOffset == endOffset) { 1729 break; 1730 } 1731 ch = data.charAt(currentOffset); 1732 } 1733 if (starIsMultiplyOperator) { 1738 if (nameHandle == fAndSymbol) { 1739 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_AND); 1740 starIsMultiplyOperator = false; 1741 } else if (nameHandle == fOrSymbol) { 1742 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_OR); 1743 starIsMultiplyOperator = false; 1744 } else if (nameHandle == fModSymbol) { 1745 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_MOD); 1746 starIsMultiplyOperator = false; 1747 } else if (nameHandle == fDivSymbol) { 1748 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_DIV); 1749 starIsMultiplyOperator = false; 1750 } else { 1751 return false; } 1754 if (isNameTestNCName) { 1755 return false; } else if (isAxisName) { 1758 return false; } 1761 break; 1762 } 1763 if (ch == '(' && !isNameTestNCName && !isAxisName) { 1768 if (nameHandle == fCommentSymbol) { 1769 addToken(tokens, XPath.Tokens.EXPRTOKEN_NODETYPE_COMMENT); 1770 } else if (nameHandle == fTextSymbol) { 1771 addToken(tokens, XPath.Tokens.EXPRTOKEN_NODETYPE_TEXT); 1772 } else if (nameHandle == fPISymbol) { 1773 addToken(tokens, XPath.Tokens.EXPRTOKEN_NODETYPE_PI); 1774 } else if (nameHandle == fNodeSymbol) { 1775 addToken(tokens, XPath.Tokens.EXPRTOKEN_NODETYPE_NODE); 1776 } else { 1777 addToken(tokens, XPath.Tokens.EXPRTOKEN_FUNCTION_NAME); 1778 tokens.addToken(prefixHandle); 1779 tokens.addToken(nameHandle); 1780 } 1781 addToken(tokens, XPath.Tokens.EXPRTOKEN_OPEN_PAREN); 1782 starIsMultiplyOperator = false; 1783 if (++currentOffset == endOffset) { 1784 break; 1785 } 1786 break; 1787 } 1788 if (isAxisName || 1793 (ch == ':' && currentOffset + 1 < endOffset && 1794 data.charAt(currentOffset + 1) == ':')) { 1795 if (nameHandle == fAncestorSymbol) { 1796 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_ANCESTOR); 1797 } else if (nameHandle == fAncestorOrSelfSymbol) { 1798 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF); 1799 } else if (nameHandle == fAttributeSymbol) { 1800 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_ATTRIBUTE); 1801 } else if (nameHandle == fChildSymbol) { 1802 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_CHILD); 1803 } else if (nameHandle == fDescendantSymbol) { 1804 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_DESCENDANT); 1805 } else if (nameHandle == fDescendantOrSelfSymbol) { 1806 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF); 1807 } else if (nameHandle == fFollowingSymbol) { 1808 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_FOLLOWING); 1809 } else if (nameHandle == fFollowingSiblingSymbol) { 1810 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING); 1811 } else if (nameHandle == fNamespaceSymbol) { 1812 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_NAMESPACE); 1813 } else if (nameHandle == fParentSymbol) { 1814 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_PARENT); 1815 } else if (nameHandle == fPrecedingSymbol) { 1816 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_PRECEDING); 1817 } else if (nameHandle == fPrecedingSiblingSymbol) { 1818 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_PRECEDING_SIBLING); 1819 } else if (nameHandle == fSelfSymbol) { 1820 addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_SELF); 1821 } else { 1822 return false; } 1825 if (isNameTestNCName) { 1826 return false; } 1829 addToken(tokens, XPath.Tokens.EXPRTOKEN_DOUBLE_COLON); 1830 starIsMultiplyOperator = false; 1831 if (!isAxisName) { 1832 currentOffset++; 1833 if (++currentOffset == endOffset) { 1834 break; 1835 } 1836 } 1837 break; 1838 } 1839 if (isNameTestNCName) { 1844 addToken(tokens, XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE); 1845 starIsMultiplyOperator = true; 1846 tokens.addToken(nameHandle); 1847 } else { 1848 addToken(tokens, XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME); 1849 starIsMultiplyOperator = true; 1850 tokens.addToken(prefixHandle); 1851 tokens.addToken(nameHandle); 1852 } 1853 break; 1854 } 1855 } 1856 if (XPath.Tokens.DUMP_TOKENS) { 1857 tokens.dumpTokens(); 1858 } 1859 return true; 1860 } 1861 int scanNCName(String data, int endOffset, int currentOffset) { 1866 int ch = data.charAt(currentOffset); 1867 if (ch >= 0x80) { 1868 if (!XMLChar.isNameStart(ch)) 1869 1873 { 1874 return currentOffset; 1875 } 1876 } 1877 else { 1878 byte chartype = fASCIICharMap[ch]; 1879 if (chartype != CHARTYPE_LETTER && chartype != CHARTYPE_UNDERSCORE) { 1880 return currentOffset; 1881 } 1882 } 1883 while (++currentOffset < endOffset) { 1884 ch = data.charAt(currentOffset); 1885 if (ch >= 0x80) { 1886 if (!XMLChar.isName(ch)) 1887 1891 { 1892 break; 1893 } 1894 } 1895 else { 1896 byte chartype = fASCIICharMap[ch]; 1897 if (chartype != CHARTYPE_LETTER && chartype != CHARTYPE_DIGIT && 1898 chartype != CHARTYPE_PERIOD && chartype != CHARTYPE_MINUS && 1899 chartype != CHARTYPE_UNDERSCORE) 1900 { 1901 break; 1902 } 1903 } 1904 } 1905 return currentOffset; 1906 } 1907 private int scanNumber(XPath.Tokens tokens, String data, int endOffset, int currentOffset) { 1912 int ch = data.charAt(currentOffset); 1913 int whole = 0; 1914 int part = 0; 1915 while (ch >= '0' && ch <= '9') { 1916 whole = (whole * 10) + (ch - '0'); 1917 if (++currentOffset == endOffset) { 1918 break; 1919 } 1920 ch = data.charAt(currentOffset); 1921 } 1922 if (ch == '.') { 1923 if (++currentOffset < endOffset) { 1924 1925 ch = data.charAt(currentOffset); 1926 while (ch >= '0' && ch <= '9') { 1927 part = (part * 10) + (ch - '0'); 1928 if (++currentOffset == endOffset) { 1929 break; 1930 } 1931 ch = data.charAt(currentOffset); 1932 } 1933 if (part != 0) { 1934 1937 throw new RuntimeException ("find a solution!"); 1938 1940 } 1941 } 1942 } 1943 tokens.addToken(whole); 1944 tokens.addToken(part); 1945 return currentOffset; 1946 } 1947 1948 1952 1960 protected void addToken(XPath.Tokens tokens, int token) 1961 throws XPathException { 1962 tokens.addToken(token); 1963 } 1965 } 1967 1971 1972 public static void main(String [] argv) throws Exception { 1973 1974 for (int i = 0; i < argv.length; i++) { 1975 final String expression = argv[i]; 1976 System.out.println("# XPath expression: \""+expression+'"'); 1977 try { 1978 SymbolTable symbolTable = new SymbolTable(); 1979 XPath xpath = new XPath(expression, symbolTable, null); 1980 System.out.println("expanded xpath: \""+xpath.toString()+'"'); 1981 } 1982 catch (XPathException e) { 1983 System.out.println("error: "+e.getMessage()); 1984 } 1985 } 1986 1987 } 1989} | Popular Tags |