0

Using AssemblyParser in Assembler::assemble causes "unknown externals" errors, when used correctly (with the correct arguments). However if I remove the arguments (which is incorrect), I get a very sensible error: 'AssemblyParser': no appropriate default constructor available

I am definitely including the right file, because VS knows about the symbol (AssemblyParser), knows whether I'm giving the correct arguments.

Here's the errors I get when including the correct arguments (as in the code below)

1>Assembler.obj : error LNK2019: unresolved external symbol "public: __thiscall AssemblyParser::AssemblyParser(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class SymbolTable &)" (??0AssemblyParser@@QAE@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAVSymbolTable@@@Z) referenced in function "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Assembler::assemble(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,bool)" (?assemble@Assembler@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V23@_N@Z)
1>Assembler.obj : error LNK2019: unresolved external symbol "public: class AssemblerInstruction * __thiscall AssemblyParser::getInstructionPtr(void)" (?getInstructionPtr@AssemblyParser@@QAEPAVAssemblerInstruction@@XZ) referenced in function "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Assembler::assemble(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,bool)" (?assemble@Assembler@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V23@_N@Z)
1>~\HackAssembler\Debug\HackAssembler.exe : fatal error LNK1120: 2 unresolved externals

Here's the use of AssemblyParser that causes the error (without the indicated line, the build succeeds)

string Assembler::assemble(std::string inputFileName, bool writeFile)
{
    ifstream inputFile;
    ofstream outputFile;
    string output;

    // open file
    inputFile.open(inputFileName);
    if (!inputFile.is_open())
        throw exception("inputFile didn't open for writing");

    string line;
    int lineNum = 0;
    // FIRST PASS
    while (getline(inputFile, line)) {
        if (line.find("(") == 0) {
            line = line.substr(1, line.length() - 2); // length - 1 is last char
            mTable.add(line, lineNum);
            lineNum++;
        }
    }

    // SECOND PASS
    while (getline(inputFile, line)) {
        // skip blank lines and comment lines
        if (line.find("//") == 0 || line.find(" ") == 0)
            continue;

        string newLine = AssemblyParser(line, mTable).getInstructionPtr()->getMachineCode(); // *** THIS LINE ***
    }
    inputFile.close();
    return output;
}

Here's the declaration of AssemblyParser. (let me know if you want to see the definitions as well)

class AssemblyParser
{
public:
    AssemblyParser(std::string assemblyCode, SymbolTable& table);
    std::unique_ptr<AssemblerInstruction> getUniqueInstructionPtr();
    AssemblerInstruction* getInstructionPtr();

private:
    AssemblerInstruction mInstruction;
    SymbolTable mSymbolTable;
    std::unique_ptr<AssemblerInstruction> mUniqueInstructionPtr;
    AssemblerInstruction* mInstructionPtr;

    void parseCInstruction(std::string assemblyCode);
    void parseAInstruction(std::string assemblyCode);
};
Jonathan Tuzman
  • 11,568
  • 18
  • 69
  • 129
  • 1
    The declaration is one thing, but where do you define the two functions the linker is complaining about? They are not in the code you've shown. – Ted Lyngmo Jan 17 '21 at 18:31
  • If this is the same problem as your last question that involved unit testing you need to split your code into a static library that can be called in the unit test executable project. Making it a reference is not going to work. – drescherjm Jan 17 '21 at 18:39

0 Answers0