我想做的是在几百个vb6文件中的每个方法顶部添加记录代码,记录方法名称和参数及其值。
编写代码很容易,但我遇到了一些麻烦,即匹配VB6语法中的方法或属性头,因为似乎有很多变化和可选关键字。
有没有人有关于如何实现这一点的建议? 我已经尝试使用RegEx并失败了,现在转而对代码进行标记化并查找令牌模式。
你可以选择将其作为 VB6 插件编写,以便枚举所有模块/过程并插入适当的代码。
或者,使用免费的 MZTools 工具,它可以自动向个别过程或新过程添加头信息。
对于这样的项目,您可能需要比普通表达式更稳健的东西。我不知道有没有任何开源的 VB6 解析器实现,但我建议使用一个适合这种任务的正确工具。如果你要概括注入编译时代码的方法,这个活动有时被称为 面向方面的编程 或 Mixins。
我想推荐我的工具 meta#,它允许您为这些情况构建模式匹配语法,但您也可以使用其他许多工具,例如 Lexx/Yacc、Flexx/Bison 或 ANTLR。
但即使您不使用我的工具,这里是解决问题的一般策略:
每次构建时运行此转换步骤。
我们的DMS软件重构工具包及其Visual Basic前端可用于此操作。
DMS使用前端解析源代码文本,生成抽象语法树,然后可以对这些树应用任意分析/转换。许多转换更改可以使用源到源程序转换完成,其中代码被重写为“如果您看到此语法,请将其替换为该语法”,使用语法作为定义抽象占位符的方法。这使得使用熟悉的语法编写代码转换相对容易。这推广了OP尝试匹配令牌序列的方法。
OP的问题可以被描述为类似于以下形式的方面重写:
default domain VisualBasic~VB6;
rule function_insert_log_call(a: attributes, t: type,
i: IDENTIFIER, p: parameters, s:statements)
= function -> function
= " \a FUNCTION \i ( \p ) AS \t
\s
END FUNCTION"
-> "\a FUNCTION \i ( \p ) AS \t
my_log(\tostring\(\i\))
\s
END FUNCTION";
rule subroutine_insert_log_call(a: attributes,
i: IDENTIFIER, p: parameters, s:statements)
= subroutine -> subroutine
= " \a SUB \i ( \p )
\s
END SUB"
-> " \a SUB \i ( \p )
my_log(\tostring\(\i\))
\s
END SUB";
这些重写的形式为
rule *rulename* ( *patternvars* ) *nonterminal* -> *nonterminal*
= " *syntaxpattern* "
-> " *syntaxpattern* ";
提供的具体规则将识别函数头和函数体,而不考虑内容/空格/注释,因为它们实际上与AST匹配。
"..."是元引用,外部是DMS规则语法,内部是VB6语法。 "..."内部的\n表示必须匹配规则头中声明的语法非终结符N的一个(AST)参数,如...n:N.... tostring是一个自定义元函数(用元括号()调用),它将树节点参数转换为文字字符串的树节点。
OP可能需要更多的规则来处理其他情况;也许他想记录GOSUB调用,并/或在log调用中捕获函数参数。
其他答案建议获取解析器生成器,并定义VB6以启用解析。重要的是要理解,正确获取VB6语法真的很难;该语言文档质量较差,并且有一些关于空格、跨行语句和跨行语句的奇怪规则。如果您没有做到这一点,您就无法解析数百个文件。我们不得不定义自己的语法(就像我们为DMS定义了许多其他语言一样)。
您可以阅读更多关于使用程序变形的代码仪表化/日志记录方面的内容此处。