【发布时间】:2022-09-23 12:36:43
【问题描述】:
我有一个非常大的野牛规则文件,想知道是否有一种简单的方法可以从后面的程序中获取这些规则的覆盖范围。
我用野牛生成一个解析器。针对不同的文件运行解析器,并希望查看在.yy文件。
标签: code-coverage bison
我有一个非常大的野牛规则文件,想知道是否有一种简单的方法可以从后面的程序中获取这些规则的覆盖范围。
我用野牛生成一个解析器。针对不同的文件运行解析器,并希望查看在.yy文件。
标签: code-coverage bison
据我所知,没有正式的方法可以生成这样的报告。但这是可能的,如果你愿意稍微闯入野牛的内部。
请注意,您只能为解析器语义操作生成覆盖率报告。 “解析器规则”没有其他直接翻译;规则被编译成状态机,状态与规则的对应是多对多的。但这会告诉你每条规则完成了多少次,这可能是你想知道的。
另请注意,解析器不区分规则最终语义动作和中间规则动作,因为中间规则动作实际上被编译为生成的非终结符的归约动作。
这篇文章的其余部分是非官方的,不应依赖于所有未来版本的 Bison。它也不适用于其他野牛骨架(尽管它可能会被改编);我基于当前版本 3.8.2 编写。
挂钩解析器的最简单方法是劫持宏YY_REDUCE_PRINT,跟踪工具使用该宏来跟踪缩减操作。所以每次减少时都会执行。即使跟踪没有编译到解析器中,也会发生这种情况;在这种情况下,宏被定义为无操作。不过,YY_REDUCE_PRINT 不是界面的官方部分,因此其名称和功能可能会更改,恕不另行通知。此外,它不是正式可用于定制的,并且生成的源不会尝试检查它是否以前定义过。所以你必须等到它在解析器模板中被定义了,然后再重新定义它。当然,重新定义它会使其无法用于跟踪日志,因此这与调试跟踪不兼容。原来½initial-action代码块是在YY_REDUCE_PRINT的定义之后注入的,所以这就是我重新定义的地方。这也不能保证。
我使用lalr1.cc 骨架,非常轻松地测试了以下代码,使用了几个最近的野牛版本(3.7.1 和 3.8.2)。它似乎有效,但您的里程可能会有所不同。
代码非常简单。首先,重新定义YY_REDUCE_PRINT,将其放入您的.yy 文件中。您可能希望以某些配置宏为条件,以保留生成调试跟踪的可能性。重新定义的YY_REDUCE_PRINT 宏所做的只是在覆盖率直方图中加一。 (这里,drv 是解析器驱动程序的一个实例,根据 Calc++ 示例):
%initial-action {
#undef YY_REDUCE_PRINT
#define YY_REDUCE_PRINT(Rule) drv.register_rule(Rule)
}
直方图本身需要实现;它可以进入driver.hh 和driver.cc:
标题:
// Register execution of a semantic action.
void register_rule(int rule);
// Count of executions of each rule.
std::vector<unsigned> rule_count;
执行:
void
driver::register_rule(int ruleno) {
if (ruleno > 0) {
if (ruleno > rule_count.size()) rule_count.resize(ruleno);
++rule_count[ruleno - 1];
}
}
规则编号对应于生成的报告文件中的编号。规则 0(接受规则)将不被计算在内。
【讨论】: