lua-users home
lua-l archive

[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