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

使用Python将VBA代码解析为更小的代码段,python,vba,excel,parsing,Python,Vba,Excel,Parsing,给定一些基于条件调用规则的VBA代码(存储在文本文件中),我想解析代码并创建生成该规则所需的所有内容的迷你代码片段(以便更容易理解规则的本质) 我开始尝试在python中正则化一些规则,但不想重新创建轮子(如果它存在的话)。我知道有一些例子喜欢重写基类来创建客户解析器。我不确定是否有最适合这个项目的软件包,也没有找到一个 背景是,有大约5000条规则,我想像这样“收缩”,更简单地陈述规则周围的逻辑,看看有多少规则受到某个变量的影响,等等 输入: Sub One(position As Long)

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

我开始尝试在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
Sub-One(位置尽可能长)
长得一样暗
带临时阵列(位置)
评论
如果.VAR_A=“A”和.VAR_B=“B”以及.VAR_C=“C”,那么
调用一些规则(“规则1”)
如果结束
更多评论
如果为空(.SUB_数组),则
调用一些规则(“规则2”)
其他的
如果.VAR_A=2,则
如果.VAR_B“”那么
还有一些评论
对于y=0到UBound(.SUB_数组)
如果.SUB_数组(y,2)=1或.SUB_数组(y,2)=2,则退出
下一个y
如果y=UBound(.SUB_数组,1)+1,则
调用一些规则(“规则3”)
如果结束
其他的
还有更多的评论
选择Case.SUB_数组(0,2)
案例3
称一些规则(“规则4”)
案例4
称一些规则(“规则5”)
结束选择
如果结束
如果结束
如果结束
以
端接头
所需输出:

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
##规则1
子1(位置尽可能长)
带临时阵列(位置)
评论
如果.VAR_A=“A”和.VAR_B=“B”以及.VAR_C=“C”,那么
调用一些规则(“规则1”)
如果结束
以
端接头
##规则2
子1(位置尽可能长)
带临时阵列(位置)
更多评论
如果为空(.SUB_数组),则
调用一些规则(“规则2”)
如果结束
以
端接头
##规则3
子1(位置尽可能长)
长得一样暗
带临时阵列(位置)
更多评论
如果为空(.SUB_数组),则
其他的
如果.VAR_A=2,则
如果.VAR_B“”那么
还有一些评论
对于y=0到UBound(.SUB_数组)
如果.SUB_数组(y,2)=1或.SUB_数组(y,2)=2,则退出
下一个y
如果y=UBound(.SUB_数组,1)+1,则
调用一些规则(“规则3”)
如果结束
如果结束
如果结束
如果结束
以
端接头
##规则4
子1(位置尽可能长)
带临时阵列(位置)
更多评论
如果为空(.SUB_数组),则
其他的
如果.VAR_A=2,则
如果.VAR_B“”那么
其他的
还有更多的评论
选择Case.SUB_数组(0,2)
案例3
称一些规则(“规则4”)
结束选择
如果结束
如果结束
如果结束
以
端接头
##规则5
子1(位置尽可能长)
带临时阵列(位置)
更多评论
如果为空(.SUB_数组),则
其他的
如果.VAR_A=2,则
如果.VAR_B“”那么
其他的
还有更多的评论
选择Case.SUB_数组(0,2)
案例4
称一些规则(“规则5”)
结束选择
如果结束
如果结束
如果结束
以
端接头
编辑:以下是我到目前为止所做的工作(更多代码,但这是它的核心)。基本上,找到一个以“Some_Rule”(使用regex)开头的行,然后从向上的方向调用这个函数。当它找到一个打开的标签时,它改变方向并开始寻找它的结束标签,然后从它停止的地方重新开始,等等。我通过这种方式成功地获得了规则1,然后是凌晨4点,所以我进入了睡眠:)。。。我在这一点上把事情弄得乱七八糟,所以还是很马虎,但我想更新我的进度

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)
def compile_规则(行、j、方向、语句_open=False):
"""
行:文件中的行总数
j:目前的情况
方向:1向上,-1向下
语句_open:vba语法尚未关闭ex:if无结束if
"""
全球规则
j-=方向
如果[0,3]中的行类型(行[j])未打开:
规则.追加(第[j]行、第j行、方向)
elif行类型(行[j])==1且未打开:
规则.追加(第[j]行、第j行、方向)
规则.开始查找(行检查(行[j]))
语句_open=True
方向*=-1
elif行类型(行[j])==2和规则。查找()==行检查(行[j])和语句打开:
规则.追加(第[j]行、第j行、方向)
语句_open=False
方向*=-1
其他:
规则.设置位置(j,方向)
如果(j>0且j
如果您的VBA代码是按照大多数Excel代码的编写方式编写的(例如,草率),那么您将无法依靠现有的VBA代码来获得任何漂亮、整洁、易于解码的结构。如果它不是非常一致,那么您就没有机会在其上使用基于ad-hoc/regex的技术