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」構造が定義されています (これらはソース コード全体に点線で示されますが、同じ名前です)。これには、同じタイプの他の構造が 1 つ以上含まれています。この例では、「スペア」と呼ばれる 1 つのみがあります。各構造には、常に同じ 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 に答える