/*
 * Copyright 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.js;

import com.google.gwt.dev.jjs.Correlation.Literal;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.js.ast.JsArrayAccess;
import com.google.gwt.dev.js.ast.JsArrayLiteral;
import com.google.gwt.dev.js.ast.JsBinaryOperation;
import com.google.gwt.dev.js.ast.JsBinaryOperator;
import com.google.gwt.dev.js.ast.JsBlock;
import com.google.gwt.dev.js.ast.JsBooleanLiteral;
import com.google.gwt.dev.js.ast.JsBreak;
import com.google.gwt.dev.js.ast.JsCase;
import com.google.gwt.dev.js.ast.JsCatch;
import com.google.gwt.dev.js.ast.JsConditional;
import com.google.gwt.dev.js.ast.JsContinue;
import com.google.gwt.dev.js.ast.JsDebugger;
import com.google.gwt.dev.js.ast.JsDefault;
import com.google.gwt.dev.js.ast.JsDoWhile;
import com.google.gwt.dev.js.ast.JsEmpty;
import com.google.gwt.dev.js.ast.JsExprStmt;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsFor;
import com.google.gwt.dev.js.ast.JsForIn;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsIf;
import com.google.gwt.dev.js.ast.JsInvocation;
import com.google.gwt.dev.js.ast.JsLabel;
import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsNew;
import com.google.gwt.dev.js.ast.JsNode;
import com.google.gwt.dev.js.ast.JsNullLiteral;
import com.google.gwt.dev.js.ast.JsNumberLiteral;
import com.google.gwt.dev.js.ast.JsObjectLiteral;
import com.google.gwt.dev.js.ast.JsParameter;
import com.google.gwt.dev.js.ast.JsPostfixOperation;
import com.google.gwt.dev.js.ast.JsPrefixOperation;
import com.google.gwt.dev.js.ast.JsRegExp;
import com.google.gwt.dev.js.ast.JsReturn;
import com.google.gwt.dev.js.ast.JsRootScope;
import com.google.gwt.dev.js.ast.JsScope;
import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.dev.js.ast.JsStringLiteral;
import com.google.gwt.dev.js.ast.JsSwitch;
import com.google.gwt.dev.js.ast.JsThisRef;
import com.google.gwt.dev.js.ast.JsThrow;
import com.google.gwt.dev.js.ast.JsTry;
import com.google.gwt.dev.js.ast.JsUnaryOperator;
import com.google.gwt.dev.js.ast.JsVars;
import com.google.gwt.dev.js.ast.JsWhile;
import com.google.gwt.dev.js.rhino.Context;
import com.google.gwt.dev.js.rhino.ErrorReporter;
import com.google.gwt.dev.js.rhino.EvaluatorException;
import com.google.gwt.dev.js.rhino.IRFactory;
import com.google.gwt.dev.js.rhino.Node;
import com.google.gwt.dev.js.rhino.Parser;
import com.google.gwt.dev.js.rhino.TokenStream;
import com.google.gwt.dev.util.collect.Stack;

import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

/**
 * Parses JavaScript source.
 */
public class JsParser {

  public static List<JsStatement> parse(SourceInfo rootSourceInfo,
      JsScope scope, Reader r) throws IOException, JsParserException {
    return new JsParser().parseImpl(rootSourceInfo, scope, r);
  }

  public static void parseInto(SourceInfo rootSourceInfo, JsScope scope,
      JsBlock block, Reader r) throws IOException, JsParserException {
    List<JsStatement> childStmts = parse(rootSourceInfo, scope, r);
    List<JsStatement> parentStmts = block.getStatements();
    parentStmts.addAll(childStmts);
  }

  private final Stack<JsScope> scopeStack = new Stack<JsScope>();
  private final Stack<SourceInfo> sourceInfoStack = new Stack<SourceInfo>();

  private JsParser() {
  }

