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;
}
}
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);
}
}
}
}
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);
}
}
}
}