我正在尝试使用pyparsing定义输入解析器。我设法正确解析了以下内容:
key = value
其中值可以是例如整数。这是Python代码:
import pyparsing as pp
_name = pp.Word(pp.alphas + '_', pp.alphanums + '_')
_key = _name + EQ
_value = pp.pyparsing_common.signed_integer
pp.dictOf(_key, _value)
现在,我想添加一个“原始”数据输入:
$raw
H 0.0 0.0 0.0
F 1.0 1.0 1.0
$end
其中$
和$end
之间的任何内容都被“拼凑”成一个字符串,其关键字将为raw
。我尝试过:
import pyparsing as pp
SDATA = pp.Literal('$').suppress()
EDATA = pp.CaselessLiteral('$end').suppress()
data_t = pp.Combine(SDATA + pp.Word(pp.alphas + '_', pp.alphanums + '_')
) + pp.SkipTo(EDATA) + EDATA
data_t.setName('raw data')
data_t.setParseAction(lambda token: (token[0], token[1]))
,这适用于输入字符串'$raw\nH 0.0 0.0 0.0\nF 1.0 1.0 1.0\n$end'
但是,我无法将key = value
解析器与data_t
组合在一起。有什么明显的我想念的地方吗?还是不可能将两者结合起来?
更新
这是测试输入:
$raw
H 0.0 0.0 0.0
F 1.0 1.0 1.0
$end
int = 42
这是我将key = value
和“原始”数据解析器组合在一起的方式:
parser = pp.dictOf(_key, _value) ^ data_t
带有解析,然后调用为:
tokens = parser.parseString(keywords).asDict()
这将返回一个空的dict
。将int = 42
移到$raw ... $end
上方只会返回{'int': 42 }
。
答案 0 :(得分:1)
Y!部分原因是dictOf
中的错误。为了在此方面取得进展,我定义了以下内容:
kv_dict = pp.Dict(pp.OneOrMore(pp.Group(_key + _value)))
然后我将解析器定义为:
parser = pp.OneOrMore(pp.Group(data_t) | pp.Group(kv_dict))
分组很重要,因此一组中的键不会踩到另一组中的键。 (dictOf
中的错误阻止了将其像这样包含在OneOrMore
中,因为dictOf
允许一个空的字典,因此它会在字符串的末尾永远循环而不是终止。)>
最后,我使用dump()
而不是asDict()
来查看结果。 asDict()
仅显示已命名的已解析令牌,而您的data_t
未显示。
print(parser.parseString(sample).dump())
礼物:
[[('raw', 'H 0.0 0.0 0.0\nF 1.0 1.0 1.0\n')], [['int', 42]]]
[0]:
[('raw', 'H 0.0 0.0 0.0\nF 1.0 1.0 1.0\n')]
[1]:
[['int', 42]]
- int: 42
如果要在data_t中添加名称,请将其定义更改为该名称,然后删除parse操作:
data_t = pp.Combine(SDATA + pp.Word(pp.alphas + '_', pp.alphanums + '_')
)("name") + pp.SkipTo(EDATA)("body") + EDATA
现在我得到了:
[['raw', 'H 0.0 0.0 0.0\nF 1.0 1.0 1.0\n'], [['int', 42]]]
[0]:
['raw', 'H 0.0 0.0 0.0\nF 1.0 1.0 1.0\n']
- body: 'H 0.0 0.0 0.0\nF 1.0 1.0 1.0\n'
- name: 'raw'
[1]:
[['int', 42]]
- int: 42