Pewnack Pewnack - 5 months ago 7
Python Question

First of two blocks of code of reading from a file not executing in python

As part of an assignment I'm writing an assembler in python that takes simplified assembly language and outputs binary machine language. Part of my code is below, where I'm reading from the assembly code in two passes. The first pass (the first line of with open(filename, "r") as asm_file) in the first block of reading from the file asm_file doesn't seem to be executing. The second one is executing fine, well it's not outputting the correct binary because the first block doesn't seem to be running correctly or at all. Am I using the "with open(filename. "r") as file:" correctly? What am I missing? Thanks in advance.

For completeness an input file is given below the code:

if __name__ == "__main__":
#fill Symbol Table and C instruction Tables
symbol_table = symbolTable()
symbol_table.initialiseTable()

comp_table = compTable()
comp_table.fillTable()

dest_table = destTable()
dest_table.fillTable()

jump_table = jumpTable()
jump_table.fillTable()

#import the file given in the command line
filename = sys.argv[-1]
#open output_file
output_file = open('output.hack', 'w')
#open said file and work on contents line by line
with open(filename, "r") as asm_file: ##### This one doesn't seem to run because
#1st pass of input file ##### The print command below doesn't output anything
num_instructions = -1
for line in asm_file:
#ignoring whitespace and comments
if line != '\n' and not line.startswith('//'):
num_instructions += 1
#remove in-line comments
if '//' in line:
marker, line = '//', line
line = line[:line.index(marker)].strip()
#search for beginning of pseudocommand
if line.startswith('('):
num_instructions -= 1
label = line.strip('()')
address = num_instructions + 1
symbol_table.addLabelAddresses(label, address)
print(num_instructions) ###### This print command doesn't output anything

with open(filename, "r") as asm_file:
#2nd pass of input file
for line in asm_file:
#ignoring whitespace and comments
if line != '\n' and not line.startswith('//') and not line.startswith('('):
#remove in-line comments
if '//' in line:
marker, line = '//', line
line = line[:line.index(marker)].strip()
#send each line to parse function to unpack into its underlying fields
instruction = parseLine(line.strip(' \n'))
inst = Instruction(instruction)
binary_string = inst.convertToBin()
#write to output file
output_file.write(binary_string +'\n')

output_file.close()


An input file example:

// This file is part of www.nand2tetris.org

// and the book "The Elements of Computing Systems"

// by Nisan and Schocken, MIT Press.

// File name: projects/06/max/Max.asm



// Computes R2 = max(R0, R1) (R0,R1,R2 refer to RAM[0],RAM[1],RAM[2])



@R0

D=M // D = first number

@R1

D=D-M // D = first number - second number

@OUTPUT_FIRST

D;JGT // if D>0 (first is greater) goto output_first

@R1

D=M // D = second number

@OUTPUT_D

0;JMP // goto output_d

(OUTPUT_FIRST)

@R0

D=M // D = first number

(OUTPUT_D)

@R2

M=D // M[2] = D (greatest number)

(INFINITE_LOOP)

@INFINITE_LOOP

0;JMP // infinite loop

Answer

In the first with, starting with

#search for beginning of pseudocommand

are you quite sure you don't want that and the following lines dedented a level?

As is, the only way to get to your print is if a line satisfies both

if '//' in line:

and

if line.startswith('('):

There are no lines in your input file satisfying both, so the print never executes.

In the second with, there are only two indented lines after its

if '//' in line:
Comments