diff --git a/include/tree_sitter/compiler.h b/include/tree_sitter/compiler.h index cade7a0e..941e2c6d 100644 --- a/include/tree_sitter/compiler.h +++ b/include/tree_sitter/compiler.h @@ -35,6 +35,7 @@ namespace tree_sitter { Conflict(std::string description); std::string description; bool operator==(const Conflict &other) const; + bool operator<(const Conflict &other) const; }; std::ostream& operator<<(std::ostream &stream, const Grammar &grammar); diff --git a/spec/compiler/build_tables/conflict_manager_spec.cc b/spec/compiler/build_tables/conflict_manager_spec.cc index c3afdf91..62cd9f44 100644 --- a/spec/compiler/build_tables/conflict_manager_spec.cc +++ b/spec/compiler/build_tables/conflict_manager_spec.cc @@ -71,8 +71,9 @@ describe("resolving parse conflicts", []() { manager->resolve_parse_action(sym1, ParseAction::Reduce(sym2, 1), ParseAction::Shift(2)); manager->resolve_parse_action(sym1, ParseAction::Shift(2), ParseAction::Reduce(sym2, 1)); - AssertThat(manager->conflicts()[0], Equals(Conflict("rule1: shift / reduce rule2"))); - AssertThat(manager->conflicts()[1], Equals(Conflict("rule1: shift / reduce rule2"))); + AssertThat(manager->conflicts(), Equals(vector({ + Conflict("rule1: shift / reduce rule2") + }))); }); it("favors the shift", [&]() { @@ -89,8 +90,10 @@ describe("resolving parse conflicts", []() { manager->resolve_parse_action(sym1, ParseAction::Reduce(sym2, 1), ParseAction::Reduce(sym1, 1)); manager->resolve_parse_action(sym1, ParseAction::Reduce(sym1, 1), ParseAction::Reduce(sym2, 1)); - AssertThat(manager->conflicts()[0], Equals(Conflict("rule1: reduce rule2 / reduce rule1"))); - AssertThat(manager->conflicts()[1], Equals(Conflict("rule1: reduce rule1 / reduce rule2"))); + AssertThat(manager->conflicts(), Equals(vector({ + Conflict("rule1: reduce rule2 / reduce rule1"), + Conflict("rule1: reduce rule1 / reduce rule2") + }))); }); it("favors the symbol listed earlier in the grammar", [&]() { diff --git a/spec/compiler/compile_examples.cc b/spec/compiler/compile_examples.cc index ce169314..38c0d782 100644 --- a/spec/compiler/compile_examples.cc +++ b/spec/compiler/compile_examples.cc @@ -24,7 +24,7 @@ describe("compiling the example grammars", []() { ofstream file(example_parser_dir + language + ".c"); auto result = compile(grammar, language); -// cout << "\n conflicts for " << language << "\n:" << result.second; +// cout << "\n\nconflicts for " << language << ":\n" << result.second; file << result.first; file.close(); diff --git a/src/compiler/build_tables/build_tables.cc b/src/compiler/build_tables/build_tables.cc index 11ed9a17..a7c6e262 100644 --- a/src/compiler/build_tables/build_tables.cc +++ b/src/compiler/build_tables/build_tables.cc @@ -171,7 +171,7 @@ namespace tree_sitter { add_error_lex_state(); } - const vector & conflicts() { + const vector conflicts() { return conflict_manager.conflicts(); }; diff --git a/src/compiler/build_tables/conflict_manager.cc b/src/compiler/build_tables/conflict_manager.cc index 753f0689..a1bba240 100644 --- a/src/compiler/build_tables/conflict_manager.cc +++ b/src/compiler/build_tables/conflict_manager.cc @@ -2,6 +2,7 @@ #include #include #include +#include namespace tree_sitter { namespace build_tables { @@ -29,7 +30,7 @@ namespace tree_sitter { } void ConflictManager::record_conflict(const rules::Symbol &symbol, const ParseAction &left, const ParseAction &right) { - conflicts_.push_back(Conflict(rule_names.find(symbol)->second + ": " + message_for_action(left, rule_names) + " / " + message_for_action(right, rule_names))); + conflicts_.insert(Conflict(rule_names.find(symbol)->second + ": " + message_for_action(left, rule_names) + " / " + message_for_action(right, rule_names))); } ConflictManager::ConflictManager(const PreparedGrammar &parse_grammar, @@ -92,8 +93,10 @@ namespace tree_sitter { return false; } - const vector & ConflictManager::conflicts() const { - return conflicts_; + const vector ConflictManager::conflicts() const { + vector result; + result.insert(result.end(), conflicts_.begin(), conflicts_.end()); + return result; } } } \ No newline at end of file diff --git a/src/compiler/build_tables/conflict_manager.h b/src/compiler/build_tables/conflict_manager.h index 4947fbc2..479245f0 100644 --- a/src/compiler/build_tables/conflict_manager.h +++ b/src/compiler/build_tables/conflict_manager.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "tree_sitter/compiler.h" #include "compiler/parse_table.h" #include "compiler/prepared_grammar.h" @@ -14,7 +15,7 @@ namespace tree_sitter { const PreparedGrammar parse_grammar; const PreparedGrammar lex_grammar; const std::map rule_names; - std::vector conflicts_; + std::set conflicts_; public: ConflictManager(const PreparedGrammar &parse_grammar, @@ -28,7 +29,7 @@ namespace tree_sitter { const ParseAction &new_action); void record_conflict(const rules::Symbol &symbol, const ParseAction &left, const ParseAction &right); - const std::vector & conflicts() const; + const std::vector conflicts() const; }; } } diff --git a/src/compiler/conflict.cc b/src/compiler/conflict.cc index 5b6f6886..2e7a6bbe 100644 --- a/src/compiler/conflict.cc +++ b/src/compiler/conflict.cc @@ -10,6 +10,10 @@ namespace tree_sitter { return other.description == description; } + bool Conflict::operator<(const tree_sitter::Conflict &other) const { + return other.description < description; + } + std::ostream& operator<<(std::ostream &stream, const Conflict &conflict) { return stream << "#"; }