Example #1
0
  public JsFunction mapFunction(Node fnNode) throws JsParserException {
    int nodeType = fnNode.getType();
    assert nodeType == TokenStream.FUNCTION
        : "Expected function node, got: " + TokenStream.tokenToName(nodeType);
    Node fromFnNameNode = fnNode.getFirstChild();
    Node fromParamNode = fnNode.getFirstChild().getNext().getFirstChild();
    Node fromBodyNode = fnNode.getFirstChild().getNext().getNext();
    JsFunction toFn = scopeContext.enterFunction();

    // Decide the function's name, if any.
    //
    String fnNameIdent = fromFnNameNode.getString();
    if (fnNameIdent != null && fnNameIdent.length() > 0) {
      scopeContext.globalNameFor(fnNameIdent);
    }

    while (fromParamNode != null) {
      String fromParamName = fromParamNode.getString();
      JsName name = scopeContext.localNameFor(fromParamName);
      toFn.getParameters().add(new JsParameter(name));
      fromParamNode = fromParamNode.getNext();
    }

    // Map the function's body.
    //
    JsBlock toBody = mapBlock(fromBodyNode);
    toFn.setBody(toBody);

    scopeContext.exitFunction();
    return toFn;
  }
Example #2
0
  private JsTry mapTryStatement(Node tryNode) throws JsParserException {
    JsTry toTry = new JsTry();

    // Map the "try" body.
    //
    Node fromTryBody = tryNode.getFirstChild();
    toTry.setTryBlock(mapBlock(fromTryBody));

    // Map zero or more catch blocks.
    //
    Node fromCatchNodes = fromTryBody.getNext();
    Node fromCatchNode = fromCatchNodes.getFirstChild();
    while (fromCatchNode != null) {
      assert (fromCatchNode.getType() == TokenStream.CATCH);
      // Map the catch variable.
      //
      Node fromCatchVarName = fromCatchNode.getFirstChild();
      JsCatch catchBlock = scopeContext.enterCatch(fromCatchVarName.getString());

      // Pre-advance to the next catch block, if any.
      // We do this here to decide whether or not this is the last one.
      //
      fromCatchNode = fromCatchNode.getNext();

      // Map the condition, with a little fixup based on whether or not
      // this is the last catch block.
      //
      Node fromCondition = fromCatchVarName.getNext();
      JsExpression toCondition = mapExpression(fromCondition);
      catchBlock.setCondition(toCondition);
      if (fromCatchNode == null) {
        if (toCondition instanceof JsBooleanLiteral) {
          if (((JsBooleanLiteral) toCondition).getValue()) {
            // Actually, this is an unconditional catch block.
            // Indicate that by nulling the condition.
            //
            catchBlock.setCondition(null);
          }
        }
      }

      // Map the catch body.
      //
      Node fromCatchBody = fromCondition.getNext();
      catchBlock.setBody(mapBlock(fromCatchBody));

      // Attach it.
      //
      toTry.getCatches().add(catchBlock);
      scopeContext.exitCatch();
    }

    Node fromFinallyNode = fromCatchNodes.getNext();
    if (fromFinallyNode != null) {
      toTry.setFinallyBlock(mapBlock(fromFinallyNode));
    }

    return toTry;
  }
Example #3
0
  private JsLabel mapLabel(Node labelNode) throws JsParserException {
    String fromName = labelNode.getFirstChild().getString();

    JsName toName = scopeContext.enterLabel(fromName);

    Node fromStmt = labelNode.getFirstChild().getNext();
    JsLabel toLabel = new JsLabel(toName);
    toLabel.setStatement(mapStatement(fromStmt));

    scopeContext.exitLabel();

    return toLabel;
  }
Example #4
0
 /** Produces a {@link JsNameRef}. */
 private JsNameRef mapAsPropertyNameRef(Node nameRefNode) throws JsParserException {
   JsNode unknown = map(nameRefNode);
   // This is weird, but for "a.b", the rhino AST calls "b" a string literal.
   // However, since we know it's for a PROPGET, we can unstringliteralize it.
   //
   if (unknown instanceof JsStringLiteral) {
     JsStringLiteral lit = (JsStringLiteral) unknown;
     return scopeContext.referenceFor(lit.getValue());
   } else {
     throw createParserException("Expecting a name reference", nameRefNode);
   }
 }
