Pyparsing - 无法将文件解析为字典结构
Pyparsing - Trouble parsing file to dictionary structure
我正在尝试使用 Pyparsing 来解析 Aspartix(.apx) 格式文件 (http://www.dbai.tuwien.ac.at/research/project/argumentation/systempage/docu.htm),但我在将结果结构化为字典时遇到了问题。
我指定的语法如下:
from pyparsing import *
ID = Word(alphanums)
arg_pair = Group(ID + Suppress(',') + ID)
value = Word(nums)
lineEnd = Suppress(').')
arg = Suppress('arg(') + ID + lineEnd
attack = Suppress('att(') + arg_pair + lineEnd
pref = Suppress('pref(') + arg_pair + lineEnd
val = Suppress('val(') + ID + Suppress(',') + value + lineEnd
valpref = Suppress('valpref(') + value + Suppress(',') + value + lineEnd
support = Suppress('support(') + arg_pair + lineEnd
apx = OneOrMore(arg.setName('arg') | attack.setName('att') | pref.setName('pref') | val.setName('val') | valpref.setName('valpref') | support.setName('support'))
我不确定如何使用 setName() 函数来定义字典键,以便每次出现的 arg、攻击等规则都映射到定义的键。使用上面的代码不会产生可用的字典键。
例如:
"""arg(a).
arg(b).
att(a,b)."""
将映射到:
{"arg": ["a","b"], "att":[["a","b"]]}
如果您能提供任何帮助,我将不胜感激。
关于您的解析器的一些其他评论:
通常,您应该避免定义将关键字与相关标点符号组合在一起的文字。例如,将 arg 定义为 Suppress('arg(')
将专门查找 "arg(",如果关键字和左括号之间有任何空格,则会失败。相反,我建议使用关键字 class 定义您的关键字。如果你愿意,你可以禁止这些,但关键字将强制完全匹配单词,并防止意外匹配 'valpref' 的前导 'val'。
将 ID 定义为 Word(alphanums)
会导致混淆 ID 和整数值。我希望标识符至少始终以字母字符开头,因此您可以使用 Word 的双参数形式将字母指定为仅允许的前导字符集,并将字母数字指定为允许的正文字符集。
请参阅我对您的 post 回复的评论:setName()
与 setResultsName()
我稍微调整了你的解析器,使所有命令都有相同的键:"cmd" 和 "args"。这允许您编写多态代码,例如本示例末尾的 for 循环。
from pyparsing import *
LPAR,RPAR,DOT,COMMA = map(Suppress,"().,")
arg,attack,pref,val,valpref,support = map(Keyword,
"arg att pref val valpref support".split())
ID = Word(alphas, alphanums)
id_pair = Group(ID + COMMA + ID)
integer = Word(nums)
int_pair = Group(integer + COMMA + integer)
arg_cmd = Group(arg("cmd") + LPAR + ID("args") + RPAR)
attack_cmd = Group(attack("cmd") + LPAR + id_pair("args") + RPAR)
pref_cmd = Group(pref("cmd") + LPAR + id_pair("args") + RPAR)
val_cmd = Group(val("cmd") + LPAR + Group(ID + COMMA + integer)("args") + RPAR)
valpref_cmd = Group(valpref("cmd") + LPAR + int_pair("args") + RPAR)
support_cmd = Group(support("cmd") + LPAR + id_pair("args") + RPAR)
apx = OneOrMore((arg_cmd | attack_cmd | pref_cmd | val_cmd | valpref_cmd | support_cmd) + DOT)
for command in apx.parseString(apxSource):
print command.dump()
print command.cmd
print command.args
如果你想按照你原来的命名计划,我想它应该是这样的。
arg_cmd = Group(arg + LPAR + ID("arg") + RPAR)
attack_cmd = Group(attack + LPAR + id_pair("attack") + RPAR)
pref_cmd = Group(pref + LPAR + id_pair("pref") + RPAR)
val_cmd = Group(val + LPAR + Group(ID + COMMA + integer)("val") + RPAR)
valpref_cmd = Group(valpref + LPAR + int_pair("valpref") + RPAR)
support_cmd = Group(support + LPAR + id_pair("support") + RPAR)
或者这个。
arg_cmd = (arg + LPAR + ID("arg*") + RPAR)
attack_cmd = (attack + LPAR + id_pair("attack*") + RPAR)
pref_cmd = (pref + LPAR + id_pair("pref*") + RPAR)
val_cmd = (val + LPAR + Group(ID + COMMA + integer)("val*") + RPAR)
valpref_cmd = (valpref + LPAR + int_pair("valpref*") + RPAR)
support_cmd = (support + LPAR + id_pair("support*") + RPAR)
如您所见,有许多方法可以构建这些解析器和生成的解析结构,围绕个人风格以及对与错展开。在最后两个示例中,没有定义 "cmd" 或 "args" 名称,因此您必须从上面的示例 for 循环代码中删除它们。如果您正在寻找 dict-key 之类的解析,我认为最后一个结构将最像您正在寻找的内容。但是,请注意,此解析器将丢弃找到命令的顺序。如果顺序很重要,您可能应该使用前两个示例之一,因为组 classes 将保持命令顺序不变。
我正在尝试使用 Pyparsing 来解析 Aspartix(.apx) 格式文件 (http://www.dbai.tuwien.ac.at/research/project/argumentation/systempage/docu.htm),但我在将结果结构化为字典时遇到了问题。
我指定的语法如下:
from pyparsing import *
ID = Word(alphanums)
arg_pair = Group(ID + Suppress(',') + ID)
value = Word(nums)
lineEnd = Suppress(').')
arg = Suppress('arg(') + ID + lineEnd
attack = Suppress('att(') + arg_pair + lineEnd
pref = Suppress('pref(') + arg_pair + lineEnd
val = Suppress('val(') + ID + Suppress(',') + value + lineEnd
valpref = Suppress('valpref(') + value + Suppress(',') + value + lineEnd
support = Suppress('support(') + arg_pair + lineEnd
apx = OneOrMore(arg.setName('arg') | attack.setName('att') | pref.setName('pref') | val.setName('val') | valpref.setName('valpref') | support.setName('support'))
我不确定如何使用 setName() 函数来定义字典键,以便每次出现的 arg、攻击等规则都映射到定义的键。使用上面的代码不会产生可用的字典键。
例如:
"""arg(a).
arg(b).
att(a,b)."""
将映射到:
{"arg": ["a","b"], "att":[["a","b"]]}
如果您能提供任何帮助,我将不胜感激。
关于您的解析器的一些其他评论:
通常,您应该避免定义将关键字与相关标点符号组合在一起的文字。例如,将 arg 定义为
Suppress('arg(')
将专门查找 "arg(",如果关键字和左括号之间有任何空格,则会失败。相反,我建议使用关键字 class 定义您的关键字。如果你愿意,你可以禁止这些,但关键字将强制完全匹配单词,并防止意外匹配 'valpref' 的前导 'val'。将 ID 定义为
Word(alphanums)
会导致混淆 ID 和整数值。我希望标识符至少始终以字母字符开头,因此您可以使用 Word 的双参数形式将字母指定为仅允许的前导字符集,并将字母数字指定为允许的正文字符集。请参阅我对您的 post 回复的评论:
setName()
与setResultsName()
我稍微调整了你的解析器,使所有命令都有相同的键:"cmd" 和 "args"。这允许您编写多态代码,例如本示例末尾的 for 循环。
from pyparsing import *
LPAR,RPAR,DOT,COMMA = map(Suppress,"().,")
arg,attack,pref,val,valpref,support = map(Keyword,
"arg att pref val valpref support".split())
ID = Word(alphas, alphanums)
id_pair = Group(ID + COMMA + ID)
integer = Word(nums)
int_pair = Group(integer + COMMA + integer)
arg_cmd = Group(arg("cmd") + LPAR + ID("args") + RPAR)
attack_cmd = Group(attack("cmd") + LPAR + id_pair("args") + RPAR)
pref_cmd = Group(pref("cmd") + LPAR + id_pair("args") + RPAR)
val_cmd = Group(val("cmd") + LPAR + Group(ID + COMMA + integer)("args") + RPAR)
valpref_cmd = Group(valpref("cmd") + LPAR + int_pair("args") + RPAR)
support_cmd = Group(support("cmd") + LPAR + id_pair("args") + RPAR)
apx = OneOrMore((arg_cmd | attack_cmd | pref_cmd | val_cmd | valpref_cmd | support_cmd) + DOT)
for command in apx.parseString(apxSource):
print command.dump()
print command.cmd
print command.args
如果你想按照你原来的命名计划,我想它应该是这样的。
arg_cmd = Group(arg + LPAR + ID("arg") + RPAR)
attack_cmd = Group(attack + LPAR + id_pair("attack") + RPAR)
pref_cmd = Group(pref + LPAR + id_pair("pref") + RPAR)
val_cmd = Group(val + LPAR + Group(ID + COMMA + integer)("val") + RPAR)
valpref_cmd = Group(valpref + LPAR + int_pair("valpref") + RPAR)
support_cmd = Group(support + LPAR + id_pair("support") + RPAR)
或者这个。
arg_cmd = (arg + LPAR + ID("arg*") + RPAR)
attack_cmd = (attack + LPAR + id_pair("attack*") + RPAR)
pref_cmd = (pref + LPAR + id_pair("pref*") + RPAR)
val_cmd = (val + LPAR + Group(ID + COMMA + integer)("val*") + RPAR)
valpref_cmd = (valpref + LPAR + int_pair("valpref*") + RPAR)
support_cmd = (support + LPAR + id_pair("support*") + RPAR)
如您所见,有许多方法可以构建这些解析器和生成的解析结构,围绕个人风格以及对与错展开。在最后两个示例中,没有定义 "cmd" 或 "args" 名称,因此您必须从上面的示例 for 循环代码中删除它们。如果您正在寻找 dict-key 之类的解析,我认为最后一个结构将最像您正在寻找的内容。但是,请注意,此解析器将丢弃找到命令的顺序。如果顺序很重要,您可能应该使用前两个示例之一,因为组 classes 将保持命令顺序不变。