Skip to content

Instantly share code, notes, and snippets.

@jiftechnify
Last active November 28, 2023 14:36
Show Gist options
  • Save jiftechnify/93adda96345ca140ff61db4c8653ce73 to your computer and use it in GitHub Desktop.
Save jiftechnify/93adda96345ca140ff61db4c8653ce73 to your computer and use it in GitHub Desktop.
package bfinterp
import scala.collection.mutable
import scala.io.StdIn
object PlainOldBrainfuckInterpreter {
private def printChar(i: Int): Unit = {
print(i.toChar)
}
private def readChar(): Int = {
print("[pobf] Input a character: ")
StdIn.readChar().toInt
}
private def lookupBracketsPair(program: String): Option[List[(Int, Int)]] = {
def loop(p: String, i: Int, open: List[Int], brackets: List[(Int, Int)]): Option[List[(Int, Int)]] = {
if (p.isEmpty) {
if (open.isEmpty) Some(brackets)
else None
}
else p.head match {
case '[' => loop(p.tail, i+1, i :: open, brackets)
case ']' =>
if (open.isEmpty) None
else loop(p.tail, i+1, open.tail, (open.head, i) :: brackets)
case _ => loop(p.tail, i+1, open, brackets)
}
}
loop(program, 0, List(), List())
}
def interpret(program: String): Unit = {
def loopEnd(ps: List[(Int, Int)], i: Int): Int = ps.find(_._1 == i).get._2 + 1
def loopBegin(ps: List[(Int, Int)], i: Int): Int = ps.find(_._2 == i).get._1 + 1
def go(pc: Int, reg: mutable.ArrayBuffer[Int], ptr: Int, brackets: List[(Int, Int)]): Unit = {
if (pc < program.length) {
program(pc) match {
case '>' => go(pc+1, reg, ptr+1, brackets)
case '<' => go(pc+1, reg, ptr-1, brackets)
case '+' => reg(ptr) += 1; go(pc+1, reg, ptr, brackets)
case '-' => reg(ptr) -= 1; go(pc+1, reg, ptr, brackets)
case '.' => printChar(reg(ptr)); go(pc+1, reg, ptr, brackets)
case ',' => reg(ptr) = readChar(); go(pc+1, reg, ptr, brackets)
case '[' =>
if (reg(ptr) == 0)
go(loopEnd(brackets, pc), reg, ptr, brackets)
else
go(pc+1, reg, ptr, brackets)
case ']' =>
if (reg(ptr) != 0)
go(loopBegin(brackets, pc), reg, ptr, brackets)
else
go(pc+1, reg, ptr, brackets)
case _ =>
}
}
}
val brackets = lookupBracketsPair(program)
brackets match {
case Some(ps) =>
go(0, mutable.ArrayBuffer.fill(n = 32768)(0), 0, ps)
case None =>
Console.err.println("[pobf] Something wrong in your program!")
}
}
}
object PlainOldBrainfuckInterpreterDemo {
def main(args: Array[String]): Unit = {
PlainOldBrainfuckInterpreter.interpret("++++>++><<[->[->>+<<]>>[-<+<+>>]<<<]>>++++++++++++++++++++++++++++++++++++++++++++++++.")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment