1 16 package com.google.gwt.dev.js; 17 18 import com.google.gwt.dev.js.ast.JsArrayAccess; 19 import com.google.gwt.dev.js.ast.JsArrayLiteral; 20 import com.google.gwt.dev.js.ast.JsBinaryOperation; 21 import com.google.gwt.dev.js.ast.JsBinaryOperator; 22 import com.google.gwt.dev.js.ast.JsBlock; 23 import com.google.gwt.dev.js.ast.JsBooleanLiteral; 24 import com.google.gwt.dev.js.ast.JsBreak; 25 import com.google.gwt.dev.js.ast.JsCase; 26 import com.google.gwt.dev.js.ast.JsCatch; 27 import com.google.gwt.dev.js.ast.JsConditional; 28 import com.google.gwt.dev.js.ast.JsContinue; 29 import com.google.gwt.dev.js.ast.JsDefault; 30 import com.google.gwt.dev.js.ast.JsDoWhile; 31 import com.google.gwt.dev.js.ast.JsExpression; 32 import com.google.gwt.dev.js.ast.JsExpressions; 33 import com.google.gwt.dev.js.ast.JsFor; 34 import com.google.gwt.dev.js.ast.JsForIn; 35 import com.google.gwt.dev.js.ast.JsFunction; 36 import com.google.gwt.dev.js.ast.JsIf; 37 import com.google.gwt.dev.js.ast.JsInvocation; 38 import com.google.gwt.dev.js.ast.JsLabel; 39 import com.google.gwt.dev.js.ast.JsName; 40 import com.google.gwt.dev.js.ast.JsNameRef; 41 import com.google.gwt.dev.js.ast.JsNew; 42 import com.google.gwt.dev.js.ast.JsNode; 43 import com.google.gwt.dev.js.ast.JsObjectLiteral; 44 import com.google.gwt.dev.js.ast.JsParameter; 45 import com.google.gwt.dev.js.ast.JsPostfixOperation; 46 import com.google.gwt.dev.js.ast.JsPrefixOperation; 47 import com.google.gwt.dev.js.ast.JsProgram; 48 import com.google.gwt.dev.js.ast.JsPropertyInitializer; 49 import com.google.gwt.dev.js.ast.JsRegExp; 50 import com.google.gwt.dev.js.ast.JsReturn; 51 import com.google.gwt.dev.js.ast.JsScope; 52 import com.google.gwt.dev.js.ast.JsStatement; 53 import com.google.gwt.dev.js.ast.JsStatements; 54 import com.google.gwt.dev.js.ast.JsStringLiteral; 55 import com.google.gwt.dev.js.ast.JsSwitch; 56 import com.google.gwt.dev.js.ast.JsThisRef; 57 import com.google.gwt.dev.js.ast.JsThrow; 58 import com.google.gwt.dev.js.ast.JsTry; 59 import com.google.gwt.dev.js.ast.JsUnaryOperator; 60 import com.google.gwt.dev.js.ast.JsVars; 61 import com.google.gwt.dev.js.ast.JsWhile; 62 import com.google.gwt.dev.js.rhino.Context; 63 import com.google.gwt.dev.js.rhino.ErrorReporter; 64 import com.google.gwt.dev.js.rhino.EvaluatorException; 65 import com.google.gwt.dev.js.rhino.IRFactory; 66 import com.google.gwt.dev.js.rhino.Node; 67 import com.google.gwt.dev.js.rhino.Parser; 68 import com.google.gwt.dev.js.rhino.TokenStream; 69 70 import java.io.IOException ; 71 import java.io.Reader ; 72 import java.math.BigInteger ; 73 import java.util.Iterator ; 74 import java.util.Stack ; 75 76 79 public class JsParser { 80 81 private JsProgram program; 82 private final Stack scopeStack = new Stack (); 83 84 public JsParser() { 85 Context.enter().setErrorReporter(new ErrorReporter() { 88 public void error(String msg, String loc, int ln, String src, int col) { 89 throw new UncheckedJsParserException(new JsParserException(msg, ln, 90 src, col)); 91 } 92 93 public EvaluatorException runtimeError(String msg, String loc, int ln, 94 String src, int col) { 95 throw new UncheckedJsParserException(new JsParserException(msg, ln, 97 src, col)); 98 } 99 100 public void warning(String msg, String loc, int ln, String src, int col) { 101 } 103 }); 104 } 105 106 public JsStatements parse(JsScope scope, Reader r, int startLine) 107 throws IOException , JsParserException { 108 try { 109 TokenStream ts = new TokenStream(r, "", startLine); 112 Parser parser = new Parser(new IRFactory(ts)); 113 Node topNode = (Node) parser.parse(ts); 114 115 program = scope.getProgram(); 118 pushScope(scope); 119 JsStatements stmts = mapStatements(topNode); 120 popScope(); 121 122 return stmts; 123 } catch (UncheckedJsParserException e) { 124 throw e.getParserException(); 125 } 126 } 127 128 public void parseInto(JsScope scope, JsBlock block, Reader r, int startLine) 129 throws IOException , JsParserException { 130 JsStatements childStmts = parse(scope, r, startLine); 131 JsStatements parentStmts = block.getStatements(); 132 for (Iterator iter = childStmts.iterator(); iter.hasNext();) { 133 parentStmts.add((JsStatement) iter.next()); 134 } 135 } 136 137 private JsParserException createParserException(String msg, Node offender) { 138 return new JsParserException(msg); 139 } 140 141 private JsScope getScope() { 142 return (JsScope) scopeStack.peek(); 143 } 144 145 private JsNode map(Node node) throws JsParserException { 146 147 switch (node.getType()) { 148 case TokenStream.SCRIPT: 149 { 150 JsBlock block = new JsBlock(); 151 mapStatements(block.getStatements(), node); 152 return block; 153 } 154 155 case TokenStream.DEBUGGER: 156 return mapDebuggerStatement(); 157 158 case TokenStream.VOID: 159 return null; 161 162 case TokenStream.EXPRSTMT: 163 return mapExpression(node.getFirstChild()).makeStmt(); 164 165 case TokenStream.REGEXP: 166 return mapRegExp(node); 167 168 case TokenStream.ADD: 169 return mapBinaryOperation(JsBinaryOperator.ADD, node); 170 171 case TokenStream.SUB: 172 return mapBinaryOperation(JsBinaryOperator.SUB, node); 173 174 case TokenStream.MUL: 175 return mapBinaryOperation(JsBinaryOperator.MUL, node); 176 177 case TokenStream.DIV: 178 return mapBinaryOperation(JsBinaryOperator.DIV, node); 179 180 case TokenStream.MOD: 181 return mapBinaryOperation(JsBinaryOperator.MOD, node); 182 183 case TokenStream.AND: 184 return mapBinaryOperation(JsBinaryOperator.AND, node); 185 186 case TokenStream.OR: 187 return mapBinaryOperation(JsBinaryOperator.OR, node); 188 189 case TokenStream.BITAND: 190 return mapBinaryOperation(JsBinaryOperator.BIT_AND, node); 191 192 case TokenStream.BITOR: 193 return mapBinaryOperation(JsBinaryOperator.BIT_OR, node); 194 195 case TokenStream.BITXOR: 196 return mapBinaryOperation(JsBinaryOperator.BIT_XOR, node); 197 198 case TokenStream.ASSIGN: 199 return mapAssignmentVariant(node); 200 201 case TokenStream.RELOP: 202 return mapRelationalVariant(node); 203 204 case TokenStream.EQOP: 205 return mapEqualityVariant(node); 206 207 case TokenStream.SHOP: 208 return mapShiftVariant(node); 209 210 case TokenStream.UNARYOP: 211 return mapUnaryVariant(node); 212 213 case TokenStream.INC: 214 return mapIncDecFixity(JsUnaryOperator.INC, node); 215 216 case TokenStream.DEC: 217 return mapIncDecFixity(JsUnaryOperator.DEC, node); 218 219 case TokenStream.HOOK: 220 return mapConditional(node); 221 222 case TokenStream.NAME: 223 return mapName(node); 224 225 case TokenStream.STRING: 226 return program.getStringLiteral(node.getString()); 227 228 case TokenStream.NUMBER: 229 return mapNumber(node); 230 231 case TokenStream.CALL: 232 return mapCall(node); 233 234 case TokenStream.GETPROP: 235 return mapGetProp(node); 236 237 case TokenStream.SETPROP: 238 return mapSetProp(node); 239 240 case TokenStream.DELPROP: 241 return mapDeleteProp(node); 242 243 case TokenStream.IF: 244 return mapIfStatement(node); 245 246 case TokenStream.WHILE: 247 return mapDoOrWhileStatement(true, node); 248 249 case TokenStream.DO: 250 return mapDoOrWhileStatement(false, node); 251 252 case TokenStream.FOR: 253 return mapForStatement(node); 254 255 case TokenStream.WITH: 256 return mapWithStatement(node); 257 258 case TokenStream.GETELEM: 259 return mapGetElem(node); 260 261 case TokenStream.SETELEM: 262 return mapSetElem(node); 263 264 case TokenStream.FUNCTION: 265 return mapFunction(node); 266 267 case TokenStream.BLOCK: 268 return mapBlock(node); 269 270 case TokenStream.SETNAME: 271 return mapBinaryOperation(JsBinaryOperator.ASG, node); 272 273 case TokenStream.BINDNAME: 274 return mapName(node); 275 276 case TokenStream.RETURN: 277 return mapReturn(node); 278 279 case TokenStream.BREAK: 280 return mapBreak(node); 281 282 case TokenStream.CONTINUE: 283 return mapContinue(node); 284 285 case TokenStream.OBJLIT: 286 return mapObjectLit(node); 287 288 case TokenStream.ARRAYLIT: 289 return mapArrayLit(node); 290 291 case TokenStream.VAR: 292 return mapVar(node); 293 294 case TokenStream.PRIMARY: 295 return mapPrimary(node); 296 297 case TokenStream.COMMA: 298 return mapBinaryOperation(JsBinaryOperator.COMMA, node); 299 300 case TokenStream.NEW: 301 return mapNew(node); 302 303 case TokenStream.THROW: 304 return mapThrowStatement(node); 305 306 case TokenStream.TRY: 307 return mapTryStatement(node); 308 309 case TokenStream.SWITCH: 310 return mapSwitchStatement(node); 311 312 case TokenStream.LABEL: 313 return mapLabel(node); 314 315 default: 316 int tokenType = node.getType(); 317 throw new JsParserException("Unexpected top-level token type: " 318 + tokenType); 319 } 320 } 321 322 private JsArrayLiteral mapArrayLit(Node node) throws JsParserException { 323 JsArrayLiteral toLit = new JsArrayLiteral(); 324 Node from = node.getFirstChild(); 325 while (from != null) { 326 toLit.getExpressions().add(mapExpression(from)); 327 from = from.getNext(); 328 } 329 return toLit; 330 } 331 332 335 private JsNameRef mapAsPropertyNameRef(Node nameRefNode) 336 throws JsParserException { 337 JsNode unknown = map(nameRefNode); 338 if (unknown instanceof JsStringLiteral) { 342 JsStringLiteral lit = (JsStringLiteral) unknown; 343 String litName = lit.getValue(); 344 return new JsNameRef(litName); 345 } else { 346 throw createParserException("Expecting a name reference", nameRefNode); 347 } 348 } 349 350 private JsExpression mapAssignmentVariant(Node asgNode) 351 throws JsParserException { 352 switch (asgNode.getIntDatum()) { 353 case TokenStream.NOP: 354 return mapBinaryOperation(JsBinaryOperator.ASG, asgNode); 355 356 case TokenStream.ADD: 357 return mapBinaryOperation(JsBinaryOperator.ASG_ADD, asgNode); 358 359 case TokenStream.SUB: 360 return mapBinaryOperation(JsBinaryOperator.ASG_SUB, asgNode); 361 362 case TokenStream.MUL: 363 return mapBinaryOperation(JsBinaryOperator.ASG_MUL, asgNode); 364 365 case TokenStream.DIV: 366 return mapBinaryOperation(JsBinaryOperator.ASG_DIV, asgNode); 367 368 case TokenStream.MOD: 369 return mapBinaryOperation(JsBinaryOperator.ASG_MOD, asgNode); 370 371 case TokenStream.BITAND: 372 return mapBinaryOperation(JsBinaryOperator.ASG_BIT_AND, asgNode); 373 374 case TokenStream.BITOR: 375 return mapBinaryOperation(JsBinaryOperator.ASG_BIT_OR, asgNode); 376 377 case TokenStream.BITXOR: 378 return mapBinaryOperation(JsBinaryOperator.ASG_BIT_XOR, asgNode); 379 380 case TokenStream.LSH: 381 return mapBinaryOperation(JsBinaryOperator.ASG_SHL, asgNode); 382 383 case TokenStream.RSH: 384 return mapBinaryOperation(JsBinaryOperator.ASG_SHR, asgNode); 385 386 case TokenStream.URSH: 387 return mapBinaryOperation(JsBinaryOperator.ASG_SHRU, asgNode); 388 389 default: 390 throw new JsParserException("Unknown assignment operator variant: " 391 + asgNode.getIntDatum()); 392 } 393 } 394 395 private JsExpression mapBinaryOperation(JsBinaryOperator op, Node node) 396 throws JsParserException { 397 Node from1 = node.getFirstChild(); 398 Node from2 = from1.getNext(); 399 400 JsExpression to1 = mapExpression(from1); 401 JsExpression to2 = mapExpression(from2); 402 403 return new JsBinaryOperation(op, to1, to2); 404 } 405 406 private JsBlock mapBlock(Node nodeStmts) throws JsParserException { 407 JsBlock block = new JsBlock(); 408 mapStatements(block.getStatements(), nodeStmts); 409 return block; 410 } 411 412 private JsBreak mapBreak(Node breakNode) { 413 Node fromLabel = breakNode.getFirstChild(); 414 if (fromLabel != null) { 415 return new JsBreak(mapName(fromLabel)); 416 } else { 417 return new JsBreak(); 418 } 419 } 420 421 private JsInvocation mapCall(Node callNode) throws JsParserException { 422 JsInvocation invocation = new JsInvocation(); 423 424 Node from = callNode.getFirstChild(); 427 JsExpression to = mapExpression(from); 428 invocation.setQualifier(to); 429 430 JsExpressions args = invocation.getArguments(); 433 from = from.getNext(); 434 while (from != null) { 435 to = mapExpression(from); 436 args.add(to); 437 from = from.getNext(); 438 } 439 440 return invocation; 441 } 442 443 private JsExpression mapConditional(Node condNode) throws JsParserException { 444 JsConditional toCond = new JsConditional(); 445 446 Node fromTest = condNode.getFirstChild(); 447 toCond.setTestExpression(mapExpression(fromTest)); 448 449 Node fromThen = fromTest.getNext(); 450 toCond.setThenExpression(mapExpression(fromThen)); 451 452 Node fromElse = fromThen.getNext(); 453 toCond.setElseExpression(mapExpression(fromElse)); 454 455 return toCond; 456 } 457 458 private JsContinue mapContinue(Node contNode) { 459 Node fromLabel = contNode.getFirstChild(); 460 if (fromLabel != null) { 461 return new JsContinue(mapName(fromLabel)); 462 } else { 463 return new JsContinue(); 464 } 465 } 466 467 private JsStatement mapDebuggerStatement() { 468 return program.getDebuggerStmt(); 471 } 472 473 private JsNode mapDeleteProp(Node node) throws JsParserException { 474 Node from = node.getFirstChild(); 475 JsExpression to = mapExpression(from); 476 if (to instanceof JsNameRef) { 477 return new JsPrefixOperation(JsUnaryOperator.DELETE, to); 478 } else if (to instanceof JsArrayAccess) { 479 return new JsPrefixOperation(JsUnaryOperator.DELETE, to); 480 } else { 481 throw createParserException( 482 "'delete' can only operate on property names and array elements", 483 from); 484 } 485 } 486 487 private JsStatement mapDoOrWhileStatement(boolean isWhile, Node ifNode) 488 throws JsParserException { 489 490 Node fromTestExpr; 493 Node fromBody; 494 if (isWhile) { 495 fromTestExpr = ifNode.getFirstChild(); 496 fromBody = ifNode.getFirstChild().getNext(); 497 } else { 498 fromBody = ifNode.getFirstChild(); 499 fromTestExpr = ifNode.getFirstChild().getNext(); 500 } 501 502 JsExpression toTestExpr = mapExpression(fromTestExpr); 505 506 JsStatement toBody = mapStatement(fromBody); 509 510 if (isWhile) { 513 return new JsWhile(toTestExpr, toBody); 514 } else { 515 return new JsDoWhile(toTestExpr, toBody); 516 } 517 } 518 519 private JsExpression mapEqualityVariant(Node eqNode) throws JsParserException { 520 switch (eqNode.getIntDatum()) { 521 case TokenStream.EQ: 522 return mapBinaryOperation(JsBinaryOperator.EQ, eqNode); 523 524 case TokenStream.NE: 525 return mapBinaryOperation(JsBinaryOperator.NEQ, eqNode); 526 527 case TokenStream.SHEQ: 528 return mapBinaryOperation(JsBinaryOperator.REF_EQ, eqNode); 529 530 case TokenStream.SHNE: 531 return mapBinaryOperation(JsBinaryOperator.REF_NEQ, eqNode); 532 533 case TokenStream.LT: 534 return mapBinaryOperation(JsBinaryOperator.LT, eqNode); 535 536 case TokenStream.LE: 537 return mapBinaryOperation(JsBinaryOperator.LTE, eqNode); 538 539 case TokenStream.GT: 540 return mapBinaryOperation(JsBinaryOperator.GT, eqNode); 541 542 case TokenStream.GE: 543 return mapBinaryOperation(JsBinaryOperator.GTE, eqNode); 544 545 default: 546 throw new JsParserException("Unknown equality operator variant: " 547 + eqNode.getIntDatum()); 548 } 549 } 550 551 private JsExpression mapExpression(Node exprNode) throws JsParserException { 552 JsNode unknown = map(exprNode); 553 if (unknown instanceof JsExpression) { 554 return (JsExpression) unknown; 555 } else { 556 throw createParserException("Expecting an expression", exprNode); 557 } 558 } 559 560 private JsStatement mapForStatement(Node forNode) throws JsParserException { 561 Node fromInit = forNode.getFirstChild(); 562 Node fromTest = fromInit.getNext(); 563 Node fromIncr = fromTest.getNext(); 564 Node fromBody = fromIncr.getNext(); 565 566 if (fromBody == null) { 567 Node fromIter = forNode.getFirstChild(); 571 Node fromObjExpr = fromIter.getNext(); 572 fromBody = fromObjExpr.getNext(); 573 574 JsForIn toForIn; 575 if (fromIter.getType() == TokenStream.VAR) { 576 Node fromIterVarName = fromIter.getFirstChild(); 579 String fromName = fromIterVarName.getString(); 580 JsName toName = getScope().declareName(fromName); 581 toForIn = new JsForIn(toName); 582 Node fromIterInit = fromIterVarName.getFirstChild(); 583 if (fromIterInit != null) { 584 toForIn.setIterExpr(mapOptionalExpression(fromIterInit)); 587 } 588 } else { 589 toForIn = new JsForIn(); 592 toForIn.setIterExpr(mapExpression(fromIter)); 593 } 594 toForIn.setObjExpr(mapExpression(fromObjExpr)); 595 596 JsStatement bodyStmt = mapStatement(fromBody); 599 if (bodyStmt != null) { 600 toForIn.setBody(bodyStmt); 601 } else { 602 toForIn.setBody(program.getEmptyStmt()); 603 } 604 605 return toForIn; 606 } else { 607 JsFor toFor = new JsFor(); 610 611 JsNode initThingy = map(fromInit); 614 if (initThingy != null) { 615 if (initThingy instanceof JsVars) { 616 toFor.setInitVars((JsVars) initThingy); 617 } else { 618 assert (initThingy instanceof JsExpression); 619 toFor.setInitExpr((JsExpression) initThingy); 620 } 621 } 622 toFor.setCondition(mapOptionalExpression(fromTest)); 623 toFor.setIncrExpr(mapOptionalExpression(fromIncr)); 624 625 JsStatement bodyStmt = mapStatement(fromBody); 626 if (bodyStmt != null) { 627 toFor.setBody(bodyStmt); 628 } else { 629 toFor.setBody(program.getEmptyStmt()); 630 } 631 return toFor; 632 } 633 } 634 635 private JsExpression mapFunction(Node fnNode) throws JsParserException { 636 637 Node fromFnNameNode = fnNode.getFirstChild(); 638 Node fromParamNode = fnNode.getFirstChild().getNext().getFirstChild(); 639 Node fromBodyNode = fnNode.getFirstChild().getNext().getNext(); 640 641 String fromFnName = fromFnNameNode.getString(); 644 JsName toFnName = null; 645 if (fromFnName != null && fromFnName.length() > 0) { 646 toFnName = getScope().declareName(fromFnName); 647 } 648 649 JsFunction toFn = new JsFunction(getScope(), toFnName); 652 653 pushScope(toFn.getScope()); 657 658 while (fromParamNode != null) { 659 String fromParamName = fromParamNode.getString(); 660 JsName paramName = toFn.getScope().declareName(fromParamName); 662 toFn.getParameters().add(new JsParameter(paramName)); 663 fromParamNode = fromParamNode.getNext(); 664 } 665 666 JsBlock toBody = mapBlock(fromBodyNode); 669 toFn.setBody(toBody); 670 671 popScope(); 674 675 return toFn; 676 } 677 678 private JsArrayAccess mapGetElem(Node getElemNode) throws JsParserException { 679 Node from1 = getElemNode.getFirstChild(); 680 Node from2 = from1.getNext(); 681 682 JsExpression to1 = mapExpression(from1); 683 JsExpression to2 = mapExpression(from2); 684 685 return new JsArrayAccess(to1, to2); 686 } 687 688 private JsNameRef mapGetProp(Node getPropNode) throws JsParserException { 689 Node from1 = getPropNode.getFirstChild(); 690 Node from2 = from1.getNext(); 691 692 JsExpression toQualifier = mapExpression(from1); 693 JsNameRef toNameRef; 694 if (from2 != null) { 695 toNameRef = mapAsPropertyNameRef(from2); 696 } else { 697 Object obj = getPropNode.getProp(Node.SPECIAL_PROP_PROP); 700 assert (obj instanceof String ); 701 toNameRef = new JsNameRef((String ) obj); 702 } 703 toNameRef.setQualifier(toQualifier); 704 705 return toNameRef; 706 } 707 708 private JsIf mapIfStatement(Node ifNode) throws JsParserException { 709 710 Node fromTestExpr = ifNode.getFirstChild(); 713 Node fromThenBlock = ifNode.getFirstChild().getNext(); 714 Node fromElseBlock = ifNode.getFirstChild().getNext().getNext(); 715 716 JsIf toIf = new JsIf(); 719 720 JsExpression toTestExpr = mapExpression(fromTestExpr); 723 toIf.setIfExpr(toTestExpr); 724 725 toIf.setThenStmt(mapStatement(fromThenBlock)); 728 729 if (fromElseBlock != null) { 732 toIf.setElseStmt(mapStatement(fromElseBlock)); 733 } 734 735 return toIf; 736 } 737 738 private JsExpression mapIncDecFixity(JsUnaryOperator op, Node node) 739 throws JsParserException { 740 switch (node.getIntDatum()) { 741 case TokenStream.PRE: 742 return mapPrefixOperation(op, node); 743 case TokenStream.POST: 744 return mapPostfixOperation(op, node); 745 default: 746 throw new JsParserException("Unknown prefix/postfix variant: " 747 + node.getIntDatum()); 748 } 749 } 750 751 private JsLabel mapLabel(Node labelNode) throws JsParserException { 752 String fromName = labelNode.getFirstChild().getString(); 753 JsName toName = getScope().declareName(fromName); 754 Node fromStmt = labelNode.getFirstChild().getNext(); 755 JsLabel toLabel = new JsLabel(toName); 756 toLabel.setStmt(mapStatement(fromStmt)); 757 return toLabel; 758 } 759 760 764 private JsNameRef mapName(Node node) { 765 String ident = node.getString(); 766 return new JsNameRef(ident); 767 } 768 769 private JsNew mapNew(Node newNode) throws JsParserException { 770 771 JsNew newExpr = new JsNew(); 772 773 Node fromCtorExpr = newNode.getFirstChild(); 777 newExpr.setConstructorExpression(mapExpression(fromCtorExpr)); 778 779 JsExpressions args = newExpr.getArguments(); 782 Node fromArg = fromCtorExpr.getNext(); 783 while (fromArg != null) { 784 args.add(mapExpression(fromArg)); 785 fromArg = fromArg.getNext(); 786 } 787 788 return newExpr; 789 } 790 791 private JsExpression mapNumber(Node numberNode) { 792 double x = numberNode.getDouble(); 793 long j = (long) x; 794 if (x == j) { 795 return program.getIntegralLiteral(BigInteger.valueOf(j)); 796 } else { 797 return program.getDecimalLiteral(String.valueOf(x)); 798 } 799 } 800 801 private JsExpression mapObjectLit(Node objLitNode) throws JsParserException { 802 JsObjectLiteral toLit = new JsObjectLiteral(); 803 Node fromPropInit = objLitNode.getFirstChild(); 804 while (fromPropInit != null) { 805 806 Node fromLabelExpr = fromPropInit; 807 JsExpression toLabelExpr = mapExpression(fromLabelExpr); 808 809 fromPropInit = fromPropInit.getNext(); 812 Node fromValueExpr = fromPropInit; 813 if (fromValueExpr == null) { 814 throw createParserException("Expected an init expression for: " 815 + toLabelExpr, objLitNode); 816 } 817 JsExpression toValueExpr = mapExpression(fromValueExpr); 818 819 JsPropertyInitializer toPropInit = new JsPropertyInitializer(toLabelExpr, 820 toValueExpr); 821 toLit.getPropertyInitializers().add(toPropInit); 822 823 fromPropInit = fromPropInit.getNext(); 826 } 827 828 return toLit; 829 } 830 831 private JsExpression mapOptionalExpression(Node exprNode) 832 throws JsParserException { 833 JsNode unknown = map(exprNode); 834 if (unknown != null) { 835 if (unknown instanceof JsExpression) { 836 return (JsExpression) unknown; 837 } else { 838 throw createParserException("Expecting an expression or null", exprNode); 839 } 840 } 841 return null; 842 } 843 844 private JsExpression mapPostfixOperation(JsUnaryOperator op, Node node) 845 throws JsParserException { 846 Node from = node.getFirstChild(); 847 JsExpression to = mapExpression(from); 848 return new JsPostfixOperation(op, to); 849 } 850 851 private JsExpression mapPrefixOperation(JsUnaryOperator op, Node node) 852 throws JsParserException { 853 Node from = node.getFirstChild(); 854 JsExpression to = mapExpression(from); 855 return new JsPrefixOperation(op, to); 856 } 857 858 private JsExpression mapPrimary(Node node) throws JsParserException { 859 switch (node.getIntDatum()) { 860 case TokenStream.THIS: 861 return new JsThisRef(); 862 863 case TokenStream.TRUE: 864 return program.getTrueLiteral(); 865 866 case TokenStream.FALSE: 867 return program.getFalseLiteral(); 868 869 case TokenStream.NULL: 870 return program.getNullLiteral(); 871 872 default: 873 throw new JsParserException("Unknown primary: " + node.getIntDatum()); 874 } 875 } 876 877 private JsNode mapRegExp(Node regExpNode) { 878 JsRegExp toRegExp = new JsRegExp(); 879 880 Node fromPattern = regExpNode.getFirstChild(); 881 toRegExp.setPattern(fromPattern.getString()); 882 883 Node fromFlags = fromPattern.getNext(); 884 if (fromFlags != null) { 885 toRegExp.setFlags(fromFlags.getString()); 886 } 887 888 return toRegExp; 889 } 890 891 private JsExpression mapRelationalVariant(Node relNode) 892 throws JsParserException { 893 switch (relNode.getIntDatum()) { 894 case TokenStream.LT: 895 return mapBinaryOperation(JsBinaryOperator.LT, relNode); 896 897 case TokenStream.LE: 898 return mapBinaryOperation(JsBinaryOperator.LTE, relNode); 899 900 case TokenStream.GT: 901 return mapBinaryOperation(JsBinaryOperator.GT, relNode); 902 903 case TokenStream.GE: 904 return mapBinaryOperation(JsBinaryOperator.GTE, relNode); 905 906 case TokenStream.INSTANCEOF: 907 return mapBinaryOperation(JsBinaryOperator.INSTANCEOF, relNode); 908 909 case TokenStream.IN: 910 return mapBinaryOperation(JsBinaryOperator.INOP, relNode); 911 912 default: 913 throw new JsParserException("Unknown relational operator variant: " 914 + relNode.getIntDatum()); 915 } 916 } 917 918 private JsReturn mapReturn(Node returnNode) throws JsParserException { 919 JsReturn toReturn = new JsReturn(); 920 Node from = returnNode.getFirstChild(); 921 if (from != null) { 922 JsExpression to = mapExpression(from); 923 toReturn.setExpr(to); 924 } 925 926 return toReturn; 927 } 928 929 private JsExpression mapSetElem(Node setElemNode) throws JsParserException { 930 JsArrayAccess lhs = mapGetElem(setElemNode); 933 934 Node fromRhs = setElemNode.getFirstChild().getNext().getNext(); 937 JsExpression toRhs = mapExpression(fromRhs); 938 939 return new JsBinaryOperation(JsBinaryOperator.ASG, lhs, toRhs); 940 } 941 942 private JsExpression mapSetProp(Node getPropNode) throws JsParserException { 943 JsNameRef lhs = mapGetProp(getPropNode); 946 947 Node fromRhs = getPropNode.getFirstChild().getNext().getNext(); 950 JsExpression toRhs = mapExpression(fromRhs); 951 952 return new JsBinaryOperation(JsBinaryOperator.ASG, lhs, toRhs); 953 } 954 955 private JsExpression mapShiftVariant(Node shiftNode) throws JsParserException { 956 switch (shiftNode.getIntDatum()) { 957 case TokenStream.LSH: 958 return mapBinaryOperation(JsBinaryOperator.SHL, shiftNode); 959 960 case TokenStream.RSH: 961 return mapBinaryOperation(JsBinaryOperator.SHR, shiftNode); 962 963 case TokenStream.URSH: 964 return mapBinaryOperation(JsBinaryOperator.SHRU, shiftNode); 965 966 default: 967 throw new JsParserException("Unknown equality operator variant: " 968 + shiftNode.getIntDatum()); 969 } 970 } 971 972 private JsStatement mapStatement(Node nodeStmt) throws JsParserException { 973 JsNode unknown = map(nodeStmt); 974 if (unknown != null) { 975 if (unknown instanceof JsStatement) { 976 return (JsStatement) unknown; 977 } else if (unknown instanceof JsExpression) { 978 return ((JsExpression) unknown).makeStmt(); 979 } else { 980 throw createParserException("Expecting a statement", nodeStmt); 981 } 982 } else { 983 return program.getEmptyStmt(); 986 } 987 } 988 989 private void mapStatements(JsStatements stmts, Node nodeStmts) 990 throws JsParserException { 991 Node curr = nodeStmts.getFirstChild(); 992 while (curr != null) { 993 JsStatement stmt = mapStatement(curr); 994 if (stmt != null) { 995 stmts.add(stmt); 996 } else { 997 } 1000 curr = curr.getNext(); 1001 } 1002 } 1003 1004 private JsStatements mapStatements(Node nodeStmts) throws JsParserException { 1005 JsStatements stmts = new JsStatements(); 1006 mapStatements(stmts, nodeStmts); 1007 return stmts; 1008 } 1009 1010 private JsSwitch mapSwitchStatement(Node switchNode) throws JsParserException { 1011 JsSwitch toSwitch = new JsSwitch(); 1012 1013 Node fromSwitchExpr = switchNode.getFirstChild(); 1016 toSwitch.setExpr(mapExpression(fromSwitchExpr)); 1017 1018 Node fromMember = fromSwitchExpr.getNext(); 1021 while (fromMember != null) { 1022 if (fromMember.getType() == TokenStream.CASE) { 1023 JsCase toCase = new JsCase(); 1024 1025 Node fromCaseExpr = fromMember.getFirstChild(); 1028 toCase.setCaseExpr(mapExpression(fromCaseExpr)); 1029 1030 Node fromCaseBlock = fromCaseExpr.getNext(); 1033 mapStatements(toCase.getStmts(), fromCaseBlock); 1034 1035 toSwitch.getCases().add(toCase); 1038 } else { 1039 assert (fromMember.getType() == TokenStream.DEFAULT); 1043 JsDefault toDefault = new JsDefault(); 1044 1045 Node fromDefaultBlock = fromMember.getFirstChild(); 1048 mapStatements(toDefault.getStmts(), fromDefaultBlock); 1049 1050 toSwitch.getCases().add(toDefault); 1053 } 1054 fromMember = fromMember.getNext(); 1055 } 1056 1057 return toSwitch; 1058 } 1059 1060 private JsThrow mapThrowStatement(Node throwNode) throws JsParserException { 1061 Node fromExpr = throwNode.getFirstChild(); 1064 JsThrow toThrow = new JsThrow(mapExpression(fromExpr)); 1065 return toThrow; 1066 } 1067 1068 private JsTry mapTryStatement(Node tryNode) throws JsParserException { 1069 JsTry toTry = new JsTry(); 1070 1071 Node fromTryBody = tryNode.getFirstChild(); 1074 toTry.setTryBlock(mapBlock(fromTryBody)); 1075 1076 Node fromCatchNodes = fromTryBody.getNext(); 1079 Node fromCatchNode = fromCatchNodes.getFirstChild(); 1080 while (fromCatchNode != null) { 1081 assert (fromCatchNode.getType() == TokenStream.CATCH); 1082 Node fromCatchVarName = fromCatchNode.getFirstChild(); 1085 JsCatch catchBlock = new JsCatch(getScope(), fromCatchVarName.getString()); 1086 1087 fromCatchNode = fromCatchNode.getNext(); 1091 1092 Node fromCondition = fromCatchVarName.getNext(); 1096 JsExpression toCondition = mapExpression(fromCondition); 1097 catchBlock.setCondition(toCondition); 1098 if (fromCatchNode == null) { 1099 if (toCondition instanceof JsBooleanLiteral) { 1100 if (((JsBooleanLiteral) toCondition).getValue()) { 1101 catchBlock.setCondition(null); 1105 } 1106 } 1107 } 1108 1109 Node fromCatchBody = fromCondition.getNext(); 1112 pushScope(catchBlock.getScope()); 1113 catchBlock.setBody(mapBlock(fromCatchBody)); 1114 popScope(); 1115 1116 toTry.getCatches().add(catchBlock); 1119 } 1120 1121 Node fromFinallyNode = fromCatchNodes.getNext(); 1122 if (fromFinallyNode != null) { 1123 toTry.setFinallyBlock(mapBlock(fromFinallyNode)); 1124 } 1125 1126 return toTry; 1127 } 1128 1129 private JsExpression mapUnaryVariant(Node unOp) throws JsParserException { 1130 switch (unOp.getIntDatum()) { 1131 case TokenStream.SUB: 1132 return mapPrefixOperation(JsUnaryOperator.NEG, unOp); 1133 1134 case TokenStream.NOT: 1135 return mapPrefixOperation(JsUnaryOperator.NOT, unOp); 1136 1137 case TokenStream.BITNOT: 1138 return mapPrefixOperation(JsUnaryOperator.BIT_NOT, unOp); 1139 1140 case TokenStream.TYPEOF: 1141 return mapPrefixOperation(JsUnaryOperator.TYPEOF, unOp); 1142 1143 case TokenStream.ADD: 1144 return mapExpression(unOp.getFirstChild()); 1146 1147 case TokenStream.VOID: 1148 return mapPrefixOperation(JsUnaryOperator.VOID, unOp); 1149 1150 default: 1151 throw new JsParserException("Unknown unary operator variant: " 1152 + unOp.getIntDatum()); 1153 } 1154 } 1155 1156 private JsVars mapVar(Node varNode) throws JsParserException { 1157 JsVars toVars = new JsVars(); 1158 Node fromVar = varNode.getFirstChild(); 1159 while (fromVar != null) { 1160 String fromName = fromVar.getString(); 1165 JsName toName = getScope().declareName(fromName); 1166 JsVars.JsVar toVar = new JsVars.JsVar(toName); 1167 1168 Node fromInit = fromVar.getFirstChild(); 1169 if (fromInit != null) { 1170 JsExpression toInit = mapExpression(fromInit); 1171 toVar.setInitExpr(toInit); 1172 } 1173 toVars.add(toVar); 1174 1175 fromVar = fromVar.getNext(); 1176 } 1177 1178 return toVars; 1179 } 1180 1181 private JsNode mapWithStatement(Node withNode) throws JsParserException { 1182 throw createParserException("Internal error: unexpected token 'with'", 1189 withNode); 1190 } 1191 1192 private void popScope() { 1193 scopeStack.pop(); 1194 } 1195 1196 private void pushScope(JsScope scope) { 1197 scopeStack.push(scope); 1198 } 1199} 1200 | Popular Tags |