private boolean matchRuleAtAllStartPoints(Evaluation evaluation, ProductionRule rule) {
        boolean matchedAtLeastOnce = false;
        int iterationCount = 0;

         // Test if it is a removal rule, if so iterate backwards so that precalculated
         // replacement positions do not become invalid as the query shrink
        boolean removalRule = false;
        if ( (rule instanceof com.yahoo.prelude.semantics.rule.ReplacingProductionRule) &&
             (rule.getProduction().toString().length() == 0) ) { // empty replacement
            removalRule = true;
            evaluation.setToLast();
        }

        int loopLimit = Math.max(15, evaluation.getQuerySize() * 3);

        while (evaluation.currentItem() != null) {
            boolean matched = matchRule(evaluation,rule);
            if (matched) {
                if (removalRule)
                    evaluation.resetToLast();
                else
                    evaluation.reset();
                matchedAtLeastOnce = true;
                if (rule.isLoop()) break;
            }
            else {
                if (removalRule)
                    evaluation.previous();
                else
                    evaluation.next();
            }

            if (matched && iterationCount++ > loopLimit) {
                throw new RuleBaseException("Rule '" + rule + "' has matched '" +
                                            evaluation.getQuery().getModel().getQueryTree().getRoot() +
                                            "' " + loopLimit + " times, aborting");
            }
        }

        return matchedAtLeastOnce;
    }
Match a rule at any starting point in the query
container-search/src/main/java/com/yahoo/prelude/semantics/engine/RuleEngine.java