Python pyparsing中嵌套结构的技巧
我正在努力用PyParsing解析嵌套结构。我已经搜索了很多,但我不知道如何解决我的问题 以下是我的内部结构:Python pyparsing中嵌套结构的技巧,python,nested,pyparsing,Python,Nested,Pyparsing,我正在努力用PyParsing解析嵌套结构。我已经搜索了很多,但我不知道如何解决我的问题 以下是我的内部结构: texture_unit optionalName { texture required_val prop_name1 prop_val1 prop_name2 prop_val1 } 这是我的外部结构,但它可以包含零个或更多的内部结构 pass optionalName { prop_name1 prop_val1 prop_name2 pr
texture_unit optionalName
{
texture required_val
prop_name1 prop_val1
prop_name2 prop_val1
}
这是我的外部结构,但它可以包含零个或更多的内部结构
pass optionalName
{
prop_name1 prop_val1
prop_name2 prop_val1
texture_unit optionalName
{
// edit 2: showing use of '.' character in value
texture required_val.file.name optional_val // edit 1: forgot this line in initial post.
// edit 2: showing potentially multiple values
prop_name3 prop_val1 prop_val2
prop_name4 prop_val1
}
}
我正在成功解析内部结构。这是我的代码
prop_ = pp.Group(pp.Word(pp.alphanums+'_')+pp.Group(pp.OneOrMore(pp.Word(pp.alphanums+'_'+'.'))))
texture_props_ = pp.Group(pp.Literal('texture') + pp.Word(pp.alphanums+'_'+'.')) + pp.ZeroOrMore(prop_)
texture_ = pp.Forward()
texture_ << pp.Literal('texture_unit').suppress() + pp.Optional(pp.Word(pp.alphanums+'_')).suppress() + pp.Literal('{').suppress() + texture_props_ + pp.Literal('}').suppress()
prop_uz=pp.Group(pp.Word(pp.alphanums+''''''')+pp.Group(pp.OneOrMore(pp.Word(pp.alphanums+''+')))
纹理属性=pp.Group(pp.Literal('texture')+pp.Word(pp.alphanums++''+'))+pp.ZeroOrMore(属性属性属性)
纹理=pp.Forward()
有两个问题:
在语法中,您在纹理单元
块中按要求标记了纹理
文字,但在第二个示例中没有纹理
在第二个示例中,pass\u props\u
与texture\u unit optionalName
一致。在它之后,pp.Literal('}')
期望}
,但给出{
。这就是错误的原因
我们可以通过如下更改通过
规则进行检查:
pass_ << pp.Literal('pass').suppress() + pp.Optional(pp.Word(pp.alphanums+'_'+'.')).suppress() + \
pp.Literal('{').suppress() + pass_props_
print pass_.parseString(s2)
我们可以看到pass\u props\u
与texture\u unit optionalName
相一致,因此,我们要做的是:prop\u
可以包含字母数
、\ucode>和但不能与texture\u unit
文字匹配。我们可以使用regex
和:
最后,工作示例如下所示:
import pyparsing as pp
s1 = '''texture_unit optionalName
{
texture required_val
prop_name prop_val
prop_name prop_val
}'''
prop_ = pp.Group( pp.Regex(r'(?!texture_unit)[a-z0-9_]+')+ pp.Group(pp.OneOrMore(pp.Regex(r'(?!texture_unit)[a-z0-9_.]+'))) )
texture_props_ = pp.Group(pp.Literal('texture') + pp.Word(pp.alphanums+'_'+'.')) + pp.ZeroOrMore(prop_)
texture_ = pp.Forward()
texture_ = pp.Literal('texture_unit').suppress() + pp.Word(pp.alphanums+'_').suppress() +\
pp.Literal('{').suppress() + pp.Optional(texture_props_) + pp.Literal('}').suppress()
print texture_.parseString(s1)
s2 = '''pass optionalName
{
prop_name1 prop_val1.name
texture_unit optionalName1
{
texture required_val1
prop_name2 prop_val12
prop_name3 prop_val13
}
texture_unit optionalName2
{
texture required_va2l
prop_name2 prop_val22
prop_name3 prop_val23
}
}'''
pass_props_ = pp.ZeroOrMore(prop_ )
pass_ = pp.Forward()
pass_ = pp.Literal('pass').suppress() + pp.Optional(pp.Word(pp.alphanums+'_'+'.')).suppress() +\
pp.Literal('{').suppress() + pass_props_ + pp.ZeroOrMore(texture_ ) + pp.Literal('}').suppress()
print pass_.parseString(s2)
输出:
[['texture', 'required_val'], ['prop_name', ['prop_val', 'prop_name', 'prop_val']]]
[['prop_name1', ['prop_val1.name']], ['texture', 'required_val1'], ['prop_name2', ['prop_val12', 'prop_name3', 'prop_val13']], ['texture', 'required_va2l'], ['prop_name2', ['prop_val22', 'prop_name3', 'prop_val23']]]
我所寻找的答案与“Forward”解析器的使用有关,如Cstruct示例所示(在OP中链接)
为嵌套结构定义语法的困难部分是定义结构的所有可能成员类型,这需要包括结构本身,而结构本身尚未定义
为嵌套结构定义pyparsing语法的“诀窍”是延迟结构的定义,但在定义结构成员时包含结构的“前向声明”版本,因此成员也可以包含结构。然后将结构语法作为成员列表完成。
struct = Forward()
member = blah | blah2 | struct
struct << ZeroOrMore( Group(member) )
1.你是对的,我的嵌套示例缺少必需的“texture”属性。这是发布时的一个输入错误。我将在帖子中更正它。@cyrf第二项和他的解决方案如何?关于#2,谢谢你的建议。我仍在测试它。我正在试图理解为什么C结构中不需要“负面展望”t解析器示例,支持嵌套的C结构(在我的原始文章中链接)。新定义的“prop_”打破了对内部结构的解析。我应该让测试更明确,我试图让它更具一般性和可读性。我现在将编辑我的帖子,以更好地说明我需要什么。你能评论一下为什么C struct示例不需要“负面前瞻”?如果内部结构在pr中没有使用“.”op_val,然后解析内部结构。但是,使用您的更改解析外部结构仍然会产生错误。下面是另一个支持嵌套结构的示例。它似乎使用了“pyparsing.Dict”。所有这些示例都显示了实现嵌套解析的不同方法,其共性是什么?
import pyparsing as pp
s1 = '''texture_unit optionalName
{
texture required_val
prop_name prop_val
prop_name prop_val
}'''
prop_ = pp.Group( pp.Regex(r'(?!texture_unit)[a-z0-9_]+')+ pp.Group(pp.OneOrMore(pp.Regex(r'(?!texture_unit)[a-z0-9_.]+'))) )
texture_props_ = pp.Group(pp.Literal('texture') + pp.Word(pp.alphanums+'_'+'.')) + pp.ZeroOrMore(prop_)
texture_ = pp.Forward()
texture_ = pp.Literal('texture_unit').suppress() + pp.Word(pp.alphanums+'_').suppress() +\
pp.Literal('{').suppress() + pp.Optional(texture_props_) + pp.Literal('}').suppress()
print texture_.parseString(s1)
s2 = '''pass optionalName
{
prop_name1 prop_val1.name
texture_unit optionalName1
{
texture required_val1
prop_name2 prop_val12
prop_name3 prop_val13
}
texture_unit optionalName2
{
texture required_va2l
prop_name2 prop_val22
prop_name3 prop_val23
}
}'''
pass_props_ = pp.ZeroOrMore(prop_ )
pass_ = pp.Forward()
pass_ = pp.Literal('pass').suppress() + pp.Optional(pp.Word(pp.alphanums+'_'+'.')).suppress() +\
pp.Literal('{').suppress() + pass_props_ + pp.ZeroOrMore(texture_ ) + pp.Literal('}').suppress()
print pass_.parseString(s2)
[['texture', 'required_val'], ['prop_name', ['prop_val', 'prop_name', 'prop_val']]]
[['prop_name1', ['prop_val1.name']], ['texture', 'required_val1'], ['prop_name2', ['prop_val12', 'prop_name3', 'prop_val13']], ['texture', 'required_va2l'], ['prop_name2', ['prop_val22', 'prop_name3', 'prop_val23']]]
struct = Forward()
member = blah | blah2 | struct
struct << ZeroOrMore( Group(member) )
EOL = LineEnd().suppress()
ident = Word( alphas+"_", alphanums+"_$@#." )
integer = Word(nums)
real = Combine(Optional(oneOf('+ -')) + Word(nums) + '.' + Optional(Word(nums)))
propVal = real | integer | ident
propList = Group(OneOrMore(~EOL + propVal))