diff options
author | crupest <crupest@outlook.com> | 2021-09-11 16:52:25 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-09-11 16:52:25 +0800 |
commit | e6eef2bda79dcf2abde080943cb8f9808941e331 (patch) | |
tree | 84d7d0faaaa6f6a9fd1eb9a401e979ca25271c7f /src/parse | |
parent | 4511eab66574b8047376a1f612e84e57d2040a95 (diff) | |
download | cru-e6eef2bda79dcf2abde080943cb8f9808941e331.tar.gz cru-e6eef2bda79dcf2abde080943cb8f9808941e331.tar.bz2 cru-e6eef2bda79dcf2abde080943cb8f9808941e331.zip |
...
Diffstat (limited to 'src/parse')
-rw-r--r-- | src/parse/Grammar.cpp | 33 |
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 |