请选择@ZackBloom 的答案作为正确答案,他马上直觉,甚至不知道 pyparsing 的语法。
只是对您的语法的一些评论/建议:
通过上面发布的答案,您可以在 ParseResultsasList()
上使用 pprint 和 pyparsing 的方法来可视化嵌套:
res = scope.parseString(vcd)
from pprint import pprint
pprint(res.asList())
给予:
[[['$scope', 'module', 'toplevel', '$end'],
[['$scope', 'module', 'midlevel', '$end'],
['$var', 'wire', 'a', '$end'],
['$var', 'wire', 'b', '$end'],
['$upscope', '$end']],
['$var', 'wire', 'c', '$end'],
['$var', 'wire', 'd', '$end'],
['$var', 'wire', 'e', '$end'],
[['$scope', 'module', 'extralevel', '$end'],
['$var', 'wire', 'f', '$end'],
['$var', 'wire', 'g', '$end'],
['$upscope', '$end']],
['$var', 'wire', 'h', '$end'],
['$var', 'wire', 'i', '$end'],
['$upscope', '$end']]]
所以现在你得到了结构良好的结果。但是你可以稍微清理一下。一方面,既然你有了结构,你就不需要所有那些$scope
,$end
等标记。您当然可以在浏览解析结果时跳过它们,但您也可以让 pyparsing 将它们从解析的输出中删除(因为结果现在是结构化的,所以您并没有真正失去任何东西)。将解析器定义更改为:
SCOPE, VAR, UPSCOPE, END = map(Suppress,
"$scope $var $upscope $end".split())
MODULE, WIRE = map(Literal, "module wire".split())
scope_header = Group(SCOPE + MODULE + Word(alphas) + END)
wire_map = Group(VAR + WIRE + Word(alphas) + END)
scope_footer = (UPSCOPE + END)
(无需分组scope_footer
- 该表达式中的所有内容都被抑制,因此Group
只会给您一个空列表。)
现在您可以更清楚地看到真正重要的部分:
[[['module', 'toplevel'],
[['module', 'midlevel'], ['wire', 'a'], ['wire', 'b']],
['wire', 'c'],
['wire', 'd'],
['wire', 'e'],
[['module', 'extralevel'], ['wire', 'f'], ['wire', 'g']],
['wire', 'h'],
['wire', 'i']]]
冒着太多分组的风险,我建议你也Group
把你的scope
表达内容,像这样:
scope << Group(scope_header +
Group(ZeroOrMore((wire_map | scope))) +
scope_footer)
这给出了这些结果:
[[['module', 'toplevel'],
[[['module', 'midlevel'], [['wire', 'a'], ['wire', 'b']]],
['wire', 'c'],
['wire', 'd'],
['wire', 'e'],
[['module', 'extralevel'], [['wire', 'f'], ['wire', 'g']]],
['wire', 'h'],
['wire', 'i']]]]
现在每个作用域结果都有 2 个可预测的元素:模块头,以及连线或子作用域的列表。这种可预测性将使编写用于导航结果的递归代码变得更加容易:
res = scope.parseString(vcd)
def dumpScope(parsedTokens, indent=''):
module,contents = parsedTokens
print indent + '- ' + module[1]
for item in contents:
if item[0]=='wire':
print indent + ' wire: ' + item[1]
else:
dumpScope(item, indent+' ')
dumpScope(res[0])
结果看起来像:
- toplevel
- midlevel
wire: a
wire: b
wire: c
wire: d
wire: e
- extralevel
wire: f
wire: g
wire: h
wire: i
好的第一个问题,欢迎来到 SO 和 pyparsing!