Package org.lilystudio.javascript.expression

Source Code of org.lilystudio.javascript.expression.BinaryExpression

package org.lilystudio.javascript.expression;

import java.io.IOException;
import java.io.Writer;

import org.lilystudio.javascript.AbstractNode;
import org.lilystudio.javascript.Environment;
import org.lilystudio.javascript.IExpression;
import org.lilystudio.javascript.Utils;
import org.lilystudio.javascript.scope.Scope;
import org.mozilla.javascript.Node;
import org.mozilla.javascript.ScriptOrFnNode;
import org.mozilla.javascript.Token;

/**
* 二元表达式节点
*
* @version 1.0.0, 2010/01/01
* @author 欧阳先伟
* @since Common 0.1
*/
public class BinaryExpression extends AbstractNode implements IExpression {

  /** 二元表达式类型 */
  private int tokenType;

  /** 二元表达式的左部表达式 */
  private IExpression leftExpression;

  /** 二元表达式的右部表达式 */
  private IExpression rightExpression;

  /**
   * 创建二元表达式节点
   *
   * @param lineno
   *          节点的行号
   * @param tokenType
   *          二元表达式的类型
   * @param leftExpression
   *          二元表达式的左部表达式
   * @param rightExpression
   *          二元表达式的右部表达式
   */
  public BinaryExpression(int lineno, int tokenType,
      IExpression leftExpression, IExpression rightExpression) {
    super(lineno);
    this.tokenType = tokenType;
    this.leftExpression = leftExpression;
    this.rightExpression = rightExpression;
  }

  /**
   * 创建二元表达式节点
   *
   * @param node
   *          表达式子节点对应的rhino节点
   * @param root
   *          表达式子节点对应的rhino根节点
   * @param scope
   *          表达式子节点生存域
   */
  public BinaryExpression(Node node, ScriptOrFnNode root, Scope scope) {
    super(node.getLineno());
    Node firstChild = node.getFirstChild();

    tokenType = node.getType();

    if (firstChild.getType() != Token.USE_STACK) {
      if (tokenType == Token.SETPROP || tokenType == Token.SETELEM
          || tokenType == Token.SETPROP_OP || tokenType == Token.SETELEM_OP) {
        leftExpression = new MemberExpression(node, root, scope);
        leftExpression.setParent(this);
      } else {
        leftExpression = addExpression(firstChild, root, scope);
      }
    }

    rightExpression = addExpression(node.getLastChild(), root, scope);
    if (tokenType == Token.SETNAME || tokenType == Token.SETPROP
        || tokenType == Token.SETELEM) {
      tokenType = Token.ASSIGN;

      if (rightExpression instanceof BinaryExpression) {
        BinaryExpression binaryExpression = (BinaryExpression) rightExpression;

        boolean flag = leftExpression.equals(binaryExpression.leftExpression);
        if (flag
            || (leftExpression.equals(binaryExpression.rightExpression) && (binaryExpression.tokenType == Token.MUL
                || binaryExpression.tokenType == Token.BITAND
                || binaryExpression.tokenType == Token.BITXOR || binaryExpression.tokenType == Token.BITOR))) {

          switch (binaryExpression.tokenType) {
          case Token.MUL:
            tokenType = Token.ASSIGN_MUL;
            break;

          case Token.DIV:
            tokenType = Token.ASSIGN_DIV;
            break;

          case Token.MOD:
            tokenType = Token.ASSIGN_MOD;
            break;

          case Token.ADD:
            tokenType = Token.ASSIGN_ADD;
            break;

          case Token.SUB:
            tokenType = Token.ASSIGN_SUB;
            break;

          case Token.LSH:
            tokenType = Token.ASSIGN_LSH;
            break;

          case Token.RSH:
            tokenType = Token.ASSIGN_RSH;
            break;

          case Token.URSH:
            tokenType = Token.ASSIGN_URSH;
            break;

          case Token.BITAND:
            tokenType = Token.ASSIGN_BITAND;
            break;

          case Token.BITXOR:
            tokenType = Token.ASSIGN_BITXOR;
            break;

          case Token.BITOR:
            tokenType = Token.ASSIGN_BITOR;
            break;

          default:
            return;
          }
          rightExpression = flag ? binaryExpression.rightExpression
              : binaryExpression.leftExpression;
          rightExpression.setParent(this);
        }
      }
    }
  }

