|
| 1 | +''' |
| 2 | +Version en python del interpretador de brainfuck, |
| 3 | +para tener una idea general a la hora de portearlo |
| 4 | +a C. |
| 5 | +''' |
| 6 | + |
| 7 | +# Libreria necesaria para los argumentos. |
| 8 | +from sys import * |
| 9 | +argc = len(argv) |
| 10 | + |
| 11 | +# Comprueba que los argumentos sean correctos |
| 12 | +if argc < 2 or argc > 3: |
| 13 | + print(f"\n\nUsage: {argv[0]} [path/to/file.bf] [args]\n") |
| 14 | + exit(1) |
| 15 | + |
| 16 | + |
| 17 | +def loop(src, pos): |
| 18 | + endLoop = 0 |
| 19 | + while 1: |
| 20 | + pos -= 1 |
| 21 | + item = src[pos] |
| 22 | + if item == "]": |
| 23 | + endLoop += 1 |
| 24 | + elif item == "[" and endLoop != 0: |
| 25 | + endLoop -= 1 |
| 26 | + elif item == "[" and endLoop == 0: |
| 27 | + break |
| 28 | + return pos |
| 29 | + |
| 30 | +# Busca errores, como bucles incompletos. |
| 31 | +def checkErrors(source): |
| 32 | + lpStat = clStat = err = 0 |
| 33 | + for i in source: |
| 34 | + if i == "[": |
| 35 | + lpStat += 1 |
| 36 | + elif i == "]": |
| 37 | + lpStat -= 1 |
| 38 | + elif i == ">": |
| 39 | + clStat += 1 |
| 40 | + elif i == "<": |
| 41 | + clStat -= 1 |
| 42 | + if lpStat != 0: |
| 43 | + err += 1 |
| 44 | + print("\n\t 001: UNFINISHED LOOP \n") |
| 45 | + if clStat < 0: |
| 46 | + err += 2 |
| 47 | + print("\n\t 002: NEGATIVE CELL POSITION \n") |
| 48 | + |
| 49 | + if err != 0: |
| 50 | + print(f"\nCode returned error {err}.") |
| 51 | + exit(err) |
| 52 | + |
| 53 | +# Version en C de checkErrors(): |
| 54 | +# |
| 55 | +# void checkErrors(char source[]){ |
| 56 | +# int lpStatus, err; |
| 57 | +# for(int i; i=<strlen(source); i++){ |
| 58 | +# if(source[i] == '['){ |
| 59 | +# lpStatus++; |
| 60 | +# }else if(source[i] == ']'){ |
| 61 | +# lpStatus--; |
| 62 | +# } |
| 63 | +# } |
| 64 | +# if(lpStatus != 0){ |
| 65 | +# err+=1; |
| 66 | +# fputs("\n\t 001: UNFINISHED LOOP \n\n", stderr); |
| 67 | +# } |
| 68 | +# } |
| 69 | + |
| 70 | + |
| 71 | +# Calcula el numero necesario de celdas |
| 72 | +# para que el programa funcione correctamente |
| 73 | +# usando el minimo numero de recursos. |
| 74 | +def getCells(source): |
| 75 | + num = cells = 0 |
| 76 | + for i in source: |
| 77 | + if i == ">": |
| 78 | + num += 1 |
| 79 | + elif i == "<": |
| 80 | + num -= 1 |
| 81 | + if num > cells: |
| 82 | + cells = num |
| 83 | + return cells + 2 |
| 84 | + |
| 85 | + |
| 86 | +# Version en C de 'getCells()': |
| 87 | +# |
| 88 | +# int getCells(char source[]){ |
| 89 | +# int num, cells; |
| 90 | +# for(int i; i=<strlen(source); i++){ |
| 91 | +# if(source[i] == '>'){ |
| 92 | +# num++; |
| 93 | +# }else if(source[i] == '<'){ |
| 94 | +# num--; |
| 95 | +# } |
| 96 | +# if(num > cells){ |
| 97 | +# cells = num; |
| 98 | +# } |
| 99 | +# } |
| 100 | +# return cells + 5; |
| 101 | +# } |
| 102 | + |
| 103 | + |
| 104 | +# Obtiene el input y se lo mete a 'stdin' |
| 105 | +if len(argv) == 3: |
| 106 | + stdin = argv[2] |
| 107 | + print(f"\nArgumentos: {stdin}") |
| 108 | + |
| 109 | +# Leer el codigo del archivo. |
| 110 | +with open(argv[1], "r") as file: |
| 111 | + source = file.read() |
| 112 | + print(f"\nCodigo fuente:\n{source}\n\n") |
| 113 | + |
| 114 | +# Comprueba que no hayan errores es el codigo. |
| 115 | +checkErrors(source) |
| 116 | + |
| 117 | +# Variables del interpretador. |
| 118 | +prgPos = cellPos = pArg = 0 |
| 119 | + |
| 120 | +# Le agrega el numero necesario de celdas necesarias + 2, |
| 121 | +# para situaciones inesperadas |
| 122 | +cells = [] |
| 123 | +for i in range(getCells(source)): |
| 124 | + cells.append(0) |
| 125 | + |
| 126 | + |
| 127 | +# Interpretador. |
| 128 | +while prgPos != len(source): |
| 129 | + # Le da el valor de la instruccion a 'obj' |
| 130 | + # para mayor facilidad de acceso. |
| 131 | + obj = source[prgPos] |
| 132 | + |
| 133 | + # Comportamiento segun el valor de la instruccion. |
| 134 | + if obj == ">": |
| 135 | + cellPos += 1 |
| 136 | + |
| 137 | + elif obj == "<": |
| 138 | + cellPos -= 1 |
| 139 | + |
| 140 | + elif obj == "+": |
| 141 | + cells[cellPos] += 1 |
| 142 | + |
| 143 | + elif obj == "-": |
| 144 | + cells[cellPos] -= 1 |
| 145 | + |
| 146 | + elif obj == ".": |
| 147 | + print(chr(cells[cellPos]), end="") |
| 148 | + |
| 149 | + elif obj == ",": |
| 150 | + cells[cellPos] = ord(stdin[pArg]) |
| 151 | + pArg += 1 |
| 152 | + |
| 153 | + elif obj == "]": |
| 154 | + if cells[cellPos] != 0: |
| 155 | + prgPos = loop(source, prgPos) |
| 156 | + |
| 157 | + # Pasa a la siguiente instruccion. |
| 158 | + prgPos += 1 |
0 commit comments