  List<JsStatement> parseImpl(final SourceInfo rootSourceInfo, JsScope scope,
      Reader r) throws JsParserException, IOException {
    // Create a custom error handler so that we can throw our own exceptions.
    Context.enter().setErrorReporter(new ErrorReporter() {
      @Override
      public void error(String msg, String loc, int ln, String src, int col) {
        throw new UncheckedJsParserException(new JsParserException(msg, ln,
            src, col, rootSourceInfo.getFileName()));
      }

      @Override
      public EvaluatorException runtimeError(String msg, String loc, int ln,
          String src, int col) {
        // Never called, but just in case.
        throw new UncheckedJsParserException(new JsParserException(msg, ln,
            src, col, rootSourceInfo.getFileName()));
      }

      @Override
      public void warning(String msg, String loc, int ln, String src, int col) {
        // Ignore warnings.
      }
    });
    try {
      // Parse using the Rhino parser.
      //
      TokenStream ts = new TokenStream(r, rootSourceInfo.getFileName(),
          rootSourceInfo.getStartLine());
      Parser parser = new Parser(new IRFactory(ts));
      Node topNode = (Node) parser.parse(ts);

      // Map the Rhino AST to ours.
      pushScope(scope, rootSourceInfo);
      List<JsStatement> stmts = mapStatements(topNode);
      popScope();
      return stmts;
    } catch (UncheckedJsParserException e) {
      throw e.getParserException();
    } finally {
      Context.exit();
    }
  }

  private JsParserException createParserException(String msg, Node offender) {
    return new JsParserException(msg, offender.getLineno(), null, 0,
        sourceInfoStack.peek().getFileName());
  }

  private JsScope getScope() {
    return scopeStack.peek();
  }

  private SourceInfo makeSourceInfo(Node node) {
    SourceInfo parent = sourceInfoStack.peek();
    int lineno = node.getLineno();
    if (lineno == -1) {
      // Rhino only reports line numbers for statement nodes, not expressions
      return parent;
    }
    return parent.makeChild(SourceOrigin.create(lineno, parent.getFileName()));
  }

  /**
   * Force a distinct child to be created, so correlations can be added.
   */
  private SourceInfo makeSourceInfoDistinct(Node node) {
    SourceInfo parent = sourceInfoStack.peek();
    int lineno = node.getLineno();
    if (lineno == -1) {
      // Rhino only reports line numbers for statement nodes, not expressions
      lineno = parent.getStartLine();
    }
    return parent.makeChild(SourceOrigin.create(lineno, parent.getFileName()));
  }

