aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2021-09-11 16:52:25 +0800
committercrupest <crupest@outlook.com>2021-09-11 16:52:25 +0800
commite6eef2bda79dcf2abde080943cb8f9808941e331 (patch)
tree84d7d0faaaa6f6a9fd1eb9a401e979ca25271c7f /src
parent4511eab66574b8047376a1f612e84e57d2040a95 (diff)
downloadcru-e6eef2bda79dcf2abde080943cb8f9808941e331.tar.gz
cru-e6eef2bda79dcf2abde080943cb8f9808941e331.tar.bz2
cru-e6eef2bda79dcf2abde080943cb8f9808941e331.zip
...
Diffstat (limited to 'src')
-rw-r--r--src/parse/Grammar.cpp33
1 files changed, 33 insertions, 0 deletions
diff --git a/src/parse/Grammar.cpp b/src/parse/Grammar.cpp
index a2dd14d4..3cf43237 100644
--- a/src/parse/Grammar.cpp
+++ b/src/parse/Grammar.cpp
@@ -2,6 +2,8 @@
#include "cru/parse/Symbol.hpp"
#include <algorithm>
+#include <iterator>
+#include <unordered_map>
namespace cru::parse {
Grammar::Grammar() {}
@@ -69,4 +71,35 @@ bool Grammar::RemoveProduction(Production* production) {
return true;
}
+Grammar* Grammar::Clone() const {
+ Grammar* g = new Grammar();
+
+ std::unordered_map<Symbol*, Symbol*> symbol_map;
+
+ for (auto old_terminal : terminals_) {
+ auto new_terminal = g->CreateTerminal(old_terminal->GetName());
+ symbol_map.emplace(old_terminal, new_terminal);
+ }
+
+ for (auto old_nonterminal : nonterminals_) {
+ auto new_nonterminal = g->CreateNonterminal(old_nonterminal->GetName());
+ symbol_map.emplace(old_nonterminal, new_nonterminal);
+ }
+
+ for (auto old_production : productions_) {
+ std::vector<Symbol*> new_right;
+ std::transform(old_production->GetRight().cbegin(),
+ old_production->GetRight().cend(),
+ std::back_inserter(new_right),
+ [&symbol_map](Symbol* old) { return symbol_map[old]; });
+
+ g->CreateProduction(
+ old_production->GetName(),
+ static_cast<Nonterminal*>(symbol_map[old_production->GetLeft()]),
+ std::move(new_right));
+ }
+
+ return g;
+}
+
} // namespace cru::parse