文档章节

Brainfuck解释器

__赵小刚__
 __赵小刚__
发布于 2016/12/22 00:57
字数 646
阅读 51
收藏 1

Brainfuck 语如其名,作为最脑残的编程语言(可能没有之一),它却是最有bigger的玩具,绝对是内涵吐槽、暗恋表白的利器。

Brainfuck C
> ++ptr;
< --ptr;
+ ++*ptr;
- --*ptr;
. putchar(*ptr);
, *ptr =getchar();
[ while (*ptr) {
] }

下面是我写的一段BF代码,需在LANG="zh_CN.UTF-8"的环境运行方能正常显示中文

        +
       +[-
      >++++
     +[->+++
    ++<]<]>>.
   --.+.++++++
  .[->++++>+++>
 +++<<<]++++[->+
    ++<]>.>--
   --.<<+++[->
  >-------<<]>>
 .<---.>>.>++++[
-<++++++>]<.<<+++
.>>++.<++++.[->-<]
       +++
       ++[
 ->--->++<<]>+.>.

我写了一个Brainfuck的解释器,它的特点是:

    没有限制内存大小

    逗号指令(getchar)读取到文件结束符EOF时不设置*ptr (这个和“标准”不太一样,“标准”会设为-1)

#include <cstdio>
#include <cstring>

class autobuf_t {
public:
    enum {
        BLOCK_SIZE = 64
    };

    autobuf_t() {
        len = BLOCK_SIZE * 2;

        buf = new char[len];
        memset(buf, 0, len);

        now = buf + BLOCK_SIZE;
    }

    ~autobuf_t() {
        delete buf;
    }

    void left() {
        if (now == buf) {
            char * p = new char[len + BLOCK_SIZE];
            memset(p, 0, BLOCK_SIZE);
            memcpy(p + BLOCK_SIZE, buf, len);
            delete buf;

            buf = p;
            now = p + BLOCK_SIZE;
            len += BLOCK_SIZE;
        }
        now--;
    }

    void right() {
        if (now + 1 == buf + len) {
            char * p = new char[len + BLOCK_SIZE];
            memcpy(p, buf, len);
            memset(p + len, 0, BLOCK_SIZE);
            delete buf;

            buf = p;
            now = p + len - 1;
            len += BLOCK_SIZE;
        }
        now++;
    }

    void increment() {
        ++*now;
    }

    void decrement() {
        --*now;
    }

    bool getch(FILE * f) {
       int c = fgetc(f);
       if (c != EOF)
           *now = c;
       return c != EOF;
    }

    void putch(FILE * f) {
        fputc(*now, f);
    }

    char val() {
        return *now;
    }

private:
    autobuf_t(const autobuf_t&);
    void operator = (const autobuf_t&);

    char * buf;
    char * now;
    size_t len;
};

class bfsrc_t {
public:
    bfsrc_t(const char * fname):buf(NULL),jump_tbl(NULL) {
        memset(errbuf, 0, sizeof(errbuf));

        FILE * f = fopen(fname, "r");
        if (f == NULL) {
            snprintf(errbuf, sizeof(errbuf), "Failed to open file");
            return;
        }

        fseek(f, 0, SEEK_END);
        size_t fsize = ftell(f);
        buf = new char[fsize + 1];

        fseek(f, 0, SEEK_SET);
        fread(buf, fsize, 1, f);
        fclose(f);

        buf[fsize] = 0;
        preprocess();
    }

    ~bfsrc_t() {
        delete buf;
        delete [] jump_tbl;
    }

    const char * error() {
        return errbuf[0] ? errbuf : NULL;
    }

    const char * c_str() {
        return errbuf[0] ? NULL : buf;
    }

    const char * jump(int * jid) {
        int j = *jid;
        *jid = jump_tbl[j].jump_id;
        return jump_tbl[*jid].pos;
    }

private:
    bfsrc_t(const bfsrc_t&);
    void operator = (const bfsrc_t&);

    struct jump_node_t {
        const char * pos;
        int line;
        int column;
        int jump_id;
    };

    void preprocess() {
        int n = 0;
        for (const char *p = buf; *p; p++) {
            if (*p == '[' || *p == ']')
                n++;
        }

        if (n == 0)
            return;

        jump_tbl = new jump_node_t[n];

        int line = 1;
        int column = 0;
        int i = 0;
        for (const char *p = buf; *p; p++) {
            column++;
            if (*p == '[' || *p == ']') {
                jump_tbl[i].pos = p;
                jump_tbl[i].line = line;
                jump_tbl[i].column = column;
                jump_tbl[i].jump_id = -1;
                i++;
            } else if (*p == '\n') {
                line++;
                column = 0;
            }
        }

        for (i = 0; i < n; i++) {
            if (jump_tbl[i].jump_id != -1)
                continue;

            int direction = (jump_tbl[i].pos[0] == '[') ? 1 : -1;
            int count = 1;
            for (int x = i + direction; x >= 0 && x < n; x += direction) {
                if (jump_tbl[x].pos[0] == jump_tbl[i].pos[0]) {
                    count++;
                } else {
                    count--;
                    if (count == 0) {
                        jump_tbl[i].jump_id = x;
                        jump_tbl[x].jump_id = i;
                        break;
                    }
                }
            }
        }

        for (i = 0; i < n; i++) {
            if (jump_tbl[i].jump_id == -1) {
                snprintf(errbuf, sizeof(errbuf), "[] unmatched @ line:%d column:%d", jump_tbl[i].line, jump_tbl[i].column);
                break;
            }
        }
    }

