1 36 38 package com.google.gwt.dev.js.rhino; 39 40 import java.io.IOException ; 41 42 53 54 public class Parser { 55 56 public Parser(IRFactory nf) { 57 this.nf = nf; 58 } 59 60 private void mustMatchToken(TokenStream ts, int toMatch, String messageId) 61 throws IOException , JavaScriptException { 62 int tt; 63 if ((tt = ts.getToken()) != toMatch) { 64 reportError(ts, messageId); 65 ts.ungetToken(tt); } 67 } 68 69 private void reportError(TokenStream ts, String messageId) 70 throws JavaScriptException { 71 this.ok = false; 72 ts.reportSyntaxError(messageId, null); 73 74 79 throw new JavaScriptException(messageId); 80 } 81 82 91 public Object parse(TokenStream ts) throws IOException { 92 this.ok = true; 93 sourceTop = 0; 94 functionNumber = 0; 95 96 int tt; int baseLineno = ts.getLineno(); 99 102 Object tempBlock = nf.createLeaf(TokenStream.BLOCK); 103 ((Node) tempBlock).setIsSyntheticBlock(true); 104 105 while (true) { 106 ts.flags |= ts.TSF_REGEXP; 107 tt = ts.getToken(); 108 ts.flags &= ~ts.TSF_REGEXP; 109 110 if (tt <= ts.EOF) { 111 break; 112 } 113 114 if (tt == ts.FUNCTION) { 115 try { 116 nf.addChildToBack(tempBlock, function(ts, false)); 117 } catch (JavaScriptException e) { 118 this.ok = false; 119 break; 120 } 121 } else { 122 ts.ungetToken(tt); 123 nf.addChildToBack(tempBlock, statement(ts)); 124 } 125 } 126 127 if (!this.ok) { 128 return null; 130 } 131 132 Object pn = nf.createScript(tempBlock, ts.getSourceName(), baseLineno, ts 133 .getLineno(), sourceToString(0)); 134 ((Node) pn).setIsSyntheticBlock(true); 135 return pn; 136 } 137 138 143 private Object parseFunctionBody(TokenStream ts) throws IOException { 144 int oldflags = ts.flags; 145 ts.flags &= ~(TokenStream.TSF_RETURN_EXPR | TokenStream.TSF_RETURN_VOID); 146 ts.flags |= TokenStream.TSF_FUNCTION; 147 148 Object pn = nf.createBlock(ts.getLineno()); 149 try { 150 int tt; 151 while ((tt = ts.peekToken()) > ts.EOF && tt != ts.RC) { 152 if (tt == TokenStream.FUNCTION) { 153 ts.getToken(); 154 nf.addChildToBack(pn, function(ts, false)); 155 } else { 156 nf.addChildToBack(pn, statement(ts)); 157 } 158 } 159 } catch (JavaScriptException e) { 160 this.ok = false; 161 } finally { 162 165 ts.flags = oldflags; 166 } 167 168 return pn; 169 } 170 171 private Object function(TokenStream ts, boolean isExpr) throws IOException , 172 JavaScriptException { 173 int baseLineno = ts.getLineno(); 175 String name; 176 Object memberExprNode = null; 177 if (ts.matchToken(ts.NAME)) { 178 name = ts.getString(); 179 if (!ts.matchToken(ts.LP)) { 180 if (Context.getContext().hasFeature( 181 Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME)) { 182 sourceAddString(ts.NAME, name); 185 Object memberExprHead = nf.createName(name); 186 name = null; 187 memberExprNode = memberExprTail(ts, false, memberExprHead); 188 } 189 mustMatchToken(ts, ts.LP, "msg.no.paren.parms"); 190 } 191 } else if (ts.matchToken(ts.LP)) { 192 name = null; 194 } else { 195 name = null; 196 if (Context.getContext().hasFeature( 197 Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME)) { 198 memberExprNode = memberExpr(ts, false); 202 } 203 mustMatchToken(ts, ts.LP, "msg.no.paren.parms"); 204 } 205 206 if (memberExprNode != null) { 207 sourceAdd((char) ts.ASSIGN); 210 sourceAdd((char) ts.NOP); 211 } 212 213 sourceAdd((char) ts.FUNCTION); 215 sourceAdd((char) functionNumber); 216 ++functionNumber; 217 218 int savedSourceTop = sourceTop; 221 int savedFunctionNumber = functionNumber; 222 Object args; 223 Object body; 224 String source; 225 try { 226 functionNumber = 0; 227 228 sourceAdd((char) ts.FUNCTION); 231 if (name != null) { 232 sourceAddString(ts.NAME, name); 233 } 234 sourceAdd((char) ts.LP); 235 args = nf.createLeaf(ts.LP); 236 237 if (!ts.matchToken(ts.GWT)) { 238 boolean first = true; 239 do { 240 if (!first) 241 sourceAdd((char) ts.COMMA); 242 first = false; 243 mustMatchToken(ts, ts.NAME, "msg.no.parm"); 244 String s = ts.getString(); 245 nf.addChildToBack(args, nf.createName(s)); 246 247 sourceAddString(ts.NAME, s); 248 } while (ts.matchToken(ts.COMMA)); 249 250 mustMatchToken(ts, ts.GWT, "msg.no.paren.after.parms"); 251 } 252 sourceAdd((char) ts.GWT); 253 254 mustMatchToken(ts, ts.LC, "msg.no.brace.body"); 255 sourceAdd((char) ts.LC); 256 sourceAdd((char) ts.EOL); 257 body = parseFunctionBody(ts); 258 mustMatchToken(ts, ts.RC, "msg.no.brace.after.body"); 259 sourceAdd((char) ts.RC); 260 262 source = sourceToString(savedSourceTop); 264 } finally { 265 sourceTop = savedSourceTop; 266 functionNumber = savedFunctionNumber; 267 } 268 269 Object pn = nf.createFunction(name, args, body, ts.getSourceName(), 270 baseLineno, ts.getLineno(), source, isExpr || memberExprNode != null); 271 if (memberExprNode != null) { 272 pn = nf.createBinary(ts.ASSIGN, ts.NOP, memberExprNode, pn); 273 } 274 275 if (!isExpr) { 278 if (memberExprNode != null) { 279 sourceAdd((char) ts.SEMI); 282 } 283 sourceAdd((char) ts.EOL); 284 wellTerminated(ts, ts.FUNCTION); 285 } 286 287 return pn; 288 } 289 290 private Object statements(TokenStream ts) throws IOException { 291 Object pn = nf.createBlock(ts.getLineno()); 292 293 int tt; 294 while ((tt = ts.peekToken()) > ts.EOF && tt != ts.RC) { 295 nf.addChildToBack(pn, statement(ts)); 296 } 297 298 return pn; 299 } 300 301 private Object condition(TokenStream ts) throws IOException , 302 JavaScriptException { 303 Object pn; 304 mustMatchToken(ts, ts.LP, "msg.no.paren.cond"); 305 sourceAdd((char) ts.LP); 306 pn = expr(ts, false); 307 mustMatchToken(ts, ts.GWT, "msg.no.paren.after.cond"); 308 sourceAdd((char) ts.GWT); 309 310 312 return pn; 313 } 314 315 private boolean wellTerminated(TokenStream ts, int lastExprType) 316 throws IOException , JavaScriptException { 317 int tt = ts.peekTokenSameLine(); 318 if (tt == ts.ERROR) { 319 return false; 320 } 321 322 if (tt != ts.EOF && tt != ts.EOL && tt != ts.SEMI && tt != ts.RC) { 323 int version = Context.getContext().getLanguageVersion(); 324 if ((tt == ts.FUNCTION || lastExprType == ts.FUNCTION) 325 && (version < Context.VERSION_1_2)) { 326 331 return true; 332 } else { 333 reportError(ts, "msg.no.semi.stmt"); 334 } 335 } 336 return true; 337 } 338 339 private String matchLabel(TokenStream ts) throws IOException , 341 JavaScriptException { 342 int lineno = ts.getLineno(); 343 344 String label = null; 345 int tt; 346 tt = ts.peekTokenSameLine(); 347 if (tt == ts.NAME) { 348 ts.getToken(); 349 label = ts.getString(); 350 } 351 352 if (lineno == ts.getLineno()) 353 wellTerminated(ts, ts.ERROR); 354 355 return label; 356 } 357 358 private Object statement(TokenStream ts) throws IOException { 359 try { 360 return statementHelper(ts); 361 } catch (JavaScriptException e) { 362 int lineno = ts.getLineno(); 364 int t; 365 do { 366 t = ts.getToken(); 367 } while (t != TokenStream.SEMI && t != TokenStream.EOL 368 && t != TokenStream.EOF && t != TokenStream.ERROR); 369 return nf.createExprStatement(nf.createName("error"), lineno); 370 } 371 } 372 373 377 378 private Object statementHelper(TokenStream ts) throws IOException , 379 JavaScriptException { 380 Object pn = null; 381 382 boolean skipsemi = false; 385 386 int tt; 387 388 int lastExprType = 0; 390 tt = ts.getToken(); 391 392 switch (tt) { 393 case TokenStream.IF: { 394 skipsemi = true; 395 396 sourceAdd((char) ts.IF); 397 int lineno = ts.getLineno(); 398 Object cond = condition(ts); 399 sourceAdd((char) ts.LC); 400 sourceAdd((char) ts.EOL); 401 Object ifTrue = statement(ts); 402 Object ifFalse = null; 403 if (ts.matchToken(ts.ELSE)) { 404 sourceAdd((char) ts.RC); 405 sourceAdd((char) ts.ELSE); 406 sourceAdd((char) ts.LC); 407 sourceAdd((char) ts.EOL); 408 ifFalse = statement(ts); 409 } 410 sourceAdd((char) ts.RC); 411 sourceAdd((char) ts.EOL); 412 pn = nf.createIf(cond, ifTrue, ifFalse, lineno); 413 break; 414 } 415 416 case TokenStream.SWITCH: { 417 skipsemi = true; 418 419 sourceAdd((char) ts.SWITCH); 420 pn = nf.createSwitch(ts.getLineno()); 421 422 Object cur_case = null; Object case_statements; 424 425 mustMatchToken(ts, ts.LP, "msg.no.paren.switch"); 426 sourceAdd((char) ts.LP); 427 nf.addChildToBack(pn, expr(ts, false)); 428 mustMatchToken(ts, ts.GWT, "msg.no.paren.after.switch"); 429 sourceAdd((char) ts.GWT); 430 mustMatchToken(ts, ts.LC, "msg.no.brace.switch"); 431 sourceAdd((char) ts.LC); 432 sourceAdd((char) ts.EOL); 433 434 while ((tt = ts.getToken()) != ts.RC && tt != ts.EOF) { 435 switch (tt) { 436 case TokenStream.CASE: 437 sourceAdd((char) ts.CASE); 438 cur_case = nf.createUnary(ts.CASE, expr(ts, false)); 439 sourceAdd((char) ts.COLON); 440 sourceAdd((char) ts.EOL); 441 break; 442 443 case TokenStream.DEFAULT: 444 cur_case = nf.createLeaf(ts.DEFAULT); 445 sourceAdd((char) ts.DEFAULT); 446 sourceAdd((char) ts.COLON); 447 sourceAdd((char) ts.EOL); 448 break; 450 451 default: 452 reportError(ts, "msg.bad.switch"); 453 break; 454 } 455 mustMatchToken(ts, ts.COLON, "msg.no.colon.case"); 456 457 case_statements = nf.createLeaf(TokenStream.BLOCK); 458 ((Node) case_statements).setIsSyntheticBlock(true); 459 460 while ((tt = ts.peekToken()) != ts.RC && tt != ts.CASE 461 && tt != ts.DEFAULT && tt != ts.EOF) { 462 nf.addChildToBack(case_statements, statement(ts)); 463 } 464 nf.addChildToBack(cur_case, case_statements); 466 467 nf.addChildToBack(pn, cur_case); 468 } 469 sourceAdd((char) ts.RC); 470 sourceAdd((char) ts.EOL); 471 break; 472 } 473 474 case TokenStream.WHILE: { 475 skipsemi = true; 476 477 sourceAdd((char) ts.WHILE); 478 int lineno = ts.getLineno(); 479 Object cond = condition(ts); 480 sourceAdd((char) ts.LC); 481 sourceAdd((char) ts.EOL); 482 Object body = statement(ts); 483 sourceAdd((char) ts.RC); 484 sourceAdd((char) ts.EOL); 485 486 pn = nf.createWhile(cond, body, lineno); 487 break; 488 489 } 490 491 case TokenStream.DO: { 492 sourceAdd((char) ts.DO); 493 sourceAdd((char) ts.LC); 494 sourceAdd((char) ts.EOL); 495 496 int lineno = ts.getLineno(); 497 498 Object body = statement(ts); 499 500 sourceAdd((char) ts.RC); 501 mustMatchToken(ts, ts.WHILE, "msg.no.while.do"); 502 sourceAdd((char) ts.WHILE); 503 Object cond = condition(ts); 504 505 pn = nf.createDoWhile(body, cond, lineno); 506 break; 507 } 508 509 case TokenStream.FOR: { 510 skipsemi = true; 511 512 sourceAdd((char) ts.FOR); 513 int lineno = ts.getLineno(); 514 515 Object init; Object cond; Object incr = null; Object body; 519 520 mustMatchToken(ts, ts.LP, "msg.no.paren.for"); 521 sourceAdd((char) ts.LP); 522 tt = ts.peekToken(); 523 if (tt == ts.SEMI) { 524 init = nf.createLeaf(ts.VOID); 525 } else { 526 if (tt == ts.VAR) { 527 ts.getToken(); init = variables(ts, true); 530 } else { 531 init = expr(ts, true); 532 } 533 } 534 535 tt = ts.peekToken(); 536 if (tt == ts.RELOP && ts.getOp() == ts.IN) { 537 ts.matchToken(ts.RELOP); 538 sourceAdd((char) ts.IN); 539 cond = expr(ts, false); 541 } else { mustMatchToken(ts, ts.SEMI, "msg.no.semi.for"); 543 sourceAdd((char) ts.SEMI); 544 if (ts.peekToken() == ts.SEMI) { 545 cond = nf.createLeaf(ts.VOID); 547 } else { 548 cond = expr(ts, false); 549 } 550 551 mustMatchToken(ts, ts.SEMI, "msg.no.semi.for.cond"); 552 sourceAdd((char) ts.SEMI); 553 if (ts.peekToken() == ts.GWT) { 554 incr = nf.createLeaf(ts.VOID); 555 } else { 556 incr = expr(ts, false); 557 } 558 } 559 560 mustMatchToken(ts, ts.GWT, "msg.no.paren.for.ctrl"); 561 sourceAdd((char) ts.GWT); 562 sourceAdd((char) ts.LC); 563 sourceAdd((char) ts.EOL); 564 body = statement(ts); 565 sourceAdd((char) ts.RC); 566 sourceAdd((char) ts.EOL); 567 568 if (incr == null) { 569 pn = nf.createForIn(init, cond, body, lineno); 571 } else { 572 pn = nf.createFor(init, cond, incr, body, lineno); 573 } 574 break; 575 } 576 577 case TokenStream.TRY: { 578 int lineno = ts.getLineno(); 579 580 Object tryblock; 581 Object catchblocks = null; 582 Object finallyblock = null; 583 584 skipsemi = true; 585 sourceAdd((char) ts.TRY); 586 sourceAdd((char) ts.LC); 587 sourceAdd((char) ts.EOL); 588 tryblock = statement(ts); 589 sourceAdd((char) ts.RC); 590 sourceAdd((char) ts.EOL); 591 592 catchblocks = nf.createLeaf(TokenStream.BLOCK); 593 594 boolean sawDefaultCatch = false; 595 int peek = ts.peekToken(); 596 if (peek == ts.CATCH) { 597 while (ts.matchToken(ts.CATCH)) { 598 if (sawDefaultCatch) { 599 reportError(ts, "msg.catch.unreachable"); 600 } 601 sourceAdd((char) ts.CATCH); 602 mustMatchToken(ts, ts.LP, "msg.no.paren.catch"); 603 sourceAdd((char) ts.LP); 604 605 mustMatchToken(ts, ts.NAME, "msg.bad.catchcond"); 606 String varName = ts.getString(); 607 sourceAddString(ts.NAME, varName); 608 609 Object catchCond = null; 610 if (ts.matchToken(ts.IF)) { 611 sourceAdd((char) ts.IF); 612 catchCond = expr(ts, false); 613 } else { 614 sawDefaultCatch = true; 615 } 616 617 mustMatchToken(ts, ts.GWT, "msg.bad.catchcond"); 618 sourceAdd((char) ts.GWT); 619 mustMatchToken(ts, ts.LC, "msg.no.brace.catchblock"); 620 sourceAdd((char) ts.LC); 621 sourceAdd((char) ts.EOL); 622 623 nf.addChildToBack(catchblocks, nf.createCatch(varName, catchCond, 624 statements(ts), ts.getLineno())); 625 626 mustMatchToken(ts, ts.RC, "msg.no.brace.after.body"); 627 sourceAdd((char) ts.RC); 628 sourceAdd((char) ts.EOL); 629 } 630 } else if (peek != ts.FINALLY) { 631 mustMatchToken(ts, ts.FINALLY, "msg.try.no.catchfinally"); 632 } 633 634 if (ts.matchToken(ts.FINALLY)) { 635 sourceAdd((char) ts.FINALLY); 636 637 sourceAdd((char) ts.LC); 638 sourceAdd((char) ts.EOL); 639 finallyblock = statement(ts); 640 sourceAdd((char) ts.RC); 641 sourceAdd((char) ts.EOL); 642 } 643 644 pn = nf.createTryCatchFinally(tryblock, catchblocks, finallyblock, 645 lineno); 646 647 break; 648 } 649 case TokenStream.THROW: { 650 int lineno = ts.getLineno(); 651 sourceAdd((char) ts.THROW); 652 pn = nf.createThrow(expr(ts, false), lineno); 653 if (lineno == ts.getLineno()) 654 wellTerminated(ts, ts.ERROR); 655 break; 656 } 657 case TokenStream.BREAK: { 658 int lineno = ts.getLineno(); 659 660 sourceAdd((char) ts.BREAK); 661 662 String label = matchLabel(ts); 664 if (label != null) { 665 sourceAddString(ts.NAME, label); 666 } 667 pn = nf.createBreak(label, lineno); 668 break; 669 } 670 case TokenStream.CONTINUE: { 671 int lineno = ts.getLineno(); 672 673 sourceAdd((char) ts.CONTINUE); 674 675 String label = matchLabel(ts); 677 if (label != null) { 678 sourceAddString(ts.NAME, label); 679 } 680 pn = nf.createContinue(label, lineno); 681 break; 682 } 683 case TokenStream.DEBUGGER: { 684 int lineno = ts.getLineno(); 685 686 sourceAdd((char) ts.DEBUGGER); 687 688 pn = nf.createDebugger(lineno); 689 break; 690 } 691 case TokenStream.WITH: { 692 696 reportError(ts, "msg.jsni.unsupported.with"); 697 698 skipsemi = true; 699 700 sourceAdd((char) ts.WITH); 701 int lineno = ts.getLineno(); 702 mustMatchToken(ts, ts.LP, "msg.no.paren.with"); 703 sourceAdd((char) ts.LP); 704 Object obj = expr(ts, false); 705 mustMatchToken(ts, ts.GWT, "msg.no.paren.after.with"); 706 sourceAdd((char) ts.GWT); 707 sourceAdd((char) ts.LC); 708 sourceAdd((char) ts.EOL); 709 710 Object body = statement(ts); 711 712 sourceAdd((char) ts.RC); 713 sourceAdd((char) ts.EOL); 714 715 pn = nf.createWith(obj, body, lineno); 716 break; 717 } 718 case TokenStream.VAR: { 719 int lineno = ts.getLineno(); 720 pn = variables(ts, false); 721 if (ts.getLineno() == lineno) 722 wellTerminated(ts, ts.ERROR); 723 break; 724 } 725 case TokenStream.RETURN: { 726 Object retExpr = null; 727 int lineno = 0; 728 729 sourceAdd((char) ts.RETURN); 730 731 if ((ts.flags & ts.TSF_FUNCTION) == 0) 733 reportError(ts, "msg.bad.return"); 734 735 736 ts.flags |= ts.TSF_REGEXP; 737 tt = ts.peekTokenSameLine(); 738 ts.flags &= ~ts.TSF_REGEXP; 739 740 if (tt != ts.EOF && tt != ts.EOL && tt != ts.SEMI && tt != ts.RC) { 741 lineno = ts.getLineno(); 742 retExpr = expr(ts, false); 743 if (ts.getLineno() == lineno) 744 wellTerminated(ts, ts.ERROR); 745 ts.flags |= ts.TSF_RETURN_EXPR; 746 } else { 747 ts.flags |= ts.TSF_RETURN_VOID; 748 } 749 750 pn = nf.createReturn(retExpr, lineno); 752 break; 753 } 754 case TokenStream.LC: 755 skipsemi = true; 756 757 pn = statements(ts); 758 mustMatchToken(ts, ts.RC, "msg.no.brace.block"); 759 break; 760 761 case TokenStream.ERROR: 762 case TokenStream.EOL: 764 case TokenStream.SEMI: 765 pn = nf.createLeaf(ts.VOID); 766 skipsemi = true; 767 break; 768 769 default: { 770 lastExprType = tt; 771 int tokenno = ts.getTokenno(); 772 ts.ungetToken(tt); 773 int lineno = ts.getLineno(); 774 775 pn = expr(ts, false); 776 777 if (ts.peekToken() == ts.COLON) { 778 782 if (lastExprType != ts.NAME || (ts.getTokenno() != tokenno)) 783 reportError(ts, "msg.bad.label"); 784 785 ts.getToken(); 787 791 String name = ts.getString(); 792 pn = nf.createLabel(name, lineno); 793 794 nf.addChildToBack(pn, statement(ts)); 798 799 sourceAdd((char) ts.COLON); 802 sourceAdd((char) ts.EOL); 803 return pn; 804 } 805 806 if (lastExprType == ts.FUNCTION) { 807 if (nf.getLeafType(pn) != ts.FUNCTION) { 808 reportError(ts, "msg.syntax"); 809 } 810 } 811 812 pn = nf.createExprStatement(pn, lineno); 813 814 823 if (ts.getLineno() == lineno 824 || (lastExprType == ts.FUNCTION && ts.getLineno() == lastExprEndLine)) { 825 wellTerminated(ts, lastExprType); 826 } 827 break; 828 } 829 } 830 ts.matchToken(ts.SEMI); 831 if (!skipsemi) { 832 sourceAdd((char) ts.SEMI); 833 sourceAdd((char) ts.EOL); 834 } 835 836 return pn; 837 } 838 839 private Object variables(TokenStream ts, boolean inForInit) 840 throws IOException , JavaScriptException { 841 Object pn = nf.createVariables(ts.getLineno()); 842 boolean first = true; 843 844 sourceAdd((char) ts.VAR); 845 846 for (;;) { 847 Object name; 848 Object init; 849 mustMatchToken(ts, ts.NAME, "msg.bad.var"); 850 String s = ts.getString(); 851 852 if (!first) 853 sourceAdd((char) ts.COMMA); 854 first = false; 855 856 sourceAddString(ts.NAME, s); 857 name = nf.createName(s); 858 859 861 if (ts.matchToken(ts.ASSIGN)) { 862 if (ts.getOp() != ts.NOP) 863 reportError(ts, "msg.bad.var.init"); 864 865 sourceAdd((char) ts.ASSIGN); 866 sourceAdd((char) ts.NOP); 867 868 init = assignExpr(ts, inForInit); 869 nf.addChildToBack(name, init); 870 } 871 nf.addChildToBack(pn, name); 872 if (!ts.matchToken(ts.COMMA)) 873 break; 874 } 875 return pn; 876 } 877 878 private Object expr(TokenStream ts, boolean inForInit) throws IOException , 879 JavaScriptException { 880 Object pn = assignExpr(ts, inForInit); 881 while (ts.matchToken(ts.COMMA)) { 882 sourceAdd((char) ts.COMMA); 883 pn = nf.createBinary(ts.COMMA, pn, assignExpr(ts, inForInit)); 884 } 885 return pn; 886 } 887 888 private Object assignExpr(TokenStream ts, boolean inForInit) 889 throws IOException , JavaScriptException { 890 Object pn = condExpr(ts, inForInit); 891 892 if (ts.matchToken(ts.ASSIGN)) { 893 sourceAdd((char) ts.ASSIGN); 895 sourceAdd((char) ts.getOp()); 896 pn = nf 897 .createBinary(ts.ASSIGN, ts.getOp(), pn, assignExpr(ts, inForInit)); 898 } 899 900 return pn; 901 } 902 903 private Object condExpr(TokenStream ts, boolean inForInit) 904 throws IOException , JavaScriptException { 905 Object ifTrue; 906 Object ifFalse; 907 908 Object pn = orExpr(ts, inForInit); 909 910 if (ts.matchToken(ts.HOOK)) { 911 sourceAdd((char) ts.HOOK); 912 ifTrue = assignExpr(ts, false); 913 mustMatchToken(ts, ts.COLON, "msg.no.colon.cond"); 914 sourceAdd((char) ts.COLON); 915 ifFalse = assignExpr(ts, inForInit); 916 return nf.createTernary(pn, ifTrue, ifFalse); 917 } 918 919 return pn; 920 } 921 922 private Object orExpr(TokenStream ts, boolean inForInit) throws IOException , 923 JavaScriptException { 924 Object pn = andExpr(ts, inForInit); 925 if (ts.matchToken(ts.OR)) { 926 sourceAdd((char) ts.OR); 927 pn = nf.createBinary(ts.OR, pn, orExpr(ts, inForInit)); 928 } 929 930 return pn; 931 } 932 933 private Object andExpr(TokenStream ts, boolean inForInit) throws IOException , 934 JavaScriptException { 935 Object pn = bitOrExpr(ts, inForInit); 936 if (ts.matchToken(ts.AND)) { 937 sourceAdd((char) ts.AND); 938 pn = nf.createBinary(ts.AND, pn, andExpr(ts, inForInit)); 939 } 940 941 return pn; 942 } 943 944 private Object bitOrExpr(TokenStream ts, boolean inForInit) 945 throws IOException , JavaScriptException { 946 Object pn = bitXorExpr(ts, inForInit); 947 while (ts.matchToken(ts.BITOR)) { 948 sourceAdd((char) ts.BITOR); 949 pn = nf.createBinary(ts.BITOR, pn, bitXorExpr(ts, inForInit)); 950 } 951 return pn; 952 } 953 954 private Object bitXorExpr(TokenStream ts, boolean inForInit) 955 throws IOException , JavaScriptException { 956 Object pn = bitAndExpr(ts, inForInit); 957 while (ts.matchToken(ts.BITXOR)) { 958 sourceAdd((char) ts.BITXOR); 959 pn = nf.createBinary(ts.BITXOR, pn, bitAndExpr(ts, inForInit)); 960 } 961 return pn; 962 } 963 964 private Object bitAndExpr(TokenStream ts, boolean inForInit) 965 throws IOException , JavaScriptException { 966 Object pn = eqExpr(ts, inForInit); 967 while (ts.matchToken(ts.BITAND)) { 968 sourceAdd((char) ts.BITAND); 969 pn = nf.createBinary(ts.BITAND, pn, eqExpr(ts, inForInit)); 970 } 971 return pn; 972 } 973 974 private Object eqExpr(TokenStream ts, boolean inForInit) throws IOException , 975 JavaScriptException { 976 Object pn = relExpr(ts, inForInit); 977 while (ts.matchToken(ts.EQOP)) { 978 sourceAdd((char) ts.EQOP); 979 sourceAdd((char) ts.getOp()); 980 pn = nf.createBinary(ts.EQOP, ts.getOp(), pn, relExpr(ts, inForInit)); 981 } 982 return pn; 983 } 984 985 private Object relExpr(TokenStream ts, boolean inForInit) throws IOException , 986 JavaScriptException { 987 Object pn = shiftExpr(ts); 988 while (ts.matchToken(ts.RELOP)) { 989 int op = ts.getOp(); 990 if (inForInit && op == ts.IN) { 991 ts.ungetToken(ts.RELOP); 992 break; 993 } 994 sourceAdd((char) ts.RELOP); 995 sourceAdd((char) op); 996 pn = nf.createBinary(ts.RELOP, op, pn, shiftExpr(ts)); 997 } 998 return pn; 999 } 1000 1001 private Object shiftExpr(TokenStream ts) throws IOException , 1002 JavaScriptException { 1003 Object pn = addExpr(ts); 1004 while (ts.matchToken(ts.SHOP)) { 1005 sourceAdd((char) ts.SHOP); 1006 sourceAdd((char) ts.getOp()); 1007 pn = nf.createBinary(ts.SHOP, ts.getOp(), pn, addExpr(ts)); 1008 } 1009 return pn; 1010 } 1011 1012 private Object addExpr(TokenStream ts) throws IOException , 1013 JavaScriptException { 1014 int tt; 1015 Object pn = mulExpr(ts); 1016 1017 while ((tt = ts.getToken()) == ts.ADD || tt == ts.SUB) { 1018 sourceAdd((char) tt); 1019 pn = nf.createBinary(tt, pn, mulExpr(ts)); 1021 } 1022 ts.ungetToken(tt); 1023 1024 return pn; 1025 } 1026 1027 private Object mulExpr(TokenStream ts) throws IOException , 1028 JavaScriptException { 1029 int tt; 1030 1031 Object pn = unaryExpr(ts); 1032 1033 while ((tt = ts.peekToken()) == ts.MUL || tt == ts.DIV || tt == ts.MOD) { 1034 tt = ts.getToken(); 1035 sourceAdd((char) tt); 1036 pn = nf.createBinary(tt, pn, unaryExpr(ts)); 1037 } 1038 1039 return pn; 1040 } 1041 1042 private Object unaryExpr(TokenStream ts) throws IOException , 1043 JavaScriptException { 1044 int tt; 1045 1046 ts.flags |= ts.TSF_REGEXP; 1047 tt = ts.getToken(); 1048 ts.flags &= ~ts.TSF_REGEXP; 1049 1050 switch (tt) { 1051 case TokenStream.UNARYOP: 1052 sourceAdd((char) ts.UNARYOP); 1053 sourceAdd((char) ts.getOp()); 1054 return nf.createUnary(ts.UNARYOP, ts.getOp(), unaryExpr(ts)); 1055 1056 case TokenStream.ADD: 1057 case TokenStream.SUB: 1058 sourceAdd((char) ts.UNARYOP); 1059 sourceAdd((char) tt); 1060 return nf.createUnary(ts.UNARYOP, tt, unaryExpr(ts)); 1061 1062 case TokenStream.INC: 1063 case TokenStream.DEC: 1064 sourceAdd((char) tt); 1065 return nf.createUnary(tt, ts.PRE, memberExpr(ts, true)); 1066 1067 case TokenStream.DELPROP: 1068 sourceAdd((char) ts.DELPROP); 1069 return nf.createUnary(ts.DELPROP, unaryExpr(ts)); 1070 1071 case TokenStream.ERROR: 1072 break; 1073 1074 default: 1075 ts.ungetToken(tt); 1076 1077 int lineno = ts.getLineno(); 1078 1079 Object pn = memberExpr(ts, true); 1080 1081 1088 int peeked; 1089 if (((peeked = ts.peekToken()) == ts.INC || peeked == ts.DEC) 1090 && ts.getLineno() == lineno) { 1091 int pf = ts.getToken(); 1092 sourceAdd((char) pf); 1093 return nf.createUnary(pf, ts.POST, pn); 1094 } 1095 return pn; 1096 } 1097 return nf.createName("err"); 1099 } 1100 1101 private Object argumentList(TokenStream ts, Object listNode) 1102 throws IOException , JavaScriptException { 1103 boolean matched; 1104 ts.flags |= ts.TSF_REGEXP; 1105 matched = ts.matchToken(ts.GWT); 1106 ts.flags &= ~ts.TSF_REGEXP; 1107 if (!matched) { 1108 boolean first = true; 1109 do { 1110 if (!first) 1111 sourceAdd((char) ts.COMMA); 1112 first = false; 1113 nf.addChildToBack(listNode, assignExpr(ts, false)); 1114 } while (ts.matchToken(ts.COMMA)); 1115 1116 mustMatchToken(ts, ts.GWT, "msg.no.paren.arg"); 1117 } 1118 sourceAdd((char) ts.GWT); 1119 return listNode; 1120 } 1121 1122 private Object memberExpr(TokenStream ts, boolean allowCallSyntax) 1123 throws IOException , JavaScriptException { 1124 int tt; 1125 1126 Object pn; 1127 1128 1129 ts.flags |= ts.TSF_REGEXP; 1130 tt = ts.peekToken(); 1131 ts.flags &= ~ts.TSF_REGEXP; 1132 if (tt == ts.NEW) { 1133 1134 ts.getToken(); 1135 sourceAdd((char) ts.NEW); 1136 1137 1138 pn = nf.createLeaf(ts.NEW); 1139 nf.addChildToBack(pn, memberExpr(ts, false)); 1140 1141 if (ts.matchToken(ts.LP)) { 1142 sourceAdd((char) ts.LP); 1143 1144 pn = argumentList(ts, pn); 1145 } 1146 1147 1151 1152 1158 tt = ts.peekToken(); 1159 if (tt == ts.LC) { 1160 nf.addChildToBack(pn, primaryExpr(ts)); 1161 } 1162 } else { 1163 pn = primaryExpr(ts); 1164 } 1165 1166 return memberExprTail(ts, allowCallSyntax, pn); 1167 } 1168 1169 private Object memberExprTail(TokenStream ts, boolean allowCallSyntax, 1170 Object pn) throws IOException , JavaScriptException { 1171 lastExprEndLine = ts.getLineno(); 1172 int tt; 1173 while ((tt = ts.getToken()) > ts.EOF) { 1174 if (tt == ts.DOT) { 1175 sourceAdd((char) ts.DOT); 1176 mustMatchToken(ts, ts.NAME, "msg.no.name.after.dot"); 1177 String s = ts.getString(); 1178 sourceAddString(ts.NAME, s); 1179 pn = nf.createBinary(ts.DOT, pn, nf.createName(ts.getString())); 1180 1185 lastExprEndLine = ts.getLineno(); 1186 } else if (tt == ts.LB) { 1187 sourceAdd((char) ts.LB); 1188 pn = nf.createBinary(ts.LB, pn, expr(ts, false)); 1189 1190 mustMatchToken(ts, ts.RB, "msg.no.bracket.index"); 1191 sourceAdd((char) ts.RB); 1192 lastExprEndLine = ts.getLineno(); 1193 } else if (allowCallSyntax && tt == ts.LP) { 1194 1195 1196 pn = nf.createUnary(ts.CALL, pn); 1197 sourceAdd((char) ts.LP); 1198 1199 1200 pn = argumentList(ts, pn); 1201 lastExprEndLine = ts.getLineno(); 1202 } else { 1203 ts.ungetToken(tt); 1204 1205 break; 1206 } 1207 } 1208 return pn; 1209 } 1210 1211 private Object primaryExpr(TokenStream ts) throws IOException , 1212 JavaScriptException { 1213 int tt; 1214 1215 Object pn; 1216 1217 ts.flags |= ts.TSF_REGEXP; 1218 tt = ts.getToken(); 1219 ts.flags &= ~ts.TSF_REGEXP; 1220 1221 switch (tt) { 1222 1223 case TokenStream.FUNCTION: 1224 return function(ts, true); 1225 1226 case TokenStream.LB: { 1227 sourceAdd((char) ts.LB); 1228 pn = nf.createLeaf(ts.ARRAYLIT); 1229 1230 ts.flags |= ts.TSF_REGEXP; 1231 boolean matched = ts.matchToken(ts.RB); 1232 ts.flags &= ~ts.TSF_REGEXP; 1233 1234 if (!matched) { 1235 boolean first = true; 1236 do { 1237 ts.flags |= ts.TSF_REGEXP; 1238 tt = ts.peekToken(); 1239 ts.flags &= ~ts.TSF_REGEXP; 1240 1241 if (!first) 1242 sourceAdd((char) ts.COMMA); 1243 else 1244 first = false; 1245 1246 if (tt == ts.RB) { break; 1248 } 1249 1250 if (tt == ts.COMMA) { 1251 nf.addChildToBack(pn, nf.createLeaf(ts.PRIMARY, ts.UNDEFINED)); 1252 } else { 1253 nf.addChildToBack(pn, assignExpr(ts, false)); 1254 } 1255 1256 } while (ts.matchToken(ts.COMMA)); 1257 mustMatchToken(ts, ts.RB, "msg.no.bracket.arg"); 1258 } 1259 sourceAdd((char) ts.RB); 1260 return nf.createArrayLiteral(pn); 1261 } 1262 1263 case TokenStream.LC: { 1264 pn = nf.createLeaf(ts.OBJLIT); 1265 1266 sourceAdd((char) ts.LC); 1267 if (!ts.matchToken(ts.RC)) { 1268 1269 boolean first = true; 1270 commaloop : do { 1271 Object property; 1272 1273 if (!first) 1274 sourceAdd((char) ts.COMMA); 1275 else 1276 first = false; 1277 1278 tt = ts.getToken(); 1279 switch (tt) { 1280 case TokenStream.NAME: 1282 case TokenStream.STRING: 1283 String s = ts.getString(); 1284 sourceAddString(ts.NAME, s); 1285 property = nf.createString(ts.getString()); 1286 break; 1287 case TokenStream.NUMBER: 1288 double n = ts.getNumber(); 1289 sourceAddNumber(n); 1290 property = nf.createNumber(n); 1291 break; 1292 case TokenStream.RC: 1293 ts.ungetToken(tt); 1295 break commaloop; 1296 default: 1297 reportError(ts, "msg.bad.prop"); 1298 break commaloop; 1299 } 1300 mustMatchToken(ts, ts.COLON, "msg.no.colon.prop"); 1301 1302 sourceAdd((char) ts.OBJLIT); 1305 nf.addChildToBack(pn, property); 1306 nf.addChildToBack(pn, assignExpr(ts, false)); 1307 1308 } while (ts.matchToken(ts.COMMA)); 1309 1310 mustMatchToken(ts, ts.RC, "msg.no.brace.prop"); 1311 } 1312 sourceAdd((char) ts.RC); 1313 return nf.createObjectLiteral(pn); 1314 } 1315 1316 case TokenStream.LP: 1317 1318 1324 sourceAdd((char) ts.LP); 1325 pn = expr(ts, false); 1326 sourceAdd((char) ts.GWT); 1327 mustMatchToken(ts, ts.GWT, "msg.no.paren"); 1328 return pn; 1329 1330 case TokenStream.NAME: 1331 String name = ts.getString(); 1332 sourceAddString(ts.NAME, name); 1333 return nf.createName(name); 1334 1335 case TokenStream.NUMBER: 1336 double n = ts.getNumber(); 1337 sourceAddNumber(n); 1338 return nf.createNumber(n); 1339 1340 case TokenStream.STRING: 1341 String s = ts.getString(); 1342 sourceAddString(ts.STRING, s); 1343 return nf.createString(s); 1344 1345 case TokenStream.REGEXP: { 1346 String flags = ts.regExpFlags; 1347 ts.regExpFlags = null; 1348 String re = ts.getString(); 1349 sourceAddString(ts.REGEXP, '/' + re + '/' + flags); 1350 return nf.createRegExp(re, flags); 1351 } 1352 1353 case TokenStream.PRIMARY: 1354 sourceAdd((char) ts.PRIMARY); 1355 sourceAdd((char) ts.getOp()); 1356 return nf.createLeaf(ts.PRIMARY, ts.getOp()); 1357 1358 case TokenStream.RESERVED: 1359 reportError(ts, "msg.reserved.id"); 1360 break; 1361 1362 case TokenStream.ERROR: 1363 1364 break; 1365 1366 default: 1367 reportError(ts, "msg.syntax"); 1368 break; 1369 1370 } 1371 return null; } 1373 1374 1412 private void sourceAdd(char c) { 1413 if (sourceTop == sourceBuffer.length) { 1414 increaseSourceCapacity(sourceTop + 1); 1415 } 1416 sourceBuffer[sourceTop] = c; 1417 ++sourceTop; 1418 } 1419 1420 private void sourceAddString(int type, String str) { 1421 int L = str.length(); 1422 if (Context.check && L > Character.MAX_VALUE) 1424 Context.codeBug(); 1425 1426 if (sourceTop + L + 2 > sourceBuffer.length) { 1427 increaseSourceCapacity(sourceTop + L + 2); 1428 } 1429 sourceAdd((char) type); 1430 sourceAdd((char) L); 1431 str.getChars(0, L, sourceBuffer, sourceTop); 1432 sourceTop += L; 1433 } 1434 1435 private void sourceAddNumber(double n) { 1436 sourceAdd((char) TokenStream.NUMBER); 1437 1438 1451 1452 long lbits = (long) n; 1453 if (lbits != n) { 1454 lbits = Double.doubleToLongBits(n); 1457 sourceAdd('D'); 1458 sourceAdd((char) (lbits >> 48)); 1459 sourceAdd((char) (lbits >> 32)); 1460 sourceAdd((char) (lbits >> 16)); 1461 sourceAdd((char) lbits); 1462 } else { 1463 if (Context.check && lbits < 0) 1466 Context.codeBug(); 1467 1468 if (lbits <= Character.MAX_VALUE) { 1471 sourceAdd('S'); 1472 sourceAdd((char) lbits); 1473 } else { sourceAdd('J'); 1475 sourceAdd((char) (lbits >> 48)); 1476 sourceAdd((char) (lbits >> 32)); 1477 sourceAdd((char) (lbits >> 16)); 1478 sourceAdd((char) lbits); 1479 } 1480 } 1481 } 1482 1483 private void increaseSourceCapacity(int minimalCapacity) { 1484 if (Context.check && minimalCapacity <= sourceBuffer.length) 1486 Context.codeBug(); 1487 int newCapacity = sourceBuffer.length * 2; 1488 if (newCapacity < minimalCapacity) { 1489 newCapacity = minimalCapacity; 1490 } 1491 char[] tmp = new char[newCapacity]; 1492 System.arraycopy(sourceBuffer, 0, tmp, 0, sourceTop); 1493 sourceBuffer = tmp; 1494 } 1495 1496 private String sourceToString(int offset) { 1497 if (Context.check && (offset < 0 || sourceTop < offset)) 1498 Context.codeBug(); 1499 return new String (sourceBuffer, offset, sourceTop - offset); 1500 } 1501 1502 private int lastExprEndLine; private IRFactory nf; 1504 private ErrorReporter er; 1505 private boolean ok; 1507 private char[] sourceBuffer = new char[128]; 1508 private int sourceTop; 1509 private int functionNumber; 1510} 1511 | Popular Tags |