151 lines
4.9 KiB
C++
151 lines
4.9 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_mips_codegen.h>
|
|
#include <iostream>
|
|
|
|
std::string preamble = ".data\n"
|
|
"\tdata_address: \t.word \t0\n"
|
|
"\tdata_pointer:\t.word\t0\n"
|
|
"\tnewline: .asciiz \"\\n\"\n"
|
|
".text\n"
|
|
"setup:\n"
|
|
"\tli $v0, 9\n"
|
|
"\tli $a0, 30000\n"
|
|
"\tsyscall\n"
|
|
"\t\n"
|
|
"\tla $t1, data_address\n"
|
|
"\tsw $v0, ($t1)\n"
|
|
"\t\n"
|
|
"\t# t0 - current address (data_pointer)\n"
|
|
"\t# t1 -\n"
|
|
"\t# t2 - temp\n"
|
|
"\tmove $t0, $v0\n"
|
|
"bf:\n";
|
|
|
|
void process_print(const std::vector<token_t>& tokens, size_t index);
|
|
|
|
void codegen(const std::vector<token_t>& tokens, std::ostream& out)
|
|
{
|
|
out << preamble;
|
|
size_t index = 0;
|
|
// skip past comments
|
|
if (tokens[index].token == bf_token::OPEN)
|
|
while (tokens[index].token != bf_token::CLOSE)
|
|
index++;
|
|
|
|
process_print(tokens, index);
|
|
|
|
size_t sp = 0;
|
|
while (index < tokens.size())
|
|
{
|
|
auto& token = tokens[index++];
|
|
std::string name{"UNNAMED"};
|
|
if (token.name.has_value())
|
|
name = token.name.value();
|
|
switch (token.token)
|
|
{
|
|
case bf_token::INC_DP:
|
|
out << "\taddi $t0, $t0, 1\n";
|
|
break;
|
|
case bf_token::DEC_DP:
|
|
out << "\tsubi $t0, $t0, 1\n";
|
|
break;
|
|
case bf_token::INC_DV:
|
|
out << "\tlb $t1, ($t0)\n"
|
|
<< "\taddi $t1, $t1, 1\n"
|
|
<< "\tsb $t1, ($t0)\n";
|
|
break;
|
|
case bf_token::DEC_DV:
|
|
out << "\tlb $t1, ($t0)\n"
|
|
<< "\tsubi $t1, $t1, 1\n"
|
|
<< "\tsb $t1, ($t0)\n";
|
|
break;
|
|
case bf_token::PRINT:
|
|
out << "\tli $v0, 11\n"
|
|
<< "\tlb $a0, ($t0)\n"
|
|
<< "\tsyscall\n";
|
|
break;
|
|
case bf_token::READ:
|
|
out << "\tli $v0, 12\n"
|
|
<< "\tsyscall\n"
|
|
<< "\tsb $v0, ($t0)\n";
|
|
break;
|
|
case bf_token::OPEN:
|
|
out << "\tlb $t1, ($t0)\n"
|
|
<< "\tbeqz $t1, BF_CLOSE_" << name << "_" << std::to_string(sp) << '\n'
|
|
<< "BF_OPEN_" << name << "_" << std::to_string(sp) << ":\n";
|
|
sp++;
|
|
break;
|
|
case bf_token::CLOSE:
|
|
sp--;
|
|
out << "\tlb $t1, ($t0)\n"
|
|
<< "\tbnez $t1, BF_OPEN_" << name << "_" << std::to_string(sp) << '\n'
|
|
<< "BF_CLOSE_" << name << "_" << std::to_string(sp) << ":\n";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
inline void tabulate(size_t v)
|
|
{
|
|
for (size_t i = 0; i < v; i++)
|
|
std::cout << '\t';
|
|
}
|
|
|
|
void process_print(const std::vector<token_t>& tokens, size_t index)
|
|
{
|
|
size_t sp = 0;
|
|
while (index < tokens.size())
|
|
{
|
|
auto& token = tokens[index++];
|
|
switch (token.token)
|
|
{
|
|
case bf_token::INC_DP:
|
|
tabulate(sp);
|
|
std::cout << "Increase DP\n";
|
|
break;
|
|
case bf_token::DEC_DP:
|
|
tabulate(sp);
|
|
std::cout << "Decrease DP\n";
|
|
break;
|
|
case bf_token::INC_DV:
|
|
tabulate(sp);
|
|
std::cout << "Increase DV\n";
|
|
break;
|
|
case bf_token::DEC_DV:
|
|
tabulate(sp);
|
|
std::cout << "Decrease DV\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;
|
|
}
|
|
}
|
|
}
|