BrainFuck Interpreter

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
coder
Beiträge: 204
Registriert: 25.09.2005 17:53
Computerausstattung: Intel Core2Quad Q8200 @ 2.33GHz
ASUS P5Q3, 2GB DDR3-1066 RAM, ATi Raedeon HD 4850
Wohnort: Deutschland
Kontaktdaten:

BrainFuck Interpreter

Beitrag von coder »

Hallo,

mir war am Wochenende mal langweilig und da hab ich einfach mal einen kleinen BrainFuck Interpreter geschrieben und wollt euch den Source nicht vorenthalten. Er teilt sich in 2 Teile: Im 1. wird Code von unbekannten Zeichen befreit und in ein Array gepackt (was sicher noch schneller mit Pointern geht) und im 2. Teil wird dann der Code ausgeführt.

Source: http://files.freakybytes.net/pb/codes/BrainFuck.pb
Eintrag in meinem Blog: http://freakybytes.net/2010/06/brainfuck-interpreter/

Viel Spaß damit :wink:

Damit der Source auch in Board bleibt, wenn meine Seite mal weg ist, stell ich ihn nochmal hier rein.

Code: Alles auswählen

EnableExplicit

Prototype BrainFuck_OutCallback(char.c)

;-Für Debugzwecke
;#BrainFuck_Debug = #True

