0

I have a college assignment to write an Assembler for a given hypothetical instruction set. I have implemented it, and when I am debugging, the std::find() function I've implemented is giving weird results. Please help.

#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;
}

By weird results, I mean that the operator== which is overloaded in the stl string class does't seem to work. The thing is, I tried to write my own find function:

lambda function :

for(auto& item : list) {
    if (item == str)         //str was passed to this lambda function
    { printf("purr"); }
}

it never went in even though item and str were equal, as the debugger showed

Like, with std::find, it always goes to type = 3

kesarling He-Him
  • 1,944
  • 3
  • 14
  • 39
  • 1
    Please be more specific than "giving weird results". What do you expect to happen, and what does actually happen? – molbdnilo Apr 11 '20 at 09:34
  • 1
    Pay very close attention to the difference between `=` and `==`. – molbdnilo Apr 11 '20 at 09:35
  • I would like to point out that .Equal() somehow works. – kesarling He-Him Apr 11 '20 at 09:47
  • 1
    https://stackoverflow.com/a/31816096/430766 – bitmask Apr 11 '20 at 09:50
  • 1
    @bitmask, Yeah, I know that. I usually replace it with the headers once I'm done with the code. Thanks a lot. That habit actually stems from competitive coding. – kesarling He-Him Apr 11 '20 at 09:52
  • 1
    I was able to somehow get rid of the annoying habit of writing `using namespace std`. This habit will go too :) – kesarling He-Him Apr 11 '20 at 09:55
  • 1
    @d4rk4ng31 Thanks for that insight. However, I feel obliged to point out that fast coding does not necessarily equal good coding. – bitmask Apr 11 '20 at 09:55
  • 1
    [Why is `iostream::eof` inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons) – molbdnilo Apr 11 '20 at 10:09

1 Answers1

1

You are adding a null character to the tokens when you parse:

return retToken += '\0';

This character is invisible in the debugger, which means that it looks like you're comparing, for instance, "AREG" and "AREG" when you're actually comparing "AREG"and "AREG\0".
And these are not equal; they're not even the same length.

Get rid of the unnecessary null character.

(There are probably other errors as well, but this should hopefully fix your comparison issue.)

molbdnilo
  • 64,751
  • 3
  • 43
  • 82