Pella86

BrainFuck interpreter

May 25th, 2018
221
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.38 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Fri May 25 00:26:37 2018
  4.  
  5. @author: Mauro
  6. """
  7.  
  8. # BrainFuck interpreter
  9.  
  10. # have a pointer that will travel an array
  11. class Pointer:
  12.    
  13.     def __init__(self):
  14.         self.p = 0
  15.         self.arr = [0 for i in range(10)]
  16.    
  17.     # >
  18.     def increment(self):
  19.         self.p += 1
  20.    
  21.     # <
  22.     def decrement(self):
  23.         self.p -= 1
  24.    
  25.     # +
  26.     def increase(self):
  27.         self.arr[self.p] += 1
  28.        
  29.     # -
  30.     def decrease(self):
  31.         self.arr[self.p] -= 1
  32.     # .
  33.     def putc(self, outstream):
  34.         output = self.arr[self.p]
  35.         print("OUTPUT:", output)
  36.         outstream.append(output)
  37.     # ,
  38.     def getc(self):
  39.         i = input("INPUT:")
  40.         self.arr[self.p] = i[0]
  41.        
  42.     def get_value(self):
  43.         return self.arr[self.p]
  44.  
  45.    
  46. class Instructions:
  47.    
  48.     def __init__(self, program):
  49.         # the underlying pointer that moves on the array
  50.         self.p = Pointer()
  51.        
  52.         # the string corresponding to the program
  53.         self.prog = program
  54.        
  55.         # the instruction pointer
  56.         self.ip = 0
  57.        
  58.         # parentheses stack
  59.         self.pstack = []
  60.         self.pcount = 0
  61.         self.current_pcount = 0
  62.        
  63.         # the output stream
  64.         self.out_stream = []
  65.    
  66.     # equivalent to char* c; *c++
  67.     # returns null when the end of the string is reached
  68.     def getc(self):
  69.         if self.ip < len(self.prog):
  70.             c = self.prog[self.ip]
  71.             self.ip += 1
  72.             return c
  73.         else:
  74.             return None  
  75.  
  76.     # runs the program
  77.     def interpret(self):
  78.        
  79.         c = self.getc()
  80.         while c:
  81.             print("-------", c, self.ip, "--------")
  82.            
  83.             if c == ">":
  84.                 self.p.increment()
  85.             elif c == "<":
  86.                 self.p.decrement()
  87.             elif c == "+":
  88.                 self.p.increase()
  89.             elif c == "-":
  90.                 self.p.decrease()
  91.             elif c == ".":
  92.                 self.p.putc(self.out_stream)
  93.             elif c == ",":
  94.                 self.p.getc()
  95.             elif c == "[":
  96.                
  97.                 # puts the character index where the loop start
  98.                 known_starts = [start for start, end in self.pstack]
  99.                 if self.ip in known_starts:
  100.                     pass
  101.                 else:
  102.                     self.pstack.append([self.ip, -1])
  103.                
  104.                 self.current_pcount = self.pcount
  105.                 self.pcount += 1
  106.                
  107.                 # if the value of the pointer is 0 and the end instruction pos
  108.                 # is not known then eat characters till you find the matching
  109.                 # parentheses
  110.                 if self.p.get_value() == 0 and self.pstack[self.current_pcount][1] == -1:
  111.                     c = self.getc()  
  112.                     # eat characters till the next MATCHING ]
  113.                     while c:
  114.                         if c == "[":
  115.                             self.pcount += 1
  116.                         elif c == "]":
  117.                             self.pcount -= 1
  118.                             # if the program finds the matching parenthes
  119.                             if self.current_pcount == self.pcount:
  120.                                 break
  121.                         c = self.getc()  
  122.                
  123.                 # if the end is known go to end    
  124.                 elif self.p.get_value() == 0:
  125.                     # end of loop
  126.                     self.ip = self.pstack[self.current_pcount][1]
  127.                    
  128.                     # pop the parentheses out of the stack (loop is skipped)
  129.                     self.pstack.pop(len(self.pstack)-1)
  130.                     self.pcount -= 1
  131.                    
  132.             elif c == "]":  
  133.                 self.pcount -= 1
  134.                 self.pstack[self.pcount][1] = self.ip
  135.                
  136.                 # if the value is different then zero jump back to the
  137.                 # loop start
  138.                 if self.p.get_value != 0:
  139.                     self.ip = self.pstack[self.pcount][0] -1
  140.                    
  141.            
  142.             c = self.getc()
  143.             # print the array
  144.             print("".join([str(i) + "|" for i in self.p.arr]))
  145.             # print the pointer position
  146.            
  147.             p_arrow = ""
  148.            
  149.             for i in range(len(self.p.arr)):
  150.                 # get the char length of the cell
  151.                 cellc = len(str(self.p.arr[i]))
  152.                 formatspec = "{:-^" + str(cellc) +"}|"
  153.                 if self.p.p == i:
  154.                     if cellc % 2 == 0:
  155.                         cell = formatspec.format("^^")
  156.                     else:
  157.                         cell = formatspec.format("^")
  158.                    
  159.                 else:
  160.                     cell = formatspec.format("")
  161.                 p_arrow += cell
  162.             print(p_arrow)
  163.        
  164.         print(self.out_stream)
  165.         print("".join([chr(c) for c in self.out_stream]))
  166.    
  167.  
  168. if __name__ == "__main__":
  169.    
  170. #     bfi = Instructions("++>+++++[<+>-]++++ ++++[<+++ +++ >-]<.")
  171. #     bfi = Instructions("++++[>++++[-]<-]")    
  172.  
  173.      bfi = Instructions("++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.")    
  174.  
  175.      bfi.interpret()
Advertisement
Add Comment
Please, Sign In to add comment