0

假设我已经有了完整的 YACC 语法。以 C 语法为例。现在我想用简单的语法为特定领域的语言创建一个单独的解析器,除了它仍然需要解析完整的 C 类型声明。我不想从原始语法中复制带有相关处理代码的长规则,而是想调用原始解析器来处理一个规则(我们称之为“声明器”)。

如果它是一个递归下降解析器,每个规则都会有一个函数,很容易调用。但是带有隐式堆栈自动机的 YACC 呢?

4

1 回答 1

4

基本上,没有。编写 LR 语法并不容易,bison 也没有提供太多帮助。

但一切都没有丢失。没有什么能阻止你包含整个语法(除了%start声明),并且只使用它的一部分,除了一个小细节:bison 会抱怨无用的产品。

如果这对您来说是一个阻碍,那么您可以使用一个技巧来创建具有多个开始规则的语法。事实上,您可以创建一个语法,让您在每次调用解析器时都指定开始符号;它甚至不必被烘烤。然后你可以把它塞进一个库中,并使用你想要的任何解析器。

当然,这也是有代价的:代价是解析器比原本需要的更大。然而,它不应该更慢,或者至少不会慢很多——可能会有一些缓存效应——与编译器的其余部分相比,额外的大小可能微不足道。

黑客在野牛常见问题解答中有很多详细的描述,所以我在这里只做一个概述:对于你想要支持的每个开始生产,你创建一个以伪令牌开头的额外生产(也就是说,词法分析器永远不会生成的词法代码)。例如,您可能会执行以下操作:

%start meta_start
%token START_C START_DSL

meta_start: START_C c_start | START_DSL dsl_start;

现在您只需安排词法分析器在首次启动时生成适当的 START 令牌。有多种方法可以做到这一点;常见问题解答建议使用全局变量,但如果您使用可重入 flex 扫描器,您可以将所需的起始令牌置于扫描器状态(以及在发送起始令牌时设置的标志)。

于 2013-05-09T06:24:41.987 回答