Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 22/08/2012, à 19:16

PJSimply

[python] ajout d'instructions au brainfuck

Bonjour / Bonsoir tout le monde big_smile

Engros je vous explique comment j'en suis arrivé ici : j'ai découvert le brainfuckil y a peu de temps et je voulais essayer donc j'ai trouvé un interpréteur en python sur Internet pour faire mes tests. Seulement pour ceux qui connaissent, c'est assez fastidieux, je me suis donc dit que ça serait cool d'ajouter des intsructions pour aider un petit coup smile
J'ai donc modifier et fait des ajouts au script pour rajouter les commandes suivantes :

{ code à ajouter } qui permet de stocker du code dans la "case" pointée
! qui exécute le code contenu dans la "case" pointée
: qui sort toutes les cases précédant celle pointée
$nom quelconque$ qui permet de nommer un case du tableau
_nom quelconque_ qui permet de pointer automatiquement sur la case nommée 

Voici le code de l'interpréteur :

#!/usr/bin/python

import re
import sys
from collections import deque

class TabCase(object):

    def right(self,car):
        self.index += 1
        if self.index == len(self.cells):
            self.cells.append(car)
        
    def left(self,car):
        self.index -= 1
        if self.index < 0:
            self.index = 0
            self.cells.appendleft(car)

    def getCell(self):
        return self.cells[self.index]

    def __repr__(self):
        return " ".join([str(x) for x in self.cells])


class Value(TabCase):
    def __init__(self):
        self.cells = deque([0])
        self.index=0
        
    def inc(self):
        self.cells[self.index] +=1
        self.cells[self.index] %=256

    def dec(self):
        self.cells[self.index] -=1
        self.cells[self.index] %=256


    def set(self, val):
        self.cells[self.index] = val

    def aff(self):
        i=0
        while i <= self.index:
            sys.stdout.write(chr(self.cells[i]))
            i+=1

class Func(TabCase):
    def __init__(self):
        self.cells = deque([''])
        self.index=0


    def add(self, cmd):
        self.cells[self.index] += cmd

class MainTab(object):

    def __init__(self):
        self.value= Value()
        self.func= Func()
        self.index=0

    def right(self):
        self.value.right(0)
        self.func.right('')
        self.index+=1

    def left(self):
        self.value.left(0)
        self.func.left('')
        self.index -= 1
        if self.index < 0:
            self.index = 0


    def goto(self,newIndex):
        self.index=newIndex
        self.value.index=newIndex
        self.func.index=newIndex

    def getIndex(self):
        return self.index


class MatchTab(object):

    def __init__(self):
        self.table=dict()

    def addName(self,name,value):
        self.table[name]=value

    def shift(self):
        for value in self.table.values():
            value+=1


class BFInterpreter(object):

    def __init__(self):
        self.mainTab = MainTab()
        self.matchTab = MatchTab()
        self.commands = []
    
    def runCommands(self, cmds):
        self.commands = cmds
        self.command_index = 0
        try:
            while True:
                self.executeNext()
        except IndexError:
            pass

    def executeNext(self):
        cmd = self.commands[self.command_index]
        # print cmd
        if cmd == '[':
            if not self.mainTab.value.getCell():
                self.gotoMatchinCroch(1)
                return
        elif cmd == ']':
            if self.mainTab.value.getCell():
                self.gotoMatchinCroch(-1)
                return
        elif cmd == '{':
            self.assignFunc(self.getBetween(']'))
        elif cmd =='}':
            print 'unmatched end function definition sign'
        else:
            self.interpret(cmd)
        
        self.command_index += 1

    def gotoMatchinCroch(self, direction):
        onstack = 1
        while onstack:
            self.command_index += direction
            if self.commands[self.command_index] == ']':
                onstack -= direction
            elif self.commands[self.command_index] == '[':
                onstack += direction
        self.command_index += 1

    def assignFunc(self,function):  
        self.mainTab.func.add(function)

    def exe(self):
        subs=self.func.getCell()
        indice=self.commands.index('!')
        self.commands=self.commands[:indice]+subs+self.commands[(indice+1):]

    def getBetween(self,endChar):
        self.command_index+=1
        between=''
        while self.commands[self.command_index] != endChar:
            between+=self.commands[self.command_index]
            self.command_index += 1
        return between


    def interpret(self, item):
        if item == '+':
            self.mainTab.value.inc()
        elif item == '-':
            self.mainTab.value.dec()
        elif item == '>':
            self.mainTab.right()
        elif item == '<':
            if self.mainTab.index==0:
                self.matchTab
            self.mainTab.left()
        elif item == ':':
            self.mainTab.value.aff()
        elif item == '$':
            self.matchTab.addName(self.getBetween('$'), self.mainTab.getIndex() )
        elif item == '_':
            self.mainTab.goto(self.matchTab.table[self.getBetween('_')])
        elif item == '.':
            sys.stdout.write(chr(self.mainTab.value.getCell()))
        elif item == '!':
            self.command_index-=1
            self.exe()
        elif item == ',':
            try:
                val = ord(raw_input())
                self.value.set(val)
            except:
                # Ignore invalid input
                pass


def printUsage():
    print "\nUsage: python FLInterp.py [-b|-o] <INPUT_FILE>\n"

if __name__ == '__main__':
    if len(sys.argv) < 3 or sys.argv[1] not in ("-o", "-b"):
        printUsage()
        sys.exit()

    fname = sys.argv[2]
    listing = file(fname, 'r').read()

    interpreter = BFInterpreter()
    interpreter.runCommands(listing)

Voila smile

J'aurais aimé connaître des moyens d'améliorer un peu le code car je suis débutant en python donc j'ai sans doute des défauts et je suis loin de maîtriser toutes les fonctions qui existent smile
Et aussi j'aurai aimé savoir si vous aviez des idées de choses à ajouter, de fonctions etc

Merci beaucoup de votre lecture et de votre éventuelle aide smile
Bonne soirée/journée/année/rentrée

PS : le code original est de Johannes Chara mais je n'ai pas l'url, je l'édit dès que je la retrouve !

Hors ligne