我需要在现有的VB6应用程序中注入一些代码。
我想要做的是在几百个vb6文件的每个方法的顶部添加日志记录代码,使用值记录方法名称和参数。
编写代码很简单,但我在苦苦挣扎的是VB6语法中的方法或属性标题的匹配,因为似乎有大量的变体和可选的关键字。
有没有人对如何实现这一点有任何建议? 我已经尝试过使用RegEx并且失败了,并且已经使用代码化代码并寻找令牌模式。
答案 0 :(得分:17)
将其编写为VB6插件可能更容易,它允许您枚举所有模块/过程并插入适合的代码。
或者,使用免费的MZTools,可以自动为各个过程或新过程添加标题。
答案 1 :(得分:1)
对于像这样的项目,您可能想要比正则表达式更强大的东西。我不知道任何OSS VB6解析器实现,但我建议使用适当的工具。如果要概括在编译时注入代码的方法,此活动有时称为Aspect Oriented Programming或Mixins。
我将花点时间插入我自己的工具meta#,它允许您为这些类型的场景构建匹配语法的模式,但您也可以使用其中许多其他工具,如Lexx / Yacc,Flexx /野牛或ANTLR。
但即使你没有特别使用我的,这也是我将采取的解决问题的一般策略:
每次构建时都运行此转换步骤。
答案 2 :(得分:1)
我们的DMS Software Reengineering Toolkit及其Visual Basic front end可用于执行此操作。
DMS使用前端解析源文本以抽象语法树,然后将任意分析/转换应用于这些树。可以使用source-to-source program transformation完成许多转换更改,其中使用“如果您看到此语法,使用语法替换 语法”来重写代码作为定义抽象占位符的一种方式。这使得使用熟悉的语法在代码上编写转换相对容易。这概括了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表示(AST) 必须与规则中声明的语法非终结符N匹配的参数 header as ... n:N .... tostring是一个自定义元函数(用meta parens()调用) 将树节点参数转换为文本字符串的树节点。
OP可能需要比处理其他案件更多的规则;也许他想要伐木 GOSUB调用,和/或在日志调用中捕获函数参数。
其他答案建议获取解析器生成器,以及定义VB6以启用解析。重要的是要理解正确地使用VB6语法非常困难;语言记录很少,并且有关于空格,行内语句和跨行边界语句的一些非常奇怪的规则。如果你没有做到这一点,你根本无法解析数百个文件。我们必须定义自己的语法(正如我们为DMS所做的那样) many other languages)。
您可以使用程序转换了解有关代码检测/日志记录的更多信息 here