是否可以从另一个调用一个yacc解析器来解析特定的令牌子流?

时间:2013-05-09 01:08:19

标签: parsing grammar bison yacc

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

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

1 个答案:

答案 0 :(得分:4)

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

但并非一切都没有丢失。没有什么可以阻止你包括整个语法(除了%start声明),只是使用它的一部分,除了一个小细节:野牛会抱怨无用的制作。

如果这对你来说是一个显示阻止,那么你可以使用一个技巧来创建一个包含多个启动规则的语法。实际上,您可以创建一个语法,让您在每次调用解析器时指定起始符号;它甚至不必被烘焙。然后你可以把它塞进一个库并使用你想要的任何解析器。

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

hack在bison FAQ中有很多细节描述,所以我在这里做一个大纲:对于你想要支持的每个开始制作,你创建一个以伪开头的额外制作-token(即lexer永远不会生成的词法代码)。例如,您可以执行以下操作:

%start meta_start
%token START_C START_DSL

meta_start: START_C c_start | START_DSL dsl_start;

现在你必须安排词法分析器在第一次启动时产生适当的START令牌。有各种方法可以做到这一点;常见问题解答建议使用全局变量,但如果使用可重入的flex扫描程序,则可以将所需的开始标记放入扫描程序状态(以及在发送开始标记时设置的标记)。