CompilerIf Defined(BrainFuck_Debug, #PB_Constant) = #False
  #BrainFuck_Debug = #False
CompilerEndIf

Macro BFDebug(__Text)
  CompilerIf #BrainFuck_Debug = #True
    Debug "BrainFuck> "+__Text
  CompilerEndIf
EndMacro

Procedure.s ParseBrainFuck(Array Source.c(1), Input$ = "", StartValue = 0, OutCallback.BrainFuck_OutCallback = 0)
  Protected NewList Cell.c(), NewList Loop.i()
  Protected Output$ = ""
  Protected x, InputLen, Depth
  
  AddElement(Cell()) : FirstElement(Cell())   ;Erste Zelle initialisieren
  
  For x = 0 To ArraySize(Source())
    Select Source(x)
      Case '<'    ;Eine Zelle zurück
        If Not PreviousElement(Cell())    ;Wenn bereits letzte Zelle aktiv ist
          ResetList(Cell())     ;Eine Zelle am Anfang hinzufügen
          AddElement(Cell()) : Cell() = StartValue
          BFDebug("Add Cell (first)")
        EndIf
        
      Case '>'    ;Eine Zelle vor
        If ListSize(Cell()) = ListIndex(Cell())+1   ;Wenn bereits letzte Zelle ausgewählt ist
          LastElement(Cell())   ;Eine Zelle am Ende hinzufügen
          AddElement(Cell()) : Cell() =  StartValue
          BFDebug("Add Cell (last)")
        Else
          NextElement(Cell())
        EndIf
        
      Case '+'    ;Zellenwert incrementieren
        Cell() + 1
        
      Case '-'    ;Zellenwert decrementieren
        Cell() - 1
        
      Case '.'    ;aktuellen Zellenwert als ASCII Character ausgeben
        BFDebug(" " + Chr(Cell()))
        If OutCallback
          OutCallback(Cell())
        EndIf
        Output$ + Chr(Cell())
        
      Case ','    ;erstes Zeichen des Input-Strings in die aktuelle Zelle einlesen
        InputLen = Len(Input$)
        If InputLen   ;Wenn ein InputString vorhanden ist
          Cell() = Asc(Left(Input$, 1))   ;Den ASCII-Wert des ersten Zeichens in die Zelle schreiben
          Input$ = Right(Input$, InputLen-1)    ;Dann den String vom ersten Zeichen befreien (damit nicht immer das selbe Zeichen eingelesen wird)
        Else
          Cell() = 0
        EndIf
        
      Case '['
        
        If Cell() <> 0   ;Wenn Zelle ungleich Null ist -> Schleife starten
          LastElement(Loop()) : AddElement(Loop())
          Loop() = x    ;Position des Schleifenbeginns speichern
          BFDebug("Beginn Loop")
        Else        ;Wenn Zelle gleich Null, an ihr Ende springen
          Depth = 0   ;Tiefe auf Null setzen
          
          For x = x+1 To ArraySize(Source())
            If Source(x) = '['    ;Eine weitere Schleife
              Depth + 1   ;Tiefe um 1 erhöhen
            ElseIf Source(x) = ']'    ;Ein Schleifenende
              If Depth = 0    ;Wenn äußere Schleife erreicht ist
                Break   ;Vorlauf beenden
              Else
                Depth - 1   ;Ansonsten Tiefe um 1 erhöhen
              EndIf
            EndIf
          Next
          
          If Not Depth = 0
            BFDebug("Syntax Error! ']' is missing!")
            ProcedureReturn ""
          EndIf
          
          BFDebug("Overjump Loop")
        EndIf
        
      Case ']'
        If Cell() <> 0   ;Wenn Zelle ungleich Null ist -> wieder an Schleifen Anfang springen
          LastElement(Loop())
          x = Loop()
          BFDebug("Repeat Loop")
        Else    ;Ansonsten
          DeleteElement(Loop()) : LastElement(Loop())   ;Schleife löschen
          BFDebug("Exit Loop")   ;und fortfahren
        EndIf
        
      Default
        BFDebug("Unkown Character: "+Chr(Source(x)))
        
    EndSelect
  Next
  
  ProcedureReturn Output$
  
EndProcedure

Procedure LexBrainFuck(source$, Array Source.c(1))  
  Protected Len = Len(source$)
  Protected Char$, RealLen = 0, x
  ReDim Source.c(Len)
  
  #BrainFuckChar$ = "<>+-[].,"
  
  For x = 1 To Len
    Char$ = Mid(source$, x, 1)
    If FindString(#BrainFuckChar$, Char$, 0)
      Source(RealLen) = Asc(Char$)
      RealLen + 1
    EndIf
  Next
  
  Debug "BrainFuck> LenDif = "+Str(Len - RealLen)
  ReDim Source.c(RealLen-1)
  ProcedureReturn RealLen
EndProcedure  

Define test$
Dim BF.c(0)

test$ = ""

; test$ + "   +++++++++++++++++++++++++++++++++++++++++++++++++++++   ."
; test$ + "<  ++++++++++++++++++++++++++++++++++++++++++++++++++++++  ."
; test$ + ">> +++++++++++++++++++++++++++++++++++++++++++++++++++++++ ."
; test$ + "<.<.>>."

; test$ + "++++++++++"
; test$ + " ["
; test$ + "    >+++++++>++++++++++>+++>+<<<<-"
; test$ + " ]                       // Schleife zur Vorbereitung der Textausgabe"
; test$ + " >++.                    // Ausgabe von 'H'"
; test$ + " >+.                     // Ausgabe von 'e'"
; test$ + " +++++++.                // 'l'"
; test$ + " .                       // 'l'"
; test$ + " +++.                    // 'o'"
; test$ + " >++.                    // Leerzeichen"
; test$ + " <<+++++++++++++++.      // 'W'"
; test$ + " >.                      // 'o'"
; test$ + " +++.                    // 'r'"
; test$ + " ------.                 // 'l'"
; test$ + " --------.               // 'd'"
; test$ + " >+.                     // '!'"
; test$ + " >.                      // Zeilenumbruch"

; test$ + ",[.,]"

;-99 Bottles of Beer
test$ + ">+++++++++[<+++++++++++>-]<[>[-]>[-]<<[>+>+<<-]>>[<<+>>-]>>>"
test$ + "[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+<"
test$ + "-]<<-<-]+++++++++>[<->-]>>+>[<[-]<<+>>>-]>[-]+<<[>+>-<<-]<<<"
test$ + "[>>+>+<<<-]>>>[<<<+>>>-]>[<+>-]<<-[>[-]<[-]]>>+<[>[-]<-]<+++"
test$ + "+++++[<++++++<++++++>>-]>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-"
test$ + "]<<<<<<.>>[-]>[-]++++[<++++++++>-]<.>++++[<++++++++>-]<++.>+"
test$ + "++++[<+++++++++>-]<.><+++++..--------.-------.>>[>>+>+<<<-]>"
test$ + ">>[<<<+>>>-]<[<<<<++++++++++++++.>>>>-]<<<<[-]>++++[<+++++++"
test$ + "+>-]<.>+++++++++[<+++++++++>-]<--.---------.>+++++++[<------"
test$ + "---->-]<.>++++++[<+++++++++++>-]<.+++..+++++++++++++.>++++++"
test$ + "++[<---------->-]<--.>+++++++++[<+++++++++>-]<--.-.>++++++++"
test$ + "[<---------->-]<++.>++++++++[<++++++++++>-]<++++.-----------"
test$ + "-.---.>+++++++[<---------->-]<+.>++++++++[<+++++++++++>-]<-."
test$ + ">++[<----------->-]<.+++++++++++..>+++++++++[<---------->-]<"
test$ + "-----.---.>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>>+++"
test$ + "+[<++++++>-]<--.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<."
test$ + "><+++++..--------.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++"
test$ + "++++++++++++.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<++"
test$ + "+++++++>-]<--.---------.>+++++++[<---------->-]<.>++++++[<++"
test$ + "+++++++++>-]<.+++..+++++++++++++.>++++++++++[<---------->-]<"
test$ + "-.---.>+++++++[<++++++++++>-]<++++.+++++++++++++.++++++++++."
test$ + "------.>+++++++[<---------->-]<+.>++++++++[<++++++++++>-]<-."
test$ + "-.---------.>+++++++[<---------->-]<+.>+++++++[<++++++++++>-"
test$ + "]<--.+++++++++++.++++++++.---------.>++++++++[<---------->-]"
test$ + "<++.>+++++[<+++++++++++++>-]<.+++++++++++++.----------.>++++"
test$ + "+++[<---------->-]<++.>++++++++[<++++++++++>-]<.>+++[<----->"
test$ + "-]<.>+++[<++++++>-]<..>+++++++++[<--------->-]<--.>+++++++[<"
test$ + "++++++++++>-]<+++.+++++++++++.>++++++++[<----------->-]<++++"
test$ + ".>+++++[<+++++++++++++>-]<.>+++[<++++++>-]<-.---.++++++.----"
test$ + "---.----------.>++++++++[<----------->-]<+.---.[-]<<<->[-]>["
test$ + "-]<<[>+>+<<-]>>[<<+>>-]>>>[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]"
test$ + ">[<+>-]>[<<++++++++++>>>+<-]<<-<-]+++++++++>[<->-]>>+>[<[-]<"
test$ + "<+>>>-]>[-]+<<[>+>-<<-]<<<[>>+>+<<<-]>>>[<<<+>>>-]<>>[<+>-]<"
test$ + "<-[>[-]<[-]]>>+<[>[-]<-]<++++++++[<++++++<++++++>>-]>>>[>+>+"
test$ + "<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>[-]>[-]++++[<++++++++>"
test$ + "-]<.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.><+++++..---"
test$ + "-----.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++++++++++++++"
test$ + ".>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<+++++++++>-]<-"
test$ + "-.---------.>+++++++[<---------->-]<.>++++++[<+++++++++++>-]"
test$ + "<.+++..+++++++++++++.>++++++++[<---------->-]<--.>+++++++++["
test$ + "<+++++++++>-]<--.-.>++++++++[<---------->-]<++.>++++++++[<++"
test$ + "++++++++>-]<++++.------------.---.>+++++++[<---------->-]<+."
test$ + ">++++++++[<+++++++++++>-]<-.>++[<----------->-]<.+++++++++++"
test$ + "..>+++++++++[<---------->-]<-----.---.+++.---.[-]<<<]"

Debug test$

CompilerIf 1
  
  Define Output$
  
  OpenConsole()
  
  Procedure BFPrint(char.c)
    Print(Chr(char))
  EndProcedure

  LexBrainFuck(test$, BF())
  Output$ = ParseBrainFuck(BF(), "", 0, @BFPrint())
  Debug Output$

  Input()

CompilerElse
  
  Define x, cicle = 100, start = ElapsedMilliseconds(), stop
  Define time, onetime.d, result$
  
  ;-Speedtest
  cicle = 100
  start = ElapsedMilliseconds()
  For x = 0 To cicle
    LexBrainFuck(test$, BF())
    result$ = ParseBrainFuck(BF())
  Next
  stop = ElapsedMilliseconds()
  
  time = stop-start
  onetime = time/cicle
  
  MessageRequester("Ergebnis", "Gesamtzeit: "+Str(time)+"ms"+#CRLF$+"Zeit pro Durchlauf: "+StrD(onetime, 2)+"ms");+#CRLF$+#CRLF$+result$)
  
CompilerEndIf

End
Windows 7 x64 | PureBasic 4.60 4.50 4.02
Ja verdammt, meine Eltern wohnen immer noch bei mir!
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: BrainFuck Interpreter

Beitrag von NicTheQuick »

Da gab es auch mal einen Wettbewerb zu: Brainfuck Interpreter
Benutzeravatar
coder
Beiträge: 204
Registriert: 25.09.2005 17:53
Computerausstattung: Intel Core2Quad Q8200 @ 2.33GHz
ASUS P5Q3, 2GB DDR3-1066 RAM, ATi Raedeon HD 4850
Wohnort: Deutschland
Kontaktdaten:

Re: BrainFuck Interpreter

Beitrag von coder »

Danke für den Link...
Aber mein Interpreter ist nur für die "normale" BrainFuck Version, also 1D
vllt. mach ja noch was für 2D, wenn ich mal wieder Langeweile hab ^^
Windows 7 x64 | PureBasic 4.60 4.50 4.02
Ja verdammt, meine Eltern wohnen immer noch bei mir!
Antworten