Fix some backend code

This commit is contained in:
Robin Jadoul 2016-05-26 16:01:24 +02:00
parent b9da21dbc5
commit f908449520
1 changed files with 47 additions and 12 deletions

View File

@ -1,6 +1,21 @@
#include "Lexesis/backends/cpp.h"
#include <cassert>
#include <iostream>
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<std::ostream> headerStream = getOstreamForFileName(lexerName + ".h");
std::unique_ptr<std::ostream> implementationStream = getOstreamForFileName(lexerName + ".cpp");
std::map<const std::string, templ::TemplateContext> 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<templ::TemplateContext> 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<char>& transition_idx, int num_transitions_per_state) const {
std::map<char, char> reverse_trans;
templ::TemplateContext CppBackend::buildTable(const DFA& dfa, const std::vector<unsigned char>& transition_idx, int num_transitions_per_state) const {
std::map<unsigned char, unsigned char> 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<templ::TemplateContext> 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<std::vector<char>, int> CppBackend::buildTransitionIndices(const DFA& /* dfa */) const {
std::pair<std::vector<unsigned char>, int> CppBackend::buildTransitionIndices(const DFA& /* dfa */) const {
//FIXME: this is not really optimal ;-)
std::vector<char> transition_idx;
std::vector<unsigned char> 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<char> transition_indices) const {
templ::TemplateContext CppBackend::transformTransitionIndices(const std::vector<unsigned char>& transition_indices) const {
std::vector<templ::TemplateContext> 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);
}