PyParsing在嵌套语法中表现不尽如人意

时间:2016-04-03 08:07:47

标签: python parsing pyparsing

我对嵌套语法有疑问。如何使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;
    }
}
"""

1 个答案:

答案 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")更具可读性。但任何一种形式都可行。