1 4 package gnu.xquery.lang; 5 import gnu.kawa.lispexpr.*; 6 import gnu.mapping.*; 7 import gnu.lists.*; 8 import gnu.text.*; 9 import gnu.expr.*; 10 import gnu.math.IntNum; 11 import java.util.Vector ; 12 import java.util.Stack ; 13 import java.io.File ; 14 import gnu.kawa.xml.*; 15 import gnu.xml.*; 16 import gnu.bytecode.*; 17 import gnu.kawa.reflect.OccurrenceType; 18 import gnu.kawa.reflect.SingletonType; 19 import gnu.kawa.functions.Convert; 20 import gnu.xquery.util.NamedCollator; 21 import gnu.xquery.util.CastableAs; 22 import gnu.xquery.util.QNameUtils; 23 import gnu.xquery.util.RelativeStep; 24 import gnu.xquery.util.ValuesFilter; 25 import kawa.standard.require; 26 27 28 29 public class XQParser extends Lexer 30 { 31 int curToken; 32 Object curValue; 33 34 36 int parseContext; 37 38 boolean seenDeclaration; 39 40 String libraryModuleNamespace; 41 42 44 int curLine; 45 46 48 int curColumn; 49 50 XQuery interpreter; 51 52 int seenPosition; 53 int seenLast; 54 55 public static boolean warnOldVersion = true; 56 public static boolean warnHidePreviousDeclaration = false; 57 58 59 static final Symbol DOT_VARNAME = Symbol.makeUninterned("$dot$"); 60 61 62 static final Symbol POSITION_VARNAME = Symbol.makeUninterned("$position$"); 63 64 65 static final Symbol LAST_VARNAME = Symbol.makeUninterned("$last$"); 66 67 public static final gnu.kawa.reflect.InstanceOf instanceOf 68 = new gnu.kawa.reflect.InstanceOf(XQuery.getInstance(), "instance"); 69 public static final CastableAs castableAs = CastableAs.castableAs; 70 public static final Convert treatAs = Convert.as; 71 72 NameLookup lexical; 73 74 NamedCollator defaultCollator = null; 75 76 79 char defaultEmptyOrder = 'L'; 80 boolean emptyOrderDeclarationSeen; 81 82 String baseURI = null; 83 boolean baseURIDeclarationSeen; 84 public String getStaticBaseUri () 85 { 86 if (baseURI == null) 87 { 88 Environment env = Environment.getCurrent(); 89 Object value = env.get(Symbol.make("", "base-uri"), null, null); 90 if (value != null) 91 baseURI = value.toString(); 92 } 93 return baseURI; 94 } 95 96 boolean boundarySpacePreserve; 97 boolean boundarySpaceDeclarationSeen; 98 99 boolean orderingModeUnordered; 100 boolean orderingModeSeen; 101 102 103 boolean copyNamespacesDeclarationSeen; 104 int copyNamespacesMode 105 = XMLFilter.COPY_NAMESPACES_PRESERVE|XMLFilter.COPY_NAMESPACES_INHERIT; 106 107 108 boolean constructionModeStrip; 109 110 boolean constructionModeDeclarationSeen; 111 112 public Namespace[] functionNamespacePath 113 = XQuery.defaultFunctionNamespacePath; 114 115 116 Declaration[] flworDecls; 117 118 int flworDeclsFirst; 119 120 int flworDeclsCount; 121 122 int parseCount; 123 int commentCount; 124 125 String errorIfComment; 126 127 131 final int skipSpace() 132 throws java.io.IOException , SyntaxException 133 { 134 return skipSpace(true); 135 } 136 137 final int skipSpace(boolean verticalToo) 138 throws java.io.IOException , SyntaxException 139 { 140 for (;;) 141 { 142 int ch = read(); 143 if (ch == '(') 144 { 145 if (! checkNext(':')) 146 return '('; 147 skipComment(); 148 } 149 else if (ch == '{') 150 { 151 ch = read(); 152 if (ch != '-') 153 { 154 unread(ch); 155 return '{'; 156 } 157 ch = read(); 158 if (ch != '-') 159 { 160 unread(ch); 161 unread('-'); 162 return '{'; 163 } 164 skipOldComment(); 165 } 166 else if (verticalToo 167 ? (ch < 0 || ! Character.isWhitespace((char) ch)) 168 : (ch != ' ' && ch != '\t')) 169 return ch; 170 } 171 } 172 173 final void skipToSemicolon () 174 throws java.io.IOException 175 { 176 for (;;) 177 { 178 int next = read(); 179 if (next < 0 || next == ';') 180 break; 181 } 182 } 183 184 final void skipOldComment() 185 throws java.io.IOException , SyntaxException 186 { 187 int seenDashes = 0; 188 int startLine = getLineNumber() + 1; 189 int startColumn = getColumnNumber() - 2; 190 warnOldVersion("use (: :) instead of old-style comment {-- --}"); 191 for (;;) 192 { 193 int ch = read(); 194 if (ch == '-') 195 seenDashes++; 196 else if (ch == '}' && seenDashes >= 2) 197 return; 198 else if (ch < 0) 199 { 200 curLine = startLine; 201 curColumn = startColumn; 202 eofError("non-terminated comment starting here"); 203 } 204 else 205 seenDashes = 0; 206 } 207 } 208 209 final void skipComment() 210 throws java.io.IOException , SyntaxException 211 { 212 commentCount++; 213 int startLine = getLineNumber() + 1; 214 int startColumn = getColumnNumber() - 1; 215 if (errorIfComment != null) 216 { 217 curLine = startLine; 218 curColumn = startColumn; 219 error('e', errorIfComment); 220 } 221 int prev = 0; 222 int commentNesting = 0; 223 char saveReadState = pushNesting(':'); 224 for (;;) 225 { 226 int ch = read(); 227 if (ch == ':') 228 { 229 if (prev == '(') 230 { 231 commentNesting++; 232 ch = 0; 233 } 234 } 235 else if (ch == ')' && prev == ':') 236 { 237 if (commentNesting == 0) 238 { 239 popNesting(saveReadState); 240 return; 241 } 242 --commentNesting; 243 } 244 else if (ch < 0) 245 { 246 curLine = startLine; 247 curColumn = startColumn; 248 eofError("non-terminated comment starting here"); 249 } 250 prev = ch; 251 } 252 } 253 254 255 final int peekNonSpace(String message) 256 throws java.io.IOException , SyntaxException 257 { 258 int ch = skipSpace(); 259 if (ch < 0) 260 eofError(message); 261 unread(ch); 262 return ch; 263 } 264 265 static final int EOF_TOKEN = -1; 266 static final int EOL_TOKEN = '\n'; 267 static final char INTEGER_TOKEN = '0'; 268 static final char DECIMAL_TOKEN = '1'; 269 static final char DOUBLE_TOKEN = '2'; 270 static final int STRING_TOKEN = '"'; 271 static final int SLASHSLASH_TOKEN = 'D'; 272 static final int DOTDOT_TOKEN = '3'; 273 static final int COLON_EQUAL_TOKEN = 'L'; static final int COLON_COLON_TOKEN = 'X'; 275 276 278 static final int NCNAME_TOKEN = 'A'; 279 280 284 static final int NCNAME_COLON_TOKEN = 'C'; 285 286 288 static final int QNAME_TOKEN = 'Q'; 289 290 static final int ARROW_TOKEN = 'R'; 291 292 293 static final int FNAME_TOKEN = 'F'; 294 295 static final int IMPORT_MODULE_TOKEN = 'I'; static final int IMPORT_SCHEMA_TOKEN = 'T'; static final int MODULE_NAMESPACE_TOKEN = 'M'; static final int DECLARE_NAMESPACE_TOKEN = 'N'; static final int DECLARE_BOUNDARY_SPACE_TOKEN = 'S'; static final int DEFAULT_ELEMENT_TOKEN = 'E'; static final int DEFAULT_FUNCTION_TOKEN = 'O'; static final int DEFAULT_COLLATION_TOKEN = 'G'; 303 static final int DEFAULT_ORDER_TOKEN = 'H'; 305 static final int DECLARE_FUNCTION_TOKEN = 'P'; static final int DECLARE_VARIABLE_TOKEN = 'V'; static final int DECLARE_BASE_URI_TOKEN = 'B'; static final int DECLARE_ORDERING_TOKEN = 'U'; static final int DECLARE_CONSTRUCTION_TOKEN = 'K'; static final int DECLARE_OPTION_TOKEN = 'o'; static final int DECLARE_COPY_NAMESPACES_TOKEN = 'L'; static final int DEFINE_QNAME_TOKEN = 'W'; static final int XQUERY_VERSION_TOKEN = 'Y'; 315 321 322 static final int OP_AXIS_FIRST = 100; 323 static final int COUNT_OP_AXIS = 13; 324 static final int AXIS_ANCESTOR = 0; 325 static final int AXIS_ANCESTOR_OR_SELF = 1; 326 static final int AXIS_ATTRIBUTE = 2; 327 static final int AXIS_CHILD = 3; 328 static final int AXIS_DESCENDANT = 4; 329 static final int AXIS_DESCENDANT_OR_SELF = 5; 330 static final int AXIS_FOLLOWING = 6; 331 static final int AXIS_FOLLOWING_SIBLING = 7; 332 static final int AXIS_NAMESPACE = 8; 333 static final int AXIS_PARENT = 9; 334 static final int AXIS_PRECEDING = 10; 335 static final int AXIS_PRECEDING_SIBLING = 11; 336 static final int AXIS_SELF = 12; 337 static final int OP_WHERE = 196; 338 static final int PRAGMA_START_TOKEN = 197; static final int OP_BASE = 400; 341 static final int OP_OR = OP_BASE; static final int OP_AND = OP_BASE + 1; static final int OP_EQU = OP_BASE + 2; static final int OP_NEQ = OP_BASE + 3; static final int OP_LSS = OP_BASE + 4; static final int OP_GRT = OP_BASE + 5; static final int OP_LEQ = OP_BASE + 6; static final int OP_GEQ = OP_BASE + 7; static final int OP_IS = OP_BASE + 8; static final int OP_ISNOT = OP_BASE + 9; static final int OP_GRTGRT = OP_BASE + 10; static final int OP_LSSLSS = OP_BASE + 11; 354 static final int OP_RANGE_TO = OP_BASE + 12; 356 static final int OP_ADD = OP_BASE + 13; static final int OP_SUB = OP_BASE + 14; 359 static final int OP_MUL = OP_BASE + 15; static final int OP_DIV = OP_BASE + 16; static final int OP_IDIV = OP_BASE + 17; static final int OP_MOD = OP_BASE + 18; 364 static final int OP_UNION = OP_BASE + 19; 366 static final int OP_INTERSECT = OP_BASE + 20; static final int OP_EXCEPT = OP_BASE + 21; 369 static final int OP_INSTANCEOF = OP_BASE + 22; static final int OP_TREAT_AS = OP_BASE + 23; static final int OP_CASTABLE_AS= OP_BASE + 24; static final int OP_CAST_AS = OP_BASE + 25; 374 static final int OP_EQ = OP_BASE + 26; static final int OP_NE = OP_BASE + 27; static final int OP_LT = OP_BASE + 28; static final int OP_LE = OP_BASE + 29; static final int OP_GT = OP_BASE + 30; static final int OP_GE = OP_BASE + 31; 381 static final int OP_NODE = 230; static final int OP_TEXT = 231; static final int OP_COMMENT = 232; static final int OP_PI = 233; static final int OP_DOCUMENT = 234; static final int OP_ELEMENT = 235; static final int OP_ATTRIBUTE = 236; static final int OP_ITEM = 237; static final int OP_EMPTY_SEQUENCE = 238; static final int OP_SCHEMA_ATTRIBUTE = 239; static final int OP_SCHEMA_ELEMENT = 240; static final int IF_LPAREN_TOKEN = 241; static final int TYPESWITCH_LPAREN_TOKEN = 242; 395 static final int FOR_DOLLAR_TOKEN = 243; static final int LET_DOLLAR_TOKEN = 244; static final int SOME_DOLLAR_TOKEN = 245; static final int EVERY_DOLLAR_TOKEN = 246; static final int CASE_DOLLAR_TOKEN = 247; static final int VALIDATE_LBRACE_TOKEN = 248; static final int ORDERED_LBRACE_TOKEN = 249; static final int UNORDERED_LBRACE_TOKEN = 250; static final int ELEMENT_TOKEN = 251; static final int ATTRIBUTE_TOKEN = 252; static final int TEXT_TOKEN = 253; static final int COMMENT_TOKEN = 254; static final int PI_TOKEN = 255; static final int DOCUMENT_TOKEN = 256; 410 private int saveToken; 411 private Object saveValue; 412 413 public void mark () 414 throws java.io.IOException 415 { 416 super.mark(); 417 saveToken = curToken; 418 saveValue = curValue; 419 } 420 421 public void reset() 422 throws java.io.IOException 423 { 424 curToken = saveToken; 425 curValue = saveValue; 426 super.reset(); 427 } 428 429 private int setToken (int token, int width) 430 { 431 curToken = token; 432 curLine = port.getLineNumber() + 1; 433 curColumn = port.getColumnNumber() + 1 - width; 434 return token; 435 } 436 437 void checkSeparator (char ch) 438 { 439 if (XName.isNameStart(ch)) 440 error('e', "missing separator", "XPST0003"); 441 } 442 443 int getRawToken() 444 throws java.io.IOException , SyntaxException 445 { 446 int next; 447 for (;;) 448 { 449 next = read(); 450 if (next < 0) 451 return setToken(EOF_TOKEN, 0); 452 if (next == '\n' || next == '\r') 453 { 454 if (nesting <= 0) 455 return setToken(EOL_TOKEN, 0); 456 } 457 else if (next == '(') 458 { 459 if (checkNext(':')) 460 skipComment(); 461 else if (checkNext('#')) 462 return setToken(PRAGMA_START_TOKEN, 2); 463 else 464 return setToken('(', 1); 465 } 466 else if (next == '{') 467 { 468 if (! checkNext('-')) 469 return setToken('{', 1); 470 next = read(); 471 if (next != '-') 472 { 473 unread(); 475 unread(); 476 return setToken('{', 1); 477 } 478 skipOldComment(); 479 } 480 else if (next != ' ' && next != '\t') 481 break; 482 } 483 tokenBufferLength = 0; 484 curLine = port.getLineNumber() + 1; 485 curColumn = port.getColumnNumber(); 486 char ch = (char) next; 487 switch (ch) 488 { 489 case ')': case '[': case ']': case '}': 490 case '$': case '@': case ',': case '?': case ';': 491 break; 492 case ':': 493 if (checkNext('=')) 494 ch = COLON_EQUAL_TOKEN; 495 else if (checkNext(':')) 496 ch = COLON_COLON_TOKEN; 497 break; 498 case '|': 499 ch = OP_UNION; 500 break; 501 case '*': 502 ch = OP_MUL; 503 break; 504 case '+': 505 ch = OP_ADD; 506 break; 507 case '-': 508 ch = OP_SUB; 509 break; 510 case '!': 511 if (checkNext('=')) 512 ch = OP_NEQ; 513 break; 514 case '/': 515 if (checkNext('/')) 516 ch = SLASHSLASH_TOKEN; 517 break; 518 case '=': 519 if (checkNext('>')) 520 ch = ARROW_TOKEN; 521 ch = OP_EQU; 522 break; 523 case '>': 524 ch = checkNext('=') ? (char) OP_GEQ 525 : checkNext('>') ? (char) OP_GRTGRT : (char) OP_GRT; 526 break; 527 case '<': 528 ch = checkNext('=') ? (char) OP_LEQ 529 : checkNext('<') ? (char) OP_LSSLSS : (char) OP_LSS; 530 break; 531 case '\'': case '\"': 532 char saveReadState = pushNesting ((char) next); 533 for (;;) 534 { 535 next = read(); 536 if (next < 0) 537 eofError("unexpected end-of-file in string starting here"); 538 if (next == '&') 539 { 540 parseEntityOrCharRef(); 541 continue; 542 } 543 else if (ch == next) 544 { 545 next = read (); 546 if (ch != next) 547 { 548 unread(next); 549 break; 550 } 551 } 552 tokenBufferAppend((char) next); 553 } 554 popNesting(saveReadState); 555 ch = STRING_TOKEN; 556 break; 557 default: 558 if (Character.isDigit(ch) 559 || (ch == '.' && Character.isDigit((char) peek()))) 560 { 561 boolean seenDot = ch == '.'; 562 for (;; ) 563 { 564 tokenBufferAppend(ch); 565 next = read(); 566 if (next < 0) 567 break; 568 ch = (char) next; 569 if (ch == '.') 570 { 571 if (seenDot) break; 572 seenDot = true; 573 } 574 else if (! Character.isDigit(ch)) 575 break; 576 } 577 if (next == 'e' || next == 'E') 578 { 579 tokenBufferAppend((char) next); 580 next = read(); 581 if (next == '+' || next == '-') 582 { 583 tokenBufferAppend((char) next); 584 next = read(); 585 } 586 int expDigits = 0; 587 for (;;) 588 { 589 if (next < 0) 590 break; 591 ch = (char) next; 592 if (! Character.isDigit(ch)) 593 { 594 checkSeparator(ch); 595 unread(); 596 break; 597 } 598 tokenBufferAppend(ch); 599 next = read(); 600 expDigits++; 601 } 602 if (expDigits == 0) 603 error('e', "no digits following exponent", "XPST0003"); 604 ch = DOUBLE_TOKEN; 605 } 606 else 607 { 608 ch = seenDot ? DECIMAL_TOKEN : INTEGER_TOKEN; 609 if (next >= 0) 610 { 611 checkSeparator((char) next); 612 unread(next); 613 } 614 } 615 } 616 else if (ch == '.') 617 { 618 if (checkNext('.')) 619 ch = DOTDOT_TOKEN; 620 break; 621 } 622 else if (XName.isNameStart(ch)) 623 { 624 for (;;) 625 { 626 tokenBufferAppend(ch); 627 next = read(); 628 ch = (char) next; 629 if (! XName.isNamePart(ch)) 630 break; 631 } 632 if (next < 0) 633 ch = NCNAME_TOKEN; 634 else 635 { 636 if (next != ':') 637 ch = NCNAME_TOKEN; 638 else 639 { 640 next = read(); 641 if (next < 0) 642 eofError("unexpected end-of-file after NAME ':'"); 643 ch = (char) next; 644 if (XName.isNameStart(ch)) 645 { 646 tokenBufferAppend(':'); 647 for (;;) 648 { 649 tokenBufferAppend(ch); 650 next = read(); 651 ch = (char) next; 652 if (! XName.isNamePart(ch)) 653 break; 654 } 655 ch = QNAME_TOKEN; 656 } 657 else if (ch == '=') 658 { 659 unread(ch); 660 ch = NCNAME_TOKEN; 661 } 662 else 663 ch = NCNAME_COLON_TOKEN; 664 } 665 unread(next); 666 } 667 } 668 else if (ch >= ' ' && ch < 127) 669 syntaxError("invalid character '"+ch+'\''); 670 else 671 syntaxError("invalid character '\\u"+Integer.toHexString(ch)+'\''); 672 } 673 curToken = ch; 674 return ch; 675 } 676 677 681 public void getDelimited(String delimiter) 682 throws java.io.IOException , SyntaxException 683 { 684 tokenBufferLength = 0; 685 int dlen = delimiter.length(); 686 char last = delimiter.charAt(dlen-1); 687 for (;;) 688 { 689 int ch = read(); 690 if (ch < 0) 691 eofError("unexpected end-of-file looking for '"+delimiter+'\''); 692 int dstart, j; 693 if (ch == last 695 && (dstart = tokenBufferLength - (j = dlen - 1)) >= 0) 696 { 697 do 699 { 700 if (j == 0) 701 { 702 tokenBufferLength = dstart; 703 return; 704 } 705 j--; 706 } 707 while (tokenBuffer[dstart+j] == delimiter.charAt(j)); 708 } 709 tokenBufferAppend((char) ch); 710 } 711 } 712 713 public void appendNamedEntity(String name) 714 { 715 name = name.intern(); 716 char ch = '?'; 717 if (name == "lt") 718 ch = '<'; 719 else if (name == "gt") 720 ch = '>'; 721 else if (name == "amp") 722 ch = '&'; 723 else if (name == "quot") 724 ch = '"'; 725 else if (name == "apos") 726 ch = '\''; 727 else 728 error("unknown enity reference: '"+name+"'"); 729 tokenBufferAppend(ch); 730 } 731 732 boolean match (String word1, String word2, boolean force) 733 throws java.io.IOException , SyntaxException 734 { 735 if (match(word1)) 736 { 737 mark(); 738 getRawToken(); 739 if (match(word2)) 740 { 741 reset(); 742 getRawToken(); 743 return true; 744 } 745 reset(); 746 if (force) 747 { 748 error('e', "'"+word1+"' must be followed by '"+word2+"'", 749 "XPST0003"); 750 return true; 751 } 752 } 753 return false; 754 } 755 756 759 int peekOperator() 760 throws java.io.IOException , SyntaxException 761 { 762 while (curToken == EOL_TOKEN) 763 { 764 if (nesting == 0) 765 return EOL_TOKEN; 766 getRawToken(); 767 } 768 if (curToken == NCNAME_TOKEN) 769 { 770 int len = tokenBufferLength; 771 char c1, c2, c3; 772 switch (len) 773 { 774 case 2: 775 c1 = tokenBuffer[0]; 776 c2 = tokenBuffer[1]; 777 if (c1 == 'o' && c2 == 'r') 778 curToken = OP_OR; 779 else if (c1 == 't' && c2 == 'o') 780 curToken = OP_RANGE_TO; 781 else if (c1 == 'i' && c2 == 's') 782 curToken = OP_IS; 783 else if (c1 == 'e' && c2 == 'q') 784 curToken = OP_EQ; 785 else if (c1 == 'n' && c2 == 'e') 786 curToken = OP_NE; 787 else if (c1 == 'g') 788 { 789 if (c2 == 'e') curToken = OP_GE; 790 else if (c2 == 't') curToken = OP_GT; 791 } 792 else if (c1 == 'l') 793 { 794 if (c2 == 'e') curToken = OP_LE; 795 else if (c2 == 't') curToken = OP_LT; 796 } 797 break; 798 799 case 3: 800 c1 = tokenBuffer[0]; 801 c2 = tokenBuffer[1]; 802 c3 = tokenBuffer[2]; 803 if (c1 == 'a') 804 { 805 if (c2 == 'n' && c3 == 'd') 806 curToken = OP_AND; 807 } 808 else if (c1 == 'm') { 809 if (c2 == 'u' && c3 == 'l') 810 curToken = OP_MUL; 811 if (c2 == 'o' && c3 == 'd') 812 curToken = OP_MOD; 813 } 814 else if (c1 == 'd') { 815 if (c2 == 'i' && c3 == 'v') 816 curToken = OP_DIV; 817 } 818 break; 819 case 4: 820 if (match("idiv")) 821 curToken = OP_IDIV; 822 else if (match("cast", "as", true)) 823 curToken = OP_CAST_AS; 824 break; 825 case 5: 826 if (match("where")) 827 curToken = OP_WHERE; 828 else if (match("isnot")) 829 curToken = OP_ISNOT; 830 else if (match("union")) 831 curToken = OP_UNION; 832 else if (match("treat", "as", true)) 833 curToken = OP_TREAT_AS; 834 break; 835 case 6: 836 if (match("except")) 837 curToken = OP_EXCEPT; 838 break; 839 case 8: 840 if (match("instance", "of", true)) 841 curToken = OP_INSTANCEOF; 842 else if (match("castable", "as", true)) 843 curToken = OP_CASTABLE_AS; 844 break; 845 case 9: 846 if (match("intersect")) 847 curToken = OP_INTERSECT; 848 break; 849 case 10: 850 if (match("instanceof")) { 852 warnOldVersion("use 'instanceof of' (two words) instead of 'instanceof'"); 853 curToken = OP_INSTANCEOF; 854 } 855 break; 856 default: 857 break; 858 } 859 } 860 return curToken; 861 } 862 863 868 private boolean lookingAt (String word0, String word1) 869 throws java.io.IOException , SyntaxException 870 { 871 if (! word0.equals(curValue)) 872 return false; 873 int i = 0; 874 int len = word1.length(); 875 for (;; ) 876 { 877 int ch = read(); 878 if (i == len) 879 { 880 if (ch < 0) 881 return true; 882 if ( ! XName.isNamePart((char) ch)) 883 { 884 unread(); 885 return true; 886 } 887 i++; 888 break; 889 } 890 if (ch < 0 || ch != word1.charAt(i++)) 891 break; 892 } 893 port.skip(-i); 894 return false; 895 } 896 897 int getAxis () 898 { 899 String name = new String (tokenBuffer, 0, tokenBufferLength).intern(); 901 int i; 902 for (i = COUNT_OP_AXIS; --i >= 0; ) 903 if (axisNames[i] == name) 904 break; 905 if (i < 0) 906 { 907 error("unknown axis name '" + name + '\''); 908 i = AXIS_CHILD; 909 } 910 return (char) (OP_AXIS_FIRST + i); 911 } 912 913 915 916 int peekOperand() 917 throws java.io.IOException , SyntaxException 918 { 919 while (curToken == EOL_TOKEN) 920 getRawToken(); 921 if (curToken == NCNAME_TOKEN || curToken == QNAME_TOKEN) 922 { 923 int next = skipSpace(nesting != 0); 924 switch (tokenBuffer[0]) 925 { 926 case 'a': 927 if (match("attribute")) 928 { 929 if (next == '(') 930 return curToken = OP_ATTRIBUTE; 931 if (next == '{' || XName.isNameStart((char) next)) 932 { 933 unread(); 934 return curToken = ATTRIBUTE_TOKEN; 935 } 936 break; 937 } 938 break; 939 case 'c': 940 if (match("comment")) 941 { 942 if (next == '(') 943 return curToken = OP_COMMENT; 944 if (next == '{') 945 { 946 unread(); 947 return curToken = COMMENT_TOKEN; 948 } 949 } 950 break; 951 case 'd': 952 if (next == '{' && match("document")) 953 { 954 unread(); 955 return curToken = DOCUMENT_TOKEN; 956 } 957 if (next == '(' && match("document-node")) 958 return curToken = OP_DOCUMENT; 959 break; 960 case 'e': 961 if (match("element")) 962 { 963 if (next == '(') 964 return curToken = OP_ELEMENT; 965 if (next == '{' || XName.isNameStart((char) next)) 966 { 967 unread(); 968 return curToken = ELEMENT_TOKEN; 969 } 970 break; 971 } 972 if (match("empty-sequence")) 973 return curToken = OP_EMPTY_SEQUENCE; 974 if (next == '$' && match("every")) 975 return curToken = EVERY_DOLLAR_TOKEN; 976 break; 977 case 'f': 978 if (next == '$' && match("for")) 979 return curToken = FOR_DOLLAR_TOKEN; 980 break; 981 case 'i': 982 if (next == '(' && match("if")) 983 return curToken = IF_LPAREN_TOKEN; 984 if (next == '(' && match("item")) 985 return curToken = OP_ITEM; 986 break; 987 case 'l': 988 if (next == '$' && match("let")) 989 return curToken = LET_DOLLAR_TOKEN; 990 break; 991 case 'n': 992 if (next == '(' && match("node")) 993 return curToken = OP_NODE; 994 break; 995 case 'o': 996 if (next == '{' && match("ordered")) 997 return curToken = ORDERED_LBRACE_TOKEN; 998 break; 999 case 'p': 1000 if (match("processing-instruction")) 1001 { 1002 if (next == '(') 1003 return curToken = OP_PI; 1004 if (next == '{' || XName.isNameStart((char) next)) 1005 { 1006 unread(); 1007 return curToken = PI_TOKEN; 1008 } 1009 break; 1010 } 1011 break; 1012 case 's': 1013 if (next == '$' && match("some")) 1014 return curToken = SOME_DOLLAR_TOKEN; 1015 if (next == '(' && match("schema-attribute")) 1016 return curToken = OP_SCHEMA_ATTRIBUTE; 1017 if (next == '(' && match("schema-element")) 1018 return curToken = OP_SCHEMA_ELEMENT; 1019 break; 1020 case 't': 1021 if (match("text")) 1022 { 1023 if (next == '(') 1024 return curToken = OP_TEXT; 1025 if (next == '{') 1026 { 1027 unread(); 1028 return curToken = TEXT_TOKEN; 1029 } 1030 } 1031 if (next == '(' && match("typeswitch")) 1032 return curToken = TYPESWITCH_LPAREN_TOKEN; 1033 break; 1034 case 'u': 1035 if (next == '{' && match("unordered")) 1036 return curToken = UNORDERED_LBRACE_TOKEN; 1037 break; 1038 case 'v': 1039 if (next == '{' && match("validate")) 1040 return curToken = VALIDATE_LBRACE_TOKEN; 1041 break; 1042 } 1043 if (next == '(' && peek() != ':') 1044 { 1045 return curToken = FNAME_TOKEN; 1046 } 1047 if (next == ':' && peek() == ':') 1048 return curToken = getAxis(); 1049 String name = new String (tokenBuffer, 0, tokenBufferLength); 1050 curValue = name; 1051 switch (next) 1052 { 1053 case 'b': 1054 if (lookingAt("declare", "ase-uri")) 1055 return curToken = DECLARE_BASE_URI_TOKEN; 1056 if (lookingAt("declare", "oundary-space")) 1057 return curToken = DECLARE_BOUNDARY_SPACE_TOKEN; 1058 break; 1059 case 'c': 1060 if (lookingAt("declare", "onstruction")) 1061 return curToken = DECLARE_CONSTRUCTION_TOKEN; 1062 if (lookingAt("declare", "opy-namespaces")) 1063 return curToken = DECLARE_COPY_NAMESPACES_TOKEN; 1064 break; 1065 case 'd': 1066 if (lookingAt("declare", "efault")) 1067 { 1068 getRawToken(); 1069 if (match("function")) 1070 return curToken = DEFAULT_FUNCTION_TOKEN; 1071 if (match("element")) 1072 return curToken = DEFAULT_ELEMENT_TOKEN; 1073 if (match("collation")) 1074 return curToken = DEFAULT_COLLATION_TOKEN; 1075 if (match("order")) 1076 return curToken = DEFAULT_ORDER_TOKEN; 1077 error("unrecognized/unimplemented 'declare default'"); 1078 skipToSemicolon(); 1079 return peekOperand(); 1080 } 1081 case 'e': 1082 if (lookingAt("default", "lement")) 1083 { 1084 warnOldVersion("replace 'default element' by 'declare default element namespace'"); 1085 return curToken = DEFAULT_ELEMENT_TOKEN; 1086 } 1087 break; 1088 case 'f': 1089 if (lookingAt("declare", "unction")) 1090 return curToken = DECLARE_FUNCTION_TOKEN; 1091 if (lookingAt("define", "unction")) 1092 { 1093 warnOldVersion("replace 'define function' by 'declare function'"); 1094 return curToken = DECLARE_FUNCTION_TOKEN; 1095 } 1096 if (lookingAt("default", "unction")) 1097 { 1098 warnOldVersion("replace 'default function' by 'declare default function namespace'"); 1099 return curToken = DEFAULT_FUNCTION_TOKEN; 1100 } 1101 break; 1102 case 'm': 1103 if (lookingAt("import", "odule")) 1104 return curToken = IMPORT_MODULE_TOKEN; 1105 break; 1106 case 'n': 1107 if (lookingAt("declare", "amespace")) 1108 return curToken = DECLARE_NAMESPACE_TOKEN; 1109 if (lookingAt("default", "amespace")) 1110 { 1111 warnOldVersion("replace 'default namespace' by 'declare default element namespace'"); 1112 return curToken = DEFAULT_ELEMENT_TOKEN; 1113 } 1114 if (lookingAt("module", "amespace")) 1115 return curToken = MODULE_NAMESPACE_TOKEN; 1116 break; 1117 case 'o': 1118 if (lookingAt("declare", "rdering")) 1119 return curToken = DECLARE_ORDERING_TOKEN; 1120 if (lookingAt("declare", "ption")) 1121 return curToken = DECLARE_OPTION_TOKEN; 1122 break; 1123 case 's': 1124 if (lookingAt("import", "chema")) 1125 return curToken = IMPORT_SCHEMA_TOKEN; 1126 break; 1127 case 'v': 1128 if (lookingAt("declare", "ariable")) 1129 return curToken = DECLARE_VARIABLE_TOKEN; 1130 if (lookingAt("define", "ariable")) 1131 { 1132 warnOldVersion("replace 'define variable' by 'declare variable'"); 1133 return curToken = DECLARE_VARIABLE_TOKEN; 1134 } 1135 if (lookingAt("xquery", "ersion")) 1136 return curToken = XQUERY_VERSION_TOKEN; 1137 break; 1138 case 'x': 1139 if (lookingAt("declare", "mlspace")) 1140 { 1141 warnOldVersion("replace 'define xmlspace' by 'declare boundary-space'"); 1142 return curToken = DECLARE_BOUNDARY_SPACE_TOKEN; 1143 } 1144 break; 1145 } 1146 if (next >= 0) 1147 { 1148 unread(); 1149 if (XName.isNameStart((char) next) && curValue.equals("define")) 1150 { 1151 getRawToken(); 1152 curToken = DEFINE_QNAME_TOKEN; 1153 } 1154 } 1155 return curToken; 1156 } 1157 if (curToken == NCNAME_COLON_TOKEN) 1158 { 1159 int next = read(); 1160 if (next == ':') curToken = getAxis(); 1162 else 1163 unread(next); 1164 } 1165 return curToken; 1166 } 1167 1168 void checkAllowedNamespaceDeclaration (String prefix, String uri) 1169 { 1170 if ("xml".equals(prefix) || "xmlns".equals(prefix)) 1171 error('e', "namespace prefix cannot be 'xml' or 'xmlns'", 1172 "XQST0070"); 1173 else if (NamespaceBinding.XML_NAMESPACE.equals(uri)) 1174 error('e', "namespace uri cannot be the same as the prefined xml namespace", 1175 "XQST0070"); 1176 } 1177 1178 void pushNamespace(String prefix, String uri) 1179 { 1180 if (uri.length() == 0) 1181 uri = null; 1182 prologNamespaces = new NamespaceBinding(prefix, uri, prologNamespaces); 1183 } 1184 1185 public XQParser(InPort port, SourceMessages messages, XQuery interp) 1186 { 1187 super(port, messages); 1188 interpreter = interp; 1189 lexical = new NameLookup(interp); 1190 nesting = 1; 1191 1192 NamespaceBinding ns = builtinNamespaces; 1194 prologNamespaces = ns; 1195 } 1196 1197 public void setInteractive(boolean v) 1198 { 1199 if (interactive != v) 1200 if (v) nesting--; else nesting++; 1201 interactive = v; 1202 } 1203 1204 private static final int priority(int opcode) 1205 { 1206 switch (opcode) 1207 { 1208 case OP_OR: 1209 return 1; 1210 case OP_AND: 1211 return 2; 1212 case OP_EQU: case OP_NEQ: 1213 case OP_LSS: case OP_GRT: case OP_LEQ: case OP_GEQ: 1214 case OP_EQ: case OP_NE: 1215 case OP_LT: case OP_GT: case OP_LE: case OP_GE: 1216 case OP_IS: case OP_ISNOT: 1217 case OP_GRTGRT: case OP_LSSLSS: 1218 return 3; 1219 case OP_RANGE_TO: 1220 return 4; 1221 case OP_ADD: case OP_SUB: 1222 return 5; 1223 case OP_MUL: case OP_DIV: case OP_IDIV: case OP_MOD: 1224 return 6; 1225 case OP_UNION: 1226 return 7; 1227 case OP_INTERSECT: case OP_EXCEPT: 1228 return 8; 1229 case OP_INSTANCEOF: 1230 return 9; 1231 case OP_TREAT_AS: 1232 return 10; 1233 case OP_CASTABLE_AS: 1234 return 11; 1235 case OP_CAST_AS: 1236 return 12; 1237 default: 1238 return 0; 1239 } 1240 } 1241 1242 static Expression makeBinary(Expression func, 1243 Expression exp1, Expression exp2) 1244 { 1245 Expression[] args = new Expression[2]; 1246 args[0] = exp1; 1247 args[1] = exp2; 1248 return new ApplyExp(func, args); 1249 } 1250 1251 static Expression makeExprSequence(Expression exp1, Expression exp2) 1252 { 1253 return makeBinary(makeFunctionExp 1254 ("gnu.kawa.functions.AppendValues", "appendValues"), 1255 exp1, exp2); 1256 } 1257 1258 Expression makeBinary(int op, Expression exp1, Expression exp2) 1259 throws java.io.IOException , SyntaxException 1260 { 1261 Expression func; 1262 switch (op) 1263 { 1264 case OP_ADD: 1265 func = makeFunctionExp("gnu.xquery.util.ArithOp", "add", "+"); 1266 break; 1267 case OP_SUB: 1268 func = makeFunctionExp("gnu.xquery.util.ArithOp", "sub", "-"); 1269 break; 1270 case OP_MUL: 1271 func = makeFunctionExp("gnu.xquery.util.ArithOp", "mul", "*"); 1272 break; 1273 case OP_DIV: 1274 func = makeFunctionExp("gnu.xquery.util.ArithOp", "div", "div"); 1275 break; 1276 case OP_IDIV: 1277 func = makeFunctionExp("gnu.xquery.util.ArithOp", "idiv", "idiv"); 1278 break; 1279 case OP_MOD: 1280 func = makeFunctionExp("gnu.xquery.util.ArithOp", "mod", "mod"); 1281 break; 1282 case OP_EQ: 1283 func = makeFunctionExp("gnu.xquery.util.Compare", "valEq", "eq"); 1284 break; 1285 case OP_NE: 1286 func = makeFunctionExp("gnu.xquery.util.Compare", "valNe", "ne"); 1287 break; 1288 case OP_LT: 1289 func = makeFunctionExp("gnu.xquery.util.Compare", "valLt", "lt"); 1290 break; 1291 case OP_LE: 1292 func = makeFunctionExp("gnu.xquery.util.Compare", "valLe", "le"); 1293 break; 1294 case OP_GT: 1295 func = makeFunctionExp("gnu.xquery.util.Compare", "valGt", "gt"); 1296 break; 1297 case OP_GE: 1298 func = makeFunctionExp("gnu.xquery.util.Compare", "valGe", "ge"); 1299 break; 1300 case OP_EQU: 1301 func = makeFunctionExp("gnu.xquery.util.Compare", "="); 1302 break; 1303 case OP_NEQ: 1304 func = makeFunctionExp("gnu.xquery.util.Compare", "!="); 1305 break; 1306 case OP_LSS: 1307 func = makeFunctionExp("gnu.xquery.util.Compare", "<"); 1308 break; 1309 case OP_LEQ: 1310 func = makeFunctionExp("gnu.xquery.util.Compare", "<="); 1311 break; 1312 case OP_GRT: 1313 func = makeFunctionExp("gnu.xquery.util.Compare", ">"); 1314 break; 1315 case OP_GEQ: 1316 func = makeFunctionExp("gnu.xquery.util.Compare", ">="); 1317 break; 1318 case OP_IS: 1319 func = makeFunctionExp("gnu.kawa.xml.NodeCompare", "$Eq", "is"); 1320 break; 1321 case OP_ISNOT: 1322 func = makeFunctionExp("gnu.kawa.xml.NodeCompare", "$Ne", "isnot"); 1323 break; 1324 case OP_GRTGRT: 1325 func = makeFunctionExp("gnu.kawa.xml.NodeCompare", "$Gr", ">>"); 1326 break; 1327 case OP_LSSLSS: 1328 func = makeFunctionExp("gnu.kawa.xml.NodeCompare", "$Ls", "<<"); 1329 break; 1330 case OP_RANGE_TO: 1331 func = makeFunctionExp("gnu.xquery.util.IntegerRange", "integerRange"); 1332 break; 1333 case OP_UNION: 1334 func = makeFunctionExp("gnu.kawa.xml.UnionNodes", "unionNodes"); 1335 break; 1336 case OP_INTERSECT: 1337 func = makeFunctionExp("gnu.kawa.xml.IntersectNodes", 1338 "intersectNodes"); 1339 break; 1340 case OP_EXCEPT: 1341 func = makeFunctionExp("gnu.kawa.xml.IntersectNodes", "exceptNodes"); 1342 break; 1343 default: 1344 return syntaxError("unimplemented binary op: "+op); 1345 } 1346 return makeBinary(func, exp1, exp2); 1347 } 1348 1349 private void parseSimpleKindType () 1350 throws java.io.IOException , SyntaxException 1351 { 1352 getRawToken(); 1353 if (curToken == ')') 1354 getRawToken(); 1355 else 1356 error("expected ')'"); 1357 } 1358 1359 public Expression parseNamedNodeType (boolean attribute) 1360 throws java.io.IOException , SyntaxException 1361 { 1362 Expression qname; 1363 getRawToken(); 1364 if (curToken == ')') 1365 { 1366 qname = QuoteExp.getInstance(ElementType.MATCH_ANY_QNAME); 1367 getRawToken(); 1368 } 1369 else 1370 { 1371 if (curToken == QNAME_TOKEN || curToken == NCNAME_TOKEN) 1372 qname = parseNameTest(attribute); 1373 else 1374 { 1375 if (curToken != OP_MUL) 1376 syntaxError("expected QName or *"); 1377 qname = QuoteExp.getInstance(ElementType.MATCH_ANY_QNAME); 1378 } 1379 1380 getRawToken(); 1381 if (curToken == ',') 1382 { 1383 getRawToken(); 1384 if (curToken == QNAME_TOKEN || curToken == NCNAME_TOKEN) 1385 { 1386 Expression tname = parseNameTest(true); 1387 } 1388 else 1389 syntaxError("expected QName"); 1390 getRawToken(); 1391 } 1392 if (curToken == ')') 1393 getRawToken(); 1394 else 1395 error("expected ')' after element"); 1396 } 1397 return makeNamedNodeType(attribute, qname); 1398 } 1399 1400 static Expression makeNamedNodeType (boolean attribute, Expression qname) 1401 { 1402 Expression[] name = new Expression[2]; 1403 ClassType nodeType = ClassType.make(attribute 1404 ? "gnu.kawa.xml.AttributeType" 1405 : "gnu.kawa.xml.ElementType"); 1406 ApplyExp elt = new ApplyExp(nodeType.getDeclaredMethod("make", 1), 1407 new Expression[] { qname }); 1408 elt.setFlag(ApplyExp.INLINE_IF_CONSTANT); 1409 return elt; 1410 } 1411 1412 private boolean warnedOldStyleKindTest; 1413 private void warnOldStyleKindTest() 1414 { 1415 if (warnedOldStyleKindTest) 1416 return; 1417 error('w', "old-style KindTest - first one here"); 1418 warnedOldStyleKindTest = true; 1419 } 1420 1421 1422 public Expression parseOptionalTypeDeclaration () 1423 throws java.io.IOException , SyntaxException 1424 { 1425 if (! match("as")) 1426 return null; 1427 getRawToken(); 1428 return parseDataType(); 1429 } 1430 1431 public Expression parseDataType() 1432 throws java.io.IOException , SyntaxException 1433 { 1434 Expression etype = parseItemType(); 1435 int min, max; 1436 if (etype == null) 1437 { 1438 if (curToken != OP_EMPTY_SEQUENCE) 1439 return syntaxError("bad syntax - expected DataType"); 1440 parseSimpleKindType(); 1441 if (curToken == '?' || curToken == OP_ADD || curToken == OP_MUL) 1442 { 1443 getRawToken(); 1444 return syntaxError("occurrence-indicator meaningless after empty-sequence()"); 1445 } 1446 etype = QuoteExp.getInstance(OccurrenceType.emptySequenceType); 1447 min = 0; 1448 max = 0; 1449 } 1450 else if (curToken == '?') 1451 { 1452 min = 0; 1453 max = 1; 1454 } 1455 else if (curToken == OP_ADD) 1456 { 1457 min = 1; 1458 max = -1; 1459 } 1460 else if (curToken == OP_MUL) 1461 { 1462 min = 0; 1463 max = -1; 1464 } 1465 else 1466 { 1467 min = 1; 1468 max = 1; 1469 } 1470 if (parseContext == 'C') 1471 { 1472 if (max != 1) 1473 return syntaxError("type to 'cast as' or 'castable as' must be a 'SingleType'"); 1474 } 1475 if (min != max) 1476 { 1477 getRawToken(); 1478 Expression[] args = { etype, 1479 QuoteExp.getInstance(gnu.math.IntNum.make(min)), 1480 QuoteExp.getInstance(gnu.math.IntNum.make(max)) }; 1481 ApplyExp otype 1482 = new ApplyExp(ClassType.make("gnu.kawa.reflect.OccurrenceType") 1483 .getDeclaredMethod("getInstance", 3), 1484 args); 1485 otype.setFlag(ApplyExp.INLINE_IF_CONSTANT); 1486 return otype; 1487 } 1488 return etype; 1489 } 1490 1491 public Expression parseMaybeKindTest () 1492 throws java.io.IOException , SyntaxException 1493 { 1494 Type type; 1495 switch (curToken) 1496 { 1497 case OP_ATTRIBUTE: 1498 case OP_ELEMENT: 1499 return parseNamedNodeType(curToken == OP_ATTRIBUTE); 1500 1501 case OP_TEXT: 1502 parseSimpleKindType(); 1503 type = NodeType.textNodeTest; 1504 break; 1505 1506 case OP_COMMENT: 1507 parseSimpleKindType(); 1508 type = NodeType.commentNodeTest; 1509 break; 1510 1511 case OP_DOCUMENT: 1512 parseSimpleKindType(); 1513 type = NodeType.documentNodeTest; 1514 break; 1515 1516 case OP_NODE: 1517 parseSimpleKindType(); 1518 type = NodeType.anyNodeTest; 1519 break; 1520 1521 case OP_PI: 1522 getRawToken(); 1523 String piTarget = null; 1524 if (curToken == NCNAME_TOKEN || curToken == STRING_TOKEN) 1525 { 1526 piTarget = new String (tokenBuffer, 0, tokenBufferLength); 1527 getRawToken(); 1528 } 1529 if (curToken == ')') 1530 getRawToken(); 1531 else 1532 error("expected ')'"); 1533 type = ProcessingInstructionType.getInstance(piTarget); 1534 break; 1535 1536 default: 1537 return null; 1538 } 1539 return QuoteExp.getInstance(type); 1540 } 1541 1542 public Expression parseItemType() 1543 throws java.io.IOException , SyntaxException 1544 { 1545 peekOperand(); 1546 Expression etype = parseMaybeKindTest(); 1547 Type type; 1548 if (etype != null) 1549 { 1550 if (parseContext == 'C') 1551 type = Type.pointer_type; 1553 else 1554 return etype; 1555 } 1556 else if (curToken == OP_ITEM) 1557 { 1558 parseSimpleKindType(); 1559 type = Type.pointer_type; 1560 } 1561 else if (curToken == NCNAME_TOKEN || curToken == QNAME_TOKEN) 1562 { 1563 String tname = new String (tokenBuffer, 0, tokenBufferLength); 1564 getRawToken(); 1565 type = interpreter.getTypeFor(tname); 1566 if (type == null) 1567 { 1568 error('e', "unknown type "+tname, "XPST0051"); 1569 type = Type.pointer_type; 1570 } 1571 } 1572 else 1573 return null; 1574 if (parseContext == 'C') 1575 { 1576 if (type == Type.pointer_type) 1577 return syntaxError("type to 'cast as' or 'castable as' must be atomic", "XPST0080"); 1578 if (type == XDataType.NotationType) 1579 return syntaxError("type to 'cast as' or 'castable as' cannot be NOTATION", "XPST0080"); 1580 } 1581 return QuoteExp.getInstance(type); 1582 } 1583 1584 1588 Object parseURILiteral () 1589 throws java.io.IOException , SyntaxException 1590 { 1591 getRawToken(); 1592 if (curToken != STRING_TOKEN) 1593 return declError("expected a URILiteral"); 1594 String str = new String (tokenBuffer, 0, tokenBufferLength); 1595 str = TextUtils.replaceWhitespace(str, true); 1596 return str; 1601 } 1602 1603 Expression parseExpr() 1604 throws java.io.IOException , SyntaxException 1605 { 1606 return parseExprSingle(); 1607 } 1608 1609 final Expression parseExprSingle () 1610 throws java.io.IOException , SyntaxException 1611 { 1612 int startLine = curLine; 1613 int startColumn = curColumn; 1614 peekOperand(); 1615 switch (curToken) 1616 { 1617 1622 case IF_LPAREN_TOKEN: 1623 return parseIfExpr(); 1624 case TYPESWITCH_LPAREN_TOKEN: 1625 return parseTypeSwitch(); 1626 case FOR_DOLLAR_TOKEN: 1627 return parseFLWRExpression(true); 1628 case LET_DOLLAR_TOKEN: 1629 return parseFLWRExpression(false); 1630 case SOME_DOLLAR_TOKEN: 1631 return parseQuantifiedExpr(false); 1632 case EVERY_DOLLAR_TOKEN: 1633 return parseQuantifiedExpr(true); 1634 default: 1635 return parseBinaryExpr(priority(OP_OR)); 1636 } 1637 } 1638 1639 Expression parseBinaryExpr(int prio) 1640 throws java.io.IOException , SyntaxException 1641 { 1642 Expression exp = parseUnaryExpr(); 1643 for (;;) 1644 { 1645 int token = peekOperator(); 1646 if (token == EOL_TOKEN 1647 || (token == OP_LSS && peek() == '/')) 1649 return exp; 1650 int tokPriority = priority(token); 1651 if (tokPriority < prio) 1652 return exp; 1653 char saveReadState = pushNesting('%'); 1654 getRawToken(); 1655 popNesting(saveReadState); 1656 if (token >= OP_INSTANCEOF && token <= OP_CAST_AS) 1657 { 1658 if (token == OP_CAST_AS || token == OP_CASTABLE_AS) 1659 parseContext = 'C'; 1660 Expression type = parseDataType(); 1661 parseContext = '\0'; 1662 Expression[] args = new Expression[2]; 1663 Expression func; 1664 switch (token) 1665 { 1666 case OP_INSTANCEOF: 1667 args[0] = exp; 1668 args[1] = type; 1669 func = makeFunctionExp("gnu.xquery.lang.XQParser", 1670 "instanceOf"); 1671 break; 1672 case OP_CASTABLE_AS: 1673 args[0] = exp; 1674 args[1] = type; 1675 func = new ReferenceExp(XQResolveNames.castableAsDecl); 1676 break; 1677 case OP_TREAT_AS: 1678 args[0] = type; 1679 args[1] = exp; 1680 func = makeFunctionExp("gnu.xquery.lang.XQParser", 1681 "treatAs"); 1682 break; 1683 default: args[0] = type; 1685 args[1] = exp; 1686 func = new ReferenceExp(XQResolveNames.castAsDecl); 1687 break; 1688 } 1689 exp = new ApplyExp(func, args); 1690 } 1691 else if (token == OP_INSTANCEOF) 1692 { 1693 Expression[] args = { exp, parseDataType() }; 1694 exp = new ApplyExp(makeFunctionExp("gnu.xquery.lang.XQParser", 1695 "instanceOf"), 1696 args); 1697 } 1698 else 1699 { 1700 Expression exp2 = parseBinaryExpr(tokPriority+1); 1701 if (token == OP_AND) 1702 exp = new IfExp(booleanValue(exp), booleanValue(exp2), XQuery.falseExp); 1703 else if (token == OP_OR) 1704 exp = new IfExp(booleanValue(exp), XQuery.trueExp, booleanValue(exp2)); 1705 else 1706 exp = makeBinary(token, exp, exp2); 1707 } 1708 } 1709 } 1710 1711 Expression parseUnaryExpr() 1712 throws java.io.IOException , SyntaxException 1713 { 1714 Expression exp; 1715 if (curToken == OP_SUB || curToken == OP_ADD) 1716 { 1717 int op = curToken; 1718 getRawToken(); 1719 exp = parseUnaryExpr(); 1720 Expression func 1721 = makeFunctionExp("gnu.xquery.util.ArithOp", 1722 op == OP_ADD ? "plus" : "minus", 1723 op == OP_ADD ? "+" : "-"); 1724 exp = new ApplyExp(func, new Expression[] { exp }); 1725 } 1726 else 1727 exp = parseUnionExpr(); 1728 return exp; 1729 } 1730 1731 Expression parseUnionExpr() 1732 throws java.io.IOException , SyntaxException 1733 { 1734 Expression exp = parseIntersectExceptExpr(); 1735 for (;;) 1736 { 1737 int op = peekOperator(); 1738 if (op != OP_UNION) 1739 break; 1740 getRawToken(); 1741 Expression exp2 = parseIntersectExceptExpr(); 1742 exp = makeBinary(op, exp, exp2); 1743 } 1744 return exp; 1745 } 1746 1747 Expression parseIntersectExceptExpr() 1748 throws java.io.IOException , SyntaxException 1749 { 1750 Expression exp = parsePathExpr(); 1751 for (;;) 1752 { 1753 int op = peekOperator(); 1754 if (op != OP_INTERSECT && op != OP_EXCEPT) 1755 break; 1756 getRawToken(); 1757 Expression exp2 = parsePathExpr(); 1758 exp = makeBinary(op, exp, exp2); 1759 } 1760 return exp; 1761 } 1762 1763 Expression parsePathExpr() 1764 throws java.io.IOException , SyntaxException 1765 { 1766 Expression step1; 1767 if (curToken == '/' || curToken == SLASHSLASH_TOKEN) 1768 { 1769 Declaration dotDecl = lexical.lookup(DOT_VARNAME, false); 1770 Expression dot; 1771 if (dotDecl == null) 1772 dot = syntaxError("context item is undefined", "XPDY0002"); 1773 else 1774 dot = new ReferenceExp(DOT_VARNAME, dotDecl); 1775 step1 = new ApplyExp(ClassType.make("gnu.xquery.util.NodeUtils") 1776 .getDeclaredMethod("root", 1), 1777 new Expression[] { dot } ); 1778 int next = skipSpace(nesting != 0); 1779 unread(next); 1780 if (next < 0 || next == ')' || next == '}') 1781 { 1782 getRawToken(); 1783 return step1; 1784 } 1785 } 1786 else 1787 step1 = parseStepExpr(); 1788 return parseRelativePathExpr(step1); 1789 } 1790 1791 1794 Expression parseNameTest (boolean attribute) 1795 throws java.io.IOException , SyntaxException 1796 { 1797 String local = null, prefix = null; 1798 if (curToken == QNAME_TOKEN) 1799 { 1800 int colon = tokenBufferLength; 1801 while (tokenBuffer[--colon] != ':') ; 1802 prefix = new String (tokenBuffer, 0, colon); 1803 colon++; 1804 local = new String (tokenBuffer, colon, 1805 tokenBufferLength - colon); 1806 } 1807 else if (curToken == OP_MUL) 1808 { 1809 int next = read(); 1810 local = ElementType.MATCH_ANY_LOCALNAME; 1811 if (next != ':') 1812 unread(next); 1813 else 1814 { 1815 next = read(); 1816 if (next < 0) 1817 eofError("unexpected end-of-file after '*:'"); 1818 if (XName.isNameStart((char) next)) 1819 { 1820 unread(); 1821 getRawToken(); 1822 if (curToken != NCNAME_TOKEN) 1823 syntaxError("invalid name test"); 1824 else 1825 local = new String (tokenBuffer, 0, tokenBufferLength) 1826 .intern(); 1827 } 1828 else if (next != '*') 1829 syntaxError("missing local-name after '*:'"); 1830 } 1831 return QuoteExp.getInstance(new Symbol(null, local)); 1832 } 1833 else if (curToken == NCNAME_TOKEN) 1834 { 1835 local = new String (tokenBuffer, 0, tokenBufferLength); 1836 if (attribute) 1837 return new QuoteExp(Namespace.EmptyNamespace.getSymbol(local.intern())); 1838 prefix = null; 1839 } 1840 else if (curToken == NCNAME_COLON_TOKEN) 1841 { 1842 prefix = new String (tokenBuffer, 0, tokenBufferLength); 1843 int next = read(); 1844 if (next != '*') 1845 syntaxError("invalid characters after 'NCName:'"); 1846 local = ElementType.MATCH_ANY_LOCALNAME; 1847 } 1848 if (prefix != null) 1849 prefix = prefix.intern(); 1850 Expression[] args = new Expression[3]; 1851 args[0] = new ApplyExp(new ReferenceExp(XQResolveNames.resolvePrefixDecl), 1852 new Expression[] { QuoteExp.getInstance(prefix) }); 1853 args[1] = new QuoteExp(local == null ? "" : local); 1854 args[2] = new QuoteExp(prefix); 1855 ApplyExp make = new ApplyExp(Compilation.typeSymbol 1856 .getDeclaredMethod("make", 3), 1857 args); 1858 make.setFlag(ApplyExp.INLINE_IF_CONSTANT); 1859 return make; 1860 } 1861 1862 Expression parseNodeTest(int axis) 1863 throws java.io.IOException , SyntaxException 1864 { 1865 int token = peekOperand(); 1866 Expression[] args = new Expression[1]; 1867 1868 Expression etype = parseMaybeKindTest(); 1869 1870 if (etype != null) 1871 { 1872 args[0] = etype; 1873 } 1874 else if (curToken == NCNAME_TOKEN || curToken == QNAME_TOKEN 1875 || curToken == NCNAME_COLON_TOKEN || curToken == OP_MUL) 1876 { 1877 args[0] = makeNamedNodeType(axis == AXIS_ATTRIBUTE, 1878 parseNameTest(axis == AXIS_ATTRIBUTE) ); 1879 } 1880 else if (axis >= 0) 1881 return syntaxError("unsupported axis '"+axisNames[axis]+"::'"); 1882 else 1883 return null; 1884 1885 Declaration dotDecl = lexical.lookup(DOT_VARNAME, false); 1886 Expression dot; 1887 if (dotDecl == null) 1888 dot = syntaxError("node test when context item is undefined", "XPDY0002"); 1889 else 1890 dot = new ReferenceExp(DOT_VARNAME, dotDecl); 1891 if (etype == null) 1892 getRawToken(); 1893 1894 Expression makeAxisStep; 1895 if (axis == AXIS_CHILD || axis == -1) 1896 makeAxisStep = makeChildAxisStep; 1897 else if (axis == AXIS_DESCENDANT) 1898 makeAxisStep = makeDescendantAxisStep; 1899 else 1900 { 1901 String axisName; 1902 switch (axis) 1903 { 1904 case AXIS_DESCENDANT_OR_SELF: axisName = "DescendantOrSelf"; break; 1905 case AXIS_SELF: axisName = "Self"; break; 1906 case AXIS_PARENT: axisName = "Parent"; break; 1907 case AXIS_ANCESTOR: axisName = "Ancestor"; break; 1908 case AXIS_ANCESTOR_OR_SELF: axisName = "AncestorOrSelf"; break; 1909 case AXIS_FOLLOWING: axisName = "Following"; break; 1910 case AXIS_FOLLOWING_SIBLING: axisName = "FollowingSibling"; break; 1911 case AXIS_PRECEDING: axisName = "Preceding"; break; 1912 case AXIS_PRECEDING_SIBLING: axisName = "PrecedingSibling"; break; 1913 case AXIS_ATTRIBUTE: axisName = "Attribute"; break; 1914 default: throw new Error (); 1915 } 1916 makeAxisStep 1917 = QuoteExp.getInstance(new PrimProcedure 1918 ("gnu.kawa.xml."+axisName+"Axis", 1919 "make", 1)); 1920 } 1921 ApplyExp mkAxis = new ApplyExp(makeAxisStep, args); 1922 mkAxis.setFlag(ApplyExp.INLINE_IF_CONSTANT); 1923 return new ApplyExp(mkAxis, new Expression[] { dot }); 1924 } 1925 1926 public static QuoteExp makeChildAxisStep 1927 = QuoteExp.getInstance(new PrimProcedure("gnu.kawa.xml.ChildAxis", "make", 1)); 1928 public static QuoteExp makeDescendantAxisStep 1929 = QuoteExp.getInstance(new PrimProcedure("gnu.kawa.xml.DescendantAxis", "make", 1)); 1930 1931 Expression parseRelativePathExpr(Expression exp) 1932 throws java.io.IOException , SyntaxException 1933 { 1934 Expression beforeSlashSlash = null; 1936 1937 while (curToken == '/' || curToken == SLASHSLASH_TOKEN) 1938 { 1939 boolean descendants = curToken == SLASHSLASH_TOKEN; 1940 1941 LambdaExp lexp = new LambdaExp(3); 1942 Declaration dotDecl = lexp.addDeclaration(DOT_VARNAME); 1943 dotDecl.setFlag(Declaration.IS_SINGLE_VALUE); 1944 dotDecl.setType(SingletonType.getInstance()); 1945 dotDecl.noteValue (null); lexp.addDeclaration(POSITION_VARNAME, LangPrimType.intType); 1947 lexp.addDeclaration(LAST_VARNAME, LangPrimType.intType); 1948 comp.push(lexp); 1949 if (descendants) 1950 { 1951 curToken = '/'; 1952 Expression dot = new ReferenceExp(DOT_VARNAME, dotDecl); 1953 Expression[] args = { dot }; 1954 TreeScanner op = DescendantOrSelfAxis.anyNode; 1955 lexp.body = new ApplyExp(op, args); 1956 beforeSlashSlash = exp; 1957 } 1958 else 1959 { 1960 getRawToken(); 1961 Expression exp2 = parseStepExpr(); 1962 1963 Expression func; 1965 ApplyExp aexp; 1966 if (beforeSlashSlash != null 1967 && exp2 instanceof ApplyExp 1968 && (func = ((ApplyExp) exp2).getFunction()) instanceof ApplyExp 1969 && (aexp = (ApplyExp) func).getFunction() == makeChildAxisStep) 1970 { 1971 aexp.setFunction(makeDescendantAxisStep); 1972 exp = beforeSlashSlash; 1973 } 1974 1975 lexp.body = exp2; 1976 beforeSlashSlash = null; 1977 } 1978 comp.pop(lexp); 1979 1980 2013 2014 Expression[] args = new Expression[] { exp, lexp }; 2015 exp = new ApplyExp(RelativeStep.relativeStep, args); 2016 } 2017 return exp; 2018 } 2019 2020 Expression parseStepExpr() 2021 throws java.io.IOException , SyntaxException 2022 { 2023 int axis; 2024 if (curToken == '.' || curToken == DOTDOT_TOKEN) 2025 { 2026 axis = curToken == '.' ? AXIS_SELF : AXIS_PARENT; 2027 getRawToken(); 2028 Declaration dotDecl = lexical.lookup(DOT_VARNAME, false); 2029 Expression exp; 2030 if (dotDecl == null) 2031 exp = syntaxError("context item is undefined", "XPDY0002"); 2032 else 2033 exp = new ReferenceExp(DOT_VARNAME, dotDecl); 2034 if (axis == AXIS_PARENT) 2035 { 2036 Expression[] args = { exp }; 2037 exp = new ApplyExp(ParentAxis.make(NodeType.anyNodeTest), args); 2038 } 2039 return parseStepQualifiers(exp, axis == AXIS_SELF ? -1 : axis); 2042 } 2043 axis = peekOperand() - OP_AXIS_FIRST; 2044 Expression unqualifiedStep; 2045 if (axis >= 0 && axis < COUNT_OP_AXIS) 2046 { 2047 getRawToken(); 2048 unqualifiedStep = parseNodeTest(axis); 2049 } 2050 else if (curToken == '@') 2051 { 2052 getRawToken(); 2053 axis = AXIS_ATTRIBUTE; 2054 unqualifiedStep = parseNodeTest(axis); 2055 } 2056 else 2057 { 2058 unqualifiedStep = parseNodeTest(-1); 2059 if (unqualifiedStep != null) 2060 { 2061 axis = AXIS_CHILD; 2062 } 2063 else 2064 { 2065 axis = -1; 2066 unqualifiedStep = parsePrimaryExpr(); 2067 } 2068 } 2069 return parseStepQualifiers(unqualifiedStep, axis); 2070 } 2071 2072 Expression parseStepQualifiers(Expression exp, int axis) 2073 throws java.io.IOException , SyntaxException 2074 { 2075 for (;;) 2076 { 2077 if (curToken == '[') 2078 { 2079 int startLine = getLineNumber() + 1; 2080 int startColumn = getColumnNumber() + 1; 2081 int saveSeenPosition = seenPosition; 2082 int saveSawLast = seenLast; 2083 getRawToken(); 2084 LambdaExp lexp = new LambdaExp(3); 2085 lexp.setFile(getName()); 2086 lexp.setLine(startLine, startColumn); 2087 Declaration dot = lexp.addDeclaration(DOT_VARNAME); 2088 if (axis >= 0) 2089 dot.setType(NodeType.anyNodeTest); 2090 else 2091 dot.setType(SingletonType.getInstance()); 2092 lexp.addDeclaration(POSITION_VARNAME, Type.int_type); 2093 lexp.addDeclaration(LAST_VARNAME, Type.int_type); 2094 comp.push(lexp); 2095 dot.noteValue(null); 2096 Expression cond = parseExprSequence(']', false); 2097 if (curToken == EOF_TOKEN) 2098 eofError("missing ']' - unexpected end-of-file"); 2099 char kind; 2100 Procedure valuesFilter; 2101 if (axis < 0) 2102 { 2103 kind = 'P'; 2104 valuesFilter = ValuesFilter.exprFilter; 2105 } 2106 else if (axis == AXIS_ANCESTOR || axis == AXIS_ANCESTOR_OR_SELF 2107 || axis == AXIS_PARENT || axis == AXIS_PRECEDING 2108 || axis == AXIS_PRECEDING_SIBLING) 2109 { 2110 kind = 'R'; 2111 valuesFilter = ValuesFilter.reverseFilter; 2112 } 2113 else 2114 { 2115 kind = 'F'; 2116 valuesFilter = ValuesFilter.forwardFilter; 2117 } 2118 2122 cond.setFile(getName()); 2123 cond.setLine(startLine, startColumn); 2124 comp.pop(lexp); 2125 lexp.body = cond; 2126 getRawToken(); 2127 Expression[] args = { exp, lexp }; 2128 exp = new ApplyExp(valuesFilter, args); 2129 } 2130 2134 else 2135 { 2136 return exp; 2137 } 2138 } 2139 } 2140 2141 2145 Expression parsePrimaryExpr() 2146 throws java.io.IOException , SyntaxException 2147 { 2148 Expression exp = parseMaybePrimaryExpr(); 2149 if (exp == null) 2150 { 2151 exp = syntaxError("missing expression"); 2152 if (curToken != EOF_TOKEN) 2153 getRawToken(); 2154 return exp; 2155 } 2156 return exp; 2157 } 2158 2159 void parseEntityOrCharRef () 2160 throws java.io.IOException , SyntaxException 2161 { 2162 int next = read(); 2163 if (next == '#') 2164 { 2165 int base; 2166 next = read(); 2167 if (next == 'x') 2168 { 2169 base = 16; 2170 next = read(); 2171 } 2172 else 2173 base = 10; 2174 int value = 0; 2175 while (next >= 0) 2176 { 2177 char ch = (char) next; 2178 int digit = Character.digit((char) ch, base); 2179 if (digit < 0) 2180 break; 2181 if (value >= 0x8000000) 2182 break; value = value * base; 2184 value += digit; 2185 next = read(); 2186 } 2187 if (next != ';') 2188 { 2189 unread(); 2190 error("invalid character reference"); 2191 } 2192 else if ((value > 0 && value <= 0xD7FF) 2194 || (value >= 0xE000 && value <= 0xFFFD) 2195 || (value >= 0x10000 && value <= 0x10FFFF)) 2196 tokenBufferAppend(value); 2197 else 2198 error('e', "invalid character value "+value, "XQST0090"); 2199 } 2200 else 2201 { 2202 int saveLength = tokenBufferLength; 2203 while (next >= 0) 2204 { 2205 char ch = (char) next; 2206 if (! XName.isNamePart(ch)) 2207 break; 2208 tokenBufferAppend(ch); 2209 next = read(); 2210 } 2211 if (next != ';') 2212 { 2213 unread(); 2214 error("invalid entity reference"); 2215 return; 2216 } 2217 String ref = new String (tokenBuffer, saveLength, 2218 tokenBufferLength - saveLength); 2219 tokenBufferLength = saveLength; 2220 appendNamedEntity(ref); 2221 } 2222 } 2223 2224 2225 int enclosedExpressionsSeen; 2226 2227 static Expression makeText = makeFunctionExp("gnu.kawa.xml.MakeText", 2228 "makeText"); 2229 2230 2235 void parseContent(char delimiter, Vector result) 2236 throws java.io.IOException , SyntaxException 2237 { 2238 tokenBufferLength = 0; 2239 int startSize = result.size(); 2240 int prevEnclosed = startSize - 1; 2241 boolean skipBoundarySpace = ! boundarySpacePreserve && delimiter == '<'; 2242 boolean skippable = skipBoundarySpace; 2243 for (;;) 2244 { 2245 int next = read(); 2246 if (next == delimiter && delimiter != '<' && checkNext(delimiter)) 2247 { 2248 tokenBufferAppend(delimiter); 2249 continue; 2250 } 2251 if (next == delimiter || next < 0 || next == '{') 2252 { 2253 addText: 2254 { 2255 String text; 2256 if (tokenBufferLength > 0 && ! skippable) 2257 text = new String (tokenBuffer, 0, tokenBufferLength); 2258 else if (next == '{' && prevEnclosed == result.size()) 2259 text = ""; 2262 else 2263 break addText; Expression[] args = { new QuoteExp(text) }; 2265 result.addElement(new ApplyExp(makeText, args)); 2266 } 2267 tokenBufferLength = 0; 2268 } 2269 if (next < 0) 2270 eofError("unexpected end-of-file"); 2271 if (next == '{') 2272 { 2273 next = read(); 2274 if (next == '{') 2275 { 2276 tokenBufferAppend('{'); 2277 skippable = false; 2278 } 2279 else 2280 { 2281 unread(next); 2282 enclosedExpressionsSeen++; 2283 Expression exp = parseEnclosedExpr(); 2284 result.addElement(exp); 2285 tokenBufferLength = 0; 2286 prevEnclosed = result.size(); 2287 skippable = skipBoundarySpace; 2288 } 2289 } 2290 else if (next == '}') 2291 { 2292 next = read(); 2293 if (next == '}') 2294 { 2295 tokenBufferAppend('}'); 2296 skippable = false; 2297 } 2298 else 2299 { 2300 error("unexpected '}' in element content"); 2301 unread(next); 2302 } 2303 } 2304 else if (next == delimiter) 2305 { 2306 if (delimiter != '<') 2307 { 2308 break; 2309 } 2310 else 2311 { 2312 next = read(); 2313 if (next == '/') 2314 break; 2315 Expression content = parseXMLConstructor(next, true); 2316 result.addElement(content); 2317 tokenBufferLength = 0; 2318 if (content instanceof ApplyExp 2319 && ((ApplyExp) content).getFunction() == makeCDATA) 2320 skippable = false; 2321 else 2322 skippable = skipBoundarySpace; 2323 } 2324 } 2325 else if (next == '&') 2326 { 2327 parseEntityOrCharRef(); 2328 skippable = false; 2329 } 2330 else 2331 { 2332 if (delimiter != '<' 2333 && (next == '\t' || next == '\n' || next == '\r')) 2334 next = ' '; 2335 if (next == '<') 2336 error('e', "'<' must be quoted in a direct attribute value"); 2337 if (skippable) 2338 skippable = Character.isWhitespace((char) next); 2339 tokenBufferAppend((char) next); 2340 } 2341 } 2342 } 2343 2344 2347 Expression parseEnclosedExpr() 2348 throws java.io.IOException , SyntaxException 2349 { 2350 String saveErrorIfComment = errorIfComment; 2351 errorIfComment = null; 2352 char saveReadState = pushNesting('{'); 2353 peekNonSpace("unexpected end-of-file after '{'"); 2354 int startLine = getLineNumber() + 1; 2355 int startColumn = getColumnNumber() + 1; 2356 getRawToken(); 2357 Expression exp = parseExpr(); 2358 for (;;) 2359 { 2360 if (curToken == '}') 2361 break; 2362 if (curToken == EOF_TOKEN || curToken == ')' || curToken == ']') 2363 { 2364 exp = syntaxError("missing '}'"); 2365 break; 2366 } 2367 if (curToken != ',') 2368 exp = syntaxError("missing '}' or ','"); 2369 else 2370 getRawToken(); 2371 2372 exp = makeExprSequence(exp, parseExpr()); 2373 2374 } 2375 exp.setFile(getName()); 2376 exp.setLine(startLine, startColumn); 2377 popNesting(saveReadState); 2378 errorIfComment = saveErrorIfComment; 2379 return exp; 2380 } 2381 2382 2383 public static Expression booleanValue(Expression exp) 2384 { 2385 Expression[] args = { exp }; 2386 Expression string 2387 = makeFunctionExp("gnu.xquery.util.BooleanValue", "booleanValue"); 2388 return new ApplyExp(string, args); 2389 } 2390 2391 static final Expression makeCDATA = 2392 makeFunctionExp("gnu.kawa.xml.MakeCDATA", "makeCDATA"); 2393 2394 2398 Expression parseXMLConstructor (int next, boolean inElementContent) 2399 throws java.io.IOException , SyntaxException 2400 { 2401 Expression exp; 2402 if (next == '!') 2403 { 2404 next = read(); 2405 if (next == '-' && peek() == '-') 2406 { 2407 skip(); 2408 getDelimited("-->"); 2409 boolean bad = false; 2410 int i = tokenBufferLength; 2411 boolean sawHyphen = true; 2412 while (--i >= 0) 2413 { 2414 boolean curHyphen = tokenBuffer[i] == '-'; 2415 if (sawHyphen && curHyphen) 2416 { 2417 bad = true; 2418 break; 2419 } 2420 sawHyphen = curHyphen; 2421 } 2422 if (bad) 2423 exp = syntaxError("consecutive or final hyphen in XML comment"); 2424 else 2425 { 2426 Expression[] args = 2427 { new QuoteExp(new String (tokenBuffer, 0, tokenBufferLength)) }; 2428 exp = new ApplyExp(makeFunctionExp("gnu.kawa.xml.CommentConstructor", 2429 "commentConstructor"), 2430 args); 2431 } 2432 } 2433 else if (next == '[' && read() == 'C' && read() == 'D' 2434 && read() == 'A' && read() == 'T' && read() == 'A' 2435 && read() == '[') 2436 { 2437 if (! inElementContent) 2438 error('e', "CDATA section must be in element content"); 2439 getDelimited("]]>"); 2440 Expression[] args = 2441 { new QuoteExp(new String (tokenBuffer, 0, tokenBufferLength)) }; 2442 exp = new ApplyExp(makeCDATA, args); 2443 } 2444 else 2445 exp = syntaxError("'<!' must be followed by '--' or '[CDATA['"); 2446 } 2447 else if (next == '?') 2448 { 2449 next = peek(); 2450 if (next < 0 || ! XName.isNameStart((char) next) 2451 || getRawToken() != NCNAME_TOKEN) 2452 syntaxError("missing target after '<?'"); 2453 String target = new String (tokenBuffer, 0, tokenBufferLength); 2454 int nspaces = 0; 2455 for (;;) 2456 { 2457 int ch = read(); 2458 if (ch < 0) 2459 break; 2460 if (! Character.isWhitespace((char) ch)) 2461 { 2462 unread(); 2463 break; 2464 } 2465 nspaces++; 2466 } 2467 getDelimited("?>"); 2468 if (nspaces == 0 && tokenBufferLength > 0) 2469 syntaxError("target must be followed by space or '?>'"); 2470 String content = new String (tokenBuffer, 0, tokenBufferLength); 2471 Expression[] args = { new QuoteExp(target), new QuoteExp(content) }; 2472 exp = new ApplyExp(makeFunctionExp("gnu.kawa.xml.MakeProcInst", 2473 "makeProcInst"), 2474 args); 2475 } 2476 else if (next < 0 || ! XName.isNameStart((char) next)) 2477 exp = syntaxError("expected QName after '<'"); 2478 else 2479 { 2480 unread(next); 2481 getRawToken(); 2482 char saveReadState = pushNesting('<'); 2483 exp = parseElementConstructor(); 2484 if (! inElementContent) 2485 exp = wrapWithBaseUri(exp); 2486 popNesting(saveReadState); 2487 } 2488 return exp; 2489 } 2490 2491 2493 static ApplyExp castQName (Expression value) 2494 { 2495 return new ApplyExp(new ReferenceExp(XQResolveNames.xsQNameDecl), 2496 new Expression[] { value }); 2497 } 2498 2499 2504 Expression parseElementConstructor() 2505 throws java.io.IOException , SyntaxException 2506 { 2507 String startTag = new String (tokenBuffer, 0, tokenBufferLength); 2512 Vector vec = new Vector (); 2513 Expression[] args; 2514 vec.addElement(castQName(new QuoteExp(startTag))); 2515 errorIfComment = "comment not allowed in element start tag"; 2516 NamespaceBinding nsBindings = null; 2517 int ch; 2518 for (;;) 2519 { 2520 ch = skipSpace(); 2521 if (ch < 0 || ch == '>' || ch == '/') 2522 break; 2523 unread(ch); 2524 getRawToken(); 2525 int vecSize = vec.size(); 2526 if (curToken != NCNAME_TOKEN && curToken != QNAME_TOKEN) 2527 break; 2528 String attrName = new String (tokenBuffer, 0, tokenBufferLength); 2529 int startLine = getLineNumber() + 1; 2530 int startColumn = getColumnNumber() + 1 - tokenBufferLength; 2531 String definingNamespace = null; 2532 if (curToken == NCNAME_TOKEN) 2533 { 2534 if (attrName.equals("xmlns")) 2535 definingNamespace = ""; 2536 } 2537 else 2538 { 2539 if (attrName.startsWith("xmlns:")) 2540 definingNamespace = attrName.substring(6).intern(); 2541 } 2542 Expression makeAttr 2543 = definingNamespace != null ? null 2544 : MakeAttribute.makeAttributeExp; 2545 vec.addElement(castQName(new QuoteExp(attrName))); 2546 ch = skipSpace(); 2547 if (ch != '=') 2548 { 2549 errorIfComment = null; 2550 return syntaxError("missing '=' after attribute"); 2551 } 2552 ch = skipSpace(); 2553 int enclosedExpressionsStart = enclosedExpressionsSeen; 2554 if (ch == '{') 2555 { 2556 warnOldVersion("enclosed attribute value expression should be quoted"); 2557 vec.addElement(parseEnclosedExpr()); 2558 } 2559 else 2560 parseContent((char) ch, vec); 2561 int n = vec.size() - vecSize; 2562 if (definingNamespace != null) 2563 { 2564 String ns = ""; 2565 if (n == 1) 2566 ns = ""; 2567 else if (enclosedExpressionsSeen > enclosedExpressionsStart) 2568 syntaxError("enclosed expression not allowed in namespace declaration"); 2569 else 2570 { 2571 Object x = vec.elementAt(vecSize+1); 2572 ApplyExp ax; 2573 if (x instanceof ApplyExp 2574 && (ax = (ApplyExp) x).getFunction() == makeText) 2575 x = ax.getArg(0); 2576 ns = ((QuoteExp) x).getValue() 2577 .toString().intern(); 2578 } 2579 vec.setSize(vecSize); 2580 checkAllowedNamespaceDeclaration(definingNamespace, ns); 2581 if (definingNamespace == "") 2582 definingNamespace = null; 2583 for (NamespaceBinding nsb = nsBindings; 2584 nsb != null; nsb = nsb.getNext()) 2585 { 2586 if (nsb.getPrefix() == definingNamespace) 2587 { 2588 error('e', 2589 definingNamespace == null 2590 ? "duplicate default namespace declaration" 2591 : "duplicate namespace prefix '"+definingNamespace+'\'', 2592 "XQST0071"); 2593 break; 2594 } 2595 } 2596 nsBindings 2597 = new NamespaceBinding(definingNamespace, 2598 ns == "" ? null : ns, 2599 nsBindings); 2600 } 2601 else 2602 { 2603 args = new Expression[n]; 2604 for (int i = n; --i >= 0; ) 2605 args[i] = (Expression) vec.elementAt(vecSize + i); 2606 vec.setSize(vecSize); 2607 ApplyExp aexp = new ApplyExp(makeAttr, args); 2608 aexp.setFile(getName()); 2609 aexp.setLine(startLine, startColumn); 2610 vec.addElement(aexp); 2611 } 2612 } 2613 errorIfComment = null; 2614 boolean empty = false; 2615 if (ch == '/') 2616 { 2617 ch = read(); 2618 if (ch == '>') 2619 empty = true; 2620 else 2621 unread(ch); 2622 } 2623 if (! empty) 2624 { 2625 if (ch != '>') 2626 return syntaxError("missing '>' after start element"); 2627 parseContent('<', vec); 2628 ch = peek(); 2629 if (ch >= 0) 2630 { 2631 if (! XName.isNameStart((char) ch)) 2632 return syntaxError("invalid tag syntax after '</'"); 2633 getRawToken(); 2634 String tag = new String (tokenBuffer, 0, tokenBufferLength); 2635 if (! (tag.equals(startTag))) 2636 return syntaxError("'<"+startTag+">' closed by '</"+tag+">'"); 2637 errorIfComment = "comment not allowed in element end tag"; 2638 ch = skipSpace(); 2639 errorIfComment = null; 2640 } 2641 if (ch != '>') 2642 return syntaxError("missing '>' after end element"); 2643 } 2644 args = new Expression[vec.size()]; 2645 vec.copyInto(args); 2646 MakeElement mkElement = new MakeElement(); 2647 mkElement.copyNamespacesMode = copyNamespacesMode; 2648 mkElement.setNamespaceNodes(nsBindings); 2652 Expression result = new ApplyExp(new QuoteExp(mkElement), args); 2653 return result; 2654 } 2655 2656 Expression wrapWithBaseUri (Expression exp) 2657 { 2658 if (getStaticBaseUri() == null) 2659 return exp; 2660 return new ApplyExp(MakeWithBaseUri.makeWithBaseUri, 2661 new Expression[] { 2662 new ApplyExp(new ReferenceExp(XQResolveNames.staticBaseUriDecl), Expression.noExpressions), 2663 exp }) 2664 .setLine(exp); 2665 } 2666 2667 2671 Expression parseParenExpr () 2672 throws java.io.IOException , SyntaxException 2673 { 2674 getRawToken(); 2675 char saveReadState = pushNesting('('); 2676 Expression exp = parseExprSequence(')', true); 2677 popNesting(saveReadState); 2678 if (curToken == EOF_TOKEN) 2679 eofError("missing ')' - unexpected end-of-file"); 2680 return exp; 2681 } 2682 2683 Expression parseExprSequence(int rightToken, boolean optional) 2684 throws java.io.IOException , SyntaxException 2685 { 2686 if (curToken == rightToken || curToken == EOF_TOKEN) 2687 { 2688 if (! optional) 2689 syntaxError("missing expression"); 2690 return QuoteExp.voidExp; 2691 } 2692 Expression exp = null; 2693 for (;;) 2694 { 2695 Expression exp1 = parseExprSingle(); 2696 2697 exp = exp == null ? exp1 : makeExprSequence(exp, exp1); 2698 if (curToken == rightToken || curToken == EOF_TOKEN) 2699 break; 2700 if (nesting == 0 && curToken == EOL_TOKEN) 2701 return exp; 2702 if (curToken != ',') 2703 return syntaxError (rightToken == ')' ? "expected ')'" 2704 : "confused by syntax error"); 2705 getRawToken(); 2706 } 2707 return exp; 2708 } 2709 2710 Expression parseTypeSwitch() 2711 throws java.io.IOException , SyntaxException 2712 { 2713 char save = pushNesting('t'); 2714 Expression selector = parseParenExpr(); 2715 getRawToken(); 2716 Object varName = null; 2717 Declaration decl; 2718 Vector vec = new Vector (); 2719 vec.addElement(selector); 2720 while (match("case")) 2721 { 2722 pushNesting('c'); 2723 getRawToken(); 2724 if (curToken == '$') 2725 { 2726 decl = parseVariableDeclaration(); 2727 if (decl == null) 2728 return syntaxError("missing Variable after '$'"); 2729 getRawToken(); 2730 if (match("as")) 2731 getRawToken(); 2732 else 2733 error('e', "missing 'as'"); 2734 } 2735 else 2736 decl = new Declaration("(arg)"); 2737 decl.setTypeExp(parseDataType()); 2738 popNesting('t'); 2739 LambdaExp lexp = new LambdaExp(1); 2740 lexp.addDeclaration(decl); 2741 if (match("return")) 2742 getRawToken(); 2743 else 2744 error("missing 'return' after 'case'"); 2745 comp.push(lexp); 2746 pushNesting('r'); 2747 Expression caseExpr = parseExpr(); 2748 lexp.body = caseExpr; 2749 popNesting('t'); 2750 comp.pop(lexp); 2751 vec.addElement(lexp); 2752 } 2753 if (curToken == '$') 2754 { 2755 decl = parseVariableDeclaration(); 2756 if (decl == null) 2757 return syntaxError("missing Variable after '$'"); 2758 getRawToken(); 2759 } 2760 else 2761 decl = new Declaration("(arg)"); 2762 LambdaExp lexp = new LambdaExp(1); 2763 lexp.addDeclaration(decl); 2764 if (match("default")) 2765 { 2766 getRawToken(); 2767 if (match("return")) 2768 getRawToken(); 2769 else 2770 error("missing 'return' after 'default'"); 2771 comp.push(lexp); 2772 Expression defaultExpr = parseExpr(); 2773 lexp.body = defaultExpr; 2774 comp.pop(lexp); 2775 } 2776 else 2777 { 2778 lexp.body = QuoteExp.voidExp; 2779 error(comp.isPedantic() ? 'e' : 'w', 2780 "no 'default' clause in 'typeswitch'", 2781 "XPST0003"); 2782 } 2783 vec.addElement(lexp); 2784 popNesting(save); 2785 Expression[] args = new Expression[vec.size()]; 2786 vec.copyInto(args); 2787 return new ApplyExp(makeFunctionExp("gnu.kawa.reflect.TypeSwitch", 2788 "typeSwitch"), 2789 args); 2790 } 2791 2792 2796 Expression parseMaybePrimaryExpr() 2797 throws java.io.IOException , SyntaxException 2798 { 2799 int startLine = curLine; 2800 int startColumn = curColumn; 2801 int token = peekOperand(); 2802 Expression exp; 2803 int c1, c2, c3; 2804 Vector vec; 2805 Expression[] args; 2806 switch (token) 2807 { 2808 case '(': 2809 exp = parseParenExpr(); 2810 break; 2811 2812 case PRAGMA_START_TOKEN: 2813 Stack extArgs = new Stack (); 2814 for (;;) 2815 { 2816 getRawToken(); 2817 Expression qname; 2818 if (curToken != QNAME_TOKEN && curToken != NCNAME_TOKEN) 2819 qname = syntaxError("missing pragma name"); 2820 else 2821 qname = QuoteExp.getInstance(new String (tokenBuffer, 0, tokenBufferLength)); 2822 extArgs.push(qname); 2823 StringBuffer sbuf = new StringBuffer (); 2824 int ch; 2825 int spaces = -1; 2826 do { ch = read(); spaces++; } 2827 while (ch >= 0 && Character.isWhitespace((char) ch)); 2828 while (ch != '#' || peek() != ')') 2829 { 2830 if (ch < 0) 2831 eofError("pragma ended by end-of-file"); 2832 if (spaces == 0) 2833 error("missing space between pragma and extension content"); 2834 spaces = 1; 2835 sbuf.append((char) ch); 2836 ch = read(); 2837 } 2838 read(); extArgs.push(QuoteExp.getInstance(sbuf.toString())); 2840 getRawToken(); 2841 if (curToken != PRAGMA_START_TOKEN) 2842 break; 2843 } 2844 if (curToken == '{') 2845 { 2846 getRawToken(); 2847 if (curToken != '}') 2848 { 2849 char saveReadState = pushNesting('{'); 2850 extArgs.push(parseExprSequence('}', false)); 2851 popNesting(saveReadState); 2852 if (curToken == EOF_TOKEN) 2853 eofError("missing '}' - unexpected end-of-file"); 2854 } 2855 args = new Expression[extArgs.size()]; 2856 extArgs.copyInto(args); 2857 exp = new ApplyExp(new ReferenceExp(XQResolveNames.handleExtensionDecl), args); 2858 } 2859 else 2860 exp = syntaxError("missing '{' after pragma"); 2861 break; 2862 2863 case '{': 2864 exp = syntaxError("saw unexpected '{' - assume you meant '('"); 2865 parseEnclosedExpr(); 2866 break; 2867 2868 case OP_LSS: 2869 int next = read(); 2870 if (next == '/') 2871 { 2872 getRawToken(); 2873 String msg; 2874 if (curToken == NCNAME_TOKEN || curToken == QNAME_TOKEN 2875 || curToken == NCNAME_COLON_TOKEN) 2876 msg = "saw end tag '</" + new String (tokenBuffer, 0, tokenBufferLength) + ">' not in an element constructor"; 2877 else 2878 msg = "saw end tag '</' not in an element constructor"; 2879 curLine = startLine; 2880 curColumn = startColumn; 2881 exp = syntaxError(msg); 2882 while (curToken != OP_GRT && curToken != EOF_TOKEN && curToken != EOL_TOKEN) 2883 getRawToken(); 2884 return exp; 2885 } 2886 else 2887 { 2888 exp = parseXMLConstructor(next, false); 2889 exp.setFile(getName()); 2890 exp.setLine(startLine, startColumn); 2891 } 2892 break; 2893 2894 case STRING_TOKEN: 2895 exp = new QuoteExp(new String (tokenBuffer, 0, tokenBufferLength).intern()); 2896 break; 2897 2898 case INTEGER_TOKEN: 2899 exp = new QuoteExp(IntNum.valueOf(tokenBuffer, 0, tokenBufferLength, 2900 10, false)); 2901 break; 2902 2903 case DECIMAL_TOKEN: 2904 case DOUBLE_TOKEN: 2905 String str = new String (tokenBuffer, 0, tokenBufferLength); 2906 try 2907 { 2908 Object val; 2909 if (token == DECIMAL_TOKEN) 2910 val = new java.math.BigDecimal (str); 2911 else 2912 val = new java.lang.Double (str); 2913 exp = new QuoteExp(val); 2914 } 2915 catch (Throwable ex) 2916 { 2917 exp = syntaxError("invalid decimal literal: '"+str+"'"); 2918 } 2919 break; 2920 case '$': 2921 Object name = parseVariable(); 2922 if (name == null) 2923 return syntaxError("missing Variable"); 2924 exp = new ReferenceExp(name); 2925 break; 2926 case FNAME_TOKEN: 2927 name = new String (tokenBuffer, 0, tokenBufferLength); 2928 char save = pushNesting('('); 2929 getRawToken(); 2930 vec = new Vector (10); 2931 if (curToken != ')') 2932 { 2933 for (;;) 2934 { 2935 Expression arg = parseExpr(); 2936 vec.addElement(arg); 2937 if (curToken == ')') 2938 break; 2939 if (curToken != ',') 2940 return syntaxError("missing ')' after function call"); 2941 getRawToken(); 2942 } 2943 } 2944 args = new Expression[vec.size()]; 2945 2946 vec.copyInto(args); 2947 ReferenceExp rexp = new ReferenceExp(name, null); 2948 rexp.setProcedureName(true); 2949 exp = new ApplyExp(rexp, args); 2950 2951 exp.setFile(getName()); 2952 exp.setLine(startLine, startColumn); 2953 popNesting(save); 2954 break; 2955 2956 case ELEMENT_TOKEN: 2957 case ATTRIBUTE_TOKEN: 2958 case COMMENT_TOKEN: 2959 case DOCUMENT_TOKEN: 2960 case TEXT_TOKEN: 2961 case PI_TOKEN: 2962 getRawToken(); vec = new Vector (); 2964 Expression func; 2965 2966 if (token == ELEMENT_TOKEN || token == ATTRIBUTE_TOKEN) 2967 { 2968 Expression element; 2969 if (curToken == NCNAME_TOKEN || curToken == QNAME_TOKEN) 2970 element = parseNameTest(token != ELEMENT_TOKEN); 2971 else if (curToken == '{') 2972 element = parseEnclosedExpr(); 2973 else 2974 return syntaxError("missing element/attribute name"); 2975 vec.addElement(castQName(element)); 2976 if (token == ELEMENT_TOKEN) 2977 { 2978 MakeElement mk = new MakeElement(); 2979 mk.copyNamespacesMode = copyNamespacesMode; 2980 func = new QuoteExp(mk); 2981 } 2982 else 2983 func = MakeAttribute.makeAttributeExp; 2984 getRawToken(); 2985 } 2986 else if (token == DOCUMENT_TOKEN) 2987 func = makeFunctionExp("gnu.kawa.xml.DocumentConstructor", 2988 "documentConstructor"); 2989 else if (token == COMMENT_TOKEN) 2990 func = makeFunctionExp("gnu.kawa.xml.CommentConstructor", 2991 "commentConstructor"); 2992 else if (token == PI_TOKEN) 2993 { 2994 Expression target; 2995 if (curToken == NCNAME_TOKEN) 2996 target = new QuoteExp(new String (tokenBuffer, 0, 2997 tokenBufferLength).intern()); 2998 else if (curToken == '{') 2999 { 3000 target = parseEnclosedExpr(); 3001 } 3002 else 3003 { 3004 target = syntaxError("expected NCName or '{' after 'processing-instruction'"); 3005 if (curToken != QNAME_TOKEN) 3006 return target; 3007 } 3008 vec.addElement(target); 3009 func = makeFunctionExp("gnu.kawa.xml.MakeProcInst", 3010 "makeProcInst"); 3011 getRawToken(); 3012 } 3013 else 3014 func = makeFunctionExp("gnu.kawa.xml.MakeText", 3015 "makeText"); 3016 char saveReadState = pushNesting('{'); 3017 peekNonSpace("unexpected end-of-file after '{'"); 3018 if (curToken != '{') 3019 return syntaxError("missing '{'"); 3020 getRawToken(); 3021 if (token == TEXT_TOKEN || token == COMMENT_TOKEN 3022 || token == PI_TOKEN) 3023 vec.addElement(parseExprSequence('}', token == PI_TOKEN)); 3024 else if (curToken != '}') 3025 { 3026 vec.addElement(parseExpr()); 3027 while (curToken == ',') 3028 { 3029 getRawToken(); 3030 vec.addElement(parseExpr()); 3031 } 3032 } 3033 popNesting(saveReadState); 3034 if (curToken != '}') 3035 return syntaxError("missing '}'"); 3036 args = new Expression[vec.size()]; 3037 vec.copyInto(args); 3038 exp = new ApplyExp(func, args); 3039 exp.setFile(getName()); 3040 exp.setLine(startLine, startColumn); 3041 if (token == DOCUMENT_TOKEN || token == ELEMENT_TOKEN) 3042 exp = wrapWithBaseUri(exp); 3043 break; 3044 3045 case ORDERED_LBRACE_TOKEN: 3046 case UNORDERED_LBRACE_TOKEN: 3047 getRawToken(); 3048 exp = parseExprSequence('}', false); 3049 break; 3050 3051 default: 3052 return null; 3053 } 3054 3063 getRawToken(); 3064 return exp; 3065 } 3066 3067 public Expression parseIfExpr() 3068 throws java.io.IOException , SyntaxException 3069 { 3070 char saveReadState1 = pushNesting('i'); 3071 getRawToken(); 3072 char saveReadState2 = pushNesting('('); 3073 Expression cond = parseExprSequence(')', false); 3074 popNesting(saveReadState2); 3075 if (curToken == EOF_TOKEN) 3076 eofError("missing ')' - unexpected end-of-file"); 3077 getRawToken(); 3078 if (! match("then")) 3079 syntaxError("missing 'then'"); 3080 else 3081 getRawToken(); 3082 Expression thenPart = parseExpr(); 3083 if (! match("else")) 3084 syntaxError("missing 'else'"); 3085 else 3086 getRawToken(); 3087 popNesting(saveReadState1); 3088 Expression elsePart = parseExpr(); 3089 return new IfExp(booleanValue(cond), thenPart, elsePart); 3090 } 3091 3092 public boolean match(String word) 3093 { 3094 if (curToken != NCNAME_TOKEN) 3095 return false; 3096 int len = word.length(); 3097 if (tokenBufferLength != len) 3098 return false; 3099 for (int i = len; --i >= 0; ) 3100 { 3101 char cs = word.charAt(i); 3102 char cb = tokenBuffer[i]; 3103 if (cs != cb) 3104 return false; 3105 } 3106 return true; 3107 } 3108 3109 3110 public Object parseVariable () 3111 throws java.io.IOException , SyntaxException 3112 { 3113 if (curToken == '$') 3114 getRawToken(); 3115 else 3116 syntaxError("missing '$' before variable name"); 3117 String str = new String (tokenBuffer, 0, tokenBufferLength); 3118 if (curToken == QNAME_TOKEN) 3121 return str; 3122 else if (curToken == NCNAME_TOKEN) 3123 return Namespace.EmptyNamespace.getSymbol(str.intern()); 3124 else 3125 return null; 3126 } 3127 3128 public Declaration parseVariableDeclaration () 3129 throws java.io.IOException , SyntaxException 3130 { 3131 Object name = parseVariable(); 3132 if (name == null) 3133 return null; 3134 Declaration decl = new Declaration(name); 3135 decl.setFile(getName()); 3136 decl.setLine(getLineNumber() + 1, 3137 getColumnNumber() + 1 - tokenBufferLength); 3138 return decl; 3139 } 3140 3141 public Expression parseFLWRExpression (boolean isFor) 3142 throws java.io.IOException , SyntaxException 3143 { 3144 int flworDeclsSave = flworDeclsFirst; 3145 flworDeclsFirst = flworDeclsCount; 3146 Expression exp = parseFLWRInner(isFor); 3147 3148 if (match ("order")) 3149 { 3150 getRawToken(); 3151 if (match ("by")) 3152 getRawToken(); 3153 else 3154 error("missing 'by' following 'order'"); 3155 Stack specs = new Stack (); 3156 for (;;) 3157 { 3158 boolean descending = false; 3159 char emptyOrder = defaultEmptyOrder; 3160 3161 LambdaExp lexp = new LambdaExp(flworDeclsCount-flworDeclsFirst); 3162 for (int i = flworDeclsFirst; i < flworDeclsCount; i++) 3163 lexp.addDeclaration(flworDecls[i].getSymbol()); 3164 comp.push(lexp); 3165 lexp.body = parseExprSingle(); 3166 comp.pop(lexp); 3167 specs.push(lexp); 3168 3169 if (match("ascending")) 3170 getRawToken(); 3171 else if (match("descending")) 3172 { 3173 getRawToken(); 3174 descending = true; 3175 } 3176 if (match("empty")) 3177 { 3178 getRawToken(); 3179 if (match("greatest")) 3180 { 3181 getRawToken(); 3182 emptyOrder = 'G'; 3183 } 3184 else if (match("least")) 3185 { 3186 getRawToken(); 3187 emptyOrder = 'L'; 3188 } 3189 else 3190 error 3191 ("'empty' sequence order must be 'greatest' or 'least'"); 3192 } 3193 specs.push(new QuoteExp((descending ? "D" : "A") + emptyOrder)); 3194 Object collation = defaultCollator; 3195 if (match("collation")) 3196 { 3197 Object uri = parseURILiteral(); 3198 if (uri instanceof String ) 3199 { 3200 try 3201 { 3202 collation = NamedCollator.make((String ) uri); 3203 } 3204 catch (Exception name) 3205 { 3206 error('e', "unknown collation '"+uri+"'", "XQST0076"); 3207 } 3208 } 3209 getRawToken(); 3210 } 3211 specs.push(new QuoteExp(collation)); 3212 if (curToken != ',') 3213 break; 3214 getRawToken(); 3215 } 3216 if (! match("return")) 3217 return syntaxError("expected 'return' clause"); 3218 getRawToken(); 3219 3220 LambdaExp lexp = new LambdaExp(flworDeclsCount-flworDeclsFirst); 3221 for (int i = flworDeclsFirst; i < flworDeclsCount; i++) 3224 lexp.addDeclaration(flworDecls[i].getSymbol()); 3225 comp.push(lexp); 3226 lexp.body = parseExprSingle(); 3227 comp.pop(lexp); 3228 int nspecs = specs.size(); 3229 Expression[] args = new Expression[2 + nspecs]; 3230 args[0] = exp; 3231 args[1] = lexp; 3232 for (int i = 0; i < nspecs; i++) 3233 args[2+i] = (Expression) specs.elementAt(i); 3234 return new ApplyExp(makeFunctionExp("gnu.xquery.util.OrderedMap", 3235 "orderedMap"), 3236 args); 3237 3238 } 3239 flworDeclsCount = flworDeclsFirst; 3240 flworDeclsFirst = flworDeclsSave; 3241 return exp; 3242 } 3243 3244 3252 public Expression parseFLWRInner (boolean isFor) 3253 throws java.io.IOException , SyntaxException 3254 { 3255 char saveNesting = pushNesting(isFor ? 'f' : 'l'); 3256 curToken = '$'; 3257 Declaration decl = parseVariableDeclaration(); 3258 if (decl == null) 3259 return syntaxError("missing Variable - saw "+tokenString()); 3260 if (flworDecls == null) 3261 flworDecls = new Declaration[8]; 3262 else if (flworDeclsCount >= flworDecls.length) 3263 { 3264 Declaration[] tmp = new Declaration[2 * flworDeclsCount]; 3265 System.arraycopy(flworDecls, 0, tmp, 0, flworDeclsCount); 3266 flworDecls = tmp; 3267 } 3268 flworDecls[flworDeclsCount++] = decl; 3269 getRawToken(); 3270 3271 Expression type = parseOptionalTypeDeclaration(); 3272 ScopeExp sc; 3273 Expression[] inits = new Expression[1]; 3274 Declaration posDecl = null; 3275 if (isFor) 3276 { 3277 boolean sawAt = match("at"); 3278 LambdaExp lexp = new LambdaExp(sawAt ? 2 : 1); 3279 if (sawAt) 3280 { 3281 getRawToken(); 3282 if (curToken == '$') 3283 { 3284 posDecl = parseVariableDeclaration(); 3285 getRawToken(); 3286 } 3287 if (posDecl == null) 3288 syntaxError("missing Variable after 'at'"); 3289 } 3290 sc = lexp; 3291 if (match("in")) 3292 getRawToken(); 3293 else 3294 { 3295 if (curToken == COLON_EQUAL_TOKEN) 3296 getRawToken(); 3297 syntaxError("missing 'in' in 'for' clause"); 3298 } 3299 } 3300 else 3301 { 3302 if (curToken == COLON_EQUAL_TOKEN) 3303 getRawToken(); 3304 else 3305 { 3306 if (match("in")) 3307 getRawToken(); 3308 syntaxError("missing ':=' in 'let' clause"); 3309 } 3310 LetExp let = new LetExp(inits); 3311 sc = let; 3312 } 3313 inits[0] = parseExprSingle(); 3314 if (type != null && ! isFor) inits[0] = Convert.makeCoercion(inits[0], type); 3316 popNesting(saveNesting); 3317 comp.push(sc); 3318 sc.addDeclaration(decl); 3319 decl.setTypeExp(type); 3320 if (isFor) 3321 { 3322 decl.noteValue (null); decl.setFlag(Declaration.IS_SINGLE_VALUE); 3324 } 3325 if (posDecl != null) 3326 { 3327 sc.addDeclaration(posDecl); 3328 posDecl.setType(LangPrimType.intType); 3329 posDecl.noteValue(null); 3330 posDecl.setFlag(Declaration.IS_SINGLE_VALUE); 3331 } 3332 Expression body; 3333 if (curToken == ',') 3334 { 3335 getRawToken(); 3336 if (curToken != '$') 3337 return syntaxError("missing $NAME after ','"); 3338 body = parseFLWRInner(isFor); 3339 } 3340 else if (match("for")) 3341 { 3342 getRawToken(); 3343 if (curToken != '$') 3344 return syntaxError("missing $NAME after 'for'"); 3345 body = parseFLWRInner(true); 3346 } 3347 else if (match("let")) 3348 { 3349 getRawToken(); 3350 if (curToken != '$') 3351 return syntaxError("missing $NAME after 'let'"); 3352 body = parseFLWRInner(false); 3353 } 3354 else 3355 { 3356 Expression cond; 3357 char save = pushNesting('w'); 3358 if (curToken == OP_WHERE) 3359 { 3360 getRawToken(); 3361 cond = parseExprSingle(); 3362 } 3363 else if (match("where")) 3364 { 3365 cond = parseExprSingle(); 3366 } 3367 else 3368 cond = null; 3369 popNesting(save); 3370 boolean sawStable = match("stable"); 3371 if (sawStable) 3372 getRawToken(); 3373 boolean sawReturn = match("return"); 3374 boolean sawOrder = match("order"); 3375 if (! sawReturn && ! sawOrder && ! match("let") && ! match("for")) 3376 return syntaxError("missing 'return' clause"); 3377 if (! sawOrder) 3378 peekNonSpace("unexpected eof-of-file after 'return'"); 3379 int bodyLine = getLineNumber() + 1; 3380 int bodyColumn = getColumnNumber() + 1; 3381 if (sawReturn) 3382 getRawToken(); 3383 if (sawOrder) 3384 { 3385 int ndecls = flworDeclsCount - flworDeclsFirst; 3386 Expression[] args = new Expression[ndecls]; 3387 for (int i = 0; i < ndecls; i++) 3388 args[i] = new ReferenceExp(flworDecls[flworDeclsFirst+i]); 3389 body = new ApplyExp(new PrimProcedure("gnu.xquery.util.OrderedMap", 3390 "makeTuple$V", 1), 3391 args); 3392 } 3393 else 3394 body = parseExprSingle(); 3395 if (cond != null) 3396 body = new IfExp(booleanValue(cond), body, QuoteExp.voidExp); 3397 body.setFile(getName()); 3398 body.setLine(bodyLine, bodyColumn); 3399 } 3400 comp.pop(sc); 3401 if (isFor) 3402 { 3403 LambdaExp lexp = (LambdaExp) sc; 3404 lexp.body = body; 3405 Expression[] args = { sc, inits[0]}; return new ApplyExp(makeFunctionExp("gnu.kawa.functions.ValuesMap", 3407 lexp.min_args == 1 ? "valuesMap" 3408 : "valuesMapWithPos"), 3409 args); 3410 } 3411 else 3412 ((LetExp) sc).setBody(body); 3413 return sc; 3414 3415 } 3416 3417 3419 public Expression parseQuantifiedExpr (boolean isEvery) 3420 throws java.io.IOException , SyntaxException 3421 { 3422 char saveNesting = pushNesting(isEvery ? 'e' : 's'); 3423 curToken = '$'; 3424 Declaration decl = parseVariableDeclaration(); 3425 if (decl == null) 3426 return syntaxError("missing Variable token:"+curToken); 3427 getRawToken(); 3428 3429 LambdaExp lexp = new LambdaExp(1); 3430 lexp.addDeclaration(decl); 3431 decl.noteValue (null); decl.setFlag(Declaration.IS_SINGLE_VALUE); 3433 decl.setTypeExp(parseOptionalTypeDeclaration()); 3434 3435 if (match("in")) 3436 getRawToken(); 3437 else 3438 { 3439 if (curToken == COLON_EQUAL_TOKEN) 3440 getRawToken(); 3441 syntaxError("missing 'in' in QuantifiedExpr"); 3442 } 3443 Expression[] inits = { parseExprSingle() }; 3444 popNesting(saveNesting); 3445 comp.push(lexp); 3446 Expression body; 3447 if (curToken == ',') 3448 { 3449 getRawToken(); 3450 if (curToken != '$') 3451 return syntaxError("missing $NAME after ','"); 3452 body = parseQuantifiedExpr(isEvery); 3453 } 3454 else 3455 { 3456 boolean sawSatisfies = match("satisfies"); 3457 if (! sawSatisfies && ! match("every") && ! match("some")) 3458 return syntaxError("missing 'satisfies' clause"); 3459 peekNonSpace("unexpected eof-of-file after 'satisfies'"); 3460 int bodyLine = getLineNumber() + 1; 3461 int bodyColumn = getColumnNumber() + 1; 3462 if (sawSatisfies) 3463 getRawToken(); 3464 body = parseExprSingle(); 3465 body.setFile(getName()); 3466 body.setLine(bodyLine, bodyColumn); 3467 } 3468 comp.pop(lexp); 3469 lexp.body = body; 3470 Expression[] args = { lexp, inits[0]}; return new ApplyExp(makeFunctionExp("gnu.xquery.util.ValuesEvery", 3472 isEvery ? "every" : "some"), 3473 args); 3474 } 3475 3476 public Expression parseFunctionDefinition(int declLine, int declColumn) 3477 throws java.io.IOException , SyntaxException 3478 { 3479 if (curToken != QNAME_TOKEN && curToken != NCNAME_TOKEN) 3480 return syntaxError("missing function name"); 3481 String name = new String (tokenBuffer, 0, tokenBufferLength); 3482 Symbol sym = namespaceResolve(name, true); 3483 String uri = sym.getNamespaceURI(); 3484 if (uri == NamespaceBinding.XML_NAMESPACE 3485 || uri == XQuery.SCHEMA_NAMESPACE 3486 || uri == XQuery.SCHEMA_INSTANCE_NAMESPACE 3487 || uri == XQuery.XQUERY_FUNCTION_NAMESPACE) 3488 { 3489 error('e', 3490 "cannot declare function in standard namespace '"+uri+'\'', 3491 "XQST0045"); 3492 } 3493 else if (uri == "") 3494 { 3495 error(comp.isPedantic() ? 'e' : 'w', 3496 "cannot declare function in empty namespace", 3497 "XQST0060"); 3498 } 3499 else if (libraryModuleNamespace != null && uri != libraryModuleNamespace 3500 && (! XQuery.LOCAL_NAMESPACE.equals(uri) || comp.isPedantic())) 3501 { 3502 error('e', "function not in namespace of library module", "XQST0048"); 3503 } 3504 getRawToken(); 3505 if (curToken != '(') 3506 return syntaxError("missing parameter list:"+curToken); 3507 getRawToken(); 3508 LambdaExp lexp = new LambdaExp(); 3509 lexp.setFile(getName()); 3510 lexp.setLine(declLine, declColumn); 3511 lexp.setName(name); 3512 Declaration decl = comp.currentScope().addDeclaration(sym); 3513 if (comp.isStatic()) 3514 decl.setFlag(Declaration.STATIC_SPECIFIED); 3515 lexp.setFlag(LambdaExp.OVERLOADABLE_FIELD); 3516 decl.setCanRead(true); 3517 decl.setProcedureDecl(true); 3518 decl.setFile(getName()); 3519 decl.setLine(declLine, declColumn); 3520 comp.push(lexp); 3521 if (curToken != ')') 3522 { 3523 paramLoop: 3524 for (;;) 3525 { 3526 Declaration param = parseVariableDeclaration(); 3527 if (param == null) 3528 error("missing parameter name"); 3529 else 3530 { 3531 lexp.addDeclaration(param); 3532 getRawToken(); 3533 lexp.min_args++; 3534 lexp.max_args++; 3535 param.setTypeExp(parseOptionalTypeDeclaration()); 3536 } 3537 if (curToken == ')') 3538 break; 3539 if (curToken != ',') 3540 { 3541 Expression err = syntaxError("missing ',' in parameter list"); 3542 for (;;) 3543 { 3544 getRawToken(); 3545 if (curToken < 0 || curToken == ';' || curToken == ';') 3546 return err; 3547 if (curToken == ')') 3548 break paramLoop; 3549 if (curToken == ',') 3550 break; 3551 } 3552 } 3553 else 3554 getRawToken(); 3555 } 3556 } 3557 getRawToken(); 3558 Expression retType = parseOptionalTypeDeclaration (); 3559 lexp.body = parseEnclosedExpr(); 3560 comp.pop(lexp); 3561 if (retType != null) 3562 Convert.setCoercedReturnValue(lexp, retType, interpreter); 3563 SetExp sexp = new SetExp(decl, lexp); 3564 sexp.setDefining (true); 3565 decl.noteValue(lexp); 3566 return sexp; 3567 } 3568 3569 public Object readObject () 3570 throws java.io.IOException , SyntaxException 3571 { 3572 return parse(null); 3573 } 3574 3575 Compilation comp; 3576 3577 String defaultElementNamespace = ""; 3578 3579 3582 NamespaceBinding constructorNamespaces = NamespaceBinding.predefinedXML; 3583 3584 3586 NamespaceBinding prologNamespaces; 3587 3588 static NamespaceBinding builtinNamespaces; 3589 static { 3590 NamespaceBinding ns = NamespaceBinding.predefinedXML; 3591 ns = new NamespaceBinding("xml", NamespaceBinding.XML_NAMESPACE, ns); 3592 ns = new NamespaceBinding("xs", XQuery.SCHEMA_NAMESPACE, ns); 3593 ns = new NamespaceBinding("xsi", XQuery.SCHEMA_INSTANCE_NAMESPACE, ns); 3594 ns = new NamespaceBinding("fn", XQuery.XQUERY_FUNCTION_NAMESPACE, ns); 3595 ns = new NamespaceBinding("html", XQuery.XHTML_NAMESPACE, ns); 3596 ns = new NamespaceBinding("kawa", XQuery.KAWA_FUNCTION_NAMESPACE, ns); 3597 ns = new NamespaceBinding("qexo", XQuery.QEXO_FUNCTION_NAMESPACE, ns); 3598 ns = new NamespaceBinding("local", XQuery.LOCAL_NAMESPACE, ns); 3599 builtinNamespaces = ns; 3600 } 3601 3602 protected Symbol namespaceResolve (String name, boolean function) 3603 { 3604 int colon = name.indexOf(':'); 3605 String prefix = colon >= 0 ? name.substring(0, colon).intern() 3606 : function ? XQuery.DEFAULT_FUNCTION_PREFIX 3607 : XQuery.DEFAULT_ELEMENT_PREFIX; 3608 String uri = QNameUtils.lookupPrefix(prefix, constructorNamespaces, 3609 prologNamespaces); 3610 3611 if (uri == null) 3612 { 3613 if (colon < 0) 3614 uri = ""; 3615 else if (! comp.isPedantic()) 3616 { 3617 try 3618 { 3619 Class cl = Class.forName(prefix); 3620 uri = "class:" + prefix; 3621 } 3622 catch (Exception ex) 3623 { 3624 uri = null; 3625 } 3626 } 3627 if (uri == null) 3628 { 3629 error('e', 3630 "unknown namespace prefix '" + prefix + "'", 3631 "XPST0081"); 3632 uri = "(unknown namespace)"; 3633 } 3634 } 3635 String local = colon < 0 ? name : name.substring(colon+1); 3636 return Symbol.make((String ) uri, local, prefix); 3637 } 3638 3639 void parseSeparator () 3640 throws java.io.IOException , SyntaxException 3641 { 3642 int startLine = port.getLineNumber() + 1; 3643 int startColumn = port.getColumnNumber() + 1; 3644 int next = skipSpace(nesting != 0); 3645 if (next == ';') 3646 return; 3647 if (warnOldVersion && next != '\n') 3648 { 3649 curLine = startLine; 3650 curColumn = startColumn; 3651 error('w', "missing ';' after declaration"); 3652 } 3653 if (next >= 0) 3654 unread(next); 3655 } 3656 3657 public static final QuoteExp getExternalFunction = 3658 QuoteExp.getInstance(new PrimProcedure("gnu.xquery.lang.XQuery", 3659 "getExternal", 2)); 3660 3661 3663 public Expression parse(Compilation comp) 3664 throws java.io.IOException , SyntaxException 3665 { 3666 this.comp = comp; 3667 int ch = skipSpace(); 3668 if (ch < 0) 3669 return null; 3670 parseCount++; 3671 unread(ch); 3672 int startLine = getLineNumber() + 1; 3673 int startColumn = getColumnNumber() + 1; 3674 3675 if (ch == '#' && startLine == 1 && startColumn == 1) 3677 { 3678 read(); 3679 if ((ch = read()) != '!' || (ch = read()) != '/') 3680 error("'#' is only allowed in initial '#!/PROGRAM'"); 3681 while (ch != '\r' && ch != '\n' && ch >= 0) 3682 ch = read(); 3683 } 3684 3685 if (getRawToken() == EOF_TOKEN) 3686 return null; 3687 peekOperand(); 3688 3689 if (curToken == NCNAME_TOKEN 3690 && "namespace".equals((String ) curValue)) 3691 { 3692 if (warnOldVersion) 3693 error('w', "use 'declare namespace' instead of 'namespace'"); 3694 curToken = DECLARE_NAMESPACE_TOKEN; 3695 } 3696 3697 int declLine, declColumn, next; 3698 Declaration decl; 3699 String prefix, uri; 3700 Object val; 3701 Expression exp; 3702 switch (curToken) 3703 { 3704 case DEFINE_QNAME_TOKEN: 3705 declLine = getLineNumber() + 1; 3706 declColumn = getColumnNumber() + 1; 3707 next = peekNonSpace("unexpected end-of-file after 'define QName'"); 3708 if (next == '(') 3709 { 3710 syntaxError("'missing 'function' after 'define'"); 3711 curToken = NCNAME_TOKEN; 3712 return parseFunctionDefinition(declLine, declColumn); 3713 } 3714 else 3715 return syntaxError("missing keyword after 'define'"); 3716 3717 case DECLARE_FUNCTION_TOKEN: 3718 declLine = getLineNumber() + 1; 3719 declColumn = getColumnNumber() + 1; 3720 getRawToken(); 3721 peekNonSpace("unexpected end-of-file after 'define function'"); 3722 char save = pushNesting('d'); 3723 exp = parseFunctionDefinition(declLine, declColumn); 3724 popNesting(save); 3725 parseSeparator(); 3726 exp.setFile(getName()); 3727 exp.setLine(startLine, startColumn); 3728 seenDeclaration = true; 3729 return exp; 3730 3731 case DECLARE_VARIABLE_TOKEN: 3732 getRawToken(); 3733 decl = parseVariableDeclaration(); 3734 if (decl == null) 3735 return syntaxError("missing Variable"); 3736 Object name = decl.getSymbol(); 3737 if (name instanceof String ) 3738 decl.setSymbol(namespaceResolve((String ) name, false)); 3739 if (libraryModuleNamespace != null) 3740 { 3741 uri = ((Symbol) decl.getSymbol()).getNamespaceURI(); 3742 if (uri != libraryModuleNamespace 3743 && (! XQuery.LOCAL_NAMESPACE.equals(uri) || comp.isPedantic())) 3744 error('e', "variable not in namespace of library module" 3745 , "XQST0048"); 3746 } 3747 comp.currentScope().addDeclaration(decl); 3748 getRawToken(); 3749 Expression type = parseOptionalTypeDeclaration(); 3750 decl.setCanRead(true); 3751 decl.setFlag(Declaration.IS_CONSTANT); 3753 Expression init = null; 3754 boolean sawEq = false; 3755 if (curToken == OP_EQU || curToken == COLON_EQUAL_TOKEN) 3756 { 3757 if (curToken==OP_EQU) 3758 error("declare variable contains '=' instead of ':='"); 3759 getRawToken(); 3760 sawEq = true; 3761 } 3762 if (curToken == '{') 3763 { 3764 warnOldVersion("obsolete '{' in variable declaration"); 3765 init = parseEnclosedExpr(); 3766 parseSeparator(); 3767 } 3768 else if (match("external")) 3769 { 3770 Expression[] args = 3771 { 3772 castQName(new QuoteExp(decl.getSymbol())), 3773 type==null ? QuoteExp.nullExp : type 3774 }; 3775 init = new ApplyExp(getExternalFunction, args); 3776 init.setFile(getName()); 3777 init.setLine(curLine, curColumn); 3778 getRawToken(); 3779 } 3780 else 3781 { 3782 init = parseExpr(); 3783 Expression err = null; 3784 if (! sawEq || init == null) 3785 err = syntaxError("expected ':= init' or 'external'"); 3786 if (init == null) 3787 init = err; 3788 } 3789 if (type != null) 3790 init = Convert.makeCoercion(init, type); 3791 decl.noteValue(init); 3792 exp = SetExp.makeDefinition(decl, init); 3793 exp.setFile(getName()); 3794 exp.setLine(startLine, startColumn); 3795 seenDeclaration = true; 3796 return exp; 3797 3798 case DECLARE_NAMESPACE_TOKEN: 3799 case MODULE_NAMESPACE_TOKEN: 3800 int command = curToken; 3801 if (command == MODULE_NAMESPACE_TOKEN 3802 && libraryModuleNamespace != null ) 3803 error('e', "duplicate module declaration"); 3804 else if (seenDeclaration && ! interactive) 3805 error('e', "namespace declared after function/variable/option"); 3806 next = skipSpace(nesting != 0); 3807 if (next >= 0) 3808 { 3809 unread(); 3810 if (XName.isNameStart((char) next)) 3811 { 3812 getRawToken(); 3813 if (curToken != NCNAME_TOKEN) 3814 return syntaxError("missing namespace prefix"); 3815 prefix = new String (tokenBuffer, 0, tokenBufferLength); 3816 getRawToken(); 3817 if (curToken != OP_EQU) 3818 return syntaxError("missing '=' in namespace declaration"); 3819 getRawToken(); 3820 if (curToken != STRING_TOKEN) 3821 return syntaxError("missing uri in namespace declaration"); 3822 uri = new String (tokenBuffer, 0, tokenBufferLength).intern(); 3823 prefix = prefix.intern(); 3824 for (NamespaceBinding ns = prologNamespaces; 3825 ns != builtinNamespaces; 3826 ns = ns.getNext()) 3827 { 3828 if (ns.getPrefix() == prefix) 3829 { 3830 error('e', 3831 "duplicate declarations for the same namespace prefix '" 3832 +prefix+"'", 3833 "XQST0033"); 3834 break; 3835 } 3836 } 3837 pushNamespace(prefix, uri); 3838 checkAllowedNamespaceDeclaration(prefix, uri); 3839 parseSeparator(); 3840 if (command == MODULE_NAMESPACE_TOKEN) 3841 { 3842 ModuleExp module = comp.getModule(); 3843 String className = Compilation.mangleURI(uri) 3844 + '.' + XQuery.makeClassName(module.getFileName()); 3845 module.setName(className); 3846 comp.mainClass = new ClassType(className); 3847 module.setType(comp.mainClass); 3848 ModuleManager manager = ModuleManager.getInstance(); 3849 ModuleInfo info = manager.find(comp); 3850 info.setNamespaceUri(uri); 3851 module.setType(comp.mainClass); 3852 if (uri.length() == 0) 3853 return syntaxError("zero-length module namespace", "XQST0088"); 3854 libraryModuleNamespace = uri; 3855 } 3856 return QuoteExp.voidExp; 3857 } 3858 } 3859 3860 case IMPORT_SCHEMA_TOKEN: 3861 fatal("'import schema' not implemented", "XQST0009"); 3862 3863 case IMPORT_MODULE_TOKEN: 3864 getRawToken(); 3865 prefix = null; 3866 if (match("namespace")) 3867 { 3868 getRawToken(); 3869 if (curToken != NCNAME_TOKEN) 3870 return syntaxError("missing namespace prefix"); 3871 prefix = new String (tokenBuffer, 0, tokenBufferLength); 3872 getRawToken(); 3873 if (curToken != OP_EQU) 3874 return syntaxError("missing '=' in namespace declaration"); 3875 getRawToken(); 3876 } 3877 if (curToken != STRING_TOKEN) 3878 return syntaxError("missing uri in namespace declaration"); 3879 if (tokenBufferLength == 0) 3880 return syntaxError("zero-length target namespace", "XQST0088"); 3881 uri = new String (tokenBuffer, 0, tokenBufferLength).intern(); 3882 if (prefix != null) 3883 { 3884 checkAllowedNamespaceDeclaration(prefix, uri); 3885 pushNamespace(prefix.intern(), uri); 3886 } 3887 getRawToken(); 3888 ModuleManager.getInstance().find(comp); 3890 3891 String at; 3892 ModuleExp module = comp.getModule(); 3893 Vector forms = new Vector (); 3894 String packageName = Compilation.mangleURI(uri); 3895 comp.setLine(port.getName(), startLine, startColumn); 3896 if (match("at")) 3897 { 3898 for (;;) 3899 { 3900 getRawToken(); 3901 if (curToken != STRING_TOKEN) 3902 return syntaxError("missing module location"); 3903 at = new String (tokenBuffer, 0, tokenBufferLength); 3904 String className = Compilation.mangleURI(uri) 3905 + '.' + XQuery.makeClassName(at); 3906 3907 ModuleInfo info = require.lookupModuleFromSourcePath(at, module); 3908 if (info == null) 3909 comp.error('e', "malformed URL: "+at); 3910 require.importDefinitions(className, info, 3911 uri, forms, module, comp); 3912 next = skipSpace(nesting != 0); 3913 if (next != ',') 3914 { 3915 unread(next); 3916 break; 3917 } 3918 } 3919 parseSeparator(); 3920 } 3921 else 3922 { 3923 ModuleManager manager = ModuleManager.getInstance(); 3924 int n = 0; 3925 try 3926 { 3927 manager.loadPackageInfo(packageName); 3928 } 3929 catch (ClassNotFoundException ex) 3930 { 3931 } 3934 catch (Throwable ex) 3935 { 3936 error('e', "error loading map for "+uri+" - "+ex); 3937 } 3938 for (ModuleInfo info = manager.firstModule(); info != null; 3939 info = info.nextModule()) 3940 { 3941 if (! uri.equals(info.getNamespaceUri())) 3942 continue; 3943 n++; 3944 require.importDefinitions(info.className, info, uri, forms, module, comp); 3945 } 3946 if (n == 0) 3947 error('e', "no module found for "+uri); 3948 at = null; 3949 if (curToken != ';') 3950 parseSeparator(); 3951 } 3952 if (comp.pendingImports != null && comp.pendingImports.size() > 0) 3953 { 3954 error('e', "module import forms a cycle", "XQST0073"); 3955 } 3956 Expression[] inits = new Expression[forms.size()]; 3957 forms.toArray(inits); 3958 return BeginExp.canonicalize(inits); 3959 3960 case DEFAULT_COLLATION_TOKEN: 3961 if (defaultCollator != null && ! interactive) 3962 error('e', "duplicate default collation declaration", "XQST0038"); 3963 val = parseURILiteral(); 3964 if (val instanceof Expression) return (Expression) val; 3966 String collation = (String ) val; 3967 try 3968 { 3969 if (! InPort.uriSchemeSpecified(collation)) 3970 { 3971 String base = getStaticBaseUri(); 3972 if (base == null) 3973 base = CallContext.getInstance().getBaseUri(); 3974 collation = URI_utils.resolve(collation, base).toString(); 3975 } 3976 defaultCollator = NamedCollator.make(collation); 3977 } 3978 catch (Exception ex) 3979 { 3980 defaultCollator = NamedCollator.codepointCollation; 3981 error('e', "unknown collation '"+collation+"'", "XQST0038"); 3982 } 3983 parseSeparator(); 3984 return QuoteExp.voidExp; 3985 3986 case DEFAULT_ELEMENT_TOKEN: 3987 case DEFAULT_FUNCTION_TOKEN: 3988 boolean forFunctions = curToken == DEFAULT_FUNCTION_TOKEN; 3989 prefix = forFunctions ? XQuery.DEFAULT_FUNCTION_PREFIX 3990 : XQuery.DEFAULT_ELEMENT_PREFIX; 3991 if (prologNamespaces.resolve(prefix, builtinNamespaces) != null) 3992 error('e', 3993 "duplicate default namespace declaration", 3994 "XQST0066"); 3995 getRawToken(); 3996 if (match("namespace")) 3997 getRawToken(); 3998 else 3999 { 4000 String msg = "expected 'namespace' keyword"; 4001 if (curToken != STRING_TOKEN && curToken != OP_EQU) 4002 return declError(msg); 4003 else 4004 warnOldVersion(msg); 4005 } 4006 if (curToken == OP_EQU || curToken == COLON_EQUAL_TOKEN) 4007 { 4008 warnOldVersion("extra '=' in default namespace declaration"); 4009 getRawToken(); 4010 } 4011 if (curToken != STRING_TOKEN) 4012 return declError("missing namespace uri"); 4013 uri = new String (tokenBuffer, 0, tokenBufferLength); 4014 if (forFunctions) 4015 { 4016 functionNamespacePath = new Namespace[1]; 4017 functionNamespacePath[0] = Namespace.getInstance(uri); 4018 } 4019 else 4020 { 4021 defaultElementNamespace = uri; 4022 } 4023 pushNamespace(prefix, uri); 4024 checkAllowedNamespaceDeclaration(prefix, uri); 4025 parseSeparator(); 4026 return QuoteExp.voidExp; 4027 4028 case DECLARE_BOUNDARY_SPACE_TOKEN: 4029 getRawToken(); 4030 if (curToken == OP_EQU) 4031 { 4032 warnOldVersion("obsolate '=' in boundary-space declaration"); 4033 getRawToken(); 4034 } 4035 if (boundarySpaceDeclarationSeen && ! interactive) 4036 syntaxError("duplicate 'declare boundary-space' seen", "XQST0068"); 4037 boundarySpaceDeclarationSeen = true; 4038 if (match("preserve")) 4039 boundarySpacePreserve = true; 4040 else if (match("strip")) 4041 boundarySpacePreserve = false; 4042 else if (match("skip")) 4043 { 4044 warnOldVersion("update: declare boundary-space skip -> strip"); 4045 boundarySpacePreserve = false; 4046 } 4047 else 4048 return syntaxError("boundary-space declaration must be preserve or strip"); 4049 parseSeparator(); 4050 return QuoteExp.voidExp; 4051 4052 case DECLARE_CONSTRUCTION_TOKEN: 4053 getRawToken(); 4054 if (constructionModeDeclarationSeen && ! interactive) 4055 syntaxError("duplicate 'declare construction' seen", "XQST0067"); 4056 constructionModeDeclarationSeen = true; 4057 if (match("strip")) 4058 constructionModeStrip = true; 4059 else if (match("preserve")) 4060 constructionModeStrip = false; 4061 else 4062 return syntaxError("construction declaration must be strip or preserve"); 4063 parseSeparator(); 4064 return QuoteExp.voidExp; 4065 4066 case DECLARE_COPY_NAMESPACES_TOKEN: 4067 getRawToken(); 4068 if (copyNamespacesDeclarationSeen && ! interactive) 4069 syntaxError("duplicate 'declare copy-namespaces' seen", "XQST0055"); 4070 copyNamespacesDeclarationSeen = true; 4071 if (match("preserve")) 4072 copyNamespacesMode |= XMLFilter.COPY_NAMESPACES_PRESERVE; 4073 else if (match("no-preserve")) 4074 copyNamespacesMode &= ~XMLFilter.COPY_NAMESPACES_PRESERVE; 4075 else 4076 return syntaxError("expected 'preserve' or 'no-preserve' after 'declare copy-namespaces'"); 4077 getRawToken(); 4078 if (curToken != ',') 4079 return syntaxError("missing ',' in copy-namespaces declaration"); 4080 getRawToken(); 4081 if (match("inherit")) 4082 copyNamespacesMode |= XMLFilter.COPY_NAMESPACES_INHERIT; 4083 else if (match("no-inherit")) 4084 copyNamespacesMode &= ~XMLFilter.COPY_NAMESPACES_INHERIT; 4085 else 4086 return syntaxError("expected 'inherit' or 'no-inherit' in copy-namespaces declaration"); 4087 parseSeparator(); 4088 return QuoteExp.voidExp; 4089 4090 case DEFAULT_ORDER_TOKEN: 4091 getRawToken(); 4092 boolean sawEmpty = match("empty"); 4093 if (emptyOrderDeclarationSeen && ! interactive) 4094 syntaxError("duplicate 'declare default empty order' seen", "XQST0069"); 4095 emptyOrderDeclarationSeen = true; 4096 if (sawEmpty) 4097 getRawToken(); 4098 else 4099 syntaxError("expected 'empty greatest' or 'empty least'"); 4100 if (match("greatest")) 4101 defaultEmptyOrder = 'G'; 4102 else if (match("least")) 4103 defaultEmptyOrder = 'L'; 4104 else 4105 return syntaxError("expected 'empty greatest' or 'empty least'"); 4106 parseSeparator(); 4107 return QuoteExp.voidExp; 4108 4109 case DECLARE_OPTION_TOKEN: 4110 getRawToken(); 4111 if (curToken != QNAME_TOKEN) 4112 syntaxError("expected QName after 'declare option'"); 4113 else 4114 { 4115 String str = new String (tokenBuffer, 0, tokenBufferLength); 4116 getRawToken(); 4117 if (curToken != STRING_TOKEN) 4118 syntaxError("expected string literal after 'declare option <QName>'"); 4119 else 4120 handleOption(namespaceResolve(str, false), 4121 new String (tokenBuffer, 0, tokenBufferLength)); 4122 } 4123 parseSeparator(); 4124 seenDeclaration = true; 4125 return QuoteExp.voidExp; 4126 4127 case DECLARE_ORDERING_TOKEN: 4128 if (orderingModeSeen && ! interactive) 4129 syntaxError("duplicate 'declare ordering' seen", "XQST0065"); 4130 orderingModeSeen = true; 4131 getRawToken(); 4132 if (match("ordered")) 4133 orderingModeUnordered = false; 4134 else if (match("unordered")) 4135 orderingModeUnordered = true; 4136 else 4137 return syntaxError("ordering declaration must be ordered or unordered"); 4138 parseSeparator(); 4139 return QuoteExp.voidExp; 4140 4141 case XQUERY_VERSION_TOKEN: 4142 if (parseCount != 1) 4143 error('e', "'xquery version' does not start module"); 4144 else if (commentCount > 0) 4145 error('w', "comments should not precede 'xquery version'"); 4146 getRawToken(); 4147 if (curToken == STRING_TOKEN) 4148 { 4149 String version = new String (tokenBuffer, 0, tokenBufferLength); 4150 if (! version.equals("1.0")) 4151 error('e', "unrecognized xquery version "+version, "XQST0031"); 4152 getRawToken(); 4153 } 4154 else 4155 return syntaxError("missing version string after 'xquery version'"); 4156 if (match("encoding")) 4157 { 4158 getRawToken(); 4159 if (curToken != STRING_TOKEN) 4160 return syntaxError("invalid encoding specification"); 4161 else 4162 { 4163 String encoding = new String (tokenBuffer, 0, tokenBufferLength); 4164 int i = tokenBufferLength; 4165 boolean bad = i == 0; 4166 while (--i >= 0 && ! bad) 4167 { 4168 ch = tokenBuffer[i]; 4169 if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) 4170 continue; 4171 if (i == 0 4172 || ! ((ch >= '0' && ch <= '9') 4173 || ch == '.' || ch == '_' || ch == '-')) 4174 bad = true; 4175 } 4176 if (bad) 4177 error('e', "invalid encoding name syntax", "XQST0087"); 4178 getRawToken(); 4180 } 4181 } 4182 if (curToken != ';') 4183 syntaxError("missing ';'"); 4184 return QuoteExp.voidExp; 4185 4186 case DECLARE_BASE_URI_TOKEN: 4187 if (baseURIDeclarationSeen && ! interactive) 4188 syntaxError("duplicate 'declare base-uri' seen", "XQST0032"); 4189 baseURIDeclarationSeen = true; 4190 val = parseURILiteral(); 4191 if (val instanceof Expression) return (Expression) val; 4193 parseSeparator(); 4194 baseURI = (String ) val; 4195 return QuoteExp.voidExp; 4196 } 4197 exp = parseExprSequence(EOF_TOKEN, true); 4198 if (curToken == EOL_TOKEN) 4199 unread('\n'); 4200 exp.setFile(getName()); 4201 exp.setLine(startLine, startColumn); 4202 return exp; 4203 } 4204 4205 public void handleOption (Symbol name, String value) 4206 { 4207 } 4209 4210 public final static String [] axisNames = new String [COUNT_OP_AXIS]; 4211 static 4212 { 4213 axisNames[AXIS_ANCESTOR] = "ancestor"; 4214 axisNames[AXIS_ANCESTOR_OR_SELF] = "ancestor-or-self"; 4215 axisNames[AXIS_ATTRIBUTE] = "attribute"; 4216 axisNames[AXIS_CHILD] = "child"; 4217 axisNames[AXIS_DESCENDANT] = "descendant"; 4218 axisNames[AXIS_DESCENDANT_OR_SELF] = "descendant-or-self"; 4219 axisNames[AXIS_FOLLOWING] = "following"; 4220 axisNames[AXIS_FOLLOWING_SIBLING] = "following-sibling"; 4221 axisNames[AXIS_NAMESPACE] = "namespace"; 4222 axisNames[AXIS_PARENT] = "parent"; 4223 axisNames[AXIS_PRECEDING] = "preceding"; 4224 axisNames[AXIS_PRECEDING_SIBLING] = "preceding-sibling"; 4225 axisNames[AXIS_SELF] = "self"; 4226 } 4227 4228 public static Expression makeFunctionExp(String className, String name) 4229 { 4230 return makeFunctionExp(className, 4231 Compilation.mangleNameIfNeeded(name), 4232 name); 4233 } 4234 4235 public static Expression makeFunctionExp(String className, 4236 String fieldName, String name) 4237 { 4238 return new ReferenceExp(name, 4239 Declaration.getDeclarationValueFromStatic 4240 (className, fieldName, name)); 4241 } 4242 4243 4244 String tokenString() 4245 { 4246 switch (curToken) 4247 { 4248 case STRING_TOKEN: 4249 StringBuffer sbuf = new StringBuffer (); 4250 sbuf.append('"'); 4251 for (int i = 0; i < tokenBufferLength; i++) 4252 { 4253 char ch = tokenBuffer[i]; 4254 if (ch == '"') 4255 sbuf.append('"'); 4256 sbuf.append(ch); 4257 } 4258 sbuf.append('"'); 4259 return sbuf.toString(); 4260 case FNAME_TOKEN: 4261 return new String (tokenBuffer, 0, tokenBufferLength) + " + '('"; 4262 case NCNAME_TOKEN: 4263 case QNAME_TOKEN: 4264 return new String (tokenBuffer, 0, tokenBufferLength); 4265 case EOF_TOKEN: 4266 return "<EOF>"; 4267 default: 4268 if (curToken >= OP_AXIS_FIRST 4269 && curToken - OP_AXIS_FIRST < COUNT_OP_AXIS) 4270 return axisNames[curToken - OP_AXIS_FIRST]+"::-axis("+curToken+")"; 4271 return Integer.toString(curToken); 4272 } 4273 } 4274 4275 public void error(char severity, String message, String code) 4276 { 4277 SourceMessages messages = getMessages(); 4278 SourceError err 4279 = new SourceError(severity, port.getName(), curLine, curColumn, message); 4280 err.code = code; 4281 messages.error(err); 4282 } 4283 4284 public void error(char severity, String message) 4285 { 4286 error(severity, message, null); 4287 } 4288 4289 public Expression declError (String message) 4290 throws java.io.IOException , SyntaxException 4291 { 4292 if (interactive) 4293 return syntaxError(message); 4294 error(message); 4295 for (;;) 4296 { 4297 if (curToken==';' || curToken == EOF_TOKEN) 4298 break; 4299 getRawToken(); 4300 } 4301 return new ErrorExp (message); 4302 } 4303 4304 4309 public Expression syntaxError (String message, String code) 4310 throws java.io.IOException , SyntaxException 4311 { 4312 error('e', message, code); 4313 if (interactive) 4314 { 4315 curToken = 0; 4316 curValue = null; 4317 nesting = 0; 4318 ((InPort) getPort()).readState = '\n'; 4319 for (;;) 4320 { 4321 int ch = read(); 4322 if (ch < 0) 4323 break; 4324 if (ch == '\r' || ch == '\n') 4325 { 4326 unread(ch); 4327 break; 4328 } 4329 } 4330 throw new SyntaxException(getMessages()); 4331 } 4332 return new ErrorExp (message); 4333 } 4334 4335 public Expression syntaxError (String message) 4336 throws java.io.IOException , SyntaxException 4337 { 4338 return syntaxError(message, "XPST0003"); 4339 } 4340 4341 public void eofError(String msg) throws SyntaxException 4342 { 4343 fatal(msg, "XPST0003"); 4344 } 4345 4346 public void fatal(String msg, String code) throws SyntaxException 4347 { 4348 SourceMessages messages = getMessages(); 4349 SourceError err 4350 = new SourceError('f', port.getName(), curLine, curColumn, msg); 4351 err.code = code; 4352 messages.error(err); 4353 throw new SyntaxException(messages); 4354 } 4355 4356 void warnOldVersion (String message) 4357 { 4358 if (warnOldVersion || comp.isPedantic()) 4359 error(comp.isPedantic() ? 'e' : 'w', message); 4360 } 4361} 4362 | Popular Tags |