ActiveState TCL中括号内非贪婪捕获失效问题求助
TCL正则匹配Verilog实例时的贪婪匹配问题修复
问题重现
在Windows上使用ActiveState TCL提取Verilog模块实例时,试图通过#\(.*?\)实现括号内非贪婪匹配,却出现贪婪匹配覆盖后续语句的情况,输出与预期不符。
原代码
proc extract_verilog_instances {text} { set rexp {(\w+)\s+(\#\s*\((?:.*?)\)\s*)?(\w+(?:\[\d+\])?)\s*\(} # rexp will match any of the following statement types: # # module_name instance_name ( # module_name instance_name[0] ( # module_name #(parameter1, parameter2) instance_name ( # module_name #(parameter1, parameter2) instance_name[0] ( set regrun [regexp -inline -all -indices -expanded $rexp $text] foreach {m0 m1 m2 m3} $regrun { set start_index [lindex $m0 0] set end_index [lindex $m0 1] set module [string range $text [lindex $m1 0] [lindex $m1 1]] set instance [string range $text [lindex $m3 0] [lindex $m3 1]] puts "module:$module instance:$instance" } } set vlog { second_module #(2) inst2 (.in2(sig2), .out2(sig3)); third_module inst3 (.in3(sig3), .out3(sig4)); fourth_module #(.in4_clk_freq(50), .in4_rst_val(1'b0)) inst4 (.in4_clk(clk), .in4_rst(rst), .in4_in1(sig4), .in4_in2(sig5), .out4(sig6)); } extract_verilog_instances $vlog
预期输出
module:second_module instance:inst2 module:third_module instance:inst3 module:fourth_module instance:inst4
实际输出
module:second_module instance:inst4
错误原因
- 非贪婪匹配仍跨范围:
.*?虽为非贪婪模式,但会匹配所有字符(包括换行),导致从第一个#(开始,一直匹配到最后一个),覆盖中间所有语句。 - 未处理嵌套括号:Verilog参数中存在嵌套括号(如
.in4_clk_freq(50)),原正则的.*?会在遇到第一个)时停止,但结合整体正则结构,最终仍会扩大匹配范围。 - 正则无语句边界限制:原正则未限制匹配仅在单个实例语句内进行,导致跨多个实例匹配。
修复方案
修改正则表达式解决上述问题:
- 用
[^\n]*?替代.*?,限制匹配不跨换行,确保每个实例语句独立匹配。 - 针对嵌套括号,使用递归匹配逻辑:
(?:[^()]|\((?:[^()]|\([^()]*\))*\))*,精准匹配括号内内容(包括嵌套括号)。 - 调整空白匹配逻辑,避免过度匹配。
修复后的代码
proc extract_verilog_instances {text} { # 修正后的正则:处理嵌套括号,限制不跨换行,精准匹配每个实例 set rexp {(\w+)\s+(#\s*\((?:[^()]|\((?:[^()]|\([^()]*\))*\))*\)\s*)?(\w+(?:\[\d+\])?)\s*\(} set regrun [regexp -inline -all -indices -expanded $rexp $text] foreach {m0 m1 m2 m3} $regrun { set module [string range $text [lindex $m1 0] [lindex $m1 1]] set instance [string range $text [lindex $m3 0] [lindex $m3 1]] puts "module:$module instance:$instance" } } set vlog { second_module #(2) inst2 (.in2(sig2), .out2(sig3)); third_module inst3 (.in3(sig3), .out3(sig4)); fourth_module #(.in4_clk_freq(50), .in4_rst_val(1'b0)) inst4 (.in4_clk(clk), .in4_rst(rst), .in4_in1(sig4), .in4_in2(sig5), .out4(sig6)); } extract_verilog_instances $vlog
修复后输出
module:second_module instance:inst2 module:third_module instance:inst3 module:fourth_module instance:inst4
内容的提问来源于stack exchange,提问作者Bill Moore
相关产品推荐
相关产品推荐

