/*
 * 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.JsPropertyInitializer;
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 toLit = new JsObjectLiteral(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);

      JsPropertyInitializer toPropInit = new JsPropertyInitializer(
          makeSourceInfo(fromLabelExpr), toLabelExpr, toValueExpr);
      toLit.getPropertyInitializers().add(toPropInit);

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

    return toLit;
  }

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