“提取c程序注释”,这是一个典型的状态机问题,但在此我想用正则表达式(regExp)工具来解决。
perl的正则表达式很强,起初我想到“多行匹配”,将c文件整个读入一个串变量,然后逐个抽取/*块注释*/。这可能需要使用选项 /m /g ,还得考虑行注释和块注释符的混合情况,是个棘手的问题。
初次尝试 发现一个大问题: 匹配最大串还是最小串?
# perl 5.12 # // 行注释 # /* */ 块注释 # 识别错误的原因:匹配最大串 /*comment1*//*comment2*/
open(ifp, "comments.txt") || die ("canot open file."); $/=undef; # 吞噬
$cnt=0; while($line = <DATA>) { $line =~ /\/\*.*\*\//s; printf("line%2d:%s", $cnt++, $&); }
__DATA__ /*comment1*/ int sum(int a, int b) { return a+b; } /*comment2*/
|
对于模式 /\/\*.*\*\//s 我期望它匹配 /*comment1*/ ,但它却匹配了 /*comment1*/ ... /*comment2*/. 有没有一种方法可以成对匹配?
有。模式对 /\/\*/ ... /\*\// 将成对匹配 /* 和 */。
据推测,模式对 /pattern1/.../pattern2/的工作过程大致如下:
bool sw=off;
if(sw==off)
{
if(line match /pattern1/)
sw=on;
}
else
{
do something, like print~
if(line match /pattern1/)
sw=off;
}
if(sw == on)
do something.
能够识别行注释和块注释的正则式式perl如下:
# // 行释 # /* 块注释 */ # 注:要求代码与注释分行,因为正则以行为单位匹配。 # 可用格式化工具(ArtisticStyle)将代码与注释分行。 # 特点:识别出的注释保持缩进。
use strict; use warnings;
my $cnt=0; my $str; my $bMultiLine=0;
while (<DATA>) { #print "$_"; $cnt++; $str = $_; # 单行内的注释 if(!$bMultiLine) { # 行注释(要求与代码不在同一行,可用格式化工具将代码与注释分行) if (/\s*\/\//) { print "$cnt S:"; print; next; # skip } if (/\/\*.*\*\//) # 只占一行的块注释 { print "$cnt B:"; print; next; # skip } } # 跨行的块注释 if (/\/\*/ ... /\*\//) # /* ... */ { print "$cnt M:"; print; $bMultiLine=1; } if($bMultiLine) { if(/.*\*\//) { $bMultiLine = 0; } } } __DATA__ 行注释 // this is a line comment // this is a line /* comment * /
块注释(只占一行) /* this is a block comment, in one line. */ /* this is a block comment, // in one line. */
块注释(跨行) /* this is a block comment, in multi-line. */
块注释中的//属于注释内容 /* this is a block comment, but // not a line comment */
块注释中的/*属于注释内容 /* this is a /* block /* comment */
块注释不能嵌套,如下面是非法的块注释 /* illegal comment, because /* nest... */ ing */
void SetPwm(unsigned long m) // 这个行注释与代码在同一行,再与块注释符混合 /* 用regExp难以识别它。 */ { printf("hi!"); }
|
它有一点不足:以行匹配。这要求注释与非注释不能在同一行,这个要求不免苛刻。至于是否可用正则的位置变量、预见性匹配等技巧来解决此问题,我没有更多的想法。
“提取c程序注释”的一种更实用和明了的方法是使用状态机思想,见[
状态机示例-提取c程序注释]
阅读(4003) | 评论(0) | 转发(0) |