int parse(GrammarParser grammar, StringBuilder text, int offset) {
        while (offset < text.length()) {
            if (endParsing || text.length() > TEXT_LENGTH_LIMIT) {
                endParsing = true;
                text.delete(0, builder.length());
                text.append("The output gets too long!");
                return -1;
            }

            if (isSymbol(text, offset)) {
                String replacement = getReplacement(grammar, text.charAt(offset));
                text.replace(offset, offset + 1, replacement);
                offset += replacement.length();
                continue;
            }

            if (isLoopStart(text, offset)) {
                int loopNumber = getLoopNumber(text, offset);
                int loopStartBlockLength = getLoopStartBlockLength(text, offset);
                text.replace(offset, offset + loopStartBlockLength, "");
                int loopStartIndex = offset;

                for (int i = 0; i < loopNumber; i++) {
                    offset = parse(grammar, text, loopStartIndex);
                }

                if (endParsing) {
                    return -1;
                }

                text.replace(offset, offset + 1, "");

                continue;
            }

            if (isLoopEnd(text, offset)) {
                return offset;
            }

            errors.add(new ParserError(0, "Could not understand the symbol: " + text.charAt(offset)));
            offset++;
        }

        return offset;
    }