diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | cpp.cpp | 85 | ||||
-rw-r--r-- | cpp.h | 10 | ||||
-rw-r--r-- | tests/test-cpp.cpp | 4 |
4 files changed, 81 insertions, 20 deletions
@@ -89,7 +89,7 @@ TESTSRC=\ SRC=$(PROGSRC) mcc.cpp all: test-$(PROJECTNAME) mcc - ./test-$(PROJECTNAME) #--gtest_filter='*preprocessing_tokenize' + ./test-$(PROJECTNAME) --gtest_filter='CppTest.compile' # testsuite ---------------------------------------------- test-$(PROJECTNAME): $(TESTSRC:.cpp=.o) @@ -64,7 +64,7 @@ void CPP::concatenate_strings() // TODO } -std::string CPP::valueOfNode(index_t node_index, const std::vector<TreeNode>& Tree) +std::string CPP::valueOfNode(index_t node_index) const { std::string result; std::optional<size_t> pos0; @@ -84,7 +84,7 @@ std::string CPP::valueOfNode(index_t node_index, const std::vector<TreeNode>& Tr last_index = TokenIdFromChildId(current_index); } else { - const TreeNode &node{Tree[current_index]}; + const TreeNode &node{m_nodes[current_index]}; // iterate backwards in childs, to get depth-first search in tree, from the beginning std::for_each(node.child_ids.rbegin(), node.child_ids.rend(), [&](int32_t child){ @@ -99,6 +99,13 @@ std::string CPP::valueOfNode(index_t node_index, const std::vector<TreeNode>& Tr return m_code.substr(*pos0, m_tokens[last_index].location.pos - *pos0) + m_tokens[last_index].value; }; +std::string CPP::typeOfNode(index_t node_id) const +{ + if (node_id >= m_nodes.size()) + throw std::runtime_error("CPP::typeOfNode(): node_id="s + std::to_string(node_id) + ", m_nodes.size()="s + std::to_string(m_nodes.size())); + return m_nodes[node_id].type; +} + namespace { std::unordered_set<std::string> pp_types { "identifier", @@ -236,28 +243,76 @@ std::vector<Gram::TreeNode> CPP::analysis(const std::vector<Token>& tokens) return compiler.compile(tokens); } -#if 0 -void CPP::traverse(index_t node_id) +std::string CPP::locationOfNode(index_t node_index) const { - fs::path current_path{parent_path / m_nodes[node_id].type}; + if (node_index >= m_nodes.size()) + throw std::runtime_error("ICE: locationOfNode(): Bad node_index "s + std::to_string(node_index) + " vs. "s + std::to_string(m_nodes.size())); - // execute callbacks - auto it{map.find(current_path.generic_string())}; - if (it != map.end()) { - it->second(current_path, node_id); - } - - // recurse tree - for (const auto& child_id: m_nodes[node_id].child_ids) { + for (const auto& child_id: m_nodes[node_index].child_ids) { if (ChildIdIsNode(child_id)) { - traverse(child_id, map, current_path); + std::string location{locationOfNode(child_id)}; + if (location.size() > 0) + return location; + } else { // ChildIdIsToken + return m_tokens[TokenIdFromChildId(child_id)].location.toString(); } } + + return ""; // not found +} + +void CPP::compileError(index_t node_id, const std::string& msg) const +{ + std::string location{locationOfNode(node_id)}; + if (location.size() == 0) + location = "Node "s + std::to_string(node_id) + "doesn't have any token"; + throw std::runtime_error("Compile error: "s + location + ": "s + msg); +} + +std::string CPP::typeOfChild(int32_t child_id) const +{ + if (ChildIdIsToken(child_id)) { + index_t token_id {TokenIdFromChildId(child_id)}; + return m_tokens[token_id].type; + } else { // ChildIdIsNode + return m_nodes[child_id].type; + } +} + +bool CPP::childTypesOfNodeMatch(index_t node_id, const std::vector<std::string>& pattern) const +{ + const std::vector<int32_t>& child_ids{m_nodes[node_id].child_ids}; + + if (child_ids.size() != pattern.size()) + return false; // mismatch + + for (size_t i = 0; i < child_ids.size(); i++) { + if (pattern[i] != "" && typeOfChild(child_ids[i]) != pattern[i]) + return false; // mismatch + } + + return true; // match +} + +void CPP::trDeclaration(index_t node_id) +{ + std::cout << "DEBUG" << std::endl; } -#endif void CPP::trTranslationUnit(index_t node_id) { + if (childTypesOfNodeMatch(node_id, {"declaration-seq"})) { + // resolve sequence + do { + node_id = m_nodes[node_id].child_ids[0]; + if (childTypesOfNodeMatch(node_id, {"declaration"})) { + trDeclaration(m_nodes[node_id].child_ids[0]); + return; + } + } while (childTypesOfNodeMatch(node_id, {"declaration-seq", "declaration"})); + compileError(node_id, "ICE: bad declaration-seq"); + } else + compileError(node_id, "declaration-seq expected"); } // Phase 7.c: Translate @@ -19,8 +19,6 @@ public: CPP(); ~CPP(); - std::string valueOfNode(index_t node_index, const std::vector<Gram::TreeNode>& Tree); - // phases of translation, according to standard void source_charset_map(); // phase 1 void backslash_escape(); // phase 2 @@ -47,6 +45,14 @@ private: CPPContext m_cpp_context; + std::string valueOfNode(index_t node_index) const; + std::string typeOfNode(index_t node_index) const; + std::string locationOfNode(index_t node_index) const; ///< Empty if no location available + void compileError(index_t node_id, const std::string& msg) const; + std::string typeOfChild(int32_t child_id) const; + bool childTypesOfNodeMatch(index_t, const std::vector<std::string>& pattern) const; ///< returns true iff specified type list matches; "" -> don't care + void trTranslationUnit(index_t node_id); + void trDeclaration(index_t node_id); }; diff --git a/tests/test-cpp.cpp b/tests/test-cpp.cpp index adfa54b..0a0276e 100644 --- a/tests/test-cpp.cpp +++ b/tests/test-cpp.cpp @@ -78,13 +78,13 @@ TEST_F(CppTest, preprocessing_tokenize_compile_error) { FAIL() << "Exception expected"; } -TEST(Cpp, compile) { +TEST_F(CppTest, compile) { CPP cpp; cpp.compile("int main() { return 1 + 1; }"); } -TEST(Cpp, compile_2_times) { +TEST_F(CppTest, compile_2_times) { CPP cpp; cpp.compile("int main() { return (1 + 2) * 2; }"); |