private DecodedInformation parseBlocks() throws FormatException {
    boolean isFinished;
    BlockParsedResult result;
    do {
      int initialPosition = current.getPosition();

      if (current.isAlpha()) {
        result = parseAlphaBlock();
        isFinished = result.isFinished();
      } else if (current.isIsoIec646()) {
        result = parseIsoIec646Block();
        isFinished = result.isFinished();
      } else { // it must be numeric
        result = parseNumericBlock();
        isFinished = result.isFinished();
      }

      boolean positionChanged = initialPosition != current.getPosition();
      if (!positionChanged && !isFinished) {
        break;
      }
    } while (!isFinished);

    return result.getDecodedInformation();
  }
  private BlockParsedResult parseNumericBlock() throws FormatException {
    while (isStillNumeric(current.getPosition())) {
      DecodedNumeric numeric = decodeNumeric(current.getPosition());
      current.setPosition(numeric.getNewPosition());

      if (numeric.isFirstDigitFNC1()) {
        DecodedInformation information;
        if (numeric.isSecondDigitFNC1()) {
          information = new DecodedInformation(current.getPosition(), buffer.toString());
        } else {
          information =
              new DecodedInformation(
                  current.getPosition(), buffer.toString(), numeric.getSecondDigit());
        }
        return new BlockParsedResult(information, true);
      }
      buffer.append(numeric.getFirstDigit());

      if (numeric.isSecondDigitFNC1()) {
        DecodedInformation information =
            new DecodedInformation(current.getPosition(), buffer.toString());
        return new BlockParsedResult(information, true);
      }
      buffer.append(numeric.getSecondDigit());
    }

    if (isNumericToAlphaNumericLatch(current.getPosition())) {
      current.setAlpha();
      current.incrementPosition(4);
    }
    return new BlockParsedResult(false);
  }
  private BlockParsedResult parseAlphaBlock() {
    while (isStillAlpha(current.getPosition())) {
      DecodedChar alpha = decodeAlphanumeric(current.getPosition());
      current.setPosition(alpha.getNewPosition());

      if (alpha.isFNC1()) {
        DecodedInformation information =
            new DecodedInformation(current.getPosition(), buffer.toString());
        return new BlockParsedResult(information, true); // end of the char block
      }

      buffer.append(alpha.getValue());
    }

    if (isAlphaOr646ToNumericLatch(current.getPosition())) {
      current.incrementPosition(3);
      current.setNumeric();
    } else if (isAlphaTo646ToAlphaLatch(current.getPosition())) {
      if (current.getPosition() + 5 < this.information.getSize()) {
        current.incrementPosition(5);
      } else {
        current.setPosition(this.information.getSize());
      }

      current.setIsoIec646();
    }
    return new BlockParsedResult(false);
  }
  private BlockParsedResult parseIsoIec646Block() throws FormatException {
    while (isStillIsoIec646(current.getPosition())) {
      DecodedChar iso = decodeIsoIec646(current.getPosition());
      current.setPosition(iso.getNewPosition());

      if (iso.isFNC1()) {
        DecodedInformation information =
            new DecodedInformation(current.getPosition(), buffer.toString());
        return new BlockParsedResult(information, true);
      }
      buffer.append(iso.getValue());
    }

    if (isAlphaOr646ToNumericLatch(current.getPosition())) {
      current.incrementPosition(3);
      current.setNumeric();
    } else if (isAlphaTo646ToAlphaLatch(current.getPosition())) {
      if (current.getPosition() + 5 < this.information.getSize()) {
        current.incrementPosition(5);
      } else {
        current.setPosition(this.information.getSize());
      }

      current.setAlpha();
    }
    return new BlockParsedResult(false);
  }