<commit_before>#include <cmath>
#include <map>
#include <set>
#include <stdexcept>
#include <string>
#include <utility>

#include "error.hpp"
#include "expression.hpp"
#include "symdiff.hpp"
#include "visitor.hpp"

class FindIdentifierVisitor: public Visitor {
public:
    explicit FindIdentifierVisitor(const identifier_set& ids): ids_(ids) {}

    void reset() { found_ = false; }
    bool found() const { return found_; }

    void visit(Expression* e) override {}

    void visit(UnaryExpression* e) override {
        if (!found()) e->expression()->accept(this);
    }

    void visit(BinaryExpression* e) override {
        if (!found()) e->lhs()->accept(this);
        if (!found()) e->rhs()->accept(this);
    }

    void visit(CallExpression* e) override {
        for (auto& e: e->args()) {
            if (found()) return;
            e->accept(this);
        }
    }

    void visit(PDiffExpression* e) override {
        if (!found()) e->arg()->accept(this);
    }

    void visit(IdentifierExpression* e) override {
        if (!found()) {
            found_ |= is_in(e->spelling(), ids_);
        }
    }

    void visit(DerivativeExpression* e) override {
        if (!found()) {
            found_ |= is_in(e->spelling(), ids_);
        }
    }
    void visit(ReactionExpression* e) override {
        if (!found()) e->lhs()->accept(this);
        if (!found()) e->rhs()->accept(this);
        if (!found()) e->fwd_rate()->accept(this);
        if (!found()) e->rev_rate()->accept(this);
    }

    void visit(StoichTermExpression* e) override {
        if (!found()) e->ident()->accept(this);
    }

    void visit(StoichExpression* e) override {
        for (auto& e: e->terms()) {
            if (found()) return;
            e->accept(this);
        }
    }

    void visit(BlockExpression* e) override {
        for (auto& e: e->statements()) {
            if (found()) return;
            e->accept(this);
        }
    }

    void visit(IfExpression* e) override {
        if (!found()) e->condition()->accept(this);
        if (!found()) e->true_branch()->accept(this);
        if (!found()) e->false_branch()->accept(this);
    }

private:
    const identifier_set& ids_;
    bool found_ = false;
};

bool involves_identifier(Expression* e, const identifier_set& ids) {
    FindIdentifierVisitor v(ids);<commit_msg>Fix issue #164<commit_after>#include <cmath>
#include <map>
#include <set>
#include <stdexcept>
#include <string>
#include <utility>

#include "error.hpp"
#include "expression.hpp"
#include "symdiff.hpp"
#include "visitor.hpp"

class FindIdentifierVisitor: public Visitor {
public:
    explicit FindIdentifierVisitor(const identifier_set& ids): ids_(ids) {}

    void reset() { found_ = false; }
    bool found() const { return found_; }

    void visit(Expression* e) override {}

    void visit(UnaryExpression* e) override {
        if (!found()) e->expression()->accept(this);
    }

    void visit(BinaryExpression* e) override {
        if (!found()) e->lhs()->accept(this);
        if (!found()) e->rhs()->accept(this);
    }

    void visit(CallExpression* e) override {
        for (auto& expr: e->args()) {
            if (found()) return;
            expr->accept(this);
        }
    }

    void visit(PDiffExpression* e) override {
        if (!found()) e->arg()->accept(this);
    }

    void visit(IdentifierExpression* e) override {
        if (!found()) {
            found_ |= is_in(e->spelling(), ids_);
        }
    }

    void visit(DerivativeExpression* e) override {
        if (!found()) {
            found_ |= is_in(e->spelling(), ids_);
        }
    }
    void visit(ReactionExpression* e) override {
        if (!found()) e->lhs()->accept(this);
        if (!found()) e->rhs()->accept(this);
        if (!found()) e->fwd_rate()->accept(this);
        if (!found()) e->rev_rate()->accept(this);
    }

    void visit(StoichTermExpression* e) override {
        if (!found()) e->ident()->accept(this);
    }

    void visit(StoichExpression* e) override {
        for (auto& expr: e->terms()) {
            if (found()) return;
            expr->accept(this);
        }
    }

    void visit(BlockExpression* e) override {
        for (auto& expr: e->statements()) {
            if (found()) return;
            expr->accept(this);
        }
    }

    void visit(IfExpression* e) override {
        if (!found()) e->condition()->accept(this);
        if (!found()) e->true_branch()->accept(this);
        if (!found()) e->false_branch()->accept(this);
    }

private:
    const identifier_set& ids_;
    bool found_ = false;
};

bool involves_identifier(Expression* e, const identifier_set& ids) {
    FindIdentifierVisitor v(ids);
{'fraction_non_alphanumeric': 0.1691129546904914, 'fraction_numerical': 0.0006381620931716656, 'mean_word_length': 2.5756653992395435, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1500416', 'n_tokens_mistral': 1438, 'n_tokens_neox': 1409, 'n_words': 345}