/* * Created by Brett on 17/11/23. * Licensed under GNU General Public License V3.0 * See LICENSE file for license detail */ #include #include #include #include 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 dis(0, 15); for (int i = 0; i < 24; i++) ss << dis(gen); return ss.str(); }