#include "first_set.h" #include "tree_sitter/compiler.h" #include "rule_can_be_blank.h" #include "rules/visitor.h" #include "rules/seq.h" #include "rules/choice.h" namespace tree_sitter { using std::set; using namespace rules; namespace build_tables { class FirstSetVisitor : Visitor { set value; const Grammar grammar; FirstSetVisitor(const Grammar &grammar) : grammar(grammar) {} set set_union(const set &left, const set &right) { set result = left; result.insert(right.begin(), right.end()); return result; } void visit(const Symbol *rule) { if (grammar.has_definition(*rule)) { value = apply(grammar.rule(*rule), grammar); } else { value = set({ *rule }); } } void visit(const Choice *rule) { value = set_union(apply(rule->left, grammar), apply(rule->right, grammar)); } void visit(const Seq *rule) { value = apply(rule->left, grammar); if (rule_can_be_blank(rule->left, grammar)) { value = set_union(value, apply(rule->right, grammar)); } } public: static set apply(const rule_ptr rule, const Grammar &grammar) { FirstSetVisitor visitor(grammar); rule->accept(visitor); return visitor.value; } }; set first_set(const rule_ptr &rule, const Grammar &grammar) { return FirstSetVisitor::apply(rule, grammar); } } }