  private JsNode map(Node node) throws JsParserException {

    switch (node.getType()) {
      case TokenStream.SCRIPT: {
        JsBlock block = new JsBlock(makeSourceInfo(node));
        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 mapExprStmt(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: {
        SourceInfo info = makeSourceInfoDistinct(node);
        info.addCorrelation(info.getCorrelator().by(Literal.STRING));
        return new JsStringLiteral(info, node.getString());
      }

      case TokenStream.NUMBER:
        return mapNumber(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 mapName(node);

      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);
    }
  }

  private JsArrayLiteral mapArrayLit(Node node) throws JsParserException {
    JsArrayLiteral toLit = new JsArrayLiteral(makeSourceInfo(node));
    Node from = node.getFirstChild();
    while (from != null) {
      toLit.getExpressions().add(mapExpression(from));
      from = from.getNext();
    }
    return toLit;
  }

  /**
   * 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;
      String litName = lit.getValue();
      return new JsNameRef(makeSourceInfo(nameRefNode), litName);
    } else {
      throw createParserException("Expecting a name reference", nameRefNode);
    }
  }

  private JsExpression mapAssignmentVariant(Node asgNode)
      throws JsParserException {
    switch (asgNode.getIntDatum()) {
      case TokenStream.NOP:
        return mapBinaryOperation(JsBinaryOperator.ASG, asgNode);

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

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

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

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

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

      case TokenStream.BITAND:
        return mapBinaryOperation(JsBinaryOperator.ASG_BIT_AND, asgNode);

      case TokenStream.BITOR:
        return mapBinaryOperation(JsBinaryOperator.ASG_BIT_OR, asgNode);

      case TokenStream.BITXOR:
        return mapBinaryOperation(JsBinaryOperator.ASG_BIT_XOR, asgNode);

      case TokenStream.LSH:
        return mapBinaryOperation(JsBinaryOperator.ASG_SHL, asgNode);

      case TokenStream.RSH:
        return mapBinaryOperation(JsBinaryOperator.ASG_SHR, asgNode);

      case TokenStream.URSH:
        return mapBinaryOperation(JsBinaryOperator.ASG_SHRU, asgNode);

      default:
        throw createParserException("Unknown assignment operator variant: "
            + asgNode.getIntDatum(), asgNode);
    }
  }

  private JsExpression mapBinaryOperation(JsBinaryOperator op, Node node)
      throws JsParserException {
    Node from1 = node.getFirstChild();
    Node from2 = from1.getNext();

    JsExpression to1 = mapExpression(from1);
    JsExpression to2 = mapExpression(from2);

    return new JsBinaryOperation(makeSourceInfo(node), op, to1, to2);
  }

  private JsBlock mapBlock(Node nodeStmts) throws JsParserException {
    SourceInfo info = makeSourceInfo(nodeStmts);
    JsBlock block = new JsBlock(info);
    pushSourceInfo(info);
    mapStatements(block.getStatements(), nodeStmts);
    popSourceInfo();
    return block;
  }

  private JsBreak mapBreak(Node breakNode) {
    Node fromLabel = breakNode.getFirstChild();
    if (fromLabel != null) {
      return new JsBreak(makeSourceInfo(breakNode), mapName(fromLabel));
    } else {
      return new JsBreak(makeSourceInfo(breakNode));
    }
  }

  private JsInvocation mapCall(Node callNode) throws JsParserException {
    JsInvocation invocation = new JsInvocation(makeSourceInfo(callNode));

    // Map the target expression.
    //
    Node from = callNode.getFirstChild();
    JsExpression to = mapExpression(from);
    invocation.setQualifier(to);

    // Iterate over and map the arguments.
    //
    List<JsExpression> args = invocation.getArguments();
    from = from.getNext();
    while (from != null) {
      to = mapExpression(from);
      args.add(to);
      from = from.getNext();
    }

    return invocation;
  }

  private JsExpression mapConditional(Node condNode) throws JsParserException {
    JsConditional toCond = new JsConditional(makeSourceInfo(condNode));

    Node fromTest = condNode.getFirstChild();
    toCond.setTestExpression(mapExpression(fromTest));

    Node fromThen = fromTest.getNext();
    toCond.setThenExpression(mapExpression(fromThen));

    Node fromElse = fromThen.getNext();
    toCond.setElseExpression(mapExpression(fromElse));

    return toCond;
  }

  private JsContinue mapContinue(Node contNode) {
    Node fromLabel = contNode.getFirstChild();
    if (fromLabel != null) {
      return new JsContinue(makeSourceInfo(contNode), mapName(fromLabel));
    } else {
      return new JsContinue(makeSourceInfo(contNode));
    }
  }

  private JsStatement mapDebuggerStatement(Node node) {
    // Calls an optional method to invoke the debugger.
    //
    return new JsDebugger(makeSourceInfo(node));
  }

  private JsExpression mapDeleteProp(Node node) throws JsParserException {
    Node from = node.getFirstChild();
    JsExpression to = mapExpression(from);
    if (to instanceof JsNameRef) {
      return new JsPrefixOperation(makeSourceInfo(node),
          JsUnaryOperator.DELETE, to);
    } else if (to instanceof JsArrayAccess) {
      return new JsPrefixOperation(makeSourceInfo(node),
          JsUnaryOperator.DELETE, to);
    } else {
      throw createParserException(
          "'delete' can only operate on property names and array elements",
          from);
    }
  }

  private JsStatement mapDoOrWhileStatement(boolean isWhile, Node ifNode)
      throws JsParserException {

    // Pull out the pieces we want to map.
    //
    Node fromTestExpr;
    Node fromBody;
    if (isWhile) {
      fromTestExpr = ifNode.getFirstChild();
      fromBody = ifNode.getFirstChild().getNext();
    } else {
      fromBody = ifNode.getFirstChild();
      fromTestExpr = ifNode.getFirstChild().getNext();
    }

    SourceInfo info = makeSourceInfo(ifNode);
    pushSourceInfo(info);

    // Map the test expression.
    //
    JsExpression toTestExpr = mapExpression(fromTestExpr);

    // Map the body block.
    //
    JsStatement toBody = mapStatement(fromBody);

    popSourceInfo();

    // Create and attach the "while" or "do" statement we're mapping to.
    //
    if (isWhile) {
      return new JsWhile(info, toTestExpr, toBody);
    } else {
      return new JsDoWhile(info, toTestExpr, toBody);
    }
  }

  private JsExpression mapEqualityVariant(Node eqNode) throws JsParserException {
    switch (eqNode.getIntDatum()) {
      case TokenStream.EQ:
        return mapBinaryOperation(JsBinaryOperator.EQ, eqNode);

      case TokenStream.NE:
        return mapBinaryOperation(JsBinaryOperator.NEQ, eqNode);

      case TokenStream.SHEQ:
        return mapBinaryOperation(JsBinaryOperator.REF_EQ, eqNode);

      case TokenStream.SHNE:
        return mapBinaryOperation(JsBinaryOperator.REF_NEQ, eqNode);

      case TokenStream.LT:
        return mapBinaryOperation(JsBinaryOperator.LT, eqNode);

      case TokenStream.LE:
        return mapBinaryOperation(JsBinaryOperator.LTE, eqNode);

      case TokenStream.GT:
        return mapBinaryOperation(JsBinaryOperator.GT, eqNode);

      case TokenStream.GE:
        return mapBinaryOperation(JsBinaryOperator.GTE, eqNode);

      default:
        throw createParserException("Unknown equality operator variant: "
            + eqNode.getIntDatum(), eqNode);
    }
  }

  private JsExpression mapExpression(Node exprNode) throws JsParserException {
    JsNode unknown = map(exprNode);
    if (unknown instanceof JsExpression) {
      return (JsExpression) unknown;
    } else {
      throw createParserException("Expecting an expression", exprNode);
    }
  }

  private JsExprStmt mapExprStmt(Node node) throws JsParserException {
    pushSourceInfo(makeSourceInfo(node));
    JsExpression expr = mapExpression(node.getFirstChild());
    popSourceInfo();
    return expr.makeStmt();
  }

  private JsStatement mapForStatement(Node forNode) throws JsParserException {
    Node fromInit = forNode.getFirstChild();
    Node fromTest = fromInit.getNext();
    Node fromIncr = fromTest.getNext();
    Node fromBody = fromIncr.getNext();

    SourceInfo info = makeSourceInfo(forNode);
    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 = getScope().declareName(fromName);
        toForIn = new JsForIn(info, toName);
        Node fromIterInit = fromIterVarName.getFirstChild();
        if (fromIterInit != null) {
          // That has an initializer expression (useful only for side effects).
          //
          toForIn.setIterExpr(mapOptionalExpression(fromIterInit));
        }
      } else {
        // An unnamed iterator var.
        //
        toForIn = new JsForIn(info);
        toForIn.setIterExpr(mapExpression(fromIter));
      }
      toForIn.setObjExpr(mapExpression(fromObjExpr));

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

      return toForIn;
    } else {
      // Regular ol' for loop.
      //
      JsFor toFor = new JsFor(info);

      // The first item is either an expression or a JsVars.
      JsNode initThingy = map(fromInit);
      if (initThingy != null) {
        if (initThingy instanceof JsVars) {
          toFor.setInitVars((JsVars) initThingy);
        } else {
          assert (initThingy instanceof JsExpression);
          toFor.setInitExpr((JsExpression) initThingy);
        }
      }
      toFor.setCondition(mapOptionalExpression(fromTest));
      toFor.setIncrExpr(mapOptionalExpression(fromIncr));

      JsStatement bodyStmt = mapStatement(fromBody);
      if (bodyStmt != null) {
        toFor.setBody(bodyStmt);
      } else {
        toFor.setBody(new JsEmpty(info));
      }
      return toFor;
    }
  }

  private JsExpression mapFunction(Node fnNode) throws JsParserException {

    Node fromFnNameNode = fnNode.getFirstChild();
    Node fromParamNode = fnNode.getFirstChild().getNext().getFirstChild();
    Node fromBodyNode = fnNode.getFirstChild().getNext().getNext();

    // Decide the function's name, if any.
    //
    String fromFnName = fromFnNameNode.getString();
    JsName toFnName = null;
    if (fromFnName != null && fromFnName.length() > 0) {
      toFnName = getScope().declareName(fromFnName);
    }

    // Create it, and set the params.
    //
    SourceInfo fnSourceInfo = makeSourceInfo(fnNode);
    JsFunction toFn = new JsFunction(fnSourceInfo, getScope(), toFnName);

    // Creating a function also creates a new scope, which we push onto
    // the scope stack.
    //
    pushScope(toFn.getScope(), fnSourceInfo);

    while (fromParamNode != null) {
      String fromParamName = fromParamNode.getString();
      // should this be unique? I think not since you can have dup args.
      JsName paramName = toFn.getScope().declareName(fromParamName);
      toFn.getParameters().add(new JsParameter(fnSourceInfo, paramName));
      fromParamNode = fromParamNode.getNext();
    }

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

    // Pop the new function's scope off of the scope stack.
    //
    popScope();

    return toFn;
  }

  private JsArrayAccess mapGetElem(Node getElemNode) throws JsParserException {
    Node from1 = getElemNode.getFirstChild();
    Node from2 = from1.getNext();

    JsExpression to1 = mapExpression(from1);
    JsExpression to2 = mapExpression(from2);

    return new JsArrayAccess(makeSourceInfo(getElemNode), to1, to2);
  }

  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 = new JsNameRef(makeSourceInfo(getPropNode), (String) obj);
    }
    toNameRef.setQualifier(toQualifier);

    return toNameRef;
  }

  private JsIf mapIfStatement(Node ifNode) throws JsParserException {

    // Pull out the pieces we want to map.
    //
    Node fromTestExpr = ifNode.getFirstChild();
    Node fromThenBlock = ifNode.getFirstChild().getNext();
    Node fromElseBlock = ifNode.getFirstChild().getNext().getNext();

    // Create the "if" statement we're mapping to.
    //
    JsIf toIf = new JsIf(makeSourceInfo(ifNode));

    // Map the test expression.
    //
    JsExpression toTestExpr = mapExpression(fromTestExpr);
    toIf.setIfExpr(toTestExpr);

    // Map the "then" block.
    //
    toIf.setThenStmt(mapStatement(fromThenBlock));

    // Map the "else" block.
    //
    if (fromElseBlock != null) {
      toIf.setElseStmt(mapStatement(fromElseBlock));
    }

    return toIf;
  }

  private JsExpression mapIncDecFixity(JsUnaryOperator op, Node node)
      throws JsParserException {
    switch (node.getIntDatum()) {
      case TokenStream.PRE:
        return mapPrefixOperation(op, node);
      case TokenStream.POST:
        return mapPostfixOperation(op, node);
      default:
        throw createParserException(
            "Unknown prefix/postfix variant: " + node.getIntDatum(), node);
    }
  }

  private JsLabel mapLabel(Node labelNode) throws JsParserException {
    String fromName = labelNode.getFirstChild().getString();
    JsName toName = getScope().declareName(fromName);
    Node fromStmt = labelNode.getFirstChild().getNext();
    JsLabel toLabel = new JsLabel(makeSourceInfo(labelNode), toName);
    toLabel.setStmt(mapStatement(fromStmt));
    return toLabel;
  }

  /**
   * Creates a reference to a name that may or may not be obfuscatable, based on
   * whether it matches a known name in the scope.
   */
  private JsNameRef mapName(Node node) {
    String ident = node.getString();
    return new JsNameRef(makeSourceInfo(node), ident);
  }

  private JsNew mapNew(Node newNode) throws JsParserException {
    // Map the constructor expression, which is often just the name of
    // some lambda.
    //
    Node fromCtorExpr = newNode.getFirstChild();
    JsNew newExpr = new JsNew(makeSourceInfo(newNode),
        mapExpression(fromCtorExpr));

    // Iterate over and map the arguments.
    //
    List<JsExpression> args = newExpr.getArguments();
    Node fromArg = fromCtorExpr.getNext();
    while (fromArg != null) {
      args.add(mapExpression(fromArg));
      fromArg = fromArg.getNext();
    }

    return newExpr;
  }

  private JsExpression mapNumber(Node numberNode) {
    return new JsNumberLiteral(makeSourceInfo(numberNode),
        numberNode.getDouble());
  }

  private JsExpression mapObjectLit(Node objLitNode) throws JsParserException {
    JsObjectLiteral.Builder objectLiteralBuilder =
        JsObjectLiteral.builder(makeSourceInfo(objLitNode));
    Node fromPropInit = objLitNode.getFirstChild();
    while (fromPropInit != null) {

      Node fromLabelExpr = fromPropInit;
      JsExpression toLabelExpr = mapExpression(fromLabelExpr);

      // Advance to the initializer expression.
      //
      fromPropInit = fromPropInit.getNext();
      Node fromValueExpr = fromPropInit;
      if (fromValueExpr == null) {
        throw createParserException("Expected an init expression for: "
            + toLabelExpr, objLitNode);
      }
      JsExpression toValueExpr = mapExpression(fromValueExpr);
      objectLiteralBuilder.add(makeSourceInfo(fromLabelExpr), toLabelExpr, toValueExpr);

      // Begin the next property initializer, if there is one.
      //
      fromPropInit = fromPropInit.getNext();
    }

    return objectLiteralBuilder.build();
  }

  private JsExpression mapOptionalExpression(Node exprNode)
      throws JsParserException {
    JsNode unknown = map(exprNode);
    if (unknown != null) {
      if (unknown instanceof JsExpression) {
        return (JsExpression) unknown;
      } else {
        throw createParserException("Expecting an expression or null", exprNode);
      }
    }
    return null;
  }

  private JsExpression mapPostfixOperation(JsUnaryOperator op, Node node)
      throws JsParserException {
    Node from = node.getFirstChild();
    JsExpression to = mapExpression(from);
    return new JsPostfixOperation(makeSourceInfo(node), op, to);
  }

  private JsExpression mapPrefixOperation(JsUnaryOperator op, Node node)
      throws JsParserException {
    Node from = node.getFirstChild();
    JsExpression to = mapExpression(from);
    return new JsPrefixOperation(makeSourceInfo(node), op, to);
  }

  private JsExpression mapPrimary(Node node) throws JsParserException {
    switch (node.getIntDatum()) {
      case TokenStream.THIS:
        return new JsThisRef(makeSourceInfo(node));

      case TokenStream.TRUE:
        return JsBooleanLiteral.TRUE;

      case TokenStream.FALSE:
        return JsBooleanLiteral.FALSE;

      case TokenStream.NULL:
        return JsNullLiteral.INSTANCE;

      case TokenStream.UNDEFINED:
        return new JsNameRef(makeSourceInfo(node),
            JsRootScope.INSTANCE.getUndefined());

      default:
        throw createParserException("Unknown primary: " + node.getIntDatum(),
            node);
    }
  }

  private JsNode mapRegExp(Node regExpNode) {
    JsRegExp toRegExp = new JsRegExp(makeSourceInfo(regExpNode));

    Node fromPattern = regExpNode.getFirstChild();
    toRegExp.setPattern(fromPattern.getString());

    Node fromFlags = fromPattern.getNext();
    if (fromFlags != null) {
      toRegExp.setFlags(fromFlags.getString());
    }

    return toRegExp;
  }

  private JsExpression mapRelationalVariant(Node relNode)
      throws JsParserException {
    switch (relNode.getIntDatum()) {
      case TokenStream.LT:
        return mapBinaryOperation(JsBinaryOperator.LT, relNode);

      case TokenStream.LE:
        return mapBinaryOperation(JsBinaryOperator.LTE, relNode);

      case TokenStream.GT:
        return mapBinaryOperation(JsBinaryOperator.GT, relNode);

      case TokenStream.GE:
        return mapBinaryOperation(JsBinaryOperator.GTE, relNode);

      case TokenStream.INSTANCEOF:
        return mapBinaryOperation(JsBinaryOperator.INSTANCEOF, relNode);

      case TokenStream.IN:
        return mapBinaryOperation(JsBinaryOperator.INOP, relNode);

      default:
        throw createParserException("Unknown relational operator variant: "
            + relNode.getIntDatum(), relNode);
    }
  }

  private JsReturn mapReturn(Node returnNode) throws JsParserException {
    SourceInfo info = makeSourceInfo(returnNode);
    JsReturn toReturn = new JsReturn(info);
    pushSourceInfo(info);
    Node from = returnNode.getFirstChild();
    if (from != null) {
      JsExpression to = mapExpression(from);
      toReturn.setExpr(to);
    }

    popSourceInfo();
    return toReturn;
  }

  private JsExpression mapSetElem(Node setElemNode) throws JsParserException {
    // Reuse the get elem code.
    //
    JsArrayAccess lhs = mapGetElem(setElemNode);

    // Map the RHS.
    //
    Node fromRhs = setElemNode.getFirstChild().getNext().getNext();
    JsExpression toRhs = mapExpression(fromRhs);

    return new JsBinaryOperation(makeSourceInfo(setElemNode),
        JsBinaryOperator.ASG, lhs, toRhs);
  }

  private JsExpression mapSetProp(Node getPropNode) throws JsParserException {
    // Reuse the get prop code.
    //
    JsNameRef lhs = mapGetProp(getPropNode);

    // Map the RHS.
    //
    Node fromRhs = getPropNode.getFirstChild().getNext().getNext();
    JsExpression toRhs = mapExpression(fromRhs);

    return new JsBinaryOperation(makeSourceInfo(getPropNode),
        JsBinaryOperator.ASG, lhs, toRhs);
  }

  private JsExpression mapShiftVariant(Node shiftNode) throws JsParserException {
    switch (shiftNode.getIntDatum()) {
      case TokenStream.LSH:
        return mapBinaryOperation(JsBinaryOperator.SHL, shiftNode);

      case TokenStream.RSH:
        return mapBinaryOperation(JsBinaryOperator.SHR, shiftNode);

      case TokenStream.URSH:
        return mapBinaryOperation(JsBinaryOperator.SHRU, shiftNode);

      default:
        throw createParserException("Unknown equality operator variant: "
            + shiftNode.getIntDatum(), shiftNode);
    }
  }

  private JsStatement mapStatement(Node nodeStmt) throws JsParserException {
    JsNode unknown = map(nodeStmt);
    if (unknown != null) {
      if (unknown instanceof JsStatement) {
        return (JsStatement) unknown;
      } else if (unknown instanceof JsExpression) {
        return ((JsExpression) unknown).makeStmt();
      } else {
        throw createParserException("Expecting a statement", nodeStmt);
      }
    } else {
      // When map() returns null, we return an empty statement.
      //
      return new JsEmpty(makeSourceInfo(nodeStmt));
    }
  }

  private void mapStatements(List<JsStatement> stmts, Node nodeStmts)
      throws JsParserException {
    Node curr = nodeStmts.getFirstChild();
    while (curr != null) {
      JsStatement stmt = mapStatement(curr);
      if (stmt != null) {
        stmts.add(stmt);
      } else {
        // When mapStatement() returns null, we just ignore it.
        //
      }
      curr = curr.getNext();
    }
  }

  private List<JsStatement> mapStatements(Node nodeStmts)
      throws JsParserException {
    List<JsStatement> stmts = new ArrayList<JsStatement>();
    mapStatements(stmts, nodeStmts);
    return stmts;
  }

  private JsSwitch mapSwitchStatement(Node switchNode) throws JsParserException {
    SourceInfo info = makeSourceInfo(switchNode);
    JsSwitch toSwitch = new JsSwitch(info);
    pushSourceInfo(info);

    // The switch expression.
    //
    Node fromSwitchExpr = switchNode.getFirstChild();
    toSwitch.setExpr(mapExpression(fromSwitchExpr));

    // The members.
    //
    Node fromMember = fromSwitchExpr.getNext();
    while (fromMember != null) {
      if (fromMember.getType() == TokenStream.CASE) {
        JsCase toCase = new JsCase(makeSourceInfo(fromMember));

        // Set the case expression. In JS, this can be any expression.
        //
        Node fromCaseExpr = fromMember.getFirstChild();
        toCase.setCaseExpr(mapExpression(fromCaseExpr));

        // Set the case statements.
        //
        Node fromCaseBlock = fromCaseExpr.getNext();
        mapStatements(toCase.getStmts(), fromCaseBlock);

        // Attach the case to the switch.
        //
        toSwitch.getCases().add(toCase);
      } else {
        // This should be the only default statement.
        // If more than one is present, we keep the last one.
        //
        assert (fromMember.getType() == TokenStream.DEFAULT);
        JsDefault toDefault = new JsDefault(makeSourceInfo(fromMember));

        // Set the default statements.
        //
        Node fromDefaultBlock = fromMember.getFirstChild();
        mapStatements(toDefault.getStmts(), fromDefaultBlock);

        // Attach the default to the switch.
        //
        toSwitch.getCases().add(toDefault);
      }
      fromMember = fromMember.getNext();
    }

    popSourceInfo();
    return toSwitch;
  }

  private JsThrow mapThrowStatement(Node throwNode) throws JsParserException {
    SourceInfo info = makeSourceInfo(throwNode);
    pushSourceInfo(info);

    // Create, map, and attach.
    //
    Node fromExpr = throwNode.getFirstChild();
    JsThrow toThrow = new JsThrow(info, mapExpression(fromExpr));

    popSourceInfo();
    return toThrow;
  }

  private JsTry mapTryStatement(Node tryNode) throws JsParserException {
    JsTry toTry = new JsTry(makeSourceInfo(tryNode));

    // 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 = new JsCatch(makeSourceInfo(fromCatchNode),
          getScope(), 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();
      pushScope(catchBlock.getScope(), catchBlock.getSourceInfo());
      catchBlock.setBody(mapBlock(fromCatchBody));
      popScope();

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

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

    return toTry;
  }

  private JsExpression mapUnaryVariant(Node unOp) throws JsParserException {
    switch (unOp.getIntDatum()) {
      case TokenStream.SUB:
        return mapPrefixOperation(JsUnaryOperator.NEG, unOp);

      case TokenStream.NOT:
        return mapPrefixOperation(JsUnaryOperator.NOT, unOp);

      case TokenStream.BITNOT:
        return mapPrefixOperation(JsUnaryOperator.BIT_NOT, unOp);

      case TokenStream.TYPEOF:
        return mapPrefixOperation(JsUnaryOperator.TYPEOF, unOp);

      case TokenStream.ADD:
        if (unOp.getFirstChild().getType() != TokenStream.NUMBER) {
          return mapPrefixOperation(JsUnaryOperator.POS, unOp);
        } else {
          // Pretend we didn't see it.
          return mapExpression(unOp.getFirstChild());
        }

      case TokenStream.VOID:
        return mapPrefixOperation(JsUnaryOperator.VOID, unOp);

      default:
        throw createParserException(
            "Unknown unary operator variant: " + unOp.getIntDatum(), unOp);
    }
  }

  private JsVars mapVar(Node varNode) throws JsParserException {
    SourceInfo info = makeSourceInfo(varNode);
    pushSourceInfo(info);
    JsVars toVars = new JsVars(info);
    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 = getScope().declareName(fromName);
      JsVars.JsVar toVar = new JsVars.JsVar(makeSourceInfo(fromVar), toName);

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

      fromVar = fromVar.getNext();
    }

    popSourceInfo();
    return toVars;
  }

  private JsNode mapWithStatement(Node withNode) throws JsParserException {
    // The "with" statement is unsupported because it introduces ambiguity
    // related to whether or not a name is obfuscatable that we cannot resolve
    // statically. This is modified in our copy of the Rhino Parser to provide
    // detailed source & line info. So, this method should never actually be
    // called.
    //
    throw createParserException("Internal error: unexpected token 'with'",
        withNode);
  }

  private void popScope() {
    scopeStack.pop();
    sourceInfoStack.pop();
  }

  private void popSourceInfo() {
    sourceInfoStack.pop();
  }

  private void pushScope(JsScope scope, SourceInfo sourceInfo) {
    scopeStack.push(scope);
    sourceInfoStack.push(sourceInfo);
  }

  /**
   * This should be called when processing any Rhino statement Node that has
   * line number data so that enclosed expressions will have a useful source
   * location.
   *
   * @see Node#hasLineno
   */
  private void pushSourceInfo(SourceInfo sourceInfo) {
    assert sourceInfo.getStartLine() >= 0 : "Bad SourceInfo line number";
    sourceInfoStack.push(sourceInfo);
  }
}
