public IMatchable findObject(MatchNode matchNode, int index) {

    int node_type = matchNode.getType();

    if (node_type == MatchNode.MATCHNODE_STATEMENT && !this.stats.isEmpty()) {
      String position = (String) matchNode.getRuleValue(MatchProperties.STATEMENT_POSITION);
      if (position != null) {
        if (position.matches("-?\\d+")) {
          return this.stats.get(
              (this.stats.size() + Integer.parseInt(position))
                  % this.stats.size()); // care for negative positions
        }
      } else if (index < this.stats.size()) { // use 'index' parameter
        return this.stats.get(index);
      }
    } else if (node_type == MatchNode.MATCHNODE_EXPRENT
        && this.exprents != null
        && !this.exprents.isEmpty()) {
      String position = (String) matchNode.getRuleValue(MatchProperties.EXPRENT_POSITION);
      if (position != null) {
        if (position.matches("-?\\d+")) {
          return this.exprents.get(
              (this.exprents.size() + Integer.parseInt(position))
                  % this.exprents.size()); // care for negative positions
        }
      } else if (index < this.exprents.size()) { // use 'index' parameter
        return this.exprents.get(index);
      }
    }

    return null;
  }
  public boolean match(MatchNode matchNode, MatchEngine engine) {

    if (matchNode.getType() != MatchNode.MATCHNODE_STATEMENT) {
      return false;
    }

    for (Entry<MatchProperties, RuleValue> rule : matchNode.getRules().entrySet()) {
      switch (rule.getKey()) {
        case STATEMENT_TYPE:
          if (this.type != ((Integer) rule.getValue().value).intValue()) {
            return false;
          }
          break;
        case STATEMENT_STATSIZE:
          if (this.stats.size() != ((Integer) rule.getValue().value).intValue()) {
            return false;
          }
          break;
        case STATEMENT_EXPRSIZE:
          int exprsize = ((Integer) rule.getValue().value).intValue();
          if (exprsize == -1) {
            if (this.exprents != null) {
              return false;
            }
          } else {
            if (this.exprents == null || this.exprents.size() != exprsize) {
              return false;
            }
          }
          break;
        case STATEMENT_RET:
          if (!engine.checkAndSetVariableValue((String) rule.getValue().value, this)) {
            return false;
          }
          break;
      }
    }

    return true;
  }
  public boolean match(MatchNode matchNode, MatchEngine engine) {

    if (!super.match(matchNode, engine)) {
      return false;
    }

    Integer type = (Integer) matchNode.getRuleValue(MatchProperties.EXPRENT_EXITTYPE);
    if (type != null) {
      if (this.exitType != type.intValue()) {
        return false;
      }
    }

    return true;
  }