gpt4 book ai didi

python - 使用 Python 将 VBA 代码解析为更小的代码片段

转载 作者:太空宇宙 更新时间:2023-11-04 05:20:46 25 4
gpt4 key购买 nike

鉴于一些 VBA 代码(存储在文本文件中)根据条件调用规则,我想解析代码并创建生成该规则所需知道的所有内容的迷你代码片段(以便理解规则的本质更容易)。

我开始尝试在 python 中对一些规则进行正则表达式,但不想重新创建轮子(如果存在的话)。我知道像 Retrieving JSON objects from a text file (using Python) 这样的例子覆盖基类以创建客户解析器。我不确定是否有任何最适合开始的软件包,而且我还没有找到一个。

背景是我想像这样“缩减”大约 5000 条规则,以便更简单地陈述围绕规则的逻辑,查看有多少规则受某个变量的影响,等等。

输入:

Sub One(position As Long)    
Dim y As Long
With TEMP_ARRAY(position)
'Comments
If .VAR_A = "A" And .VAR_B = "B" And .VAR_C = "C" Then
Call Some_Rule("Rule 1")
End If

'More Comments
If IsEmpty(.SUB_ARRAY) Then
Call Some_Rule("Rule 2")
Else
If .VAR_A = 2 Then
If .VAR_B <> "" Then
'Some more comments
For y = 0 To UBound(.SUB_ARRAY)
If .SUB_ARRAY(y, 2) = 1 Or .SUB_ARRAY(y, 2) = 2 Then Exit For
Next y
If y = UBound(.SUB_ARRAY, 1) + 1 Then
Call Some_Rule("Rule 3")
End If
Else
'Still more comments
Select Case .SUB_ARRAY(0, 2)
Case 3
Call Some_Rule("Rule 4")
Case 4
Call Some_Rule("Rule 5")
End Select
End If
End If
End If
End With
End Sub

期望的输出:

## RULE 1
Sub One(position As Long)
With TEMP_ARRAY(position)
'Comments
If .VAR_A = "A" And .VAR_B = "B" And .VAR_C = "C" Then
Call Some_Rule("Rule 1")
End If
End With
End Sub

## RULE 2
Sub One(position As Long)
With TEMP_ARRAY(position)
'More Comments
If IsEmpty(.SUB_ARRAY) Then
Call Some_Rule("Rule 2")
End If
End With
End Sub

## RULE 3
Sub One(position As Long)
Dim y As Long
With TEMP_ARRAY(position)
'More Comments
If IsEmpty(.SUB_ARRAY) Then
Else
If .VAR_A = 2 Then
If .VAR_B <> "" Then
'Some more comments
For y = 0 To UBound(.SUB_ARRAY)
If .SUB_ARRAY(y, 2) = 1 Or .SUB_ARRAY(y, 2) = 2 Then Exit For
Next y
If y = UBound(.SUB_ARRAY, 1) + 1 Then
Call Some_Rule("Rule 3")
End If
End If
End If
End If
End With
End Sub

## RULE 4
Sub One(position As Long)
With TEMP_ARRAY(position)
'More Comments
If IsEmpty(.SUB_ARRAY) Then
Else
If .VAR_A = 2 Then
If .VAR_B <> "" Then
Else
'Still more comments
Select Case .SUB_ARRAY(0, 2)
Case 3
Call Some_Rule("Rule 4")
End Select
End If
End If
End If
End With
End Sub

## RULE 5
Sub One(position As Long)
With TEMP_ARRAY(position)
'More Comments
If IsEmpty(.SUB_ARRAY) Then
Else
If .VAR_A = 2 Then
If .VAR_B <> "" Then
Else
'Still more comments
Select Case .SUB_ARRAY(0, 2)
Case 4
Call Some_Rule("Rule 5")
End Select
End If
End If
End If
End With
End Sub

编辑:这是我到目前为止所做的(更多代码,但这是它的核心)。基本上,找到以“Some_Rule”开头的行(使用正则表达式),然后从向上方向开始调用此函数。当它找到一个打开的标签时,它会改变方向并开始寻找它的结束标签,然后从它停止的地方再次开始,等等。我通过这种方式成功地获得了规则 1,然后是凌晨 4 点,所以我去 sleep 了:) ...我现在正在折腾,所以仍然很马虎,但想更新我的进度

def compile_rule(lines, j, direction, statement_open=False):
"""
lines : total lines in file
j : current position
direction : 1 is up, -1 is down
statement_open : vba syntax not yet closed ex: if without end if
"""
global rule
j -= direction
if line_type(lines[j]) in [0, 3] and not statement_open:
rule.append(lines[j], j, direction)
elif line_type(lines[j]) == 1 and not statement_open:
rule.append(lines[j], j, direction)
rule.start_looking_for(line_check(lines[j]))
statement_open = True
direction *= -1
elif line_type(lines[j]) == 2 and rule.looking_for() == line_check(lines[j]) and statement_open:
rule.append(lines[j], j, direction)
statement_open = False
direction *= -1
else:
rule.set_position(j, direction)
if (j > 0 and j < len(lines) - 1) or (j == 0 and statement_open):
compile_rule(lines, rule.get_position(direction), direction, statement_open)

最佳答案

如果您的 VBA 代码的编写方式与大多数 Excel 代码的编写方式相似(例如草率),您将无法依赖现有的 VBA 代码来获得任何漂亮、整洁、易于解码的结构。如果它不是很一致,您将没有机会对其使用基于临时/正则表达式的技术。

在那种情况下,您将需要一个完整的 VBA 解析器,而不是一个糟糕的近似值。您无法使用正则表达式编写像样的解析器(众所周知的事实)。如果你使用更合理的解析技术,你将很难定义语法,因为它的文档非常少。

这里的教训是您可能不想尝试编写自己的解析器。您最好找到一个有效的并使用它。我怀疑您会很容易找到一个,更不用说恰好是用 Python 编写的了;但我可能是错的。

我公司正好 have such a parser for VB6 ,(本质上是 VBA)建立在我们的 DMS 软件再造工具包之上。这个解析器已经在数百万行代码上进行了测试。它自动构建代表程序的抽象语法树。

做你想做的事,你必须:

  • 解析源码
  • 查找规则调用
  • 发现从函数开始到规则调用的控制流路径
  • 沿该路径编写条件

鉴于 VBA 有 goto 语句(您的示例代码没有,但是 5000 个实例似乎是一个非常糟糕的选择),您将需要构建代码的控制流图,以便您可以沿着它导航以找到从函数入口到规则调用的路径。 DMS 支持在代码中查找模式、构建控制和数据流图、遍历流图以及从原始代码的子树中组成有效的程序 block 。您很可能需要所有这些。

[根据您的示例,它们似乎都是有效的 VBA 子例程,而不仅仅是条件的一些结合,看来您想计算 backward slices从每个规则调用。这需要我上面描述的所有机器。]

这不是适合胆小者的任务,也不太可能是周末练习。但它很可能是可行的。

鉴于您的目标含糊地“使它们更具可读性”,您可能无法证明为正确完成这项工作而付出的工程努力是合理的。

如果您坚持采用临时方法,您可能无法完成,并且您可能会发现您的“更具可读性”的规则版本(如果您得到它们)并不是真正的事实,您的读者会反叛。没有人愿意浪费时间阅读可能有误的内容。

关于python - 使用 Python 将 VBA 代码解析为更小的代码片段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40434494/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com