我正在尝试使用DFS方法编写通用的AST构建器。
语法的原理很简单:一个表达式可以具有一个或多个选项,每个选项都由节点列表组成,其中每个节点可以是终结符或表达式。
我的状态正常,但是正在为“无穷循环”寻找退出条件。
如果我这样定义语法:
expr := addExpr;
addExpr := NUMBER
| NUMBER OPERATOR expr
;
它通过。该结构在语义上是正确的,但是遍历时将产生错误的结果。将“ 4-2 + 2”计算为“ 4-(2 + 2)”,而不是所需的“(4-2)+ 2”。
我需要这样定义语法:
expr := addExpr;
addExpr := NUMBER
| expr OPERATOR NUMBER
;
这里的问题是,它导致无休止的迭代:
expr -> addExpr -> expr -> addExpr -> ...
这就是我被困住的地方。关于何时停止尝试,我无法提出退出条件。我当时想拥有一个历史,如果我将相同的表达式与其余标记进行比较,我可以停下来。但这停止得太早了,不会产生任何结果。
我想我需要的堆栈看起来像这样:
expr (against 4 - 2 + 2)
addExpr (against 4 - 2 + 2)
0: NUMBER -> matches 4, won't finish.
1: expr OPERATOR NUMBER
expr (against 4 - 2 + 2) -> I cannot break yet.
addExpr (against 4 - 2 + 2) -> I cannot break yet.
0: NUMBER -> matches 4, won't finish.
1: expr OPERATOR NUMBER
expr (against 4 - 2 + 2) -> I cannot break yet.
addExpr (against 4 - 2 + 2) -> I cannot break yet.
0: NUMBER -> matches 4, will resolve in the end.
1: expr OPERATOR NUMBER
expr (against 4 - 2 + 2) -> BREAK!
何时中断似乎有些武断。是否有一些良好的规则或条件可以实现这一目标?
如果可以避免的话,我真的不想只设置一个“随机”最大深度。也许我应该考虑采用BFS方法(一系列不同的问题),但是如果可能的话,我想坚持使用DFS。