Skip to content

Instantly share code, notes, and snippets.

@0xa
Created July 24, 2012 23:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0xa/3173315 to your computer and use it in GitHub Desktop.
Save 0xa/3173315 to your computer and use it in GitHub Desktop.
BrainFUUU
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <exception>
#define LOOP_STACK_SIZE 64
#define DATA_BUFFER_SIZE 1024
class BrainFUUU {
public:
class FileException : public std::exception {};
class CodeBufferException : public std::exception {};
BrainFUUU(const char* filename)
: m_codeBufferSize(0)
, m_codeBuffer(NULL)
, m_codePointer(NULL)
, m_dataBufferSize(DATA_BUFFER_SIZE)
, m_dataBuffer(NULL)
, m_dataPointer(NULL)
, m_loopStackSize(0)
{
FILE* handler = fopen(filename, "r");
if (!handler) {
perror("Cannot open file");
return;
}
fseek(handler, 0, SEEK_END);
m_codeBufferSize = ftell(handler);
m_codeBuffer = new char[m_codeBufferSize];
fseek(handler, 0, SEEK_SET);
fread(m_codeBuffer, 1, m_codeBufferSize, handler);
m_codePointer = m_codeBuffer;
fclose(handler);
}
void setDataBufferSize(uint s) {
m_dataBufferSize = s;
}
bool checkSyntax() {
int loops = 0;
uint i;
for(m_codePointer = m_codeBuffer;
m_codePointer < m_codeBuffer+m_codeBufferSize;
m_codePointer++) {
switch(*m_codePointer) {
case '[':
loops++;
break;
case ']':
loops--;
break;
}
}
if (loops < 0) {
printf("Syntax error: unexpected ']'\n");
return false;
}
if (loops > 0) {
printf("Syntax error: Unclosed loop\n");
return false;
}
return true;
}
bool exec() {
m_dataBuffer = new char[m_dataBufferSize];
m_dataPointer = m_dataBuffer;
for(m_codePointer = m_codeBuffer;
m_codePointer < m_codeBuffer+m_codeBufferSize;
m_codePointer++) {
if (!execCommand()) {
return false;
}
}
delete[] m_dataBuffer;
m_dataBuffer = NULL;
}
~BrainFUUU() {
if (m_codeBuffer) {
delete[] m_codeBuffer;
}
}
private:
bool checkDataPointer() {
if (m_dataPointer < m_dataBuffer) {
printf("Data error: Buffer underflow\n");
return false;
}
if (m_dataPointer > m_dataBuffer+m_dataBufferSize) {
printf("Data error: Buffer overflow\n");
return false;
}
return true;
}
bool checkLoopStackId() {
if (m_loopStackSize < 0) {
printf("Loop error: Stack underflow\n");
return false;
}
if (m_loopStackSize > LOOP_STACK_SIZE) {
printf("Loop error: Stack overflow\n");
return false;
}
return true;
}
bool execCommand() {
switch(*m_codePointer) {
case '>':
++m_dataPointer;
break;
case '<':
--m_dataPointer;
break;
case '+':
if (!checkDataPointer()) {
return false;
}
++*m_dataPointer;
break;
case '-':
if (!checkDataPointer()) {
return false;
}
--*m_dataPointer;
break;
case '.':
putchar(*m_dataPointer);
break;
case ',':
(*m_dataPointer) = getchar();
break;
case '[':
m_loopStackSize++;
if (!checkLoopStackId()) {
return false;
}
m_loopStack[m_loopStackSize] = m_codePointer;
break;
case ']':
if (*m_dataPointer != 0) {
m_codePointer = m_loopStack[m_loopStackSize];
break;
}
m_loopStackSize--;
if (!checkLoopStackId()) {
return false;
}
break;
//default:
// Comment
}
return true;
}
uint m_codeBufferSize;
char* m_codeBuffer;
char* m_codePointer;
uint m_dataBufferSize;
char* m_dataBuffer;
char* m_dataPointer;
uint m_loopStackSize;
char* m_loopStack[LOOP_STACK_SIZE];
};
void usage() {
printf("BrainFUUU: brainfuuu <filename> [--buffer <size>]\n");
exit(1);
}
int main(int argc, char **argv) {
char* filename = NULL;
uint bufferSize = 0;
int i = 1;
while(i < argc) {
if (strcmp(argv[i], "--buffer") == 0) {
i++;
if (i > argc) {
usage();
}
bufferSize = atoi(argv[i]);
} else {
filename = argv[i];
}
i++;
}
if (filename == NULL) {
usage();
}
BrainFUUU o(filename);
if (bufferSize > 0) {
o.setDataBufferSize(bufferSize);
}
if (!o.checkSyntax()) {
return 1;
}
if (!o.exec()) {
return 1;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment