diff options
-rw-r--r-- | demos/CMakeLists.txt | 2 | ||||
-rw-r--r-- | demos/parse/CMakeLists.txt | 2 | ||||
-rw-r--r-- | demos/parse/EliminateLeftRecursion.cpp | 21 | ||||
-rw-r--r-- | include/cru/parse/Grammar.hpp | 5 | ||||
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/parse/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/parse/Grammar.cpp | 26 |
7 files changed, 55 insertions, 4 deletions
diff --git a/demos/CMakeLists.txt b/demos/CMakeLists.txt index 3afb5f91..f2df325d 100644 --- a/demos/CMakeLists.txt +++ b/demos/CMakeLists.txt @@ -16,6 +16,8 @@ elseif(UNIX) add_subdirectory(xcb) endif() +add_subdirectory(parse) + # My computer graphics practice source codes. Needs `dlib` as dependency. if (CRU_BUILD_GRAPHICS_EXPERIMENTS) add_subdirectory(graphics_experiments) diff --git a/demos/parse/CMakeLists.txt b/demos/parse/CMakeLists.txt new file mode 100644 index 00000000..ceaa5c4e --- /dev/null +++ b/demos/parse/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(cru_demo_parse_eliminate_left_recursion EliminateLeftRecursion.cpp) +target_link_libraries(cru_demo_parse_eliminate_left_recursion PRIVATE cru_parse) diff --git a/demos/parse/EliminateLeftRecursion.cpp b/demos/parse/EliminateLeftRecursion.cpp new file mode 100644 index 00000000..e5b97cc0 --- /dev/null +++ b/demos/parse/EliminateLeftRecursion.cpp @@ -0,0 +1,21 @@ +#include <iostream> + +#include "cru/parse/Grammar.hpp" + +int main() { + using namespace cru::parse; + Grammar grammar; + + auto S = grammar.CreateNonterminal(u"S"); + auto a = grammar.CreateTerminal(u"a"); + + grammar.CreateProduction(u"S := S a", S, {S, a}); + grammar.CreateProduction(u"S := a", S, {a}); + grammar.SetStartSymbol(S); + + grammar.EliminateLeftRecursions(); + + std::cout << grammar.ProductionsToString().ToUtf8(); + + return 0; +} diff --git a/include/cru/parse/Grammar.hpp b/include/cru/parse/Grammar.hpp index 659c4302..606fcc33 100644 --- a/include/cru/parse/Grammar.hpp +++ b/include/cru/parse/Grammar.hpp @@ -49,8 +49,11 @@ class Grammar : public Object { // Algorithm 4.21 void LeftFactor(); + public: + String ProductionsToString() const; + private: - Nonterminal* start_symbol_; + Nonterminal* start_symbol_ = nullptr; std::vector<Terminal*> terminals_; std::vector<Nonterminal*> nonterminals_; std::vector<Symbol*> symbols_; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba2fbce6..5059cc82 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,3 +10,4 @@ endif() add_subdirectory(ui) +add_subdirectory(parse) diff --git a/src/parse/CMakeLists.txt b/src/parse/CMakeLists.txt index de096c08..5c8a6dfa 100644 --- a/src/parse/CMakeLists.txt +++ b/src/parse/CMakeLists.txt @@ -7,4 +7,4 @@ add_library(cru_parse SHARED Token.cpp TokenType.cpp ) -target_link_libraries(cru_parse PUBLIC cru_common) +target_link_libraries(cru_parse PUBLIC cru_base) diff --git a/src/parse/Grammar.cpp b/src/parse/Grammar.cpp index 9d486c38..19095150 100644 --- a/src/parse/Grammar.cpp +++ b/src/parse/Grammar.cpp @@ -1,4 +1,5 @@ #include "cru/parse/Grammar.hpp" +#include "cru/common/String.hpp" #include "cru/parse/Symbol.hpp" #include <algorithm> @@ -19,6 +20,10 @@ Grammar::~Grammar() { } } +void Grammar::SetStartSymbol(Nonterminal* start_symbol) { + start_symbol_ = start_symbol; +} + Terminal* Grammar::CreateTerminal(String name) { auto terminal = new Terminal(this, std::move(name)); terminals_.push_back(terminal); @@ -147,8 +152,10 @@ void Grammar::EliminateLeftRecursions() { auto new_right = right; new_right.insert(new_right.cbegin(), jp->GetRight().cbegin(), jp->GetRight().cend()); - // TODO: What should this name be. - CreateProduction(u"", ni, std::move(new_right)); + CreateProduction( + Format(u"Merge of {} and {} (Eliminate Left Recursion)", + production->GetName(), jp->GetName()), + ni, std::move(new_right)); } } } @@ -278,4 +285,19 @@ void Grammar::LeftFactor() { } } } + +String Grammar::ProductionsToString() const { + String result; + + for (const auto& production : productions_) { + result += production->GetName() + u" : "; + result += production->GetLeft()->GetName() + u" := "; + for (auto s : production->GetRight()) { + result += s->GetName() + u" "; + } + result += u"\n"; + } + + return result; +} } // namespace cru::parse |