I made a simple Brainfuck interpreter, this is a step towards a microcontroller assembly/machine code simulation.
Learn about Brainfuck and its syntax here:
http://en.wikipedia.org/wiki/Brainfuck
Note that my version allows variables and pointers to decrement from 0 to 255 and increment from 255 to 0
Turing: |
setscreen ("graphics:1000,600;position:center,center;offscreenonly;title:Brainfuck") %;nobuttonbar")
const maxAddress := 255
var address : array 0 .. maxAddress of int
var _pointer : int
var code : string := ""
var ch : string (1)
var loopCounter, location : int
var finished, _return : boolean
var chars : array char of boolean
fcn getInput (fieldName, starting : string, maxLength : int, interger : boolean) : string
var character : string (1)
var cursorLoc : int := 0
var output : string := starting
var legalString : string := " ~!@#$%\^&*()_+`1234567890-=qwertyuiop[]\\asdfghjkl;'zxcvbnm,./QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?" %"<>+-,.[]"
var exit123 : boolean := false
if interger then
legalString := "1234567890"
end if
loop
if hasch then
getch (character )
if character = KEY_BACKSPACE then
if length (output ) > 0 and cursorLoc > 0 then
output := output (1 .. cursorLoc - 1) + output (cursorLoc + 1 .. *)
cursorLoc - = 1
end if
elsif character = KEY_DELETE then
if cursorLoc < length (output ) then
output := output (1 .. cursorLoc ) + output (cursorLoc + 2 .. *)
end if
elsif character = KEY_ENTER then
cursorLoc := 0
exit123 := true
elsif character = KEY_RIGHT_ARROW then
if cursorLoc < length (output ) then
cursorLoc + = 1
end if
elsif character = KEY_LEFT_ARROW then
if cursorLoc > 0 then
cursorLoc - = 1
end if
elsif character = KEY_HOME then
cursorLoc := 0
elsif character = KEY_END then
cursorLoc := length (output )
else
if length (output ) < maxLength and index (legalString, character ) not= 0 then
output := output (1 .. cursorLoc ) + character + output (cursorLoc + 1 .. *)
cursorLoc + = 1
end if
end if
end if
Text.Locate (Text.WhatRow, 1)
for i : 1 .. length (fieldName ) + length (output ) + 2
put " " ..
end for
Text.Locate (Text.WhatRow, 1)
put fieldName ..
for i : 1 .. cursorLoc - 1
put output (i ) ..
end for
if (Time.Elapsed div 500) mod 2 = 1 and exit123 = false then
if cursorLoc not= 0 then
put output (cursorLoc ) ..
end if
if cursorLoc = length (output ) then
put "|" ..
else
put "<" ..
end if
for i : cursorLoc + 2 .. length (output )
if i not= 0 then
put output (i ) ..
end if
end for
else
if cursorLoc not= 0 then
put output (cursorLoc ) ..
end if
for i : cursorLoc + 1 .. length (output )
if i not= 0 then
put output (i ) ..
end if
end for
end if
put " " ..
View.Update
Time.DelaySinceLast (100)
exit when exit123
end loop
if interger and strintok (output ) = false then
output := "0"
end if
put ""
result output
end getInput
proc executeCommand (toExe : string)
if toExe = "<" then
if _pointer = 0 then
_pointer := maxAddress
else
_pointer - = 1
end if
elsif toExe = ">" then
if _pointer = maxAddress then
_pointer := 0
else
_pointer + = 1
end if
elsif toExe = "+" then
if address (_pointer ) = 255 then
address (_pointer ) := 0
else
address (_pointer ) + = 1
end if
elsif toExe = "-" then
if address (_pointer ) = 0 then
address (_pointer ) := 255
else
address (_pointer ) - = 1
end if
elsif toExe = "," then
loop
Time.DelaySinceLast (100)
exit when hasch
end loop
getch (ch )
if ord (ch ) > 126 then
address (_pointer ) := 126
elsif ord (ch ) = 10 then
address (_pointer ) := 10
elsif ord (ch ) < 32 then
address (_pointer ) := 32
else
address (_pointer ) := ord (ch )
end if
elsif toExe = "." then
%put "Byte: ", address (_pointer), " " ..
if address (_pointer ) >= 32 and address (_pointer ) <= 126 or address (_pointer ) = 10 then
put chr (address (_pointer )) .. %put "Char: ", chr (address (_pointer))
else
%put ""
end if
View.Update
end if
end executeCommand
loop
put "Welcome to the Brainfuck Interpreter by Frank26080115"
View.Update
code := getInput ("Input Code: ", code, 250, false) + " "
put "Begin Execution (EXE to stop)"
put "Output:"
put "-----------------------------"
put ""
View.Update
_pointer := 0
for i : 0 .. 255
address (i ) := 0
end for
loopCounter := 0
location := 1
finished := false
loop
for i : location .. length (code )
_return := false
executeCommand (code (i )) %executes simple code
%these handle loops, loopCounter is used to
%deal with nested loops
if code (i ) = "[" then
if address (_pointer ) = 0 then
for j : i + 1 .. length (code )
if code (j ) = "[" then
loopCounter + = 1
elsif code (j ) = "]" then
if loopCounter = 0 then
exit
else
loopCounter - = 1
end if
end if
end for
end if
elsif code (i ) = "]" then
if address (_pointer ) > 0 then
for decreasing j : i - 1 .. 1
if code (j ) = "[" then
if loopCounter = 0 then
location := j
_return := true
exit
else
loopCounter - = 1
end if
end if
end for
end if
end if
if i = length (code ) then
finished := true
end if
if _return then
_return := false
exit
end if
Input.KeyDown (chars )
if chars (KEY_ESC) then
finished := true
exit
end if
end for
exit when finished
end loop
put ""
put ""
put "-----------------------------"
put "Finished Execution" ..
if chars (KEY_ESC) then
put " (User Interrupted)"
end if
put "\n"
end loop
|
for an example, "+[,.]" will become something like notepad, "+[.+]" will show all printable characters and then exit the loop, "+[.+.+]" will loop forever while printing all printable characters, have fun[/syntax] |