protected boolean doMatchSequentially(@NotNull NodeIterator patternNodes,
                                        @NotNull NodeIterator matchNodes,
                                        @NotNull MatchContext context) {
    final int previousMatchedOccurs = matchedOccurs;
    final FilteringNodeIterator fNodes = new FilteringNodeIterator(matchNodes, VARS_DELIM_FILTER);

    try {
      final CompiledPattern pattern = context.getPattern();
      final PsiElement currentPatternNode = patternNodes.current();
      final MatchingHandler handler = pattern.getHandler(currentPatternNode);
      matchedOccurs = 0;

      boolean flag = false;
      final List<PsiElement> matchedNodes = new SmartList<>();

      while (fNodes.hasNext() && (matchedOccurs < minOccurs || target && !myRepeatedVar && !(handler instanceof TopLevelMatchingHandler))) {
        final PsiElement current = matchNodes.current();
        if (handler.match(currentPatternNode, current, context)) {
          matchedNodes.add(current);
          ++matchedOccurs;
        }
        else if (handler instanceof TopLevelMatchingHandler && matchedOccurs == 0 ||
                 currentPatternNode instanceof PsiComment ||
                 !(matchNodes.current() instanceof PsiComment)) {
          break;
        }
        fNodes.advance();
        flag = true;
      }

      if (matchedOccurs != minOccurs && (!target || myRepeatedVar || matchedOccurs == 0)) {
        // failed even for min occurs
        removeLastResults(matchedOccurs, context);
        fNodes.rewind(matchedOccurs);
        return false;
      }

      if (greedy) {
        // go greedily to maxOccurs

        while (fNodes.hasNext() && matchedOccurs < maxOccurs) {
          final PsiElement current = matchNodes.current();
          if (handler.match(currentPatternNode, current, context)) {
            matchedNodes.add(current);
            ++matchedOccurs;
          }
          else if (handler instanceof TopLevelMatchingHandler && matchedOccurs == 0 ||
                   currentPatternNode instanceof PsiComment ||
                   !(matchNodes.current() instanceof PsiComment)) {
            break;
          }
          fNodes.advance();
          flag = true;
        }

        if (flag) {
          fNodes.rewind();
          matchNodes.advance();
        }

        patternNodes.advance();

        if (patternNodes.hasNext()) {
          final MatchingHandler nextHandler = pattern.getHandler(patternNodes.current());

          while (matchedOccurs >= minOccurs && patternNodes.hasNext()) {
            if (nextHandler.matchSequentially(patternNodes, matchNodes, context)) {
              totalMatchedOccurs = matchedOccurs;
              // match found
              return true;
            }

            final int size = matchedNodes.size();
            if (size > 0) {
              matchNodes.rewindTo(matchedNodes.remove(size - 1));
            }
            removeLastResults(1, context);
            --matchedOccurs;
          }

          if (matchedOccurs > 0) {
            removeLastResults(matchedOccurs, context);
          }
          patternNodes.rewind();
        }
        else {
          // match found
          if (handler.isMatchSequentiallySucceeded(matchNodes)) {
            return checkSameOccurrencesConstraint(context);
          }
          removeLastResults(matchedOccurs, context);
        }
        return false;
      }
      else {
        patternNodes.advance();

        if (flag) {
          fNodes.rewind();
          matchNodes.advance();
        }

        if (patternNodes.hasNext()) {
          final MatchingHandler nextHandler = pattern.getHandler(patternNodes.current());

          flag = false;

          while (matchNodes.hasNext() && matchedOccurs <= maxOccurs) {
            if (nextHandler.matchSequentially(patternNodes, matchNodes, context)) {
              return checkSameOccurrencesConstraint(context);
            }

            if (flag) {
              matchNodes.rewind();
              fNodes.advance();
            }

            if (handler.match(patternNodes.current(), matchNodes.current(), context)) {
              matchedOccurs++;
            }
            else {
              patternNodes.rewind();
              removeLastResults(matchedOccurs, context);
              return false;
            }
            matchNodes.advance();
            flag = true;
          }

          patternNodes.rewind();
          removeLastResults(matchedOccurs, context);
          return false;
        }
        else {
          return checkSameOccurrencesConstraint(context);
        }
      }
    }
    finally {
      matchedOccurs = previousMatchedOccurs;
    }
  }
protected boolean doMatchSequentially(@NotNull NodeIterator patternNodes,
                                        @NotNull NodeIterator matchNodes,
                                        @NotNull MatchContext context)