From f908449520981f40c41ed5c18e805e6f6182a53b Mon Sep 17 00:00:00 2001 From: Robin Jadoul Date: Thu, 26 May 2016 16:01:24 +0200 Subject: [PATCH] Fix some backend code --- src/backends/cpp.cpp | 59 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/src/backends/cpp.cpp b/src/backends/cpp.cpp index 64fd7d6..f1df7b3 100644 --- a/src/backends/cpp.cpp +++ b/src/backends/cpp.cpp @@ -1,6 +1,21 @@ #include "Lexesis/backends/cpp.h" #include +#include + +namespace { + lxs::templ::TemplateContext make_map_elem(std::string key, std::string value) { + return lxs::templ::make_map({{key, lxs::templ::make_string(value)}}); + } + + lxs::templ::TemplateContext make_int(int i) { + return lxs::templ::make_string(std::to_string(i)); + } + + lxs::templ::TemplateContext make_State(lxs::State i) { + return lxs::templ::make_string(std::to_string(i)); + } +} namespace lxs { namespace backends { @@ -10,6 +25,10 @@ namespace lxs { namespace backends { CppBackend::~CppBackend() {} + std::string CppBackend::getName() { + return "c++"; + } + bool CppBackend::canProcessLang(std::string lang) { for (char& c : lang) c = std::tolower(c); @@ -23,34 +42,49 @@ namespace lxs { namespace backends { { assert(lexerName.length()); + lexerName[0] = std::toupper(lexerName[0]); std::unique_ptr headerStream = getOstreamForFileName(lexerName + ".h"); std::unique_ptr implementationStream = getOstreamForFileName(lexerName + ".cpp"); std::map topLevel; - lexerName[0] = std::toupper(lexerName[0]); topLevel["name"] = templ::make_string(lexerName); //The DEADSTATE gets a brand new state: dfa.numStates - topLevel["reject_state"] = templ::make_string(std::to_string(dfa.numStates)); - topLevel["num_states"] = templ::make_string(std::to_string(dfa.numStates + 1)); + topLevel["reject_state"] = make_State(dfa.numStates); + topLevel["num_states"] = make_State(dfa.numStates + 1); auto transition_indices = buildTransitionIndices(dfa); topLevel["trans_idx"] = transformTransitionIndices(transition_indices.first); - topLevel["num_transitions_per_state"] = templ::make_string(std::to_string(transition_indices.second)); + topLevel["num_transitions_per_state"] = make_int(transition_indices.second); topLevel["table"] = buildTable(dfa, transition_indices.first, transition_indices.second); topLevel["token_types"] = buildTokenList(dfa); + std::vector acTokens; + for (State s = 0; s < dfa.numStates; s++) { + if (dfa.accepting.count(s)) { + acTokens.push_back(make_map_elem("token", dfa.acceptingToken.find(s)->second)); + } else { + acTokens.push_back(make_map_elem("token", "nonmatching")); + } + } + acTokens.push_back(make_map_elem("token", "nonmatching")); + topLevel["tokens"] = templ::make_array(acTokens); + templ::TemplateContext topLevelMap = templ::make_map(topLevel); doTemplate(*headerStream, "c++/lexer.h", topLevelMap); doTemplate(*implementationStream, "c++/lexer.cpp", topLevelMap); + + for (const auto& p : dfa.acceptingToken) { + std::cout << p.first << " " << p.second << std::endl; + } } - templ::TemplateContext CppBackend::buildTable(const DFA& dfa, const std::vector& transition_idx, int num_transitions_per_state) const { - std::map reverse_trans; + templ::TemplateContext CppBackend::buildTable(const DFA& dfa, const std::vector& transition_idx, int num_transitions_per_state) const { + std::map reverse_trans; for (int i = 0; i < 256; i++) { reverse_trans[transition_idx[i]] = i; } @@ -63,8 +97,9 @@ namespace lxs { namespace backends { State to = dfa.delta.find(s)->second.find(reverse_trans[i])->second; if (to == deadState) to = dfa.numStates; //The new Dead state name - row.push_back(templ::make_map({{"state", templ::make_string(std::to_string(to))}})); + row.push_back(templ::make_map({{"state", make_State(to)}})); } + table.push_back(templ::make_map({{"row", templ::make_array(row)}})); } // NOTE: there is no transition table entry for the dead state // since the algorithm should never loop in the dead state @@ -81,23 +116,23 @@ namespace lxs { namespace backends { std::vector tokenList; for (const std::string& s : tokens) { - tokenList.push_back(templ::make_map({{"type", templ::make_string(s)}})); + tokenList.push_back(make_map_elem("type", s)); } return templ::make_array(tokenList); } - std::pair, int> CppBackend::buildTransitionIndices(const DFA& /* dfa */) const { + std::pair, int> CppBackend::buildTransitionIndices(const DFA& /* dfa */) const { //FIXME: this is not really optimal ;-) - std::vector transition_idx; + std::vector transition_idx; for (int i = 0; i < 256; i++) transition_idx.push_back(i); return std::make_pair(transition_idx, 256); } - templ::TemplateContext CppBackend::transformTransitionIndices(std::vector transition_indices) const { + templ::TemplateContext CppBackend::transformTransitionIndices(const std::vector& transition_indices) const { std::vector new_trans; for (auto& i : transition_indices) { - new_trans.push_back(templ::make_map({{"trans", templ::make_string("(char)" + std::to_string(i))}})); + new_trans.push_back(make_map_elem("trans", "(unsigned char)" + std::to_string(i))); } return templ::make_array(new_trans); }