def main(): readPaths: List[Path] writePath: Path inputPath = Path(sys.argv[1]) if inputPath.is_dir(): readPaths = [p for p in inputPath.iterdir() if p.suffix == ".vm"] writePath = (inputPath / inputPath.stem).with_suffix(".asm") else: assert inputPath.suffix == ".vm", "Invalid input file: must have .vm extension" readPaths = [inputPath] writePath = inputPath.with_suffix(".asm") with open(writePath, "w+") as writeFile: writer = VMCodeWriter(writeFile) writer.writeInit() for p in readPaths: parser = VMParser(p, writer) # sets up the VMParser while parser.hasMoreCommands(): parser.writeNextCommand()
class VMTranslator: def __init__(self): self.parser = VMParser() self.coder = CodeWriter() self.myPath = Path(sys.argv[1]) self.initParameters() def initParameters(self): self.filelists = list() if self.myPath.is_file(): self.filelists = [self.myPath] self.outputFile = str(self.myPath.with_suffix('.asm')) elif self.myPath.is_dir(): self.filelists = [ file for file in self.myPath.iterdir() if str(file).endswith('.vm') ] self.outputFile = str( self.myPath) + ('/' + str(self.myPath.stem) + '.asm') self.outputFileHandle = open(self.outputFile, 'w') def run(self): self.outputFileHandle.write( self.coder.translateCode(['bootstrap'], 'Call Sys.init 0')) for file in self.filelists: fileHandle = open(str(file)) filename = file.stem #extract filename without the extendion e.g foo.vm => foo self.coder.setFilename(filename) for line in fileHandle: sanitizedLine = self.sanitizeInput(line) if len(sanitizedLine) == 0: continue parsedInstruction = self.parser.parse(sanitizedLine) codeString = self.coder.translateCode(parsedInstruction, sanitizedLine) self.outputFileHandle.write(codeString) fileHandle.close() print('Translated VM code to assembly successfully.') # noinspection PyUnboundLocalVariable self.outputFileHandle.close() # remove whitespace and comments from input[line] def sanitizeInput(self, line): if len(line) == 0 or line.startswith('//'): return '' line = line.strip() commentIndex = line.find('//') if commentIndex > -1: line = line[:commentIndex] return line
def __init__(self): self.parser = VMParser() self.coder = CodeWriter() self.myPath = Path(sys.argv[1]) self.initParameters()
filenames = [args.source] output_filename = split(args.source)[0] + ".asm" if args.stdout: output_file = sys.stdout else: output_file = open(output_filename, "w") cw = CodeWriter(output_file, args.stamp) if args.bootstrap: cw.writeInit() for filename in filenames: cw.setFileName(filename) p = VMParser(filename) while p.hasMoreCommands(): t = p.commandType() if t in ["C_PUSH", "C_POP"]: cw.WritePushPop(t, p.arg1(), p.arg2()) elif t == "C_ARITHMETIC": cw.writeArithmetic(p.arg1()) elif t == "C_LABEL": cw.writeLabel(p.arg1()) elif t == "C_GOTO": cw.writeGoto(p.arg1()) elif t == "C_IF": cw.writeIf(p.arg1()) elif t == "C_FUNCTION": cw.writeFunction(p.arg1(), p.arg2()) elif t == "C_RETURN":
def runSingleFile(self, isWrite=True): parser = VMParser(self.content) codeWriter = VMCodeWriter(self.className) asmCmds = self.asmCmds while(parser.hasMoreCommands()): parser.advance() commandType = parser.commandType() if commandType in ['C_PUSH','C_POP']: segment,index = parser.arg1(),parser.arg2() asmCmds += codeWriter.writePushPop(commandType, segment, index) elif commandType == 'C_ARITHMETIC': cmd = parser.arg1() asmCmds += codeWriter.writeArithmetic(cmd) elif commandType == 'C_LABEL': cmd = parser.arg1() asmCmds += codeWriter.writeLabel(cmd) elif commandType == 'C_GOTO': cmd = parser.arg1() asmCmds += codeWriter.writeGoto(cmd) elif commandType == 'C_IF': cmd = parser.arg1() asmCmds += codeWriter.writeIf(cmd) elif commandType == 'C_FUNCTION': functionName,numVars = parser.arg1(),parser.arg2() asmCmds += codeWriter.writeFunction(functionName, numVars) elif commandType == 'C_CALL': functionName,numArgs = parser.arg1(),parser.arg2() asmCmds += codeWriter.writeCall(functionName, numArgs) elif commandType == 'C_RETURN': asmCmds += codeWriter.writeReturn() if isWrite: with open(self.outputPath, 'w') as f: f.write(''.join(asmCmds))