/** Class constructor. */
  public SwitchStatement() {
    if (!SectionInfo.in() && !FunctionInfo.in())
      throw new NslContextException(EnumSet.of(NslContext.Section, NslContext.Function), "switch");

    int lineNo = ScriptParser.tokenizer.lineno();
    ScriptParser.tokenizer.matchOrDie('(');
    this.switchExpression = Expression.matchComplex();
    ScriptParser.tokenizer.matchOrDie(')');
    ScriptParser.tokenizer.matchOrDie('{');

    // Set non-null values so that the block statement can contain break statements.
    CodeInfo.getCurrent().setBreakLabel(RelativeJump.Zero);

    this.statementList = new ArrayList<Statement>();
    this.casesList = new ArrayList<SwitchCaseStatement>();
    this.defaultCase = null;

    // Get the statements including case statements.
    while (true) {
      if (ScriptParser.tokenizer.match("case")) {
        Statement statement = new SwitchCaseStatement();
        if (this.defaultCase != null)
          throw new NslException(
              "The \"default\" case in a \"switch\" statement must be the last case", true);
        this.casesList.add((SwitchCaseStatement) statement);
        this.statementList.add(statement);
      } else if (ScriptParser.tokenizer.match("default")) {
        this.defaultCase = new SwitchDefaultCaseStatement();
        this.statementList.add(this.defaultCase);
      } else {
        Statement statement = Statement.match();
        if (statement == null) break;
        this.statementList.add(statement);
      }
    }

    // No cases?
    if (this.casesList.isEmpty())
      throw new NslException(
          "A \"switch\" statement must have at least one \"case\" statement", true);

    // Validate switch cases for jump instructions.
    if (this.switchExpression instanceof JumpExpression)
      ((JumpExpression) this.switchExpression).checkSwitchCases(this.casesList, lineNo);

    // Check the last statement is a break statement.
    boolean noBreak = true;
    if (!this.statementList.isEmpty()) {
      Statement last = this.statementList.get(this.statementList.size() - 1);
      if (last instanceof BlockStatement) last = ((BlockStatement) last).getLast();
      if (last instanceof BreakStatement) noBreak = false;
    }
    if (noBreak)
      throw new NslException("A \"switch\" statement must end with a \"break\" statement", true);

    CodeInfo.getCurrent().setBreakLabel(null);

    ScriptParser.tokenizer.matchOrDie('}');
  }
  /**
   * Class constructor.
   *
   * @param returns the number of values to return
   */
  public GetErrorLevelInstruction(int returns) {
    if (!SectionInfo.in() && !FunctionInfo.in())
      throw new NslContextException(EnumSet.of(NslContext.Section, NslContext.Function), name);
    if (returns != 1) throw new NslReturnValueException(name, 1);

    ArrayList<Expression> paramsList = Expression.matchList();
    if (!paramsList.isEmpty()) throw new NslArgumentException(name, 0);
  }
  /**
   * Class constructor.
   *
   * @param returns the number of values to return
   */
  public FlushINIInstruction(int returns) {
    if (!SectionInfo.in() && !FunctionInfo.in())
      throw new NslContextException(EnumSet.of(NslContext.Section, NslContext.Function), name);
    if (returns > 0) throw new NslReturnValueException(name);

    ArrayList<Expression> paramsList = Expression.matchList();
    if (paramsList.size() != 1) throw new NslArgumentException(name, 1);

    this.iniFile = paramsList.get(0);
  }
  /**
   * Class constructor.
   *
   * @param returns the number of values to return
   */
  public LockWindowInstruction(int returns) {
    if (!SectionInfo.in() && !FunctionInfo.in())
      throw new NslContextException(EnumSet.of(NslContext.Section, NslContext.Function), name);
    if (returns > 0) throw new NslReturnValueException(name);

    ArrayList<Expression> paramsList = Expression.matchList();
    if (paramsList.size() != 1) throw new NslArgumentException(name, 1);

    this.value = paramsList.get(0);
    if (!ExpressionType.isString(this.value))
      throw new NslArgumentException(name, 1, ExpressionType.String);
  }