197 lines
5.0 KiB
C++
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();
|
|
} |