lua-users home
lua-l archive

Re: lpeg: bug or intentional? `… * (Cmt(0,f1) + Cmt(0,f2)) * …` doesn't call f2

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On 08/04/2019 03.07, Sean Conner wrote:
It was thus said that the Great nobody once stated:
 -- wrap pattern with enter/leave (pattern simplified to "foo" here)
 -- leave should always ping once (on success or by backtracking)
 p = (enter + leave) * C"foo" * leave
 For p:match("bar"), the enter rule will *always* match, because it matches
the empty string; leave will never be called at all. So depth becomes 1.
Then the rule C"foo" is attempted, and since it fails, the entire match
fails at that point, so leave (which is an "and this pattern") is never
called. To properly keep track of level, you might have to do:
	p = C"foo" * enter * rest_of_foo * leave
If you do:
	p = enter * C"foo" * rest_of_foo * leave
	 + leave
Oh, right. As a sub-pattern, (enter+leave) succeeded via the first branch, and there's no backtracking *into* that sub-pattern – that was my misconception. So the correct thing is
 p = enter * (C"foo" * leave + leave)
or (de-simplified a bit)
 p = enter * (C"foo" * leave + fail_hard)
and things work as expected now.
That still left me wondering about those huge negative numbers in the debug output. Digging further, they seem to be produced by any failing match, even by something as simple as
 require"lpeg".P"x":match""
and looking at the source reveals that the PC is computed by pointer difference to the pcode base address, but `giveup` is actually a
 static const Instruction giveup = {{IGiveup, 0, 0}};
i.e. located in a completely different place, hence the big difference.
So all is well – thanks for the help!
-- nobody

AltStyle によって変換されたページ (->オリジナル) /