#include "compiler/rules/choice.h" #include #include #include "compiler/rules/visitor.h" namespace tree_sitter { namespace rules { using std::string; using std::make_shared; using std::vector; using std::set; using std::dynamic_pointer_cast; Choice::Choice(const vector &elements) : elements(elements) {} void add_choice_element(vector *vec, const rule_ptr new_rule) { auto choice = dynamic_pointer_cast(new_rule); if (choice.get()) { for (auto &child : choice->elements) add_choice_element(vec, child); } else { for (auto &el : *vec) if (el->operator==(*new_rule)) return; vec->push_back(new_rule); } } rule_ptr Choice::build(const vector &inputs) { vector elements; for (auto &el : inputs) add_choice_element(&elements, el); if (elements.size() == 1) return elements.front(); else return make_shared(elements); } bool Choice::operator==(const Rule &rule) const { const Choice *other = dynamic_cast(&rule); if (!other) return false; size_t size = elements.size(); if (size != other->elements.size()) return false; for (size_t i = 0; i < size; i++) if (!elements[i]->operator==(*other->elements[i])) return false; return true; } size_t Choice::hash_code() const { size_t result = std::hash()(elements.size()); for (const auto &element : elements) result ^= element->hash_code(); return result; } rule_ptr Choice::copy() const { return std::make_shared(*this); } string Choice::to_string() const { string result = "(choice"; for (const auto &element : elements) result += " " + element->to_string(); return result + ")"; } void Choice::accept(Visitor *visitor) const { visitor->visit(this); } } // namespace rules } // namespace tree_sitter