Brain_Fuck/src/bf_tokenizer.cpp

197 lines
5.0 KiB
C++

/*
* Created by Brett on 17/11/23.
* Licensed under GNU General Public License V3.0
* See LICENSE file for license detail
*/
#include <bf_tokenizer.h>
#include <sstream>
#include <random>
#include <iostream>
struct char_pair
{
char type;
size_t count;
};
class characterizer
{
private:
std::string program;
size_t currentIndex = 0;
public:
explicit characterizer(std::string program): program(std::move(program))
{}
inline bool hasNext()
{
return currentIndex < program.size();
}
inline size_t advance()
{
return currentIndex++;
}
inline char next()
{
return program[advance()];
}
inline char_pair fetch()
{
size_t start = currentIndex;
char type = next();
while (peek() == type)
advance();
return {type, currentIndex - start};
}
inline char peek()
{
return program[currentIndex];
}
};
void bf_tokenizer::tokenize(const std::string& program)
{
characterizer tk{program};
while (tk.hasNext())
{
auto dv = tk.fetch();
bf_token type = bf_token::PRINT;
switch (dv.type)
{
case '>':
type = (bf_token::INC_DP);
break;
case '<':
type = (bf_token::DEC_DP);
break;
case '+':
type = (bf_token::INC_DV);
break;
case '-':
type = (bf_token::DEC_DV);
break;
case '.':
type = (bf_token::PRINT);
break;
case ',':
type = (bf_token::READ);
break;
case '[':
type = (bf_token::OPEN);
break;
case ']':
type = (bf_token::CLOSE);
break;
default:
break;
}
tokens.emplace_back(type, dv.count);
}
}
void bf_tokenizer::bf_name()
{
size_t search_index = 0;
while (search_index < tokens.size())
{
if (tokens[search_index].type == bf_token::OPEN)
{
auto name = ++conditionalCount;
size_t sp = 1;
size_t search_2 = search_index;
tokens[search_index].name = name;
while (++search_2 < tokens.size())
{
if (tokens[search_2].type == bf_token::OPEN)
sp++;
if (tokens[search_2].type == bf_token::CLOSE)
sp--;
if (sp == 0)
break;
}
tokens[search_2].name = name;
}
search_index++;
}
}
inline void tabulate(signed long long v)
{
for (signed long long i = 0; i < v; i++)
std::cout << '\t';
}
void bf_tokenizer::print(size_t index)
{
signed long long sp = 0;
while (index < tokens.size())
{
auto& token = tokens[index++];
switch (token.type)
{
case bf_token::INC_DP:
tabulate(sp);
std::cout << "Increase DP " << token.offset << "\n";
break;
case bf_token::DEC_DP:
tabulate(sp);
std::cout << "Decrease DP " << token.offset << "\n";
break;
case bf_token::INC_DV:
tabulate(sp);
std::cout << "Increase DV " << token.offset << "\n";
break;
case bf_token::DEC_DV:
tabulate(sp);
std::cout << "Decrease DV " << token.offset << "\n";
break;
case bf_token::PRINT:
tabulate(sp);
std::cout << "Print\n";
break;
case bf_token::READ:
tabulate(sp);
std::cout << "Read\n";
break;
case bf_token::OPEN:
tabulate(sp);
std::cout << "If(";
if (token.name.has_value())
std::cout << token.name.value() << "\n";
else
std::cout << "UNNAMED" << "\n";
sp++;
break;
case bf_token::CLOSE:
sp--;
tabulate(sp);
if (token.name.has_value())
std::cout << token.name.value();
else
std::cout << "UNNAMED";
std::cout << ")\n";
break;
}
}
}
std::string generateName()
{
std::stringstream ss;
ss << std::hex;
static std::random_device rd;
static std::seed_seq seed{rd(), rd(), rd(), rd()};
static std::mt19937_64 gen(seed);
static std::uniform_int_distribution<int> dis(0, 15);
for (int i = 0; i < 24; i++)
ss << dis(gen);
return ss.str();
}