Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python3
- import sys, getopt
- class State:
- def __init__(self, cmd, bar, jmp):
- self.cmd=cmd
- self.bar=bar
- self.jmp=jmp
- #close everything up
- def close(code=2):
- global p
- global IMET
- global OMET
- global out
- global inFile
- try:
- p.close()
- except NameError:
- pass
- try:
- out.close()
- except NameError:
- pass
- try:
- inFile.close()
- except NameError:
- pass
- sys.exit(code)
- #show help
- def showHelp():
- print("""Usage: """+sys.argv[0]+""" [OPTION]... [FILE]
- Runs a .ffb file
- --inputfile=file specifies a file to get input from, rather than from a user
- --outputfile=file specifies a file to output to, rather than from the console
- -h, --help shows this help page
- """)
- #run a command
- def runCmd(cmd):
- global tape
- global ip
- global IMET
- global OMET
- global inBuffer
- global inFile
- global out
- if cmd=="LFT":
- ip+=1
- if ip==len(tape):
- tape+=[0]
- elif cmd=="RGT":
- if ip==0:
- tape=[0]+tape
- else:
- ip-=1
- elif cmd=="INC":
- tape[ip]+=1
- if tape[ip]>255:
- tape[ip]=0
- if tape[ip]<0:
- tape[ip]=255
- elif cmd=="DEC":
- tape[ip]-=1
- if tape[ip]>255:
- tape[ip]=0
- if tape[ip]<0:
- tape[ip]=255
- elif cmd=="INP":
- while True:
- if len(inBuffer)>0:
- try:
- tape[ip]=ord(inBuffer[0])
- except TypeError:
- tape[ip]=inBuffer[0]
- inBuffer=inBuffer[1:]
- return
- #we need to refill the buffer
- if IMET=="USER":
- inBuffer=input()
- if len(inBuffer)==0:
- #no input
- inBuffer=[-1]
- else:
- inBuffer=inFile.read(1)
- if len(inBuffer)==0:
- #no input
- inBuffer=[-1]
- elif cmd=="OUT":
- if OMET=="USER":
- print(chr(max(tape[ip],0)),end="")
- else:
- out.write(bytes([max(tape[ip],0)]))
- elif cmd=="HLT":
- close(0)
- #IO methods
- IMET="USER"
- OMET="USER"
- #where we save input that is waiting to be used
- inBuffer=""
- #get arguments
- args=sys.argv[1:]
- try:
- opts,args=getopt.getopt(args,"h",["help","inputfile=","outputfile="])
- except getopt.GetoptError:
- showHelp()
- close(2)
- #read options
- for opt, arg in opts:
- if opt in ('-h','--help'):
- showHelp()
- close(0)
- elif opt=="--inputfile":
- IMET="FILE"
- try:
- inFile=open(arg,'rb')
- inBuffer=inFile.read()
- except IOError:
- print("ERROR: Could not open input file.")
- close()
- elif opt=="--outputfile":
- OMET="FILE"
- try:
- out=open(arg,'wb')
- except IOError:
- print("ERROR: Could not open output file.")
- close()
- #make sure we were given a file
- if len(args)==0:
- print("ERROR: no files given!")
- close()
- #and not too many
- if len(args)>1:
- print("ERROR: too many files given!")
- close()
- #open the program
- try:
- p=open(args[0],'rb')
- except IOError:
- print("ERROR: could not open file \""+args[0]+"\"!")
- close()
- #parse the program
- try:
- #get the byte width
- BYTEWIDTH=ord(p.read(1))
- except ValueError:
- print("ERROR: program is empty!")
- close()
- #state map
- states=[]
- #read first state
- s=p.read(2*BYTEWIDTH+2)
- while len(s)==2*BYTEWIDTH+2:
- #get info from the state
- try:
- cmd=("LFT","RGT","INC","DEC","INP","OUT","NOP","HLT")[s[0]]
- except IndexError:
- print("ERROR: unrecognized command byte \""+s[0]+"\"")
- close()
- bar=s[1]
- jmps=s[2:]
- jmp=[jmps[:len(jmps)//2],jmps[len(jmps)//2:]]
- jmp[0]=int.from_bytes(jmp[0], byteorder='big', signed=False)
- jmp[1]=int.from_bytes(jmp[1], byteorder='big', signed=False)
- #add it to the list
- states.append(State(cmd, bar, jmp))
- #read states by chucks
- s=p.read(2*BYTEWIDTH+2)
- #run the program!!
- tape=[0]
- ip=0
- state=0
- while True:
- try:
- runCmd(states[state].cmd)
- except IndexError:
- print("ERROR: There is no state \""+str(state)+"\"")
- close(2)
- if states[state].bar<=tape[ip]:
- state=states[state].jmp[1]
- else:
- state=states[state].jmp[0]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement