lua-users home
lua-l archive

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


It was thus said that the Great nobody once stated:
> Hey everyone,
> 
> this behavior has surprised me a bit.  I was trying to use this to keep
> track of the nesting of structures (to produce a backtrace in terms of
> grammar rules when stuff fails to match), but it doesn't work as
> expected…  Simplified example:
> 
> (checked in versions 1.0.1 and 1.0.2)
> 
>     lpeg = require "lpeg" ; C, Cmt, P = lpeg.C, lpeg.Cmt, lpeg.P
>     depth = 0
>     enter = Cmt( 0, function(_,p)  depth = depth + 1 ; return p  end )
>     leave = Cmt( 0, function(_,p)  depth = depth - 1 ; return p  end )
> 
>     -- 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
> 
>     -- tests
>     p:match "foo" ; print( depth ) --> 0 - ok!
>     p:match "bar" ; print( depth ) --> 1 - huh?!?

  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

depth will become out of sync with the actual depth level because you are
leaving a level you never entered.  You could simplify this with:

	function enter(pattern)
	  return pattern 
               * Cmt(0,function(_,p) depth = depth + 1 return p end )
        end

	p = enter(C"foo") * rest_of_grammar * leave

or maybe even

	function adjust_depth(delta)
	  return Cmt(0,function(_,p) depth = depth + delta return p end )
	end

	function deeper(start_pattern,rest_pattern)
	  return start_pattern
               * adjust_depth(1)
	       * rest_pattern)
	       * adjust_depth(-1)
	end

	p = deeper(C"foo",rest_of_foo)
	  + deeper(C"bar",rest_of_bar)

  -spc (Or maybe use LPEG to to parse a grammar that tracks the depth of a
	gammar ... )