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

Brainfuck

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//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;
    }
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//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);
            }
        }
    }
}