我对嵌套语法有疑问。如何使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;
}
}
"""
答案 0 :(得分:1)
要定义递归语法,即具有自身属于其自身定义的一个术语的递归语法,您需要使用pyparsing的Forward
类。在您的情况下,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")
更具可读性。但任何一种形式都可行。