private boolean matchRule(Evaluation evaluation, ProductionRule rule) {
        RuleEvaluation ruleEvaluation=evaluation.freshRuleEvaluation();

        ruleEvaluation.indentTrace();
        if (ruleEvaluation.getTraceLevel() >= 3) {
            ruleEvaluation.trace(3,"Evaluating rule '" + rule +
                                   "' on '" + ruleEvaluation.getEvaluation().getQuery().getModel().getQueryTree().getRoot() +
                                   "' at '" + ruleEvaluation.currentItem() + "':");
        }

        ruleEvaluation.indentTrace();

        boolean matches = rule.matches(ruleEvaluation);

        boolean matchedBefore = false;
        int currentMatchDigest = ruleEvaluation.calculateMatchDigest(rule);
        if (evaluation.hasMatchDigest(currentMatchDigest))
            matchedBefore = true;

        boolean queryGotShorter = false;
        if (evaluation.getPreviousQuerySize() > evaluation.getQuerySize())
            queryGotShorter = true;

        boolean doProduction =! matchedBefore || queryGotShorter;

        ruleEvaluation.unindentTrace();

        if (ruleEvaluation.getTraceLevel() >= 2) {
            if (matches && doProduction)
                ruleEvaluation.trace(2,"Matched rule '" + rule + "' at " + ruleEvaluation.previousItem());
            else if ( ! matches)
                ruleEvaluation.trace(2,"Did not match rule '" + rule + "' at " + ruleEvaluation.currentItem());
            else
                ruleEvaluation.trace(2,"Ignoring repeated match of '" + rule + "'");
        }

        ruleEvaluation.unindentTrace();

        if (!matches || !doProduction) return false;

        // Do production barrier

        evaluation.addMatchDigest(currentMatchDigest);
        String preQuery = null;
        if (evaluation.getTraceLevel()>=1) {
            preQuery = evaluation.getQuery().getModel().getQueryTree().getRoot().toString();
        }
        rule.produce(ruleEvaluation);
        if (evaluation.getTraceLevel() >= 1) {
            evaluation.trace(1,"Transforming '" + preQuery + "' to '" +
                               evaluation.getQuery().getModel().getQueryTree().getRoot().toString()
                               + "' since '" + rule + "' matched");
        }

        return true;
    }
Matches a rule at the current starting point of the evaluation, and carries
out the production if there is a match

@return whether this rule matched
container-search/src/main/java/com/yahoo/prelude/semantics/engine/RuleEngine.java