在规则执行阶段,你的解析器动作可以利用“值栈”来组织自定义对象(如 AST 节点)的构造。值栈是一个简单的栈结构,作为临时存储服务于自定义对象。
通常,规则可以以任何方式修改值栈。可以创建新的值并推到栈上,或者消费已有的值,或者转换已有的值并重新推到栈上,等等。Parboiled 解析引擎并不关心你的规则和解析器动作与值栈之间的交互。
有两个特殊异常:
如果规则因任何原因未匹配成功,则将值栈重置为执行该失败规则之前的状态。这意味着失败的规则无法修改值栈(这包括失败的语义判定动作)。
此行为的原因是使您不仅可以将动作放在一系列规则的最后位置。考虑如下规则:
1 | Rule ← ‘a’ ‘b’ action ‘c’ |
假设匹配规则 “b” 之后将一个新值推到栈上。如果因为最终的元素 “c” 不能匹配到规则而导致规则序列失败,该值栈仍然会包含刚才被动作推入的新值。即使您的规则逻辑可能能够处理这些情况,这也会使动作设计复杂化并使解析器逻辑更加脆弱。
事实上,当规则不匹配时 Parboiled 重置堆栈的行为使得你可以自由的放置解析器动作,并将值栈用于规则内临时存储,这在很多情况下都非常方便。
Test 和 TestNot 规则永远不会影响值栈。Parboiled 会使用一个以保存的快照将值栈重置回 Test/TestNot 规则匹配之前的状态。因此,您可以确定语法判定永远不会“混乱”您的值栈设置,即使它们包含解析器动作或引用其他规则。