aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--demos/CMakeLists.txt2
-rw-r--r--demos/parse/CMakeLists.txt2
-rw-r--r--demos/parse/EliminateLeftRecursion.cpp21
-rw-r--r--include/cru/parse/Grammar.hpp5
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/parse/CMakeLists.txt2
-rw-r--r--src/parse/Grammar.cpp26
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