用tcl分割不同格式的输入行

时间:2013-06-04 16:53:17

标签: tcl

下午好,

我正在尝试编写一个给出输入文件

的tcl脚本
input               hreadyin;
input  wire         htrans;       
input  wire [7:0]   haddr;   
output logic [31:0] hrdata;
output              hreadyout;

将产生

hreadyin(hreadyin),
htrans(htrans),
haddr(haddr[7:0]),
hrdata(hrdata[31:0]),
hready(hreadyout)

换句话说,格式是:

<input/output> <wire/logic optional> <width, optional> <paramName>;

每个空格之间的空格数量不受限制。

我从输入文件中读取没有问题,并且能够将每一行放在$line元素中。现在我一直在尝试这样的事情:

  set param0 [split $line "input"]
  set param1 [lindex $param0 1]

但是因为并非所有行都有“input"行,所以我无法得到我想要的元素(名称和宽度,如果存在的话)。”

tcl中是否还有另一个能够进行此类解析的命令?

3 个答案:

答案 0 :(得分:2)

我认为你应该看看像

这样的东西
# Compress all multiple spaces to single spaces

set compressedLine [resgub " +" $line " "]

set items [split [string range $compressedLine 0 end-1] $compressedLine " "]
switch [llength $items] {
    2 {
        # Handle case where neither wire/logic nor width is specificed

        set inputOutput [lindex $items 0]
        set paramName [lindex $items 1]
        .
        .
        .
    }

    4 {
        # Handle case where both wire/logic and width are specified

        set inputOutput [lindex $items 0]
        set wireLogic [lindex $items 1]
        set width [lindex $items 2]
        set paramName [lindex $items 3]
        .
        .
        .
    }

    default {
        # Don't know how to handle other cases - add them in if you know
        puts stderr "Can't handle $line
    }
}

我希望指定一个指定的线/逻辑和宽度是不合法的 - 你需要努力确定哪个是哪个。

(注意[string range...]小提琴丢弃行尾的分号)

答案 1 :(得分:2)

regexp命令可用于查找由任意空格分隔的单词:

while {[gets $fh line] != -1} {
    # get all whitespace-separated words in the line, ignoring the semi-colon
    set i [string first ";" $line]
    set fields [regexp -inline -all {\S+} [string range $line 0 $i-1]]

    switch -exact -- [llength $fields] {
        2 - 3 {
            set name [lindex $fields end]
            puts [format "%s(%s)," $name $name]
        }
        4 {
            lassign $fields - - width name
            puts [format "%s(%s%s)," $name $name $width]
        }
    }
}

答案 2 :(得分:1)

或者,如果你可以编写一个捕获正确数据的正则表达式,你可以这样做:

set data [open "file.txt" r]
set output [open "output.txt" w]

while {[gets $data line] != -1} {
    regexp -- {(\[\d+:\d+\])?\s*(\w+);} $line - width params
    puts $output "$params\($params$width\),"
}

close $data
close $output

这个也会打印你在预期输出中插入的逗号,但也会将它插入到最后一行,这样你就得到了:

hreadyin(hreadyin),
htrans(htrans),
haddr(haddr[7:0]),
hrdata(hrdata[31:0]),
hready(hreadyout),

如果你不想要它并且文件不是太大(显然我要使用的列表的限制是2147483672字节),你可以使用这样的组:

set data [open "file.txt" r]
set output [open "output.txt" w]

set listing "" #Empty list

while {[gets $data line] != -1} {
    regexp -- {(\[\d+:\d+\])?\s*(\w+);} $line - width params
    lappend listing "$params\($params$width\)" #Appending to list instead
}

puts $output [join $listing ",\n"] #Join all in a single go

close $data
close $output