我有一个可以解析的类型化和可选的嵌套参数列表。
Input:
(int:1, float:3, list:(float:4, int:5))
Expected Dump:
[[['int', '1'], ['float', '3'], ['list', [['float', '4'], ['int', '5']]]]]
如果省略该类型,则应根据以下值选择标准类型:
Input:
(1, float:3, (4, int:5))
Expected Dump:
[[['str', '1'], ['float', '3'], ['tuple', [['str', '4'], ['int', '5']]]]]
正如您所料,我将使用parseAction中的类型在解析过程中自动转换值。但是这一步已经有效,因此我在这里跳过它。
我解决这个问题的方法是:
import pyparsing as pp
diCastTypes={
"str": lambda value: value,
"int": lambda value: int(value),
"float": lambda value: float(value),
"tuple": lambda value: tuple(value),
"list": lambda value: list(value),
"set": lambda value: set(value),
"dict": lambda value: dict(value),
}
bsQuoted = lambda expr : pp.Literal('\\').suppress() + expr
def parsingString (specialSigns = '', printables = pp.printables):
seSpecialSigns = set(specialSigns).union(set('\\'))
signs = ''.join(sorted(set(printables).difference(seSpecialSigns)))
allowedLiterals = (
pp.Literal(r"\t").setParseAction(lambda : "\t") |
pp.Literal(r"\ ").setParseAction(lambda : " ") |
pp.Literal(r"\n").setParseAction(lambda : "\n") |
pp.Word(signs) |
bsQuoted('"') |
bsQuoted("'")
)
for special in seSpecialSigns:
allowedLiterals = allowedLiterals | bsQuoted(special)
return pp.Combine(pp.OneOrMore(allowedLiterals))
value = parsingString('(),=:')
nestedValue = pp.Forward()
castPattern = pp.Optional(pp.oneOf(list(diCastTypes.keys())) + pp.Literal(":").suppress(), "str")("castType")
castPatternSeq = pp.Optional(pp.oneOf(list(diCastTypes.keys())) + pp.Literal(":").suppress(), "tuple")("castType")
parameterValue = pp.nestedExpr(content=(
pp.Group(
(castPattern + value("rawValue")) |
(castPatternSeq + nestedValue)
) |
pp.Literal(',').suppress()
))
nestedValue <<= parameterValue
此实现几乎正确,但我的嵌套序列的默认值存在严重问题:
parameterValue.parseString('(int:1, float:3, list:(float:4, int:5))').dump()
"[[['int', '1'], ['float', '3'], ['list', [['float', '4'], ['int', '5']]]]]"
parameterValue.parseString('(1, float:3, (4, int:5))').dump()
"[[['str', '1'], ['float', '3'], [['str', '4'], ['int', '5']]]]"
如您所见,未设置序列的预期默认值元组,并且结果列表的深度不正确。我想nestedExpr()
在通过解析器(4, int:5)
之前捕获了模式(castPatternSeq + nestedValue)
。这个问题对我来说很严重,因为我打算在 nestedExpr 模式中调用parserAction:
(castPattern + value("rawValue")).setParseAction(castParameter)) |
(castPatternSeq + nestedValue).setParseAction(castParameter))
如果明确给出了类型,这种方法很有效,但当然不会失败。
是否有机会让nestedExpr
稍微贪婪一点?
我在实施中添加了delimitedList
:
value = parsingString('(),=:')
nestedValue = pp.Forward()
castPattern = pp.Optional(pp.oneOf(list(diCastTypes.keys())) + pp.Literal(":").suppress(), "str")("castType")
castPatternSeq = pp.Optional(pp.oneOf(list(diCastTypes.keys())) + pp.Literal(":").suppress(), "tuple")("castType")
parameterValue = pp.nestedExpr(content=pp.delimitedList(
pp.Group(
(castPattern + value("rawValue")) |
(castPatternSeq + nestedValue)
)
))
nestedValue <<= parameterValue
这很有效,但不是很好,正如您在以下示例中所看到的那样:
parameterValue.parseString('(int:1, (int:2, int:4))').dump()
"[[['int', '1'], ['tuple', [['int', '2'], ['int', '4']]]]]"
parameterValue.parseString('(int:1, ((int:2, int:4), (int:6, int9)) )').dump()
pyparsing.ParseException: Expected ")" (at char 6), (line:1, col:7)
parameterValue.parseString('(int:1, ((int:2, int:4) (int:6, int:9)) )').dump()
"[[['int', '1'], ['tuple', [[['int', '2'], ['int', '4']], [['int', '6'], ['int', '9']]]]]]"
parameterValue.parseString('(int:1, (tuple:(int:2, int:4) tuple:(int:6, int9)) )').dump()
"[[['int', '1'], ['tuple', [['tuple', [['int', '2'], ['int', '4']]], ['tuple', [['int', '6'], ['str', 'int9']]]]]]]"
示例2中的例外让我想到,nestedExpr
和delimitedList
彼此不能很好地工作,他们正在相互捕捉模式。无论原因是什么,这似乎都是问题所在,因为如果省略示例3中的,
,delimitedList
没有什么可以捕捉到的,整个模式都匹配。但不像我预期的那样,因为默认类型再次丢失。只有没有,
和显式类型,解析才能正常工作。
有什么想法吗?
问题,即声明
parameterValue.parseString('(int:1, ((int:2, int:4), (int:6, int9)) )').dump()
引发异常,可以通过稍微改变实现来解决(但这似乎更像是一个黑客而不是真正的解决方案)。我刚刚添加了表达式| pp.Literal(",").suppress()
:
value = parsingString('(),=:')
nestedValue = pp.Forward()
castPattern = pp.Optional(pp.oneOf(list(diCastTypes.keys())) + pp.Literal(":").suppress(), "str")("castType")
castPatternSeq = pp.Optional(pp.oneOf(list(diCastTypes.keys())) + pp.Literal(":").suppress(), "tuple")("castType")
parameterValue = pp.nestedExpr(content=pp.delimitedList(
pp.Group(
(castPattern + value("rawValue")) |
(castPatternSeq + nestedValue)
)
) | pp.Literal(",").suppress())
nestedValue <<= parameterValue