I’m using pyparsing to parse vcd (value change dump) files. Essentially, I want to read in the files, parse it into an internal dictionary, and manipulate the values.
Without going into details on the structure, my problem occurs with identifying nested categories.
In vcd files, you have ‘scopes’ which include wires and possibly some deeper (nested) scopes. Think of them like levels.
So in my file, I have:
$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
So ‘toplevel’ encompasses everything (a – i), ‘midlevel’ has (a – b), ‘extralevel’ has (f – g), etc.
Here is my code (snippet) for parsing this section:
scope_header = Group(Literal('$scope') + Word(alphas) + Word(alphas) + \
Literal('$end'))
wire_map = Group(Literal('$var') + Literal('wire') + Word(alphas) + \
Literal('$end'))
scope_footer = Group(Literal('$upscope') + Literal('$end'))
scope = Forward()
scope << (scope_header + ZeroOrMore(wire_map) + ZeroOrMore(scope) + \
ZeroOrMore(wire_map) + scope_footer)
Now, what I thought happens is that as it hits each scope, it would keep track of each ‘level’ and I would end up with a structure containing nested scopes. However, it errors out on
$scope module extralevel $end
saying it expects ‘$upscope’.
So I know I’m not using the recursion correctly. Can someone help me out? Let me know if I need to provide more info.
Thanks!!!!
According to your definition, a scope cannot contain another scope, followed by some maps, followed by another scope.
If the parser has a debug mode where it prints its parse tree, you will be able to see this immediately. But in short, you’re saying there are zero or more maps, followed by zero or more scopes, followed by zero or more maps, so if there is a scope, followed by a map, you have already passed the scope field, so any more scopes are invalid. If the language used by pyparsing supports “or” you could use: