boolean (@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; } }