/*
 * 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 java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * 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() {
      public void error(String msg, String loc, int ln, String src, int col) {
        throw new UncheckedJsParserException(new JsParserException(msg, ln,
            src, col, rootSourceInfo.getFileName()));
      }

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

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