0

我有一个使用空格构造的大型源代码文件。我只对结构化文本文件的一个特定部分感兴趣,如下所示:

   SP : STRUCT  
    Spare : STRUCT  //Spare
     Val : INT  := 100; 
     UpLim : INT  := 100;   
     LoLim : INT ;  
     Def : INT  := 100; 
     Prot : INT  := 2;  
    END_STRUCT ;    
   END_STRUCT ; 

如您所见,定义了一个“SP”结构(它们将在整个源代码中点缀,但名称相同),其中包含一个或多个相同类型的其他结构。在此示例中,只有一个,称为“备用”。每个结构将始终包含相同的 5 个元素。如果未定义任何值,则为零。

提取结构名称及其元素值的最优雅方法是什么?提取后,它们将存储在字典中,以便快速轻松地访问。

我尝试过使用正则表达式,但我不确定它是否是解决这个特定问题的一个非常有效的解决方案。通常采取什么方法来解决这样的问题?

4

2 回答 2

3

此代码似乎使用了类似 algol 的大括号 ( struct/end_struct)。我不认为缩进在语法上很重要。因此解析器应该是基于关键字的,例如:

import re

def parse(data):
    stack = [{}]

    for x in data.splitlines():
        x = re.sub(r'\s+', '', x)

        m = re.match(r'(\w+):STRUCT', x)
        if m:
            d = {}
            stack[-1][m.group(1)] = d
            stack.append(d)
            continue

        m = re.match(r'(\w+):INT(?::=(\w+))?', x)
        if m:
            stack[-1][m.group(1)] = int(m.group(2) or 0)
            continue

        m = re.match(r'END_STRUCT', x)
        if m:
            stack.pop()
            continue

    return stack[0]

结果:

data = """
   SP : STRUCT  
    Spare : STRUCT  //Spare
     Val : INT  := 100; 
     UpLim : INT  := 100;   
     LoLim : INT ;  
     Def : INT  := 100; 
     Prot : INT  := 2;  
    END_STRUCT ;    
   END_STRUCT ; 
"""

print parse(data)
# {'SP': {'Spare': {'LoLim': 0, 'Prot': 2, 'Def': 100, 'UpLim': 100, 'Val': 100}}}
于 2013-03-20T09:48:20.083 回答
1

如果你只想提取 SP : STRUCT 并且你想手动解析它(当你这样做时要小心),你可以使用这样的东西:

data = {}
found = False
with open("code.txt", "r") as code:
    for line in code.readline():
        clean = line.split("//")[0].strip().rstrip(";").split(":")
        fields = map(lambda f: f.strip(), clean)
        if found and fields[0].upper() == "END_STRUCT":
            break
        elif len(fields) == 2:
            if fields[0].upper() == "SP" and fields[1].upper() == "STRUCT":
                found = True
        elif len(fields) == 3 and found:
            if fields[1].upper() != "STRUCT":
                data[fields[0]] = fields[2].lstrip("=").strip()

出于安全原因,我使用了 .upper() 并检查了 len(fields),而我使用 .strip() 主要是为了忽略缩进(似乎不需要:没有它,代码可能有效)。

您还可以添加这段代码(在最后一行的相同缩进级别)以正确的格式存储信息:

if fields[1].upper() == "INT":
    data[fields[0]] = int(data[fields[2]])
#elif field[1].upper == "SOMETHING_ELSE":
#    data[fields[0]] = convert(data[fields[2]])

建议:解析时尽量避免使用正则表达式。

于 2013-03-20T09:24:57.677 回答