    char * buf;
    jump_node_t * jump_tbl;
    char errbuf[64];
};

int main(int argc, char *argv[])
{
    if (argc != 2) {
        printf("Usage: %s <brainfuck_src>\n", argv[0]);
        return 1;
    }

    bfsrc_t code(argv[1]);
    if (code.error()) {
        printf("%s\n", code.error());
        return 2;
    }

    autobuf_t v;

    int jump_id = -1;
    for (const char * p = code.c_str(); *p; p++) {
        switch (*p) {
            case '<' : v.left(); break;
            case '>' : v.right(); break;
            case '+' : v.increment(); break;
            case '-' : v.decrement(); break;
            case '.' : v.putch(stdout); fflush(stdout); break;
            case ',' : v.getch(stdin); break;
            case '[' :
                jump_id++;
            loop :
                if (v.val() == 0)
                    p = code.jump(&jump_id);
                break;
            case ']' :
                jump_id++;
                p = code.jump(&jump_id);
                goto loop;
        }
    }

    return 0;
}

 

© 著作权归作者所有

共有 人打赏支持
__赵小刚__
粉丝 5
博文 40
码字总数 19077
作品 0
成都
程序员
私信 提问
Brainfuck语言编译器--awib

如果你觉得用C语言来实现BrainFuck语言的解释器是对BrainFuck这种语言的一种侮辱的话,我们的BrainFuck社区是绝对不能容忍你有这种想法的。因为我们有一个使用100%纯brainfuck写成的一个Bra...

匿名
2009/07/14
3.1K
0
BrainFuck下的HappyNewYear

今天看了下一个语言叫BrainFuck,写了个打印“Happy New Year!”的程序 (今天是2015年1月1日,顺便祝大家新年快乐哈) 1.写在前面 BrainFuck的主页在: http://www.muppetlabs.com/~breadbo...

北风其凉
2015/01/01
0
0
C语言实现的轻量级brainfuck语言解释器

知道brainfuck的时候是在大一下学期的时候了,一直觉得这语言好神奇,但是觉得实现的功能应该有限。直到最近想要做一个小的解释器才开始深入了解和研究。 Brainfuck语言,因为其中带有脏话,...

冰雪飞扬
2013/01/20
0
3
Boost.Spirit+LLVM,双剑合璧开发一个脑残编译器

周末闲来无事,打算拿LLVM构造一个小程序练练手,正巧我最近在玩Brainfuck语言,所以决定拿LLVM构造一个Brainfuck的编译器。 一个典型的编译器分为几个部分: Lex/Parse,构造AST 将AST转换为...

Windoze
2012/09/10
2.2K
1
然并卵:BF 科普 & BF 解释器的 JS 实现

最近在 Codewars上做练习,某道题的内容是实现一个 brainFuck(简称BF语言) 解释器(c/python/js等等均可)。动手实践的过程还是很有趣的,中间也遇到了各种各样的问题,最终通过测试,代码...

parksben
08/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

php获取客户端IP

php获取客户端IP 首先先阅读关于IP真实性安全的文章:如何正確的取得使用者 IP? 「任何從客戶端取得的資料都是不可信任的!」 HTTP_CLIENT_IP头是有的,但未成标准,不一定服务器都实现。 ...

DrChenXX
昨天
0
0
. The valid characters are defined in RFC 7230 and RFC 问题

通过这里的回答,我们可以知道: Tomcat在 7.0.73, 8.0.39, 8.5.7 版本后,添加了对于http头的验证。 具体来说,就是添加了些规则去限制HTTP头的规范性 参考这里 具体来说: org.apache.tom...

west_coast
昨天
1
0
刷leetcode第704题-二分查找

今天双十一买的算法书到货了,路上刷到有人说的这个题,借(chao)鉴(xi)一下别人的思路,这个是C++标准库里面的经典方法,思路精巧,优雅好品味 int search(int* nums, int numsSize, in...

锟斤拷烫烫烫
昨天
2
0
【分享实录】BANCOR算法详解及代码实现

1 活动基本信息 1)主题:【区块链技术工坊22期】BANCOR算法详解及代码实现 2)议题: BANCOR算法的特点和优劣势 BANCOR算法和举例 如何加入BANCOR.NETWORK交易所 如何开发自己的BANCOR去中心...

HiBlock
昨天
2
0
微信小程序(2)

开始看微信小程序的教程了。刚刚看完官方教程的视图层部分。这里摘录一些自己认为的部分关键点。 1.直接修改数值无法重新渲染,需要使用setData()方法; 2.列表渲染中:wx:key用于保持项目在...

MKjy
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部