2017-08-19 46 views
1

我有以下Brainfuck解释器通过最小测试套件。除了像打印斐波那契序列这样的大问题似乎失败(套件中的最后一个测试)。我解释失误执行的brainfuck斐波那契代码是从http://esoteric.sange.fi/brainfuck/bf-source/prog/fibonacci.txt我的解释有什么问题? 这里是一个小提琴:https://jsfiddle.net/rt017kpz/Brainfuck解释器错误行为

function brainLuck(code, input) { 
 
    // "Infinite" heap of memory initialized as 0 for bf to store program values 
 
    let data = new Proxy([], {get: (arr, i) => arr[i] ? arr[i] : 0 }) 
 
    let ptr = 0; 
 
    let inputPtr = 0; 
 
    let codePtr = 0; 
 
    let output = ''; 
 
    let loopStack = [] 
 

 
    const op = { 
 
    '+' :() => { 
 
     if (data[ptr] === 255) { data[ptr] = 0; } 
 
     else { data[ptr]++; } 
 
     codePtr++; 
 
    }, 
 
    '-' :() => { 
 
     if (data[ptr] === 0) { data[ptr] = 255; } 
 
     else { data[ptr]--; } 
 
     codePtr++; 
 
    }, 
 
    '.' :() => { 
 
     output += String.fromCharCode(data[ptr]); 
 
     codePtr++; 
 
    }, 
 
    ',' :() => { 
 
     data[ptr] = input.charCodeAt(inputPtr++); 
 
     codePtr++; 
 
    }, 
 
    '>' :() => { 
 
     ptr++; codePtr++; 
 
    }, 
 
    '<' :() => { 
 
     if (ptr > 0) { ptr--; } 
 
     codePtr++; 
 
    }, 
 
    '[' :() => { 
 
     if (data[ptr] === 0) { 
 
     while(code[codePtr] !== ']') codePtr++; 
 
     } else { 
 
     loopStack.unshift(codePtr); 
 
     } 
 
     codePtr++ 
 
    }, 
 
    ']' :() => { 
 
     if (data[ptr] === 0) { loopStack.shift(); } 
 
     else { codePtr = loopStack[0] } 
 
     codePtr++ 
 
    } 
 
    } 
 

 
    while(codePtr < code.length) { 
 
    if(op[code[codePtr]]) op[code[codePtr]]() 
 
    else codePtr++ 
 
    } 
 
    return output; 
 
} 
 

 

 

 
////////// TESTS ////////////// 
 

 
it('handles `+` and `.` operants',() => { 
 
    expect(
 
    brainLuck('+++.') 
 
).to.equal(
 
    String.fromCharCode(3) 
 
) 
 
}) 
 

 
it('handles `-` operant and underflows from 0 to 255',() => { 
 
    expect(
 
    brainLuck('+++----.') 
 
).to.equal(
 
    String.fromCharCode(255) 
 
) 
 
}) 
 

 
it('handles `,` the input operand',() => { 
 
    expect(
 
    brainLuck(',.', 'A') 
 
).to.equal(
 
    'A' 
 
) 
 
}) 
 

 
it('handles input in conjuction with arithmetic',() => { 
 
    expect(
 
    brainLuck(',+.', 'A') 
 
).to.equal(
 
    'B' 
 
) 
 
}) 
 

 
it('handles looping (`[`, `]`) and shift (`<`, `>`) operants',() => { 
 
    expect(
 
    brainLuck(',>+++[<.>-]', 'A') 
 
).to.equal(
 
    'AAA' 
 
) 
 
}) 
 

 
it('only parses known symbols',() => { 
 
    expect(
 
    brainLuck(',nothing>++else+[<.>matters!-]', 'A') 
 
).to.equal(
 
    'AAA' 
 
) 
 
}) 
 

 
it('handles nested loops',() => { 
 
    expect(
 
    brainLuck(',>+++[->+++[<<.>>-]<]', 'A') 
 
).to.equal(
 
    'AAAAAAAAA' 
 
) 
 
}) 
 

 
it('can multiply two numbers',() => { 
 
    expect(
 
    brainLuck(',>,<[>[->+>+<<]>>[-<<+>>]<<<-]>>.', String.fromCharCode(8,9)) 
 
).to.equal(
 
    String.fromCharCode(72) 
 
) 
 
}) 
 

 
it('can print the fibonacci sequence',() => { 
 
    expect(
 
    brainLuck('++++>+>>>>++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++<<<<<<[>[>>>>>>+>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<[>++++++++++[-<-[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<[>>>+<<<-]>>[-]]<<]>>>[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<+>>[-]]<<<<<<<]>>>>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]++++++++++<[->-<]>++++++++++++++++++++++++++++++++++++++++++++++++.[-]<<<<<<<<<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<-[>>.>.<<<[-]]<<[>>+>+<<<-]>>>[<<<+>>>-]<<[<+>-]>[<+>-]<<<-]') 
 
).to.equal(
 
    '1, 1, 2, 3' 
 
) 
 
}) 
 

 

 
mocha.run();
<html> 
 
