parsimonious
parsimonious copied to clipboard
rule1 = rule2 Seems to cause the parser to ignore rule 1
Have a rule that looks like the following
rule0 = rule1 / rule3
rule1 = rule2
rule2 = [a-z][a-zA-Z0-9]*
rule3 = rule2 & rule2
The tree seems to optimise out rule1 but I need it do work. How can I work around this?
For a quick fix, you could attach some zero-length production to rule1, like rule1 = rule2 ""
. But I'm interested in hearing more detail about what you're trying to do. (Because indeed, I did design it to optimize out "passthrough" rules.)
Not the OP, but in my case I need to be able to distinguish between two different matches of the same rule within the context of another rule. Example:
rule0 = [a-z]+
rule1 = rule0 " " rule0? " " rule0
This is a pretty meaningless example, but later when I get to visiting rule1, I have no easy way to tell by looking at the children which rule0
matched.
Thanks for the concrete example. If we can show there's a definite need, this is certainly worth addressing. However, for situations like your example, I don't see a problem: I would generally do something like this in the rule1 visitor:
def visit_rule1(self, node, (first_rule0, _, second_rule0, _, third_rule0)):
...
You can then tell which rule0 instance matched by position. DId you mean, instead, to posit an alternation, like rule0 " " / rule0? " " / rule0
? That might make it more interesting.
That's a helpful use of tuple unpacking. Thanks! :)
In my case I have some rule like:
verse = (verse_open block verse_close) / block
and then the implementation of visit_verse is messy because I need to check how to unpack visited_children:
def visit_verse(self, node, visited_children):
try:
_, block, _ = visited_children[0]
except ValueError:
block = visited_children[0]
if I had 2 rules:
verse = (verse_open block verse_close)
simple_verse = block
there could be just 2 separate visit methods (visit_verse
and visite_simple_verse
)
Update: Found out a way to rewrite the rules so the alternation has always single element like:
verse_block = verse_open block verse_close
verse = verse_block / block