> would be possible to let visitExpr and visitIntervening
> return a value (None or a bool)
> to indicate if they like to be called again or not for
> the remaining tokens?
Thanks for your suggestion. I've thought about it a bit, see what you
I think the default behavior would be that these methods, if defined, would
continue to be called as long as there are parsed matches in the input text.
Since Python methods that don't explicitly return anything actually return
None, then I would interpret a None return as the same as the default case,
that is, to keep on matching. To add an overt return value to indicate that
no more calls should be made, we could return True to keep on calling, or
False to stop calling. Oddly, this would have pyparsing treating returned
values of True and None equally, which is a bit of a code smell. If I
invert the meaning of the returned flag, False meaning keeping calling and
True meaning stop calling, then my flag asserts a negative, which is a
different kind of smell to me.
Instead of returning a flag, the methods could raise an exception, and
StopIteration seems like a logical choice. My first thought is to have
either one of these visit methods raise StopIteration, and have that stop
the parsing process altogether - this seems to me to be in line with the
spirit of the original Visitor pattern, in which all visit() methods were
roughly the same, differing only in argument signatures. Or I could track
visitExpr and visitIntervening separately, and if one raises StopIteration,
I could have pyparsing continue to call the other. But this feels weird, my
instinct would be to have StopIteration just stop parsing altogether,
whichever visit method raised it.
Here is an alternative: instead of adding this flag or exception as part of
the interaction between pyparsing and your Visitor code, you could have your
Visitor class handle the alternative logic. Here is a class that, after
having had a method called once, changes the instance's method to a
# redefine method, since we just wanted the first
self.method = self.do_nothing
co = CallOnceVisitor()
You could do the same in visitExpr, by changing self.visitExpr to
self.donothing. Pyparsing will still make the function calls, but they will
just return immediately. But now you have more control over what happens
when, and pyparsing's logic stays fairly simple-minded.
Overall, I think adding support for StopIteration (or similar exception) is
good, in which any visitXXX method can raise it and stop the parsing
process. If finer control is needed, then I would put the burden back on
the visitXXX method implementations to keep track, perhaps using techniques
like in CallOnceVisitor.