From 6fb60a72012f97f846477eb370d1a0706b1b4bc2 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 6 Apr 2015 00:22:44 +0200 Subject: generator: detect LR(0) conflicts --- src/generator.cpp | 8 ++++---- src/generator.hpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/generator.cpp b/src/generator.cpp index 6198aba..d63b859 100644 --- a/src/generator.cpp +++ b/src/generator.cpp @@ -97,9 +97,9 @@ void generator_t::generate_itemsets() { auto added = add_set(entry.second); if (entry.first.get_type() == SYMBOL_TYPE_NONTERM) - gotos.emplace(std::make_pair(cur.second, entry.first.get_value()), added.first->second); + add_goto(cur.second, entry.first.get_value(), added.first->second); else - shifts.emplace(std::make_pair(cur.second, entry.first), added.first->second); + add_shift(cur.second, entry.first, added.first->second); if (added.second) queue.push(*added.first); @@ -109,9 +109,9 @@ void generator_t::generate_itemsets() { auto it = rule_ids.find(item); if (it != rule_ids.end()) { if (it->second) - reductions.emplace(cur.second, it->second); + add_reduction(cur.second, it->second); else - shifts.emplace(std::make_pair(cur.second, symbol_t::make_nonterm("")), 0); + add_shift(cur.second, symbol_t::make_nonterm(""), 0); } } } diff --git a/src/generator.hpp b/src/generator.hpp index 8178bbd..47ef6bf 100644 --- a/src/generator.hpp +++ b/src/generator.hpp @@ -28,6 +28,7 @@ #include "item.hpp" +#include #include #include @@ -35,6 +36,13 @@ namespace solar { class generator_t { +public: + class conflict_error : public std::runtime_error { + public: + explicit conflict_error(const std::string& what_arg) : std::runtime_error(what_arg) {} + explicit conflict_error(const char* what_arg) : std::runtime_error(what_arg) {} + }; + private: std::vector> rules; std::map rule_ids; @@ -49,6 +57,8 @@ private: std::map reductions; std::map, size_t> gotos; + std::set shift_conflicts; + void close_set(std::set *set); std::set get_set(const std::string &nonterm); @@ -56,6 +66,27 @@ private: return itemsets.emplace(set, itemsets.size()); } + void add_reduction(size_t from, size_t to) { + if (reductions.count(from)) + throw conflict_error("reduce/reduce conflict"); + if (shift_conflicts.count(from)) + throw conflict_error("shift/reduce conflict"); + + reductions.emplace(from, to); + } + + void add_shift(size_t from, const symbol_t &sym, size_t to) { + if (reductions.count(from)) + throw conflict_error("shift/reduce conflict"); + + shift_conflicts.insert(from); + shifts.emplace(std::make_pair(from, sym), to); + } + + void add_goto(size_t from, const std::string &nonterm, size_t to) { + gotos.emplace(std::make_pair(from, nonterm), to); + } + void generate_itemsets(); public: -- cgit v1.2.3