lua-users home
lua-l archive

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

On Mon, Feb 21, 2011 at 12:55 PM, Tony Finch <> wrote:
On Mon, 21 Feb 2011, Wim Langers wrote:
> the first part of below code (recursuve pattern) will print :
> input  key  peer
> input  key2  peer2
> input  key2  peer2
> insert key
> insert key2
>   Inputs_ = V('Input') * V('_SPC') * V('Inputs_') + V('Input')
> Lpeg.match(PATTERN,'(key::peer key2::peer2)')

The reason for this is the match-time capture is exposing LPEG's
backtracking. The first time LPEG sees the second Input it tries to parse
it as Input * _SPC * Inputs_. This fails after matching Input when it
tries to match _SPC against the closing bracket. So it backtracks and
successfully matches against the alternative Input. So it matched the
second Input twice.

Why are you using match-time captures? I didn't see anything in your
grammar that required them.

This is a stripped down version of the pattern that still exposes the phenomen.
The actual pattern creates objects from the match time captures.  Since the data has a tree structure these objects combined with other data generate encapsulating objects etc...

Your explanation sounds logical (given my very limited knowledge of LPEG), but then why does the following example behave "as expected" (my pattern further stripped down) ?

prints twice :
insert a
insert b

Lpeg = require('lpeg')

local C,Cc,Cf,Cmt,Cp,Ct,P,R,S,V = Lpeg.C,Lpeg.Cc,Lpeg.Cf,Lpeg.Cmt,Lpeg.Cp,Lpeg.Ct,Lpeg.P,Lpeg.R,Lpeg.S,Lpeg.V
local PATTERN = {
      Inputs = Cmt(P('(') * Cf(Ct('') * V('Inputs_'),function(t,v) print ('insert',v) table.insert(t,v) return t end) * P(')'),function(s,i,t) return i end),
      Inputs_ = C(R('az')) * P(' ') * V('Inputs_') + C(R('az'))

Lpeg.match(PATTERN,'(a b)')

print('pattern without recursion')

local PATTERN = {
      Inputs = Cmt(P('(') * Cf(Ct('') * V('Inputs_')    ^1    ,function(t,v) print ('insert',v) table.insert(t,v) return t end) * P(')'),function(s,i,t) return i end),
      Inputs_ = C(R('az')) * P(' ')^0

Lpeg.match(PATTERN,'(a b)')

And to make my story complete :-)
This same methodology has following results :
- the simplest example C(R('az')) works as expected
- my other example prints the second "input" twice
- on a higher level the match doesn't produce any results (and the same match with ^1) does => this one triggered my "debug session"

Cheers ,


f.anthony.n.finch  <>
Dover, Wight: Southeast, backing northeast 3 or 4, occasionally 5. Slight or
moderate. Occasional rain. Moderate or poor.