Example #5
0
  private JsNameRef mapGetProp(Node getPropNode) throws JsParserException {
    Node from1 = getPropNode.getFirstChild();
    Node from2 = from1.getNext();

    JsExpression toQualifier = mapExpression(from1);
    JsNameRef toNameRef;
    if (from2 != null) {
      toNameRef = mapAsPropertyNameRef(from2);
    } else {
      // Special properties don't have a second expression.
      //
      Object obj = getPropNode.getProp(Node.SPECIAL_PROP_PROP);
      assert (obj instanceof String);
      toNameRef = scopeContext.referenceFor((String) obj);
    }
    toNameRef.setQualifier(toQualifier);

    return toNameRef;
  }
Example #6
0
  @Nullable
  private JsNameRef getTargetLabel(@NotNull Node statementWithLabel) {
    int type = statementWithLabel.getType();
    if (type != TokenStream.BREAK && type != TokenStream.CONTINUE) {
      String tokenTypeName = TokenStream.tokenToName(statementWithLabel.getType());
      throw new AssertionError("Unexpected node type with label: " + tokenTypeName);
    }

    Node label = statementWithLabel.getFirstChild();
    if (label == null) return null;

    String identifier = label.getString();
    assert identifier != null : "If label exists identifier should not be null";

    JsName labelName = scopeContext.labelFor(identifier);
    assert labelName != null : "Unknown label name: " + identifier;

    return labelName.makeRef();
  }
Example #7
0
  private JsVars mapVar(Node varNode) throws JsParserException {
    JsVars toVars = new JsVars();
    Node fromVar = varNode.getFirstChild();
    while (fromVar != null) {
      // Use a conservative name allocation strategy that allocates all names
      // from the function's scope, even the names of properties in field
      // literals.
      //
      String fromName = fromVar.getString();
      JsName toName = scopeContext.localNameFor(fromName);
      JsVars.JsVar toVar = new JsVars.JsVar(toName);

      Node fromInit = fromVar.getFirstChild();
      if (fromInit != null) {
        JsExpression toInit = mapExpression(fromInit);
        toVar.setInitExpression(toInit);
      }
      toVars.add(toVar);

      fromVar = fromVar.getNext();
    }

    return toVars;
  }
Example #8
0
  private JsStatement mapForStatement(Node forNode) throws JsParserException {
    Node fromInit = forNode.getFirstChild();
    Node fromTest = fromInit.getNext();
    Node fromIncr = fromTest.getNext();
    Node fromBody = fromIncr.getNext();

    if (fromBody == null) {
      // This could be a "for...in" structure.
      // We could based on the different child layout.
      //
      Node fromIter = forNode.getFirstChild();
      Node fromObjExpr = fromIter.getNext();
      fromBody = fromObjExpr.getNext();

      JsForIn toForIn;
      if (fromIter.getType() == TokenStream.VAR) {
        // A named iterator var.
        //
        Node fromIterVarName = fromIter.getFirstChild();
        String fromName = fromIterVarName.getString();
        JsName toName = scopeContext.localNameFor(fromName);
        toForIn = new JsForIn(toName);
        Node fromIterInit = fromIterVarName.getFirstChild();
        if (fromIterInit != null) {
          // That has an initializer expression (useful only for side effects).
          //
          toForIn.setIterExpression(mapOptionalExpression(fromIterInit));
        }
      } else {
        // An unnamed iterator var.
        //
        toForIn = new JsForIn();
        toForIn.setIterExpression(mapExpression(fromIter));
      }
      toForIn.setObjectExpression(mapExpression(fromObjExpr));

      // The body stmt.
      //
      JsStatement bodyStmt = mapStatement(fromBody);
      if (bodyStmt != null) {
        toForIn.setBody(bodyStmt);
      } else {
        toForIn.setBody(JsEmpty.INSTANCE$);
      }

      return toForIn;
    } else {
      // Regular ol' for loop.
      //
      JsFor toFor;

      // The first item is either an expression or a JsVars.
      JsNode init = map(fromInit);
      JsExpression condition = mapOptionalExpression(fromTest);
      JsExpression increment = mapOptionalExpression(fromIncr);
      assert (init != null);
      if (init instanceof JsVars) {
        toFor = new JsFor((JsVars) init, condition, increment);
      } else {
        assert (init instanceof JsExpression);
        toFor = new JsFor((JsExpression) init, condition, increment);
      }

      JsStatement bodyStmt = mapStatement(fromBody);
      if (bodyStmt != null) {
        toFor.setBody(bodyStmt);
      } else {
        toFor.setBody(JsEmpty.INSTANCE$);
      }
      return toFor;
    }
  }
