Преподаватель информационных технологий Рязанского политехнического колледжа,
кандадат педагогических наук


Compiler Bufunge

from sys import *
import time
import random

# =======================================
# =           Классы и методы           =
# =======================================


class Pointer:
    def __init__(self, x=0, y=0, vector=2, value=None):
        self.x = x
        self.y = y
        self.vector = vector
        self.value = value
        self.stack = []
        self.stack_sf = 0

    def __str__(self):
        return 'Point ({},{}) vektor:{} value:{} stack_sf:{} stack:{}'.format(self.x, self.y, self.vector, self.value, self.stack_sf, self.stack)

    def step(self):
        if self.vector == 1:
            self.x -= 1
        elif self.vector == 2:
            self.y += 1
        elif self.vector == 3:
            self.x += 1
        elif self.vector == 4:
            self.y -= 1

    def action(self):

        if self.value == '"' and self.stack_sf == 0:                # Первая, вторая "
            self.stack_sf = 1
        elif self.value == '"' and self.stack_sf == 1:
            self.stack_sf = 0
        elif self.stack_sf == 1:                                    # "Hello" в стек кодами
            self.stack.append(ord(self.value))
        elif self.value in numbers and self.stack_sf == 0:
            # 123 в стек цифрами
            self.stack.append(int(self.value))

        elif self.value in operators and self.stack_sf == 0:
            b = self.stack.pop()
            a = self.stack.pop()
            if self.value == '+':
                res = a + b                                         # a+b в стек
            elif self.value == '-':
                res = a - b                                         # a-b в стек
            elif self.value == '*':
                res = a * b                                         # a*b в стек
            elif self.value == '/':
                if b == 0:
                    res = 0
                else:
                    res = a // b                                    # a//b в стек
            elif self.value == '%':
                res = a % b                                         # a%b в стек
            self.stack.append(res)

        elif self.value == '!' and self.stack_sf == 0:
            a = self.stack.pop()
            if a == 0:
                a = 1
            else:
                a = 0
            # 0->1, 1->0
            self.stack.append(a)

        elif self.value == '`' and self.stack_sf == 0:
            a = self.stack.pop()        # вершина
            b = self.stack.pop()        # подвершина
            if b > a:
                res = 1
            else:
                res = 0
            # b>a -> 1|0
            self.stack.append(res)

        elif self.value == '?' and self.stack_sf == 0:
            # ? (случайное направление)
            a = random.randint(1, 4)
            self.vector = a

        elif self.value == ':' and self.stack_sf == 0:              # голова голова
            last = self.stack.pop()
            self.stack.append(last)
            self.stack.append(last)

        elif self.value == '\\' and self.stack_sf == 0:             # ab => ba
            a = self.stack.pop()
            b = self.stack.pop()
            self.stack.append(a)
            self.stack.append(b)

        elif self.value == '#' and self.stack_sf == 0:              # прыжок "вперед"
            self.step()

        elif self.value == ',' and self.stack_sf == 0:              # голова=65=A
            value = self.stack.pop()
            print(chr(value), end='')

        elif self.value == '.' and self.stack_sf == 0:              # Print голова
            a = self.stack.pop()
            print(a, end='')

        elif self.value == '_' and self.stack_sf == 0:              # Условие "_"
            test = self.stack.pop()
            if test == 0:
                # голова = 0, вправо(2)
                self.vector = 2
            else:
                # голова !=0, влево(4)
                self.vector = 4

        elif self.value == '|' and self.stack_sf == 0:              # Условие "|"
            test = self.stack.pop()
            if test == 0:
                self.vector = 3
            else:
                self.vector = 1

        elif self.value == '$' and self.stack_sf == 0:              # удалить голову
            self.stack.pop()

        elif self.value == '~' and self.stack_sf == 0:              # Input: A => 65
            val = input('Введите символ: ')
            self.stack.append(ord(val[0]))

        elif self.value == '&' and self.stack_sf == 0:              # Input: 65 => 65
            val = int(input('Введите число: '))
            self.stack.append((val))

        elif self.value == 'p' and self.stack_sf == 0:              # x, y, symcode
            x = self.stack.pop()                                    # A(x,y) = symcode
            y = self.stack.pop()
            symcode = self.stack.pop()
            A[x][y] = chr(symcode)

        # x, y, value=A(x,y)
        elif self.value == 'g' and self.stack_sf == 0:
            x = self.stack.pop()                                    # ord(value) => стек
            y = self.stack.pop()
            value = A[x][y]
            self.stack.append(ord(value))

        elif self.value == '>' and self.stack_sf == 0:              # >
            self.vector = 2
        elif self.value == '<' and self.stack_sf == 0:              # <
            self.vector = 4
        elif self.value == '^' and self.stack_sf == 0:              # ^
            self.vector = 1
        elif self.value == 'v' and self.stack_sf == 0:              # v
            self.vector = 3
        self.step()                                                 # Один шаг

# ===============================
# =           Функции           =
# ===============================


def open_file(name):
    data = open(name, 'r').read()
    return data


def field_print():
    for row in A:
        for elem in row:
            print(elem, end='')
        print()

# ===========================================
# =           Начальные настройки           =
# ===========================================


numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
operators = ['+', '-', '*', '/', '%']
point = Pointer()                           # Указатель исполнителя
text = open_file(argv[1]).split("\n")       # Считать программу
n = len(text)                               # n = всего строк
m = 0                                       # m = всего столбцов

# Поиск максимальной строки (это и будет m)
for line in text:
    if len(line) > m:
        m = len(line)

# Поле программы (массив n на m пробелов)
A = [' '] * n
for i in range(n):
    A[i] = [' '] * m

# Забиваем символами программы поле
for i in range(len(text)):
    for j in range(len(text[i])):
        A[i][j] = text[i][j]

# ==========================================
# =           Основная программа           =
# ==========================================

# field_print()

while point.value != '@':
    try:
        point.value = A[point.x][point.y]       # 1) Считали команду под point
        point.action()                          # 2) Выполнили команду
        # print(point)                            # 3) Отладка: вывод указателя
        # time.sleep(0.5)                         # 4) Отладка: задержка 0.5 cек
    except IndexError:                          # Если выход за поле = стоп программа
        print('Кончился стек или вышли за поле')
        break

# field_print()
print()

Источники:

  1. https://ru.wikipedia.org/wiki/Befunge
  2. http://bef-93.blogspot.com/2014/06/bef-93-tutorial.html
  3. http://befungius.aurlien.net/
  4. https://esolangs.org/wiki/Befunge

Рязанский политехнический колледж
390043, Рязанская обл., Рязань, ул. Солнечная, 6, тел. 8 (491) 293-84-87, polytech-rzn.ru

Edit
Pub: 20 Mar 2020 05:43 UTC
Edit: 17 Apr 2020 21:53 UTC
Views: 1087