在解释器上实现break语句的最佳方法是什么?

时间:2017-05-24 21:03:54

标签: interpreter brainfuck compiler-construction

我一直在为Brain(类似Brainfuck的语言)开发一名翻译,并且对休息语句的设计有一些担忧。

考虑JS中的以下代码:

var Stmt = (function() {
  var Stmt = function() {};
    Stmt.prototype = {
      update_expression: function(update) { return false; },
      value: function() { return this; },
      exec: function(delegate) { },
      zerofy: function (tapeObj) {
        if (tapeObj.data[tapeObj.d_ptr] === undefined) {
          tapeObj.data[tapeObj.d_ptr] = 0;
      }
    }
  };

  return Stmt;
})();

var BreakStmt = (function() {
  var BreakStmt = function(){ };
  BreakStmt.prototype = Object.create(Stmt.prototype);
  return BreakStmt;
})();

var LoopStmt = (function() {
  var LoopStmt = function(stmts, type) {
    this.type = 'undefined';
    this.stmts = null;

    if (tokens[type] === 'TT_BEGIN_WHILE'
      || tokens[type] === 'TT_BEGIN_FOR') {
      this.type = type;
      this.stmts = stmts;
    }
  };

  LoopStmt.prototype = Object.create(Stmt.prototype);
  return LoopStmt;
})();

var IfStmt = (function() {
  var IfStmt = function(stmts_then) {
    this.stmts_then = stmts_then;
    this.stmts_else = null;
  };

  IfStmt.prototype = Object.create(Stmt.prototype);
  IfStmt.prototype.set_else = function(stmts_else) {
      this.stmts_else = stmts_else;
  };

  return IfStmt;
})();

解析器将递归遍历语句,然后返回AST。现在想象一下AST,其中包含以下语句:

LoopStmt
  IfStmt
    IfStmt
      BreakStmt
...

元素exec函数也是递归的。尽管对这个实现有很多想法,经过大量的研究,我仍然无法找到如何递归地停止这种递归的最佳方法(如果这有意义),直到找到最近的LoopStmt。 / p>

最好的设计是什么? 任何帮助都会很棒,谢谢!

1 个答案:

答案 0 :(得分:0)

经过大量研究,我相信我找到了答案。

实施tree accumulation的方法对我的设计来说是最好的想法。事实上,为此,我们只会使用向上累积的方法,其中每个节点(在本例中我的 Stmts )都有关于其后代的信息。

在这种情况下,对于上面提到的AST:

1. LoopStmt 
2.  IfStmt
3.    IfStmt
4.      BreakStmt
   ...

我们需要做的就是将#4 Stmt的信息存储(或累积)到#3 Stmt,将#3的信息存储到#2,最后#2进入#1。然后我们会递归地将语句的执行中断到最近的循环。

我希望我会帮助任何人!