Package org.lilystudio.javascript.statement

Source Code of org.lilystudio.javascript.statement.LoopStatement

package org.lilystudio.javascript.statement;

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

import org.lilystudio.javascript.Environment;
import org.lilystudio.javascript.IExpression;
import org.lilystudio.javascript.INode;
import org.lilystudio.javascript.IStatement;
import org.lilystudio.javascript.expression.InbuildLiteral;
import org.lilystudio.javascript.scope.Constant;
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 LoopStatement extends Statement implements IBodyStatement {

  /** 循环的类型 */
  private int tokenType;

  /** 循环的开始节点,用于for语句 */
  private INode startNode;

  /** 循环的条件表达式 */
  private IExpression checkExpression;

  /** 循环的周期结束表达式,用于for语句 */
  private IExpression endExpression;

  /** 循环体语句 */
  private IStatement bodyStatement;

  /**
   * 创建循环语句节点
   *
   * @param node
   *          语句子节点对应的rhino节点
   * @param root
   *          语句子节点对应的rhino根节点
   * @param scope
   *          语句子节点生存域
   */
  public LoopStatement(Node node, ScriptOrFnNode root, Scope scope) {
    super(node);
    Node childNode = node.getFirstChild();

    switch (childNode.getType()) {
    case Token.EXPR_VOID:
      tokenType = Token.FOR;
      startNode = addExpression(childNode.getFirstChild(), root, scope);
      childNode = childNode.getNext();
      break;

    case Token.VAR:
      tokenType = Token.FOR;
      startNode = addStatement(childNode, root, scope);
      childNode = childNode.getNext();
      break;
    }

    if (childNode.getType() == Token.TARGET) {
      bodyStatement = addStatement(childNode.getNext(), root, scope);
      childNode = bodyStatement.getNext().getNext();
      checkExpression = addExpression(childNode.getFirstChild(), root, scope);
      if (tokenType == 0) {
        tokenType = Token.DO;
      }
    } else if (childNode.getType() == Token.GOTO) {
      bodyStatement = addStatement(childNode.getNext().getNext(), root, scope);
      childNode = bodyStatement.getNext().getNext();

      if (childNode.getType() == Token.EXPR_VOID) {
        tokenType = Token.FOR;
        endExpression = addExpression(childNode.getFirstChild(), root, scope);
        childNode = childNode.getNext().getNext();
      }

      childNode = childNode.getNext();
      if (childNode.getType() == Token.TARGET) {
        checkExpression = addExpression(childNode.getNext().getFirstChild(),
            root, scope);
        tokenType = Token.FOR;
      } else {
        checkExpression = addExpression(childNode.getFirstChild(), root, scope);
        if (tokenType == 0) {
          tokenType = Token.WHILE;
        }
      }
    }
  }

  public boolean isNeedLeftSeparator() {
    return true;
  }

  public boolean isNeedRightSeparator() {
    switch (tokenType) {
    case Token.DO:
      return true;
    default:
      return bodyStatement.isNeedRightSeparator();
    }
  }

  public void write(Writer writer, Environment env) throws IOException {
    switch (tokenType) {
    case Token.DO:
    case Token.WHILE:
      if (checkExpression instanceof InbuildLiteral) {
        Constant literal = ((InbuildLiteral) checkExpression).getLiteral();
        if (literal.getString(false).equals("true")) {
          literal.dec(false);
          writer.write("for(;;)");
          bodyStatement.write(writer, env);
          break;
        }
      }

      if (tokenType == Token.DO) {
        writer.write("do");
        if (bodyStatement.isNeedLeftSeparator()) {
          writer.write(" ");
        }

        bodyStatement.write(writer, env);

        if (bodyStatement.isNeedRightSeparator()) {
          writer.write(";");
        }

        writer.write("while(");
        checkExpression.write(writer, env);
        writer.write(")");
      } else {
        writer.write("while(");
        checkExpression.write(writer, env);
        writer.write(")");
        bodyStatement.write(writer, env);
      }
      break;

    default:
      writer.write("for(");

      if (startNode != null) {
        startNode.write(writer, env);
      }

      writer.write(";");

      if (checkExpression instanceof InbuildLiteral) {
        Constant literal = ((InbuildLiteral) checkExpression).getLiteral();
        if (literal.getString(false).equals("true")) {
          literal.dec(false);
        }
      } else {
        checkExpression.write(writer, env);
      }

      writer.write(";");

      if (endExpression != null) {
        endExpression.write(writer, env);
      }

      writer.write(")");

      bodyStatement.write(writer, env);
    }
  }

  public boolean isIfBody() {
    return tokenType != Token.DO && bodyStatement instanceof IBodyStatement
        && ((IBodyStatement) bodyStatement).isIfBody();
  }
}
TOP

Related Classes of org.lilystudio.javascript.statement.LoopStatement

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.