  @Override
  public boolean equals(Object obj) {
    return obj.getClass() == this.getClass()
        && tokenType == ((BinaryExpression) obj).tokenType
        && leftExpression.equals(((BinaryExpression) obj).leftExpression)
        && rightExpression.equals(((BinaryExpression) obj).rightExpression);
  }

  public int getType() {
    return tokenType;
  }

  public IExpression getLeftExpression() {
    return leftExpression;
  }

  public IExpression getRightExpression() {
    return rightExpression;
  }

  public int getLevel() {
    switch (tokenType) {
    case Token.MUL:
    case Token.DIV:
    case Token.MOD:
      return 50;
    case Token.ADD:
    case Token.SUB:
      return 60;
    case Token.LSH:
    case Token.RSH:
    case Token.URSH:
      return 70;
    case Token.LT:
    case Token.LE:
    case Token.GT:
    case Token.GE:
    case Token.INSTANCEOF:
    case Token.IN:
      return 80;
    case Token.EQ:
    case Token.NE:
    case Token.SHEQ:
    case Token.SHNE:
      return 90;
    case Token.BITAND:
      return 101;
    case Token.BITXOR:
      return 102;
    case Token.BITOR:
      return 103;
    case Token.AND:
      return 111;
    case Token.OR:
      return 112;
    case Token.SETNAME:
    case Token.SETPROP:
    case Token.SETELEM:
      return 130;
    default:
      return 140;
    }
  }

  public boolean isNeedLeftSeparator() {
    if (leftExpression.getLevel() <= this.getLevel()) {
      return leftExpression.isNeedLeftSeparator();
    }
    return false;
  }

  public boolean isNeedRightSeparator() {
    if (rightExpression.getLevel() < this.getLevel()) {
      return rightExpression.isNeedRightSeparator();
    }
    return false;
  }

  public void write(Writer writer, Environment env) throws IOException {
    boolean flag = tokenType == Token.INSTANCEOF || tokenType == Token.IN;

    if (leftExpression == null) {
      writer.write(Utils.escapeLiteral(tokenType));
      writer.write("=");
    } else {
      if (leftExpression.getLevel() <= this.getLevel()) {
        leftExpression.write(writer, env);
        if (flag && leftExpression.isNeedRightSeparator()) {
          writer.write(" ");
        }
      } else {
        writer.write("(");
        leftExpression.write(writer, env);
        writer.write(")");
      }

      if (leftExpression instanceof PostfixExpression) {
        if (((PostfixExpression) leftExpression).getType() == Token.INC) {
          if (tokenType == Token.ADD) {
            writer.write(" ");
          }
        } else {
          if (tokenType == Token.SUB) {
            writer.write(" ");
          }
        }
      }

      String s = Utils.escapeLiteral(tokenType);
      writer.write(s != null ? s : "");
    }

    if (rightExpression.getLevel() < this.getLevel()
        || (rightExpression.getLevel() == this.getLevel() && (tokenType == Token.ASSIGN || ((tokenType == Token.AND
            || tokenType == Token.OR
            || tokenType == Token.BITAND
            || tokenType == Token.BITOR
            || tokenType == Token.BITXOR
            || tokenType == Token.ADD || tokenType == Token.MUL) && rightExpression instanceof BinaryExpression)))) {

      if (rightExpression instanceof UnaryExpression) {
        int type = ((UnaryExpression) rightExpression).getType();
        if (type == Token.INC || type == Token.POS) {
          if (tokenType == Token.ADD) {
            writer.write(" ");
          }
        } else if (type == Token.DEC || type == Token.NEG) {
          if (tokenType == Token.SUB) {
            writer.write(" ");
          }
        }
      }

      if (flag && rightExpression.isNeedLeftSeparator()) {
        writer.write(" ");
      }
      rightExpression.write(writer, env);
    } else {
      writer.write("(");
      rightExpression.write(writer, env);
      writer.write(")");
    }
  }
}
TOP

Related Classes of org.lilystudio.javascript.expression.BinaryExpression

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.