From cf237b04eb5e465090aa6fdf7f4c9efa80d70461 Mon Sep 17 00:00:00 2001 From: Robin Jadoul Date: Wed, 11 Jan 2017 17:49:40 +0100 Subject: [PATCH 1/2] Infinite loop, to debug --- include/Parsodus/backendmanager.h | 2 + include/Parsodus/lrtables/LALR1Itemset.h | 24 +++++++++++ include/Parsodus/lrtables/LR1ItemsetBase.h | 20 +++------ parser.example.pds | 12 ++---- src/CMakeLists.txt | 1 + src/lrtables/LALR1Itemset.cpp | 49 ++++++++++++++++++++++ 6 files changed, 86 insertions(+), 22 deletions(-) create mode 100644 include/Parsodus/lrtables/LALR1Itemset.h create mode 100644 src/lrtables/LALR1Itemset.cpp diff --git a/include/Parsodus/backendmanager.h b/include/Parsodus/backendmanager.h index 1bad134..51ac58c 100644 --- a/include/Parsodus/backendmanager.h +++ b/include/Parsodus/backendmanager.h @@ -11,6 +11,7 @@ #include "Parsodus/lrtables/LR0Itemset.h" #include "Parsodus/lrtables/SLR1Itemset.h" #include "Parsodus/lrtables/LR1Itemset.h" +#include "Parsodus/lrtables/LALR1Itemset.h" #include "Parsodus/util/parserType.h" namespace pds { @@ -32,6 +33,7 @@ namespace pds { registerBackend(std::make_unique>>(util::ParserType::LR_0)); registerBackend(std::make_unique>>(util::ParserType::SLR_1)); registerBackend(std::make_unique>>(util::ParserType::LR_1)); + registerBackend(std::make_unique>>(util::ParserType::LALR_1)); } /** diff --git a/include/Parsodus/lrtables/LALR1Itemset.h b/include/Parsodus/lrtables/LALR1Itemset.h new file mode 100644 index 0000000..682e11b --- /dev/null +++ b/include/Parsodus/lrtables/LALR1Itemset.h @@ -0,0 +1,24 @@ +#pragma once +#ifndef PARSODUS_LRTABLES_LALR1ITEMSET_H_TJ1FUOEG +#define PARSODUS_LRTABLES_LALR1ITEMSET_H_TJ1FUOEG + +#include "Parsodus/lrtables/LR1ItemsetBase.h" + +namespace pds { +namespace lr { + +class LALR1Itemset : public LR1ItemsetBase { +public: + LALR1Itemset(); + LALR1Itemset(std::shared_ptr start); + + bool canMerge(const LALR1Itemset& rhs) const; + void merge(const LALR1Itemset& rhs); + +private: +}; + +} /* lr */ +} /* pds */ + +#endif /* PARSODUS_LRTABLES_LALR1ITEMSET_H_TJ1FUOEG */ diff --git a/include/Parsodus/lrtables/LR1ItemsetBase.h b/include/Parsodus/lrtables/LR1ItemsetBase.h index 738770d..108bfa5 100644 --- a/include/Parsodus/lrtables/LR1ItemsetBase.h +++ b/include/Parsodus/lrtables/LR1ItemsetBase.h @@ -24,8 +24,8 @@ public: bool empty() const; std::set getReduces(const Grammar& g, std::string lookahead) const; -private: - std::set m_items; +protected: + std::vector m_items; }; template @@ -34,7 +34,7 @@ LR1ItemsetBase::LR1ItemsetBase() template LR1ItemsetBase::LR1ItemsetBase(std::shared_ptr start) { - m_items.emplace(LR1Item{start, 0, {util::EOF_PLACEHOLDER}}); + m_items.emplace_back(LR1Item{start, 0, {util::EOF_PLACEHOLDER}}); } template @@ -78,13 +78,9 @@ void LR1ItemsetBase::close(const Grammar& g) { } } - std::vector newItems; - for (auto& it : m_items) { - newItems.emplace_back(std::move(it)); - } for (const auto& newItem : toAdd) { bool found = false; - for (auto& oldItem : newItems) { + for (auto& oldItem : m_items) { if (newItem.dotIdx == oldItem.dotIdx && newItem.rule == oldItem.rule) { found = true; oldItem.lookaheads.insert(newItem.lookaheads.begin(), newItem.lookaheads.end()); @@ -92,13 +88,9 @@ void LR1ItemsetBase::close(const Grammar& g) { } } if (!found) { - newItems.push_back(newItem); + m_items.push_back(newItem); } } - m_items.clear(); - for (auto& it : newItems) { - m_items.emplace(std::move(it)); - } } } @@ -108,7 +100,7 @@ Itemset LR1ItemsetBase::succ(std::string sym) const { for (auto& item : m_items) { if (item.dotIdx < item.rule->tail.size()) { if (item.rule->tail[item.dotIdx] == sym) { - sc.m_items.insert(LR1Item{item.rule, item.dotIdx + 1, item.lookaheads}); + sc.m_items.push_back(LR1Item{item.rule, item.dotIdx + 1, item.lookaheads}); } } } diff --git a/parser.example.pds b/parser.example.pds index 79a6999..42367e1 100644 --- a/parser.example.pds +++ b/parser.example.pds @@ -1,12 +1,8 @@ -parser: SLR(1) +parser: lalr(1) lexesis: lexer.lxs terminals: - TERMINAL + A B start: s grammar: - s -> a s - | b - ; - - a → TERMINAL; - b -> a; + s -> x x; + x -> A x | B; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ef09aca..1ca0b7d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,6 +25,7 @@ add_library(Parsodus-tables lrtables/SLR1Itemset.cpp lrtables/LR1Item.cpp lrtables/LR1Itemset.cpp + lrtables/LALR1Itemset.cpp ) # add_library(Parsodus-backends diff --git a/src/lrtables/LALR1Itemset.cpp b/src/lrtables/LALR1Itemset.cpp new file mode 100644 index 0000000..73611e3 --- /dev/null +++ b/src/lrtables/LALR1Itemset.cpp @@ -0,0 +1,49 @@ +#include "Parsodus/lrtables/LALR1Itemset.h" + +#include + +namespace pds { +namespace lr { + +LALR1Itemset::LALR1Itemset() : LR1ItemsetBase() +{} + +LALR1Itemset::LALR1Itemset(std::shared_ptr start) : LR1ItemsetBase(start) +{} + +bool LALR1Itemset::canMerge(const LALR1Itemset& rhs) const { + if (rhs.m_items.size() != m_items.size()) { + return false; + } + + for (auto& rhsIt : rhs.m_items) { + bool ok = false; + for (auto& it : m_items) { + if (it.rule == rhsIt.rule && it.dotIdx == rhsIt.dotIdx) { + ok = true; + break; + } + } + if (!ok) + return false; + } + + return true; +} + +void LALR1Itemset::merge(const LALR1Itemset& rhs) { + for (auto& toMerge : rhs.m_items) { + bool found = false; + for (auto& it : m_items) { + if (it.rule == toMerge.rule && it.dotIdx == toMerge.dotIdx) { + found = true; + it.lookaheads.insert(toMerge.lookaheads.begin(), toMerge.lookaheads.end()); + break; + } + } + assert(found); + } +} + +} /* lr */ +} /* pds */ From 029dbf6bcb2c3311850882d64f16f1171490f14a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Av=C3=A9?= Date: Wed, 11 Jan 2017 18:43:05 +0100 Subject: [PATCH 2/2] Fix LALR infinite loop --- include/Parsodus/lrtables/LALR1Itemset.h | 2 +- include/Parsodus/lrtables/LR0ItemsetBase.h | 5 +++-- include/Parsodus/lrtables/LR1Itemset.h | 2 +- include/Parsodus/lrtables/generator.h | 7 ++++--- parser.example.pds | 12 ++++++++---- src/lrtables/LALR1Itemset.cpp | 11 +++++++++-- src/lrtables/LR1Itemset.cpp | 3 ++- 7 files changed, 28 insertions(+), 14 deletions(-) diff --git a/include/Parsodus/lrtables/LALR1Itemset.h b/include/Parsodus/lrtables/LALR1Itemset.h index 682e11b..83d8141 100644 --- a/include/Parsodus/lrtables/LALR1Itemset.h +++ b/include/Parsodus/lrtables/LALR1Itemset.h @@ -13,7 +13,7 @@ public: LALR1Itemset(std::shared_ptr start); bool canMerge(const LALR1Itemset& rhs) const; - void merge(const LALR1Itemset& rhs); + bool merge(const LALR1Itemset& rhs); private: }; diff --git a/include/Parsodus/lrtables/LR0ItemsetBase.h b/include/Parsodus/lrtables/LR0ItemsetBase.h index 7b0f0b3..5888fa6 100644 --- a/include/Parsodus/lrtables/LR0ItemsetBase.h +++ b/include/Parsodus/lrtables/LR0ItemsetBase.h @@ -21,7 +21,7 @@ public: Itemset succ(std::string sym) const; bool operator==(const Itemset& rhs) const; bool canMerge(const Itemset& rhs) const; - void merge(const Itemset& rhs); + bool merge(const Itemset& rhs); bool empty() const; protected: @@ -89,8 +89,9 @@ bool LR0ItemsetBase::canMerge(const Itemset&) const { } template -void LR0ItemsetBase::merge(const Itemset&) { +bool LR0ItemsetBase::merge(const Itemset&) { //NO-OP + return false; } template diff --git a/include/Parsodus/lrtables/LR1Itemset.h b/include/Parsodus/lrtables/LR1Itemset.h index 70d78f9..1727b80 100644 --- a/include/Parsodus/lrtables/LR1Itemset.h +++ b/include/Parsodus/lrtables/LR1Itemset.h @@ -13,7 +13,7 @@ public: LR1Itemset(std::shared_ptr start); bool canMerge(const LR1Itemset& rhs) const; - void merge(const LR1Itemset& rhs); + bool merge(const LR1Itemset& rhs); private: }; diff --git a/include/Parsodus/lrtables/generator.h b/include/Parsodus/lrtables/generator.h index 52aecc7..e95d35f 100644 --- a/include/Parsodus/lrtables/generator.h +++ b/include/Parsodus/lrtables/generator.h @@ -24,7 +24,7 @@ namespace lr { * - Itemset succ(std::string) const; compute the successor of this set, over the given symbol * - bool operator==(const Itemset&); are these two Itemsets equal * - bool canMerge(const Itemset&) const; Can the given Itemset be merged into this one - * - void merge(const Itemset&); Merge the given Itemset into this one + * - bool merge(const Itemset&); Merge the given Itemset into this one, return whether there was a change * - bool empty() const; is this Itemset empty (== not useful) * - std::set getReduces(const Grammar&, std::string) const; get all Rule indices where a reduce should happen with given lookahead (not necessarily a set, but iterable) * - static bool needsFollow() const; does this type of Itemset need Follow sets to work, if so the first and follow unique_ptr's of the grammar passed will be initialized @@ -99,8 +99,9 @@ LRTable Generator::generate() { if (itemsets[idx] == s) { break; } else if (itemsets[idx].canMerge(s)) { - itemsets[idx].merge(s); - q.emplace(idx, std::move(s)); + if (itemsets[idx].merge(s)) { + q.emplace(idx, std::move(s)); + } break; } } diff --git a/parser.example.pds b/parser.example.pds index 42367e1..79a6999 100644 --- a/parser.example.pds +++ b/parser.example.pds @@ -1,8 +1,12 @@ -parser: lalr(1) +parser: SLR(1) lexesis: lexer.lxs terminals: - A B + TERMINAL start: s grammar: - s -> x x; - x -> A x | B; + s -> a s + | b + ; + + a → TERMINAL; + b -> a; diff --git a/src/lrtables/LALR1Itemset.cpp b/src/lrtables/LALR1Itemset.cpp index 73611e3..e9543c4 100644 --- a/src/lrtables/LALR1Itemset.cpp +++ b/src/lrtables/LALR1Itemset.cpp @@ -31,18 +31,25 @@ bool LALR1Itemset::canMerge(const LALR1Itemset& rhs) const { return true; } -void LALR1Itemset::merge(const LALR1Itemset& rhs) { +bool LALR1Itemset::merge(const LALR1Itemset& rhs) { + bool change = false; for (auto& toMerge : rhs.m_items) { bool found = false; for (auto& it : m_items) { if (it.rule == toMerge.rule && it.dotIdx == toMerge.dotIdx) { found = true; - it.lookaheads.insert(toMerge.lookaheads.begin(), toMerge.lookaheads.end()); + for (auto& la : toMerge.lookaheads) { + if (!it.lookaheads.count(la)) { + change = true; + it.lookaheads.insert(la); + } + } break; } } assert(found); } + return change; } } /* lr */ diff --git a/src/lrtables/LR1Itemset.cpp b/src/lrtables/LR1Itemset.cpp index 425f0d8..a0534e3 100644 --- a/src/lrtables/LR1Itemset.cpp +++ b/src/lrtables/LR1Itemset.cpp @@ -13,8 +13,9 @@ bool LR1Itemset::canMerge(const LR1Itemset&) const { return false; } -void LR1Itemset::merge(const LR1Itemset&) { +bool LR1Itemset::merge(const LR1Itemset&) { //NO-OP + return false; } } /* lr */