Brainfuck Compiler und Interpreter

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

BtbN

Betreff: Brainfuck Compiler und Interpreter

BeitragSa, März 11, 2006 18:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Das Modul:
Code: [AUSKLAPPEN]
SuperStrict

Rem
bbdoc: Brainfuck
EndRem
Module BtbN.Brainfuck

ModuleInfo "Version: 1.75"
ModuleInfo "Author: BtbN"
ModuleInfo "License: Public Domain"

ModuleInfo "History: 1.75 Release"
ModuleInfo "History: Optimizing C++-Source"
ModuleInfo "History: 1.50 Release"
ModuleInfo "History: Compiler added"

Import Pub.StdC
Import Pub.FreeProcess
Import BRL.Stream
Import BRL.FileSystem
Import BRL.StandardIO

Private
Function Sys:Int(cmd$)
   Return system_(cmd)
End Function
Public

Rem
bbdoc: The Brainfuck Interpreter Type
EndRem
Type TBrainfuck

   Field code:String
   Field arr:Int[256]

   Rem
   bbdoc: Insert a Brainfuck-Code for interpreting
   EndRem
   Method SetCode(inp:String)
      self.code = inp
   EndMethod

   Rem
   bbdoc: Read the Brainfuck-Code from a Stream
   EndRem
   Method SetCodeStream(strm:TStream)
      self.SetCode(LoadString(strm))
   EndMethod

   Rem
   bbdoc: Read the Brainfuck-Code from a File
   EndRem
   Method SetCodeFile(url:Object)
      Local tmp:TStream = ReadStream(url)
      self.SetCodeStream(tmp)
      CloseStream(tmp)
   EndMethod

   Rem
   bbdoc: Compiles the Brainfuck-Code into the given @file.
   about: If @keepsource is set, the tmp.cpp source-File will not be deleted.
   EndRem
   Method Compile(file:String,keepsource:Byte=False)
      Local cpph:String = "#include <iostream>~n"
      cpph :+ "~n"
      cpph :+ "int main(int argc,char *argv[])~n"
      cpph :+ "{~n"
      cpph :+ "    int *p = new int[256];~n"
      cpph :+ "    char cell = 0;~n"
      cpph :+ "    char tmp;~n"
      cpph :+ "~n"
      Local cppf:String = "}~n"
      Local out:TStream = WriteStream(AppDir+"/tmp.cpp")

      Local plcount:Int,plfound:Byte,micount:Int,mifound:Byte
      Local slcount:Int,slfound:Byte,srcount:Int,srfound:Byte
      Local whilecount:Int,bevadder:String,i:Int

      WriteString(out,cpph)

      Local pos:Long = 0

      While(pos<self.code.Length)
         If (Chr(self.code[pos]) = "." Or ..
            Chr(self.code[pos]) = "," Or ..
            Chr(self.code[pos]) = "[" Or ..
            Chr(self.code[pos]) = "]" Or ..
            Chr(self.code[pos]) = "<" Or ..
            Chr(self.code[pos]) = ">" Or ..
            Chr(self.code[pos]) = "-") And ..
            plfound = 1 ..
         Then
            WriteLine(out,bevadder+"    p[cell] += "+plcount+";")
            plcount = 0
            plfound = 0
         EndIf
         If (Chr(self.code[pos]) = "." Or ..
            Chr(self.code[pos]) = "," Or ..
            Chr(self.code[pos]) = "[" Or ..
            Chr(self.code[pos]) = "]" Or ..
            Chr(self.code[pos]) = "<" Or ..
            Chr(self.code[pos]) = ">" Or ..
            Chr(self.code[pos]) = "+") And ..
            mifound = 1 ..
         Then
            WriteLine(out,bevadder+"    p[cell] -= "+micount+";")
            micount = 0
            mifound = 0
         EndIf
         If (Chr(self.code[pos]) = "." Or ..
            Chr(self.code[pos]) = "," Or ..
            Chr(self.code[pos]) = "[" Or ..
            Chr(self.code[pos]) = "]" Or ..
            Chr(self.code[pos]) = ">" Or ..
            Chr(self.code[pos]) = "-" Or ..
            Chr(self.code[pos]) = "+") And ..
            slfound = 1 ..
         Then
            WriteLine(out,bevadder+"    cell -= "+slcount+";")
            slcount = 0
            slfound = 0
         EndIf
         If (Chr(self.code[pos]) = "." Or ..
            Chr(self.code[pos]) = "," Or ..
            Chr(self.code[pos]) = "[" Or ..
            Chr(self.code[pos]) = "]" Or ..
            Chr(self.code[pos]) = "<" Or ..
            Chr(self.code[pos]) = "-" Or ..
            Chr(self.code[pos]) = "+") And ..
            srfound = 1 ..
         Then
            WriteLine(out,bevadder+"    cell += "+srcount+";")
            srcount = 0
            srfound = 0
         EndIf
         Select Chr(self.code[pos])
            Case ">"
               srcount :+ 1
               srfound = 1
            Case "<"
               slcount :+ 1
               slfound = 1
            Case "."
               WriteLine(out,bevadder+"    std::printf(~q%c~q,p[cell]);")
            Case ","
               WriteLine(out,bevadder+"    std::cin >> tmp;")
               WriteLine(out,bevadder+"    p[cell] = (int)tmp;")
            Case "-"
               micount :+ 1
               mifound = 1
            Case "+"
               plcount :+ 1
               plfound = 1
            Case "["
               WriteLine(out,bevadder+"    while(p[cell]) {")
               whilecount :+ 1
               bevadder = ""
               For i = 0 Until whilecount
                  bevadder :+ "    "
               Next
            Case "]"
               whilecount :- 1
               bevadder = ""
               For i = 0 Until whilecount
                  bevadder :+ "    "
               Next
               WriteLine(out,bevadder+"    }")
         EndSelect
         pos :+ 1
      Wend

      WriteString(out,cppf)

      CloseStream(out)
      Sys("g++ "+AppDir+"/tmp.cpp -o "+file)
      If Not keepsource Then DeleteFile(AppDir+"/tmp.cpp")
   EndMethod

   Rem
   bbdoc: Starts interpreting the Brainfuck-Code.<br>The output will be written in @out and outoutted to sthe StdIO, if @ToStdIO is True.
   EndRem
   Method RunEx(out:String Var,ToStdIO:Byte=False)
      Local pos:Long,cast:Byte
      Local loop_pos:Long[256],lnum:Byte=0
      Local tmps:String

      pos = 0
      While(pos<self.code.Length)
         Select Chr(self.code[pos])
            Case ">"
               cast :+ 1
               If cast = 256 Then cast = 0
            Case "<"
               cast :- 1
               If cast = -1 Then cast = 255
            Case "."
               tmps :+ Chr(Byte(self.arr[cast]))
            Case ","
               self.arr[cast] = getchar_()
            Case "-"
               self.arr[cast] :- 1
            Case "+"
               self.arr[cast] :+ 1
            Case "["
               loop_pos[lnum] = pos
               lnum :+ 1
            Case "]"
               If self.arr[cast] <> 0 Then
                  pos = loop_pos[lnum-1]
               Else
                  lnum :- 1
               EndIf
         EndSelect
         pos :+ 1
      Wend

      If ToStdIO Then
         WriteString(StandardIOStream,tmps)
         FlushStream(StandardIOStream)
      EndIf
      out = tmps

      For pos = 0 To 255
         arr[pos] = 0
      Next
   EndMethod

   Rem
   bbdoc: Easyer way to start Interpreting the the Brainfuck-Code
   EndRem
   Method Run(ToStdIO:Byte=True)
      Local tmp:String
      self.RunEx(tmp,ToStdIO)
   EndMethod

EndType


Und hier ein Hello World:

Code: [AUSKLAPPEN]
SuperStrict

Framework BtbN.Brainfuck

Global b:TBrainfuck = New TBrainfuck
b.SetCode("++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.")
b.Compile("test",1)
b.run()


Sollte eine Binary "test" erzugen, die beim ausführen "Hello World!" ausgibt und einmal selbst "Hello World!" ausgeben. Allerdings nur über die StdIO(Konsole).
Auf Windows muss zum kompilieren das MinGW installiert sein(für g++).

Edit: Update auf Version 1.75, der C++-Source wird jetzt optimiert, sodass die ellenlangen cell++;..... Reihen darin ausbleiben. Desweiteren kann man unterbinden, dass das C++-Source-File gelöscht wird. So kann man es z.B. selber kompilieren, fals man kein g++ hat.
  • Zuletzt bearbeitet von BtbN am So, März 12, 2006 12:24, insgesamt 2-mal bearbeitet

Justus

BeitragSa, März 11, 2006 19:25
Antworten mit Zitat
Benutzer-Profile anzeigen
http://de.wikipedia.org/wiki/Brainfuck

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group