Fix some backend code
This commit is contained in:
parent
b9da21dbc5
commit
f908449520
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue