私は現在非常に基本的なアセンブラを扱っています。アセンブラは、アセンブリ命令を受け取り、16ビットのバイナリ命令を出力して、使用しているコンピュータで使用する必要があります。子クラスの変数を設定する
私のデザイン戦略は、3つの子クラスを持つCommandクラスを作成することでした。 Aコマンド、Cコマンド、およびLコマンドの各タイプのコマンドがあります。私が扱っているコマンドのタイプを特定するために、コマンドタイプに "A"、 "C"、または "L"の文字列を指定しました。
EDIT:
私はまだ適切にこれらのクラスを派生する方法を考え出す多くの問題が生じています。基本的に、AとLのコマンドには変換が必要な整数値を表す "シンボル"文字列が必要ですが、Cコマンドには "dest"、 "comp"、 "jump"の値も必要ですが、 "シンボル"の値はありません。
Command.h
#include <fstream>
#include <string>
class Command {
std::string command_type = "";
protected:
void set_commandType(std::string x){command_type = x;}
public:
Command();
virtual ~Command();
std::string commandType() const {return command_type;}
};
class A_COMMAND : public Command
{
std::string symbol;
public:
A_COMMAND(std::string s);
std::string get_symbol(){return symbol;}; //Returns the symbol or decimal Xxx of the current command @Xxx or (Xxx) . Should be called only when commandType() is A_COMMAND or L_COMMAND.
};
class C_COMMAND : public Command
{
std::string comp;
std::string dest;
std::string jump;
public:
C_COMMAND(std::string s, std::string d, std::string j);
std::string get_comp(){return comp;}; //Returns the comp mnemonic in the current C-command (28 possibilities). Should be called only when commandType() is C_COMMAND.
std::string get_dest(){return dest;}; //Returns the dest mnemonic in the current C-command (8 possibilities). Should be called only when commandType() is C_COMMAND.
std::string get_jump(){return jump;}; //Returns the jump mnemonic in the current C-command (8 possibilities). Should be called only when commandType() is C_COMMAND.
};
class L_COMMAND : public Command
{
std::string symbol;
public:
L_COMMAND(std::string s);
std::string get_symbol(){return symbol;}; //Returns the symbol or decimal Xxx of the current command @Xxx or (Xxx) . Should be called only when commandType() is A_COMMAND or L_COMMAND.
};
Command.cpp
#include "Command.h"
//---------------------------------------------
//A-Command functions
Command::Command(){}
A_COMMAND::A_COMMAND(std::string s) : symbol(s)
{
set_commandType("A");
}
//---------------------------------------------
//C-Command functions
C_COMMAND::C_COMMAND(std::string c, std::string d, std::string j) : comp(c), dest(d), jump(j)
{
set_commandType("C");
}
//---------------------------------------------
//L-Command functions
L_COMMAND::L_COMMAND(std::string s) : symbol(s)
{
set_commandType("L");
}
私が持っている入力を処理しての両端キューを作成するための責任があるParser.cppとParser.hコマンド:
Parser.h
#include "Command.h"
#include <vector>
#include <deque>
class Parser {
private:
std::deque<Command> commands;
public:
Parser(std::vector<std::string>);
bool hasMoreCommands() //are there more commands in the input?
{
if(commands.size() != 0)
return true;
else
return false;
}
void advance(){commands.pop_front();} //move to next command, should only work if hasMoreCommands returns false}
Command currentCommand(){return commands.front();}
std::vector<std::string> translateCommands(); //convert commands into binary strings
};
Parser.cpp
#include "Parser.h"
#include "Command.h"
#include <vector>
#include <iostream>
#include <string>
#include <unordered_map>
bool inList(std::string& str, std::vector<std::string> list) //check if a given string contains one of the elements in the comp, dest, jump vectors. if so extract string for use in constructor
{
for(auto i = list.begin(); i!=list.end(); ++i)
{
std::size_t found = str.find(*i);
if(found!=std::string::npos)
{
return true;
}
}
return false;
}
Parser::Parser(std::vector<std::string> input) {
std::vector<std::string> dest_list = {"","M","D","MD","A","AM","AD","AMD"}; //all possible dests
std::vector<std::string> comp_list = {"0","1","D","A","!D","!A","-D","-A","D+1","A+1","D-1","A-1","D+A","D-A","A-D","D&A","D|A","M","!M","-M","M+1","M-1","D+M","D-M","M-D","D&M","D|M"}; //all possible comps
std::vector<std::string> jump_list = {"","JGT","JEQ","JGE","JLT","JNE","JLE","JMP"}; //all possible jumps
std::string dest, comp, jump;
std::deque<Command> commands;
for(std::vector<std::string>::const_iterator i = input.begin(); i != input.end(); ++i)
{
std::string line = *i;
if(*line.begin()=='@') //A-command
{
A_COMMAND command(line.substr(1));
std::cout << "Command type: " << command.commandType() << "\n";
std::cout << "symbol: " << command.get_symbol() << "\n";
commands.push_back(command);
}
else if(*line.begin()=='(' && *line.rbegin() == ')' && line.size() > 2) //L-command
{
L_COMMAND command(line.substr(1, line.size() - 2));
std::cout << "Command type: " << command.commandType() << "\n";
std::cout << "symbol: " << command.get_symbol() << "\n";
commands.push_back(command); }
else
{
std::string rhs = line;
std::string dest_string = "";
std::string comp_string = "";
std::string jump_string = "";
size_t equals_pos = line.find('='); //position of = in string, if present
size_t semi_pos = line.find(';'); //position of ; in string, if present
if(equals_pos != line.npos) //if there is an = then we have a dest
{
dest_string = line.substr(0,equals_pos);
rhs = line.substr(equals_pos+1);
}
if(semi_pos != line.npos) //jump
{
comp_string = rhs.substr(0,semi_pos);
jump_string = rhs.substr(semi_pos+1);
}
else //no jump
{
comp_string = rhs;
}
//now confirm if inputs are valid
if(inList(dest_string, dest_list))
dest = dest_string;
else
std::cout << "invalid dest \n";
if(inList(comp_string, comp_list))
comp = comp_string;
else
std::cout << "invalid comp \n";
if(inList(jump_string, jump_list))
jump = jump_string;
else
std::cout << "invalid jump \n";
C_COMMAND command(comp, dest, jump);
std::cout << "Command type: " << command.commandType() << "\n";
std::cout << "dest: " << command.get_dest() << "\n";
std::cout << "comp: " << command.get_comp() << "\n";
std::cout << "jump: " << command.get_jump() << "\n";
commands.push_back(command);
}
}
}
私のmain.cppには、入力をロードし、パーサを通してそれを渡します。私が持っている問題は、入力に何もできないということです。
私はそうのような関数を記述しようとしています
string translateLine(Command command, Code code) //Code is a table for translating the command
{
string output;
if(command.commandType() == "A")
{
string symbol = parser.currentCommand().get_symbol();
cout << symbol << endl;
//perform binary conversion
}
/*else if(command.commandType() == "C")
{
string dest = command.get_dest();
}*/
//shouldn't be any L commands in symbol-less version
else
{
std::cout << "unexpected command value \n";
}
return output;
}
しかし、すぐに、私は()get_symbolを呼び出すよう、コンパイラが関数を認識しません。これは基本コマンドにget_symbol()関数がないためですが、関数を基本クラスに正しく追加して下位3に引き出す方法がわかりません。それぞれのクラスですべての関数が使用されているわけではないため、純粋な仮想クラスです。どうすればこれを正しく行うことができますか?
投稿したコードに問題はありません。したがって、問題はあなたが投稿していないコードになります。質問を編集し、[mcve]を含める必要があります。 –
本当にset_commandType()をパブリック関数にしますか?そうでない場合は、 'command_type'を保護することを検討してください。派生クラスが実行中に型を変更できるようにしますか?そうでなければ、それを非公開にして、Commandから派生したクラスだけが使用できる保護されたコンストラクタの引数を値にします。 *(タイプのないコマンドについて話が合理的でない場合は、Commandインスタンスを作成する人を避けるために最善の方法です)。* – HostileFork
元の例はうまくいくはずですか?面白い、食はこれらの宣言について不平を言う。私は元の質問を編集してより多くの情報を提供します。 – Araganor