a brainfuck parser in swift

To write a Brainfuck parser in Swift, you can follow these steps:

  1. Define the Brainfuck language syntax and the instructions set.
main.swift
enum BrainfuckInstruction: String {
    case moveRight = ">"
    case moveLeft = "<"
    case increment = "+"
    case decrement = "-"
    case input = ","
    case output = "."
    case jumpForward = "["
    case jumpBackward = "]"
}
235 chars
11 lines
  1. Define the Brainfuck data memory.
main.swift
class BrainfuckMemory {
    private var memory: [Int]
    private var pointer: Int = 0
    
    init(size: Int) {
        memory = Array(repeating: 0, count: size)
    }
    
    func increment() {
        memory[pointer] += 1
    }
    
    func decrement() {
        memory[pointer] -= 1
    }
    
    func moveRight() {
        pointer += 1
    }
    
    func moveLeft() {
        pointer -= 1
    }
    
    func getInput() -> Int {
        return Int(readLine()!)!
    }
    
    func setOutput(_ value: Int) {
        print(Character(UnicodeScalar(value)!), terminator: "")
    }
    
    func getValue() -> Int {
        return memory[pointer]
    }
    
    func setValue(_ value: Int) {
        memory[pointer] = value
    }
}
738 chars
41 lines
  1. Implement the Brainfuck interpreter.
main.swift
func interpret(code: String, input: String = "") {
    let memory = BrainfuckMemory(size: 30000)
    var codeIndex = code.startIndex
    var inputIndex = input.startIndex
    
    while codeIndex < code.endIndex {
        switch code[codeIndex] {
        case BrainfuckInstruction.increment.rawValue:
            memory.increment()
        case BrainfuckInstruction.decrement.rawValue:
            memory.decrement()
        case BrainfuckInstruction.moveRight.rawValue:
            memory.moveRight()
        case BrainfuckInstruction.moveLeft.rawValue:
            memory.moveLeft()
        case BrainfuckInstruction.input.rawValue:
            memory.setValue(memory.getInput())
        case BrainfuckInstruction.output.rawValue:
            memory.setOutput(memory.getValue())
        case BrainfuckInstruction.jumpForward.rawValue:
            if memory.getValue() == 0 {
                var bracketCount = 0
                while true {
                    codeIndex = code.index(after: codeIndex)
                    if code[codeIndex] == BrainfuckInstruction.jumpForward.rawValue {
                        bracketCount += 1
                    } else if code[codeIndex] == BrainfuckInstruction.jumpBackward.rawValue {
                        if bracketCount == 0 {
                            break
                        } else {
                            bracketCount -= 1
                        }
                    }
                }
            }
        case BrainfuckInstruction.jumpBackward.rawValue:
            if memory.getValue() != 0 {
                var bracketCount = 0
                while true {
                    codeIndex = code.index(before: codeIndex)
                    if code[codeIndex] == BrainfuckInstruction.jumpBackward.rawValue {
                        bracketCount += 1
                    } else if code[codeIndex] == BrainfuckInstruction.jumpForward.rawValue {
                        if bracketCount == 0 {
                            break
                        } else {
                            bracketCount -= 1
                        }
                    }
                }
            }
        default:
            break
        }
        
        codeIndex = code.index(after: codeIndex)
    }
}
2264 chars
59 lines

You can now use the interpret function to run any Brainfuck code.

main.swift
let code = "++++[>+++[>+++<-]<-]>>."
interpret(code: code)
59 chars
3 lines

This would output the ASCII character T.

gistlibby LogSnag