/var/log/life.log
Блог программиста из солнечной Бурятии

Brainfuck

Что-то взбрело в голову и решил написать интерпретатор Brainfuck’а 🙂 Вот что получилось:

Сам Интерпретатор

//BFInt.java
public class BFInt {
    /**
     * Указатель на текущую ячейку памяти
     */

    private int pointer;
    /**
     * Память
     */

    private Memory mem;
    /**
     * Текст Программы
     */

    private byte[] text;
    /**
     * Указатель на текущую инструкцию
     */

    private int pinst;
    /**
     * Выходная лента
     */

    private String out;
    /**
     * Входная лента
     */

    private String in;
    /**
     * Указатель на входной символ
     */

    private int pin;
    /**
     * Конструктор
     * @param s - тест программы
     * @param i - входная строка
     */

    public BFInt(String s, String i){
        mem = new Memory();
        pointer = 0;
        text = s.getBytes();
        in = i;
        out = "";
        pinst = 0;
    }
    /**
     * Переход на следующую ячейку памяти
     */

    private void nextCeil(){
        pointer++;
        pinst++;
    }
    /**
     * Переход на предыдущую ячейку памяти
     */

    private void prevCeil(){
        pointer--;
        pinst++;
    }
    /**
     * Увеличить значение на 1
     */

    private void incValue(){
        char cur = mem.getValue(pointer);
        mem.setValue(pointer,(char)((cur+1)%256));
        pinst++;
    }
    /**
     * Уменьшить значение на 1
     */

    private void decValue(){
        char cur = mem.getValue(pointer);
        mem.setValue(pointer,(char)((cur+255)%256));
        pinst++;
    }
    /**
     * поведение при чтении '['
     */

    private void goForrward(){
        char cur = mem.getValue(pointer);
        int count = 1;
        if (cur == 0){
            int i = pinst+1;
            for (; i < text.length; i++){
                if (text[i]=='[') {count++;}
                if (text[i]==']') {count--;}
                if (count == 0 )break;
            }
            pinst = i;
        } else {
            pinst++;
        }
    }
    /**
     * поведение при чтении ']'
     */

    private void goBack(){
        char cur = mem.getValue(pointer);
        int count = 1;
        if (cur != 0){
            int i = pinst-1;
            for (; i >= 0; i--){
                if (text[i]=='[') {count--;}
                if (text[i]==']') {count++;}
                if (count == 0 )break;
            }
            pinst = i;
        } else {
            pinst++;
        }
    }
    /**
     * Запись на выходную ленту
     */

    private void print(){
        char cur = mem.getValue(pointer);
        out += cur;
        pinst++;
    }
    /**
     * Чтение с входной ленты
     */

    private void read(){
        mem.setValue(pointer,in.charAt(pin));
        pin++;
        pinst++;
    }
    public String run(){
        while(pinst < text.length && pinst >=0){
            switch(text[pinst]){
                case '>':nextCeil();break;
                case '<':prevCeil();break;
                case '+':incValue();break;
                case '-':decValue();break;
                case '[':goForrward();break;
                case ']':goBack();break;
                case '.':print();break;
                case ',':read();break;
                default:System.out.println("Error");
            }
        }
        return out;
    }
}

И класс памяти, решил вот так реализовать.

//Memory.java
public class Memory {
    /**
     * Указатель на нулевую ячейку
     */

    private int pointerzero;
    /**
     * Память
     */

    private char[] memory;
    /**
     * Конструктор
     */

    public Memory(){
        pointerzero = 0;
        memory = new char [1]; 
    }
    /**
     * Геттер
     * @param pointer - указатель на ячейку, значение которой нужно получить
     * @return - значение ячейки, на которую указывает pointer
     */

    public char getValue(int pointer){
        int newpointer = pointerzero + pointer;
        if ( memory.length > newpointer && newpointer >= 0){
            return memory[newpointer];
        } else {
            char [] tmp = new char[(newpointer>0)?newpointer+1:memory.length+Math.abs(newpointer)];
            for (int i = 0; i < tmp.length; i++){
                tmp[i] = 0;
            }
            for (int i =0, k=(newpointer>0?0:Math.abs(newpointer)); i < memory.length; i++){
                tmp[k++] = memory[i];
            }
            memory = tmp;
            if (newpointer < 0 ){
                pointerzero += Math.abs(newpointer);
            }
            return 0;
        }
    }
    /**
     * Сеттер
     * @param pointer - указатель на ячейку
     * @param value - новое значение
     */

    public void setValue(int pointer,char value){
        int newpointer = pointerzero + pointer;
        if ( memory.length > newpointer && newpointer >= 0){
            memory[newpointer] = value;
        } else {
            char [] tmp = new char[(newpointer>0)?newpointer+1:memory.length+Math.abs(newpointer)];
            for (int i = 0; i < tmp.length; i++){
                tmp[i] = 0;
            }
            for (int i =0, k=(newpointer>0?0:Math.abs(newpointer)); i < memory.length; i++){
                tmp[k++] = memory[i];
            }
            memory = tmp;
            if (newpointer > 0){
                memory[newpointer] = value;
            } else {
                memory[0] = value;
                pointerzero += Math.abs(newpointer);
            }
        }
    }
}

Оставить комментарий

Вы так же можете оставить комментарий используя ваш OpenId, для этого нужно войти.