我一直在为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。
最好的设计是什么?任何帮助都会很棒,谢谢!
经过大量研究,我相信我找到了答案。
实现树积累的方法将是我的设计的最佳想法之一。事实上,为此,我们只会使用向上累积的方法,其中每个节点(在本例中为我的 Stmts(都有关于其十进点的信息。
在这种情况下,对于提到的 AST:
1. LoopStmt
2. IfStmt
3. IfStmt
4. BreakStmt
...
我们需要做的就是将#4 Stmt
的信息存储(或积累(到#3 Stmt
中,将#3
的信息存储(或积累(到#2
中,最后#2
到#1
中。然后,我们将递归地将语句的执行分解到最近的循环。
我希望我能帮助任何人!