2

条件付きステートメントを含むファイルを解析する必要があります。これらのファイルは、相互にネストされている場合があります。

構成データを格納するファイルがありますが、ユーザー定義のオプションによって構成データが少し異なります。条件文を処理できます。これらはすべて操作のないブール値ですが、ネストされた条件を再帰的に評価する方法がわかりません。たとえば、ファイルの一部は次のようになります。

...
#if CELSIUS
    #if FROM_KELVIN ; this is a comment about converting kelvin to celsius.
        temp_conversion = 1, 273
    #else
        temp_conversion = 0.556, -32
    #endif
#else
    #if FROM_KELVIN
        temp_conversion = 1.8, -255.3
    #else
        temp_conversion = 1.8, 17.778
    #endif
#endif
...

...また、一部の条件文には#elseステートメントがなく、ただ#if CONDITION statement(s) #endif

これは、ファイルがXMLで記述されているか、最初から優れたパーサーを使用して作成されている場合は簡単ですが、これを処理する必要があるため、このファイルを解析する比較的簡単な方法があるかどうか疑問に思います。 。かっこマッチングに似ているので、モジュールがあると思いますが、何も見つかりませんでした。

私はPythonで作業していますが、別の言語でこれを解決する方が簡単な場合は、この関数に切り替えることができます。

4

2 に答える 2

6

この構文の単純な再帰パーサーは次のとおりです。

def parse(lines):
    result = []
    while lines:
        if lines[0].startswith('#if'):
            block = [lines.pop(0).split()[1], parse(lines)]
            if lines[0].startswith('#else'):
                lines.pop(0)
                block.append(parse(lines))
            lines.pop(0) #endif
            result.append(block)
        elif not lines[0].startswith(('#else', '#endif')):
            result.append(lines.pop(0))
        else:
            break
    return result

tree = parse([x.strip() for x in your_code.splitlines() if x.strip()])

あなたの例から、それは次のツリー構造を作成します:

[['CELSIUS',
  [['FROM_KELVIN',
    ['temp_conversion = 1, 273'],
    ['temp_conversion = 0.556, -32']]],
  [['FROM_KELVIN',
    ['temp_conversion = 1.8, -255.3'],
    ['temp_conversion = 1.8, 17.778']]]]]

これは簡単に評価できるはずです。

より高度な解析については、Pythonで利用できる多くの解析ツールの1つを検討してください。

于 2012-08-22T20:47:09.887 に答える
1

すべての条件はバイナリであり、すべての値を事前に知っているので(プログラミング言語のように順番に評価する必要はありません)、正規表現でそれを行うことができました。これは私にとってはうまくいきます。最下位レベルの条件(ネストされた条件がないもの)を見つけて評価し、正しい内容に置き換えます。次に、より高いレベルの条件などについて繰り返します。

import re

conditions = ['CELSIUS', 'FROM_KELVIN']

def eval_conditional(matchobj):
    statement = matchobj.groups()[1].split('#else')
    statement.append('') # in case there was no else statement
    if matchobj.groups()[0] in conditions: return statement[0]
    else: return statement[1]

def parse(text):
    pattern = r'#if\s*(\S*)\s*((?:.(?!#if|#endif))*.)#endif'
    regex = re.compile(pattern, re.DOTALL)
    while True:
        if not regex.search(text): break
        text = regex.sub(eval_conditional, text)
    return text

if __name__ == '__main__':
    i = open('input.txt', 'r').readlines()
    g = ''.join([x.split(';')[0] for x in i if x.strip()])
    o = parse(g)
    open('output.txt', 'w').write(o)

元の投稿に入力すると、次のように出力されます。

...
        temp_conversion = 1, 273

...

それが私に必要なものです。皆様のご回答ありがとうございました!

于 2012-08-23T22:58:49.637 に答える