Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 解析嵌套的条件语句_Python_Regex_Conditional Compilation - Fatal编程技术网

Python 解析嵌套的条件语句

Python 解析嵌套的条件语句,python,regex,conditional-compilation,Python,Regex,Conditional Compilation,我需要解析一个包含条件语句的文件,这些语句有时相互嵌套 我有一个存储配置数据的文件,但根据用户定义的选项,配置数据略有不同。我可以处理条件语句,它们都是布尔型的,没有任何操作,但我不知道如何递归地计算嵌套的条件语句。例如,文件的一部分可能如下所示: ... #if CELSIUS #if FROM_KELVIN ; this is a comment about converting kelvin to celsius. temp_conversion = 1, 273

我需要解析一个包含条件语句的文件,这些语句有时相互嵌套

我有一个存储配置数据的文件,但根据用户定义的选项,配置数据略有不同。我可以处理条件语句,它们都是布尔型的,没有任何操作,但我不知道如何递归地计算嵌套的条件语句。例如,文件的一部分可能如下所示:

...
#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条件语句#endif

我意识到,如果文件是用XML或其他语言编写的,并且有一个很好的解析器,那么这可能很容易,但这就是我必须处理的,所以我想知道是否有相对简单的方法来解析这个文件。它类似于括号匹配,所以我想会有一些模块,但我没有找到任何东西


我正在使用python,但是如果用另一种语言更容易解决这个问题,我可以切换到这个函数。

这里有一个简单的递归语法分析器:

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中许多可用的一种。

< P>因为所有的条件都是二进制的,并且我事先知道它们的值(不需要按照编程语言顺序对它们进行评估),所以我能够用正则表达式来完成。这对我更有效。它查找最低级别的条件(没有嵌套条件的条件),计算它们并用正确的内容替换它们。然后对更高级别的条件句进行重复,以此类推

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)
根据原始post中的输入,它输出:

...
        temp_conversion = 1, 273

...

这正是我需要的。感谢大家的回复,我真的很感谢大家的帮助

这种格式有名称或标准吗?如何/在哪里定义像FROM_KELVIN这样的常数?最后,为什么每个赋值都有两个值?它是否应该为
temp_conversion
分配一个元组?不确定这是否是一个好主意,但您可以通过几个正则表达式替换将此代码转换为Python代码(我用了四个)并在沙盒环境中对其进行评估。@DavidRobinson该格式没有我所知的标准,我正在尝试制作一个小型开源程序,该程序将与现有专有应用程序使用的旧格式兼容,这就是他们使用的格式。处理条件和语句不是问题,我会为条件保留一个布尔字典,我已经有了一个用于temp_转换的正则表达式解析器。谢谢!这很有帮助,但是文件有多个条件,这个函数将把它们都放在同一个结构中。此外,如果代码可以在不破坏解析器的情况下以笨拙的形式形成,这将是一件好事,这段代码期望所有内容都能通过换行符很好地分割,等等。也许解析器是一种可行的方法,看起来YAPPS(来自您发布的链接)可以很好地解决这个问题。