У меня есть задание колледжа написать ассемблер для данного гипотетического набора инструкций. Я реализовал это, и когда я отлаживаю, реализованная мной функция std::find()
дает странные результаты. Пожалуйста, помогите.
#include <bits/stdc++.h>
//imperative keywords
std::list<std::string> Mn_imp = { "READ","PRINT","MOVER","MOVEM","ADD","SUB","MUL","DIV" };
//declarative keywords
std::list<std::string> Mn_dcl = { "DS","DS" };
//assembler directives
std::list<std::string> Mn_drc = { "START","STOP","LTORG","EQU" };
struct Row {
std::string name;
long LC_val;
Row(std::string _name, long LC) : name(_name), LC_val(LC) { }
bool operator==(const Row& row) {
return ((this->name == row.name) && (this->LC_val == row.LC_val));
}
};
long LOCCTR = 0;
std::vector<Row> SYMTAB;
std::vector<Row> LITTAB;
std::vector<int> POOLTAB;
std::string getToken(std::string& buffer) {
std::string retToken;
int i = 0;
while (1) {
if (i == buffer.size()) {
buffer.clear();
break;
}
else if (buffer[i] == ' ' || buffer[i] == ',') {
i++;
std::string newString(buffer.begin() + i, buffer.end());
buffer.clear();
buffer = newString;
break;
}
retToken += buffer[i];
i++;
}
return retToken += '\0';
}
bool getNumber(char* str, long* num_ptr) {
bool flag = false;
int i = 0;
*num_ptr = 0;
char ch = ' ';
while (ch != '\0') {
ch = *(str + i);
if (ch >= '0' && ch <= '9') {
*num_ptr = (*num_ptr) * 10 + (long)(ch - 48);
flag = true;
}
i++;
}
return flag;
}
short process_imp(std::vector<std::string> statement) {
auto isRegister = [](const std::string& token) {
return (token == "AREG" || token == "BREG" || token == "CREG" || token == "DREG");
};
auto find = [](std::string str, char c) {
for (const auto& ch : str) {
if (ch == c) {
return true;
}
}
return false;
};
//first argument
if (!isRegister(statement[1])) {
if (find(statement[1], '=')) { //isLiteral
if (std::find(LITTAB.begin(), LITTAB.end(), Row(statement[1], -1)) != LITTAB.end()) { //check for presence
LITTAB.push_back(Row(statement[1], -1));
}
}
else if (statement[1][1] == 'F') { //isNumber
long number = 0;
getNumber(const_cast<char*>(statement[1].c_str()), &number);
}
else { //isVariable
for (const auto& row : SYMTAB) {
if (row.name == statement[1]) {
return 0;
}
}
SYMTAB.push_back(Row(statement[1], -1));
return 0;
}
}
//second argument
if (!isRegister(statement[2])) {
if (find(statement[2], '=')) { //isLiteral
if (std::find(LITTAB.begin(), LITTAB.end(), Row(statement[2], -1)) != LITTAB.end()) { //check for presence
LITTAB.push_back(Row(statement[2], -1));
}
}
else if (statement[2][1] == 'F') { //isNumber
long number = 0;
getNumber(const_cast<char*>(statement[2].c_str()), &number);
}
else { //isVariable
for (auto& row : SYMTAB) {
if (row.name == statement[2]) {
return 0;
}
}
SYMTAB.push_back(Row(statement[2], -1));
return 0;
}
}
return 0;
}
short process_drc(std::vector<std::string> statement) {
if (statement.front() == std::string("START")) {
if (statement.size() > 1) {
getNumber(const_cast<char*>(statement[1].c_str()), &LOCCTR);
}
}
else if (statement.front() == std::string("LTORG")) {
int i = POOLTAB.back();
for (; i < LITTAB.size(); i++) {
LITTAB[i].LC_val = LOCCTR++;
}
POOLTAB.push_back(LITTAB.size());
}
else if (statement.front() == std::string("EQU")) {
for (auto& row : SYMTAB) {
if (row.name == statement[0]) {
for (auto& _row : SYMTAB) {
if (_row.name == statement[2]) {
row.LC_val = _row.LC_val;
return 0;
}
}
}
}
}
else if (statement.front() == "STOP") {
return 1;
}
}
short process_dcl(std::vector<std::string> statement) {
for (auto& row : SYMTAB) {
if (row.name == statement[0]) {
row.LC_val = LOCCTR++;
return 0;
}
}
SYMTAB.push_back(Row(statement[0], LOCCTR));
LOCCTR++;
return 0;
}
int process_line(std::string line) {
auto find = [](std::list<std::string> list, std::string str) { //could have used std::find()
for (const auto& var : list) {
if (std::string(var) == str) {
return true;
}
}
return false;
};
int retVal = 0;
std::vector<std::string> token_vec;
while (line != "") {
token_vec.push_back(getToken(line));
}
//start processing the tokenised array
auto token = token_vec.begin();
std::string tok = token_vec.front();
//pop the label
if (tok[tok.size() - 1] == ':') {
SYMTAB.push_back(Row(tok, LOCCTR));
token_vec.pop_back();
}
//find the type of statement
unsigned short type = 0;
if (std::find(Mn_imp.begin(), Mn_imp.end(), tok) != Mn_imp.end()) {
type = 1;
}
else if (std::find(Mn_drc.begin(), Mn_drc.end(), tok) != Mn_drc.end()) {
type = 2;
}
else {
type = 3;
}
switch (type) {
case 1: //imperative statement
retVal = process_imp(token_vec);
break;
case 2: //assembler directive
retVal = process_drc(token_vec);
break;
case 3: //declarative statement
retVal = process_dcl(token_vec);
break;
//default: (not needed)
}
return retVal;
}
int main(int argc, const char** argv) {
std::vector<std::string> code;
std::ifstream infile;
infile.open(argv[1]);
while (!infile.eof()) {
std::string str;
std::getline(infile, str);
code.push_back(str);
}
infile.close();
//Now we have the code in a string vector
//check for a proper end
if (code.back() != "STOP") {
std::cerr << "Where do I stop?? Perhaps you forgot to put an end (STOP) statement?\n";
return -1;
}
//if code is proper then begin pass1
for (int i = 0; ; i++) {
auto line = code[i];
short success = process_line(line);
if (success == -1) {
std::cerr << "Something wrong at line number " << i + 1 << std::endl;
break;
}
else if (success == 0) {
//silence is golden :P
}
else if (success == 1) {
std::cout << "Pass1 completed successfully :)" << std::endl;
break;
}
}
return 0;
}
Под странными результатами я имею в виду, что оператор ==, перегруженный в классе строки stl, похоже, не работает. Дело в том, что я пытался написать свою собственную функцию поиска:
лямбда-функция:
for(auto& item : list) {
if (item == str) //str was passed to this lambda function
{ printf("purr"); }
}
она никогда не входила, даже если item
и str
были равны, как отладчик показал
Как и в случае с std :: find, он всегда идет к type = 3