アセンブラを作る / Parserクラス完成

要領が分かったのでParserクラスのメソッドを全部作る。

class Parser:
    def __init__(self, file_path):
        self.file = open(file_path, "r")

        self.file.seek(0, 2)
        self.EOF_POS = self.file.tell()
        self.file.seek(0)

        self.current_inst = ""
       
    def __readline_scrapeoff(self):
        line = self.file.readline()

        # 先頭の空白と末尾の改行記号とを削除する。
        line = line.strip()
        # コメントを削除する
        line = line.split("//")[0]
        # 文字列中のスペースを削除する。
        line = line.replace(" ", "")
        # 文字列中のタブ文字を削除する。
        line = line.replace("\t", "")

        return line if line else None

    def has_more_lines(self):
        return self.file.tell() != self.EOF_POS

    def advance(self):
        self.current_inst = self.__readline_scrapeoff()

    def inst_type(self):
        # 空行ならNoneを返す。
        if not self.current_inst:
            return None
        # @があったらA命令。
        elif "@" in self.current_inst:
            return "A"
        # (~)があったらL命令。
        elif ("(" in self.current_inst) and (")" in self.current_inst):
            return "L"
        # それ以外ならC命令。
        else:
            return "C"

    def symbol(self):
        if self.inst_type() == "A":
            # @の次の文字以降を返す。
            return self.current_inst[1:]
        elif self.inst_type() == "L":
            # (の次から)の手前までを返す。
            return self.current_inst[1:-1]

    def dest(self):
        # 格納先が指定してあったら=の左辺を返す。
        if (self.inst_type() == "C") and ("=" in self.current_inst):
            return self.current_inst.split("=")[0]

    def comp(self):
        # dest=comp;jump
        if self.inst_type() == "C":
            # destを切り落とす。
            comp_part = self.current_inst.split("=")[-1]
            # jumpを切り落とす。
            comp_part = comp_part.split(";")[0]
            return comp_part

    def jump(self):
        # ジャンプ先が指定してあったら;の右側を返す。
        if (self.inst_type() == "C") and (";" in self.current_inst):
            return self.current_inst.split(";")[-1]


    def close(self):
        self.file.close()

###################################################
if __name__ == "__main__":
    s = Parser("test.asm")

    while (s.has_more_lines()):
        s.advance()
        print("命令        :", s.current_inst)
        print("命令タイプ  :", s.inst_type())
        print("シンボル    :", s.symbol())
        print("格納先      :", s.dest())
        print("ALU出力     :", s.comp())
        print("ジャンプ命令:", s.jump())
        print("")

    s.close()

テストファイル:

@2
D=A
@3
D=D+A
(LOOP)
@0
M=D
@LOOP
0;JMP

// 以下はテスト
dest=comp;jump
comp;jump
dest=comp
comp

実行結果:

命令        : @2
命令タイプ  : A
シンボル    : 2
格納先      : None
ALU出力     : None
ジャンプ命令: None

命令        : D=A
命令タイプ  : C
シンボル    : None
格納先      : D
ALU出力     : A
ジャンプ命令: None

命令        : @3
命令タイプ  : A
シンボル    : 3
格納先      : None
ALU出力     : None
ジャンプ命令: None

命令        : D=D+A
命令タイプ  : C
シンボル    : None
格納先      : D
ALU出力     : D+A
ジャンプ命令: None

命令        : (LOOP)
命令タイプ  : L
シンボル    : LOOP
格納先      : None
ALU出力     : None
ジャンプ命令: None

命令        : @0
命令タイプ  : A
シンボル    : 0
格納先      : None
ALU出力     : None
ジャンプ命令: None

命令        : M=D
命令タイプ  : C
シンボル    : None
格納先      : M
ALU出力     : D
ジャンプ命令: None

命令        : @LOOP
命令タイプ  : A
シンボル    : LOOP
格納先      : None
ALU出力     : None
ジャンプ命令: None

命令        : 0;JMP
命令タイプ  : C
シンボル    : None
格納先      : None
ALU出力     : 0
ジャンプ命令: JMP

命令        : None
命令タイプ  : None
シンボル    : None
格納先      : None
ALU出力     : None
ジャンプ命令: None

命令        : None
命令タイプ  : None
シンボル    : None
格納先      : None
ALU出力     : None
ジャンプ命令: None

命令        : dest=comp;jump
命令タイプ  : C
シンボル    : None
格納先      : dest
ALU出力     : comp
ジャンプ命令: jump

命令        : comp;jump
命令タイプ  : C
シンボル    : None
格納先      : None
ALU出力     : comp
ジャンプ命令: jump

命令        : dest=comp
命令タイプ  : C
シンボル    : None
格納先      : dest
ALU出力     : comp
ジャンプ命令: None

命令        : comp
命令タイプ  : C
シンボル    : None
格納先      : None
ALU出力     : comp
ジャンプ命令: None