<head> 
 
    <meta charset="utf-8"> 
 
    <title>Mocha Tests</title> 
 
    <link href="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.css" rel="stylesheet" /> 
 
</head> 
 
<body> 
 
    <div id="mocha"></div> 
 
    <script src="https://cdn.rawgit.com/Automattic/expect.js/0.3.1/index.js"></script> 
 
    <script src="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.js"></script> 
 
    <script>mocha.setup('bdd')</script> 
 
</body> 
 
</html>

+0

您是否尝试过通过代码在调试器步进找出它可能是什么? * *测试失败了吗?它会“崩溃”吗?意想不到的结果?还有别的吗? –

+0

感谢您的回应,如果您运行我的代码片段,您可以看到'错误:预期':',等于'1,1,2,3''。至于使用调试器进行调试,我已经尝试过,但是bf代码是如此严重混淆。到目前为止我没有运气。斐波那契bf代码非常大。不幸的是,这是我唯一知道的不能正确执行的人。 –

+0

你的']'实现是否正确?我希望看到像'if(data [ptr]!== 0){while(code [codePtr]!=='[')codePtr - ;'(我认为可能没关系)数组作为堆栈)。 –

回答

2

你实现[搜索第一],而不是匹配],这可能是第二,第三,第四等]符号。扫描时需要对它们进行计数。下面的代码片段有[的实现,这样做,和FIB测试现在工作:

function brainLuck(code, input) { 
 
    // "Infinite" heap of memory initialized as 0 for bf to store program values 
 
    let data = new Proxy([], {get: (arr, i) => arr[i] ? arr[i] : 0 }) 
 
    let ptr = 0; 
 
    let inputPtr = 0; 
 
    let codePtr = 0; 
 
    let output = ''; 
 
    let loopStack = [] 
 

 
    const op = { 
 
    '+' :() => { 
 
     if (data[ptr] === 255) { data[ptr] = 0; } 
 
     else { data[ptr]++; } 
 
     codePtr++; 
 
    }, 
 
    '-' :() => { 
 
     if (data[ptr] === 0) { data[ptr] = 255; } 
 
     else { data[ptr]--; } 
 
     codePtr++; 
 
    }, 
 
    '.' :() => { 
 
     output += String.fromCharCode(data[ptr]); 
 
     codePtr++; 
 
    }, 
 
    ',' :() => { 
 
     data[ptr] = input.charCodeAt(inputPtr++); 
 
     codePtr++; 
 
    }, 
 
    '>' :() => { 
 
     ptr++; codePtr++; 
 
    }, 
 
    '<' :() => { 
 
     if (ptr > 0) { ptr--; } 
 
     codePtr++; 
 
    }, 
 
    '[' :() => { 
 
     if (data[ptr] === 0) { 
 
     let level = 0; 
 
     while(code[codePtr] !== ']' || level > 1) { 
 
      if (code[codePtr] === '[') 
 
       level += 1; 
 
      if (code[codePtr] === ']') 
 
       level -= 1; 
 
      codePtr++; 
 
     } 
 
     } else { 
 
     loopStack.unshift(codePtr); 
 
     } 
 
     codePtr++ 
 
    }, 
 
    ']' :() => { 
 
     if (data[ptr] === 0) { loopStack.shift(); } 
 
     else { codePtr = loopStack[0] } 
 
     codePtr++ 
 
    } 
 
    } 
 

 
    while(codePtr < code.length) { 
 
    if(op[code[codePtr]]) op[code[codePtr]]() 
 
    else codePtr++ 
 
    } 
 
    return output; 
 
} 
 

 

 

 
////////// TESTS ////////////// 
 

 
it('handles `+` and `.` operants',() => { 
 
    expect(
 
    brainLuck('+++.') 
 
).to.equal(
 
    String.fromCharCode(3) 
 
) 
 
}) 
 

 
it('handles `-` operant and underflows from 0 to 255',() => { 
 
    expect(
 
    brainLuck('+++----.') 
 
).to.equal(
 
    String.fromCharCode(255) 
 
) 
 
}) 
 

 
it('handles `,` the input operand',() => { 
 
    expect(
 
    brainLuck(',.', 'A') 
 
).to.equal(
 
    'A' 
 
) 
 
}) 
 

 
it('handles input in conjuction with arithmetic',() => { 
 
    expect(
 
    brainLuck(',+.', 'A') 
 
).to.equal(
 
    'B' 
 
) 
 
}) 
 

 
it('handles looping (`[`, `]`) and shift (`<`, `>`) operants',() => { 
 
    expect(
 
    brainLuck(',>+++[<.>-]', 'A') 
 
).to.equal(
 
    'AAA' 
 
) 
 
}) 
 

 
it('only parses known symbols',() => { 
 
    expect(
 
    brainLuck(',nothing>++else+[<.>matters!-]', 'A') 
 
).to.equal(
 
    'AAA' 
 
) 
 
}) 
 

 
it('handles nested loops',() => { 
 
    expect(
 
    brainLuck(',>+++[->+++[<<.>>-]<]', 'A') 
 
).to.equal(
 
    'AAAAAAAAA' 
 
) 
 
}) 
 

 
it('can multiply two numbers',() => { 
 
    expect(
 
    brainLuck(',>,<[>[->+>+<<]>>[-<<+>>]<<<-]>>.', String.fromCharCode(8,9)) 
 
).to.equal(
 
    String.fromCharCode(72) 
 
) 
 
}) 
 

 
it('can print the fibonacci sequence',() => { 
 
    expect(
 
    brainLuck('++++>+>>>>++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++<<<<<<[>[>>>>>>+>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<[>++++++++++[-<-[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<[>>>+<<<-]>>[-]]<<]>>>[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<+>>[-]]<<<<<<<]>>>>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]++++++++++<[->-<]>++++++++++++++++++++++++++++++++++++++++++++++++.[-]<<<<<<<<<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<-[>>.>.<<<[-]]<<[>>+>+<<<-]>>>[<<<+>>>-]<<[<+>-]>[<+>-]<<<-]') 
 
).to.equal(
 
    '1, 1, 2, 3' 
 
) 
 
}) 
 

 

 
mocha.run();
<html> 
 
<head> 
 
    <meta charset="utf-8"> 
 
    <title>Mocha Tests</title> 
 
    <link href="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.css" rel="stylesheet" /> 
 
</head> 
 
<body> 
 
    <div id="mocha"></div> 
 
    <script src="https://cdn.rawgit.com/Automattic/expect.js/0.3.1/index.js"></script> 
 
    <script src="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.js"></script> 
 
    <script>mocha.setup('bdd')</script> 
 
</body> 
 
</html>