为什么 pyparsing 会删除空格?

问题描述 投票:0回答:1

我正在使用 pyparsing 来解析 sass 文件。我需要将 sass 文件转换为特定格式才能使用它们,保留空格非常重要。

import pyparsing as pp

pp.ParserElement.set_default_whitespace_chars('')

def parse(input_str):
    nested_exp = pp.nestedExpr('{','}').parseString("{"+input_str+"}").asList()
    return nested_exp

input_str = """selector
{
  a:b;
  c:d;
  selector
  {
    a:b;
    c:d;
  }
  y:z;
}"""

my_output = parse(input_str)

Expected Output: 
[['selector\n',['\n  a:b;\n  c:d;\n  selector\n',['\n    a:b;\n    c:d;\n'],'\n  y:z;\n']]]
My output: 
[['selector', ['a:b;\n  c:d;\n  selector', ['a:b;\n    c:d;'], 'y:z;']]]

注意“a:b;”之前应该有 2 个空格和“y:z;”。即使我使用了 set_default_whitespace_chars(''),为什么 pyparsing 会删除它们?一些空格被删除,而另一些则没有。

pyparsing
1个回答
0
投票

nested_expr
对所需的结果内容做出了许多假设,最值得注意的是,构成表达式“内容”的项目将是空格分隔的值。所以由此而来:

pp.nestedExpr().parse_string("(1 2 3( 4 5) 'xyz()')").as_list()

我们得到这个:

[['1', '2', '3', ['4', '5'], "'xyz()'"]]

您可以传递一些参数来自定义它,例如定义

ignore_expr
(默认为
quoted_string
expr,以便引号内的括号不会意外地被解析为嵌套分隔符)。您还可以尝试更具体地定义应该位于嵌套表达式内的
content
,例如获取嵌套整数列表的示例:

nested_ints = pp.nested_expr(content=pp.DelimitedList(pp.common.integer))
result = nested_ints.parse_string("(1,2(3,4,5)(6)7)")
print(result.as_list())

[[1, 2, [3, 4, 5], [6], 7]]

感谢您将其提取为易于重现的示例。不幸的是,你如何解决这个问题取决于你试图用这个嵌套列表做什么。

如果您只想检测嵌套列表并保持其完整,您可以将表达式包装在

original_text_for
帮助器中,如下所示:

    nested_exp = pp.original_text_for(pp.nestedExpr('{','}')).parseString("{"+input_str+"}").asList()

这只是将原始文本作为字符串返回:

['{selector\n{\n  a:b;\n  c:d;\n  selector\n  {\n    a:b;\n    c:d;\n  }\n  y:z;\n}}']

您可以看到这保留了所有内部空白,尽管这与您发布的预期列表不匹配。

不幸的是,

nested_expr
的当前实现会进行一些内部空白剥离,即使您已将默认空白字符设置为
''
。我将考虑在下一个版本中使其更加了解默认值。现在,您可能需要滚动自己的
nested_expr
来保留空白,如下所示:

opener = "{"
closer = "}"
ignoreExpr = pp.quoted_string().leave_whitespace()
content = pp.Combine(
                        pp.OneOrMore(
                            ~ignoreExpr
                            + pp.CharsNotIn(
                                opener + closer + pp.ParserElement.DEFAULT_WHITE_CHARS,
                                exact=1,
                            )
                        )
                    )
nested_expr = pp.Forward()
nested_expr <<= pp.Group(pp.Suppress(opener) + (nested_expr | content)[...] + pp.Suppress(closer))

def parse(input_str):
    nested_exp = nested_expr.parseString("{"+input_str+"}").asList()
    return nested_exp
© www.soinside.com 2019 - 2024. All rights reserved.