Make sure conflicts returned by compile are unique

This commit is contained in:
Max Brunsfeld 2014-04-10 08:38:14 -07:00
parent 53285f7d0c
commit e1e0cc6278
7 changed files with 23 additions and 11 deletions

View file

@ -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);

View file

@ -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>({
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>({
Conflict("rule1: reduce rule2 / reduce rule1"),
Conflict("rule1: reduce rule1 / reduce rule2")
})));
});
it("favors the symbol listed earlier in the grammar", [&]() {

View file

@ -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();

View file

@ -171,7 +171,7 @@ namespace tree_sitter {
add_error_lex_state();
}
const vector<Conflict> & conflicts() {
const vector<Conflict> conflicts() {
return conflict_manager.conflicts();
};

View file

@ -2,6 +2,7 @@
#include <vector>
#include <map>
#include <string>
#include <set>
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<Conflict> & ConflictManager::conflicts() const {
return conflicts_;
const vector<Conflict> ConflictManager::conflicts() const {
vector<Conflict> result;
result.insert(result.end(), conflicts_.begin(), conflicts_.end());
return result;
}
}
}

View file

@ -4,6 +4,7 @@
#include <vector>
#include <map>
#include <string>
#include <set>
#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<rules::Symbol, std::string> rule_names;
std::vector<Conflict> conflicts_;
std::set<Conflict> 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<Conflict> & conflicts() const;
const std::vector<Conflict> conflicts() const;
};
}
}

View file

@ -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 << "#<conflict " + conflict.description + ">";
}