我有一个关于嵌套语法的问题。如何让 pyparsing 查找嵌套语法结构。
from pyparsing import Word, alphas, alphanums, Suppress, LineEnd, LineStart, nums, Or, Group, OneOrMore, Literal, CaselessLiteral, Combine, Optional
word = Word(alphanums+'_')
object_type = Suppress("object ")+word.setResultsName("object_type")+Suppress('{')+LineEnd()
point = Literal('.')
e = CaselessLiteral('E')
plusorminus = Literal('+') | Literal('-')
number = Word(nums)
integer = Combine( Optional(plusorminus) + number )
floatnumber = Combine( integer +
Optional( point + Optional(number) ) +
Optional( e + integer )
)
attribute = word.setResultsName("attribute")
value = Or([floatnumber, word]).setResultsName("value")
attributes = Group(attribute+value+Suppress(";")+LineEnd())
namespace = Group(object_type+\ OneOrMore(attributes).setResultsName("attributes") + Suppress("}"))
all = OneOrMore(namespace).setResultsName("namespaces")
result = all.parseString(glm)
for n in result.namespaces:
print(n)
以下是我想要解析的示例。第一个命名空间按预期工作。然而,第二个无法解析。谁能解释一下我缺少什么?
"""object object_type1{
attr1 0.0111;
name name_of_object_1;
}
object object_type1{
attr1 0.02;
name name_of_object_2;
object object_type2{
name name_of_object_3;
}
}
"""
最佳答案
要定义递归语法,即具有一个术语本身就是其自身定义的一部分的语法,您需要使用 pyparsing 的 Forward
类(class)。在您的情况下, namespace
可以包含属性或嵌套命名空间。为此,您首先必须为 namespace
定义一种占位符。 :
namespace = Forward()
然后,当需要定义内容时(其中包括 namespace
作为定义的一部分),请使用 <<=
运算符而不是 =
:
namespace <<= Group(object_type + OneOrMore(attributes|namespace).setResultsName("attributes") + Suppress("}"))
all = OneOrMore(namespace).setResultsName("namespaces")
除此之外,您的解析器应该可以正常工作。
还有一些其他提示:
我最近添加了
pprint()
方法来简化列出 ParseResults 对象的内容。试试result.pprint()
而不是您现在使用的 for 循环。您实际上不需要输出中的换行符,因此替换所有
LineEnd()
条款LineEnd().suppress()
- 这将使您的结果稍微整洁一些。在这种情况下,我不确定结果名称是否真的对您有多大作用。但我发现使用
expr("name")
比expr.setResultsName("name")
更具可读性。但任何一种形式都可以。
关于python - PyParsing 的嵌套语法行为不符合预期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36383030/