0

我的主要目标是解析 python 循环,以便我可以插入一些语句进行分析。

Normal code:
#A.py

[code Starts]
.
.
.
while [condition]:
    [statements]
    [statements]
    [statements]

.
.
.
[code ends]

检测代码:

Normal code:
#A.py

[code Starts]
.
.
.
count =0                                    <---------- inserted code 
print "Entry of loop"                       <---------- inserted code
while [condition]:
    print "Iteration Number " + count++     <---------- inserted code
    [statements]
    [statements]
    [statements]
print "Exit of loop"                        <---------- inserted code
.
.
.
[code ends]

我的目标是以适当的缩进将上述代码插入到适当的位置。该循环也可以是一个 for 循环。为了实现上述检测代码,我需要解析 A.py 文件中的循环并插入这些代码。

有没有一种好方法来解析这些循环并获取循环的行号以便我可以检测?

谢谢

4

3 回答 3

1

pyparsing有一个包含完整 (?) Python 语法分析器的示例文件。从长远来看,这可能是一个有趣的选择——尤其是当您的分析项目将获得更多功能时:

于 2013-06-11T09:10:43.583 回答
1

解析通常是一项艰巨的任务。您可以使用Pygments python 库,它是一个语法高亮库。这可能看起来与您打算做的不同,但事实并非如此。毕竟,着色代码基本上是在代码块中添加颜色信息。

使用 PythonLexer,您可以为每一行提取标记并添加您想要的任何注释。如果您不想只在 while 循环上工作,而且在 for 循环上工作,这将派上用场,如果语句......

于 2013-06-11T09:07:05.707 回答
0

执行此操作的最简单方法是简单地逐行扫描文件并在找到匹配的行时添加语句。

以下代码可以满足您的需求,但它根本可靠:

def add_info_on_loops(iterable):
    in_loop = False
    for line in iterable:
        if not in_loop:
            if line.startswith('for ') or line.startswith('while '):
                in_loop = True
                yield 'count = 0\n'
                yield 'print "Entry of loop"\n'
                yield line
                yield '    print "Iteration Number:", count'
                yield '    count += 1\n'
            else:
                yield line
        else:
            if not line.startswith('    '):
                in_loop = False
                yield 'print "Exit of loop"\n'
            yield line

用法:

>>> code = StringIO("""[code Starts]
... .
... .
... .
... while [condition]:
...     [statements]
...     [statements]
...     [statements]
... 
... .
... .
... .
... [code ends]""")
>>> print ''.join(add_info_on_loops(code))
[code Starts]
.
.
.
count = 0
print "Entry of loop"
while [condition]:
    print "Iteration Number:", count    count += 1
    [statements]
    [statements]
    [statements]
print "Exit of loop"

.
.
.
[code ends]

代码的陷阱:

  1. 该代码处理顶层的循环。类似的东西if condition: for x in a: ...无法识别。这可以解决在检查我们是否有循环之前剥离空白行(但您必须考虑不同级别的缩进等)
  2. 只要循环中有一行没有缩进,代码就会中断。例如,如果您用空行“拆分”代码并且 IDE 去除了空白,就会发生这种情况。一个解决方案可能是等待非空白、非缩进的行而不是非缩进的行。
  3. 该代码不处理用于缩进的制表符(很容易修复)
  4. 该代码不处理单行循环(例如for x in a: print x)。在这种情况下,您将获得错误的输出。轻松修复检查:.
  5. count如果要添加对嵌套循环的支持,使用单个变量会很麻烦。您可能应该在某处有一个整数 id 并使用变量名称,例如count_0,count_1每次找到新循环时,id 都会增加。
  6. 该代码不处理带有括号且键盘上没有空格的表达式。eg for(a,b) in x:不被检测为循环,whilefor (a,b) in x:被检测到。这很容易解决。首先检查该行是否以 and 开头,for并且while下一个字符不能是字母、数字、下划线(实际上在 python3 中你也可以使用 unicode 字符,这变得更难测试,但可能)。
  7. 该代码不处理以缩进循环行结尾的源代码。例如不会添加for x in a: indented_last_line_of_code()出口。(很容易修复在函数外部添加检查以查看我们是否有这种情况)。printin_loopfor

正如您所看到的,编写一段执行您所要求的代码并不是那么简单。我相信你能做的最好的就是使用ast解析代码然后访问树并在正确的位置添加节点,然后重新访问代码并生成python源代码(通常节点在源代码的行上有指示代码,它允许您复制粘贴完全相同的代码)。

于 2013-06-11T10:52:22.460 回答