Example #9
0
  private JsNode map(Node node) throws JsParserException {
    switch (node.getType()) {
      case TokenStream.SCRIPT:
        {
          JsBlock block = new JsBlock();
          mapStatements(block.getStatements(), node);
          return block;
        }

      case TokenStream.DEBUGGER:
        return mapDebuggerStatement(node);

      case TokenStream.VOID:
        // VOID = nothing was parsed for this node
        return null;

      case TokenStream.EXPRSTMT:
        return mapExpressionStatement(node);

      case TokenStream.REGEXP:
        return mapRegExp(node);

      case TokenStream.ADD:
        return mapBinaryOperation(JsBinaryOperator.ADD, node);

      case TokenStream.SUB:
        return mapBinaryOperation(JsBinaryOperator.SUB, node);

      case TokenStream.MUL:
        return mapBinaryOperation(JsBinaryOperator.MUL, node);

      case TokenStream.DIV:
        return mapBinaryOperation(JsBinaryOperator.DIV, node);

      case TokenStream.MOD:
        return mapBinaryOperation(JsBinaryOperator.MOD, node);

      case TokenStream.AND:
        return mapBinaryOperation(JsBinaryOperator.AND, node);

      case TokenStream.OR:
        return mapBinaryOperation(JsBinaryOperator.OR, node);

      case TokenStream.BITAND:
        return mapBinaryOperation(JsBinaryOperator.BIT_AND, node);

      case TokenStream.BITOR:
        return mapBinaryOperation(JsBinaryOperator.BIT_OR, node);

      case TokenStream.BITXOR:
        return mapBinaryOperation(JsBinaryOperator.BIT_XOR, node);

      case TokenStream.ASSIGN:
        return mapAssignmentVariant(node);

      case TokenStream.RELOP:
        return mapRelationalVariant(node);

      case TokenStream.EQOP:
        return mapEqualityVariant(node);

      case TokenStream.SHOP:
        return mapShiftVariant(node);

      case TokenStream.UNARYOP:
        return mapUnaryVariant(node);

      case TokenStream.INC:
        return mapIncDecFixity(JsUnaryOperator.INC, node);

      case TokenStream.DEC:
        return mapIncDecFixity(JsUnaryOperator.DEC, node);

      case TokenStream.HOOK:
        return mapConditional(node);

      case TokenStream.STRING:
        return program.getStringLiteral(node.getString());

      case TokenStream.NUMBER_INT:
        return mapIntNumber(node);

      case TokenStream.NUMBER:
        return mapDoubleNumber(node);

      case TokenStream.CALL:
        return mapCall(node);

      case TokenStream.GETPROP:
        return mapGetProp(node);

      case TokenStream.SETPROP:
        return mapSetProp(node);

      case TokenStream.DELPROP:
        return mapDeleteProp(node);

      case TokenStream.IF:
        return mapIfStatement(node);

      case TokenStream.WHILE:
        return mapDoOrWhileStatement(true, node);

      case TokenStream.DO:
        return mapDoOrWhileStatement(false, node);

      case TokenStream.FOR:
        return mapForStatement(node);

      case TokenStream.WITH:
        return mapWithStatement(node);

      case TokenStream.GETELEM:
        return mapGetElem(node);

      case TokenStream.SETELEM:
        return mapSetElem(node);

      case TokenStream.FUNCTION:
        return mapFunction(node);

      case TokenStream.BLOCK:
        return mapBlock(node);

      case TokenStream.SETNAME:
        return mapBinaryOperation(JsBinaryOperator.ASG, node);

      case TokenStream.NAME:
      case TokenStream.BINDNAME:
        return scopeContext.globalNameFor(node.getString()).makeRef();

      case TokenStream.RETURN:
        return mapReturn(node);

      case TokenStream.BREAK:
        return mapBreak(node);

      case TokenStream.CONTINUE:
        return mapContinue(node);

      case TokenStream.OBJLIT:
        return mapObjectLit(node);

      case TokenStream.ARRAYLIT:
        return mapArrayLit(node);

      case TokenStream.VAR:
        return mapVar(node);

      case TokenStream.PRIMARY:
        return mapPrimary(node);

      case TokenStream.COMMA:
        return mapBinaryOperation(JsBinaryOperator.COMMA, node);

      case TokenStream.NEW:
        return mapNew(node);

      case TokenStream.THROW:
        return mapThrowStatement(node);

      case TokenStream.TRY:
        return mapTryStatement(node);

      case TokenStream.SWITCH:
        return mapSwitchStatement(node);

      case TokenStream.LABEL:
        return mapLabel(node);

      default:
        int tokenType = node.getType();
        throw createParserException("Unexpected top-level token type: " + tokenType, node);
    }
  }