我需要解析一个包含条件语句的文件,有时会互相嵌套。
我有一个存储配置数据的文件,但配置数据略有不同,具体取决于用户定义的选项。我可以处理条件语句,它们都只是没有操作的布尔值,但我不知道如何递归地评估嵌套条件。例如,文件的一部分可能如下所示:
...
#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,但如果用另一种语言更容易解决这个问题,我可以切换这个函数。
答案 0 :(得分: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中可用的许多parsing tools之一。
答案 1 :(得分: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
...
这就是我需要的。感谢大家的回复,我非常感谢你的帮助!