3

我正在尝试为 vera++ 静态分析器编写规则。由于我在这里没有找到 vera++ 的组,并且 vera++ 使用 TCL 来实现其分析规则,所以我发布到 TCL 论坛。我曾在 vera++inspirel.com/vera/ce/doc/tclapi.html 上工作过,但由于我不太了解 TCL,所以我希望得到进一步的建议。

由于我是 TCL 编程的初学者,但想知道 TCL 程序列出 C++ 源代码文件中所有局部变量的方法?我的意思是什么方法以及如何实现?

我面临的问题是在解析 C++ 源代码文件以检测局部变量声明时?

4

2 回答 2

4

使用 vera++ 规则解析本地(或任何其他)变量定义非常复杂,但当然可行。基本的 C++ 解析和标记化由 vera++ 完成。

基本方法是将 vera++ 的getTokens函数与一个检查已完成 C++ 语句的小型状态机结合使用。您需要收集标记(并且可能是它们的值,因为稍后您需要变量名来设置列表)并将它们连接起来,直到您有完整的语句。如果您有完整的语句,您可以使用正则表达式来检查它是否是变量定义并从子匹配中提取变量名称。此外,您需要记住您是否在{}块内以了解它是否是局部变量定义。

您可以在 vera++ 的规则 T019 中找到一个构建简单状态机的示例,以将标记收集到语句中,该规则检查完整的花括号代码块,作为起点。

我已经使用 vera++ 解析了变量定义(以检查各种命名约定),但遗憾的是无法发布完整的代码,因为它是我雇主的专有工作。但我可以给你一个片段,显示我用来检查变量声明的正则表达式:

set isVar false
if [regexp {\s+((extern\s+)?(static\s+|mutable\s+|register\s+|volatile\s+)?(const\s+)?)?((identifier#[^#]+#\s+colon_colon\s+)*identifier#[^#]+#)\s+(star\s+|const\s+|and\s+|less.*greater\s+|greater\s+)*(identifier#[^#]+#\s+colon_colon\s+)*identifier#([^#]+)#(\s+leftbracket.*rightbracket)?(\s+assign)?.*semicolon$} $statement m s1 s2 s3 s4 s5 s6 s7 s8 s9 s10] {
    set locVarname $s9
    set isVar true
    set currentMatch $m
} elseif [regexp {\s+((extern\s+)?(static\s+|mutable\s+|register\s+|volatile\s+)?(const\s+)?)?(char\s+|int\s+|short\s+|long\s+|void\s+|bool\s+|double\s+|float\s+|unsigned\s+|and\s+|star\s+|unsigned\s+)+(identifier#[^#]+#\s+colon_colon)*\s+identifier#([^#]+)#(\s+leftbracket.*rightbracket)?(\s+assign)?.*semicolon$} $statement m s1 s2 s3 s4 s5 s6 s7 s8] {
    set locVarname $s7
    set isVar true
    set currentMatch $m
}

$statement包含前面提到的完整语句。请注意,我将令牌值连接到identifier令牌使用identifier#<value>#并使用正则表达式组来提取它。

于 2012-10-30T16:04:32.517 回答
1

不幸的是,我认为您严重低估了任务的复杂性。问题是你无法对 C++ 文件的内容进行任何猜测(无论有多么受过教育),除非你真的按照 C++ 标准中的定义对其进行了解析,而且这样做非常困难

现在应该很明显,使用什么编程语言来实现这种解析的问题实际上并不那么重要。您当然可以在 Tcl 中实现这一点,但是问题并不具体,因为以当前形式正确回答它实际上相当于发布现成的解析器代码。

于 2012-10-30T13:30:56.613 回答