@NotNull
  @Override
  public Result process(@NotNull String text) throws CalculatorParseException {
    final String result;

    int maxNumberOfOpenGroupSymbols = 0;
    int numberOfOpenGroupSymbols = 0;

    final StringBuilder text1 = new StringBuilder();

    int resultOffset = 0;

    final AbstractNumberBuilder numberBuilder;
    if (!formatNumber) {
      numberBuilder = new LiteNumberBuilder(CalculatorEngine.instance.getEngine());
    } else {
      numberBuilder = new NumberBuilder(CalculatorEngine.instance.getEngine());
    }
    for (int i = 0; i < text.length(); i++) {
      MathType.Result mathType = MathType.getType(text, i, numberBuilder.isHexMode());

      if (numberBuilder instanceof NumberBuilder) {
        final MutableObject<Integer> numberOffset = new MutableObject<Integer>(0);
        ((NumberBuilder) numberBuilder).process(text1, mathType, numberOffset);
        resultOffset += numberOffset.getObject();
      } else {
        ((LiteNumberBuilder) numberBuilder).process(mathType);
      }

      final String match = mathType.getMatch();
      switch (mathType.getMathType()) {
        case open_group_symbol:
          numberOfOpenGroupSymbols++;
          maxNumberOfOpenGroupSymbols =
              Math.max(maxNumberOfOpenGroupSymbols, numberOfOpenGroupSymbols);
          text1.append(text.charAt(i));
          break;
        case close_group_symbol:
          numberOfOpenGroupSymbols--;
          text1.append(text.charAt(i));
          break;
        case operator:
          text1.append(match);
          if (match.length() > 1) {
            i += match.length() - 1;
          }
          break;
        case function:
          i = processHighlightedText(text1, i, match, "i", null);
          break;
        case constant:
          i = processHighlightedText(text1, i, match, "b", null);
          break;
        case numeral_base:
          i = processHighlightedText(text1, i, match, "b", null);
          break;
        default:
          if (mathType.getMathType() == MathType.text || match.length() <= 1) {
            text1.append(text.charAt(i));
          } else {
            text1.append(match);
            i += match.length() - 1;
          }
      }
    }

    if (numberBuilder instanceof NumberBuilder) {
      final MutableObject<Integer> numberOffset = new MutableObject<Integer>(0);
      ((NumberBuilder) numberBuilder).processNumber(text1, numberOffset);
      resultOffset += numberOffset.getObject();
    }

    if (maxNumberOfOpenGroupSymbols > 0) {

      final StringBuilder text2 = new StringBuilder();

      String s = text1.toString();
      int i = processBracketGroup(text2, s, 0, 0, maxNumberOfOpenGroupSymbols);
      for (; i < s.length(); i++) {
        text2.append(s.charAt(i));
      }

      // Log.d(CalculatorEditor.class.getName(), text2.toString());

      result = text2.toString();
    } else {
      result = text1.toString();
    }

    return new Result(result, resultOffset);
  }