【发布时间】:2020-05-26 04:55:28
【问题描述】:
编辑概述和范围
这个问题归结为以下问题;给定一个源文件,自动为 C/C++ 中的可选控制块放置左大括号和右大括号。这些块是if、else、do、while 和 for afaik。
概述
我正在尝试跟踪和分析大量代码库中的各种循环、语句等,而这些代码库不是我自己编写的。我的最终目标是在给定的代码源中对所有循环执行时序统计(将来会扩展到其他事情,但超出了这个问题的范围)。这些跟踪函数做了各种各样的事情,但它们都遵循类似的问题;在感兴趣的块执行之前和之后放置。
本质上,我想改造代码:
for (i = 0; i < some_condition; i++) {
some_code = goes(here);
}
for (i = 0; i < some_condition; i++)
{
some_code = goes(here);
}
for (i = 0; i < some_condition; i++) { some_code = goes(here); }
for (i = 0; i < some_condition; i++)
some_code = goes(here);
for (i = 0; i < some_condition; i++)
for (i = 0; i < some_condition; i++)
some_code = goes(here);
到以下:
S_TRACE(); for (i = 0; i < some_condition; i++) {
some_code = goes(here);
} E_TRACE();
S_TRACE(); for (i = 0; i < some_condition; i++)
{
some_code = goes(here);
} E_TRACE();
S_TRACE(); for (i = 0; i < some_condition; i++) { some_code = goes(here); } E_TRACE();
S_TRACE(); for (i = 0; i < some_condition; i++) {
some_code = goes(here); } E_TRACE();
S_TRACE(); for (i = 0; i < some_condition; i++) {
S_TRACE(); for (i = 0; i < some_condition; i++) {
some_code = goes(here); } E_TRACE(); } E_TRACE();
基本上,如果没有添加新的 行 代码,我想在语句开始(简单)和 之后插入一个函数 before > 声明(这可能很难)。比如下面的代码其实就在代码的仓库里:
for( int i = 0; names[i]; i++ )
if( !STRCMP( arg, names[i] ) )
{
*dst = names[i];
return 0;
}
return -1;
撇开糟糕的可读性不谈,我想在这种类型的循环上放置大括号,并插入我的跟踪函数。我省略了函数的参数(考虑嵌套)。
当前实施
我目前的实现在 Python 中使用正则表达式,因为我对这种语言相当熟悉和快速。相关实施环节如下:
import re
source = []
loops = [r"^\s*(for\s*\(.*\))\s*($|{\s*$|\s*)", r"^\s*(while\s*\(.*\))\s*($|{\s*$|\s*)", r"^\s*(do)\s*({?)$"]
def analyize_line(out_file):
lnum, lstr = source.pop(0)
for index, loop_type in enumerate(loops):
match = re.findall(loop_type, lstr)
if match:
print(lnum + 1, ":", match[0][0])
if '{' in match[0][1]:
out_file.write(lstr.replace(match[0][0], "S_TRACE(); {}".format(match[0][0])))
look_ahead_place()
return
else:
last_chance = lstr + source[0][1]
last_match = re.findall(loop_type, last_chance)
if last_match and '{' in last_match[0][1]:
# same as above
out_file.write(lstr.replace(match[0][0], "S_TRACE(); {}".format(match[0][0])))
lcnum, lcstr = source.pop(0)
out_file.write(lcstr)
look_ahead_place()
else:
# No matching bracket, make one
out_file.write(lstr.replace(match[0][0], "S_TRACE(); {} {{".format(match[0][0])))
look_ahead_and_place_bracket()
return
# if we did not match, just a normal line
out_file.write(lstr)
def look_ahead_place():
depth = 1
for idx, nl in enumerate(source):
substr = ""
for c in nl[1]:
substr += c
if depth > 0:
if c == '{':
depth += 1
elif c == '}':
depth -= 1
if depth == 0:
substr += " E_TRACE(); "
if depth == 0:
source[idx][1] = substr
return
print("Error finding closing bracket here!")
exit()
def look_ahead_and_place_bracket():
for idx, nl in enumerate(source):
# Is the next line a scopable? how to handle multiline? ???
# TODO
return
def trace_loops():
global source
src_filename = "./example.c"
src_file = open(src_filename)
out_file = open(src_filename + ".tr", 'w')
source = [[number, line] for number, line in enumerate(src_file.readlines())]
while len(source) > 0:
analyize_line(out_file)
trace_loops()
example.c 是上面提供的示例,用于演示目的。我正在努力想出一种算法来处理内联循环、没有匹配大括号的循环以及不包含大括号但具有多行内部的循环。
对我的算法开发的任何帮助将不胜感激。如果有需要进一步解决的问题,请在 cmets 中告诉我。
编辑 :: 更多示例和预期结果
添加的字符用< 和> 标记包围以提高可见性。
嵌套无括号:
for( int i = 0; i < h->fdec->i_plane; i++ )
for( int y = 0; y < h->param.i_height >> !!i; y++ )
fwrite( &h->fdec->plane[i][y*h->fdec->i_stride[i]], 1, h->param.i_width >> !!i, f );
<S_TRACE(); >for( int i = 0; i < h->fdec->i_plane; i++ )< {>
<S_TRACE(); >for( int y = 0; y < h->param.i_height >> !!i; y++ )< {>
fwrite( &h->fdec->plane[i][y*h->fdec->i_stride[i]], 1, h->param.i_width >> !!i, f );< } E_TRACE();>< } E_TRACE();>
嵌套混合:
for( int i = 0; i < h->fdec->i_plane; i++ ) {
for( int y = 0; y < h->param.i_height >> !!i; y++ )
fwrite( &h->fdec->plane[i][y*h->fdec->i_stride[i]], 1, h->param.i_width >> !!i, ff );
}
<S_TRACE(); >for( int i = 0; i < h->fdec->i_plane; i++ ) {
<S_TRACE(); >for( int y = 0; y < h->param.i_height >> !!i; y++ )< {>
fwrite( &h->fdec->plane[i][y*h->fdec->i_stride[i]], 1, h->param.i_width >> !!i, ff );< } E_TRACE();>
}< E_TRACE();>
大型多行嵌套无括号:
for( int i = 0; i < h->sh.i_mmco_command_count; i++ )
for( int j = 0; h->frames.reference[j]; j++ )
if( h->frames.reference[j]->i_poc == h->sh.mmco[i].i_poc )
x264_frame_push_unused(
h,
x264_frame_shift( &h->frames.reference[j] )
);
<S_TRACE(); >for( int i = 0; i < h->sh.i_mmco_command_count; i++ )< {>
<S_TRACE(); >for( int j = 0; h->frames.reference[j]; j++ )< {>
if( h->frames.reference[j]->i_poc == h->sh.mmco[i].i_poc )
x264_frame_push_unused(
h,
x264_frame_shift( &h->frames.reference[j] )
);< } E_TRACE();>< } E_TRACE();>
这个总多线器:
for( int j = 0;
j < ((int) offsetof(x264_t,stat.frame.i_ssd) - (int) offsetof(x264_t,stat.frame.i_mv_bits)) / (int) sizeof(int);
j++ )
((int*)&h->stat.frame)[j] += ((int*)&t->stat.frame)[j];
for( int j = 0; j < 3; j++ )
h->stat.frame.i_ssd[j] += t->stat.frame.i_ssd[j];
h->stat.frame.f_ssim += t->stat.frame.f_ssim;
<S_TRACE(); >for( int j = 0;
j < ((int) offsetof(x264_t,stat.frame.i_ssd) - (int) offsetof(x264_t,stat.frame.i_mv_bits)) / (int) sizeof(int);
j++ )< {>
((int*)&h->stat.frame)[j] += ((int*)&t->stat.frame)[j];< } E_TRACE();>
<S_TRACE(); >for( int j = 0; j < 3; j++ )< {>
h->stat.frame.i_ssd[j] += t->stat.frame.i_ssd[j];< } E_TRACE();>
h->stat.frame.f_ssim += t->stat.frame.f_ssim;
If 语句边缘情况:
也许我的实现需要包含 if 语句来解决这个问题?
if( h->sh.i_type != SLICE_TYPE_I )
for( int i_list = 0; i_list < 2; i_list++ )
for( int i = 0; i < 32; i++ )
h->stat.i_mb_count_ref[h->sh.i_type][i_list][i] += h->stat.frame.i_mb_count_ref[i_list][i];
【问题讨论】:
-
我预计非空连续行的数量在某些情况下会很大。是的? 25+?我建议您在示例中包含一两个特别困难的块(连同所需的结果)。
-
当然可以。我现在将浏览代码并选择一些具有预期结果的示例。
-
包括了一些可能是最严重的违规者。如果你愿意,我会包括更多。由于这篇文章很长,我可能会将所有这些都制作一个文件并将其附加到帖子中。
-
看来我的算法应该先执行大括号/括号传递,然后我的原始实现才能生效......
-
@CarySwoveland 更新了问题描述,使问题简洁明了。希望对您有所帮助。
标签: python regex python-3.x algorithm parsing