我正在尝试从以下一组模式中提取所有名称*。
name1 name2 ( .name3 ( name4 ) , .name5 ( name6 ) , ..... , .nameM ( nameN ) )
在上面的行间距和新行字符可以互换。 所以这种模式可以扩展到多行。 对于每个模式,N可以是任意长度。
这是verilog语法,表示模块,实例和端口名称。
我需要一个正则表达式才能得到它。
除了首先加入所有行之外,还有一种简单的方法吗?
name *只是一个占位符。它可以是 a-zA-Z0-9 _
我正在使用的示例文件
module1 instance1 (
.A(B) ,.C(D))
一段代码,其中我得到A $ 1和B $ 2。我无法得到C和D.
while(<ORIG>)
{
if($_ =~ m/\.(.*?)\((.*?)\)/g)
{
print "$1\n$2\n$3\n$4";
}
}
答案 0 :(得分:0)
这样做的一种方法是首先提取整个实例声明。然后技巧是将端口列表提取为一个字符串。
\s*\n*\s*\.\w+\s*\(\s*\w+\s*\)\s*\n*\s*,?
会匹配任何端口,但我们不想填充缓冲区列表(我们不知道该号码),因此我们应该使用(?:...)
。然后使用((?:...)+)
((?:\s*\n*\s*\.\w+\s*\(\s*\w+\s*\)\s*\n*\s*,?)+)
对端口进行采样
从文件中提取:
$dosample = 0;
$sample = "";
while (my $line = <ORIG>)
{
if ( $line =~ m/^\s*(\w+)\s+\w+\s*\(/) {
if ( $1 ne "module" ) {
$dosample = 1;
$sample = "";
}
}
if ($dosample == 1) {
$sample .= $line;
if ( $line =~ m/\)\s*;/ ) {
# instance declaration sampled, now extract
@names = &extractNames($sample);
# cleanup
$sample = "";
$dosample = 0;
printf "%s\n", join(", ", @names);
}
}
}
sub extractNames {
my $toParse = shift;
if ( $toParse =~ m/(\w+)\s+(\w+)\s*\(((?:\s*\n*\s*\.\w+\s*\(\s*\w+\s*\)\s*\n*\s*,?)+)\s*\)/ )
{
($moduleName,$instName,$portlist_string) = ($1,$2,$3);
$portlist_string =~ s/[\n\s]//g; # get rid of spaces and newlines
$portlist_string =~ s/\(/,/g; # swap opening parenthesis with comas
$portlist_string =~ s/[\.\)]//g; # get rid of periods and closing parenthesis
@portlist = split( ",", $portlist_string); # array of .name(name)
return ($moduleName,$instName,@portlist);
}
else {
die "bad match:\n\n$_\n\n";
}
}
输入文件:
module dut ( A, B,
C, D);
module1 instance1 (
.A(B) ,.C(D));
module2 inst2 ( .A ( B ) , .B ( B ) , .M ( N ) );
module3 inst3 ( .n3 ( B ) , .n5 ( D ),
.M ( N ),
.Y( Z) ) ;
endmodule
输出:
module1, instance1, A, B, C, D
module2, inst2, A, B, B, B, M, N
module3, inst3, n3, B, n5, D, M, N, Y, Z