Extending lpeg's gsub example

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Extending lpeg's gsub example

Marcus Mason
I'd like to extend this example so that I can specify the maximum number of replacements as in normal string.gsub

function gsub (s, patt, repl) patt = lpeg.P(patt) patt = lpeg.Cs((patt / repl + 1)^0) return lpeg.match(patt, s) end

What would be the best way to achieve this?

Reply | Threaded
Open this post in threaded view
|

Re: Extending lpeg's gsub example

Sean Conner
It was thus said that the Great Marcus Mason once stated:

> I'd like to extend this example so that I can specify the maximum
> number of replacements as in normal string.gsub
>
> function gsub (s, patt, repl)
>   patt = lpeg.P(patt)
>   patt = lpeg.Cs((patt / repl + 1)^0)
>   return lpeg.match(patt, s)
> end
>
> What would be the best way to achieve this?

Here's one way that works:

        lpeg = require "lpeg"

        function gsub(s,patt,repl,n)
          n = n or math.maxinteger
          local match = 0

          patt = lpeg.Cmt(lpeg.P(patt),function(sub,pos,cap)
            if n == 0 then
              return
            else
              match = match + 1
              n     = n     - 1
              return pos
            end
          end)

          patt = lpeg.Cs((patt / repl + 1)^0)
          return lpeg.match(patt, s),match
        end

        test = "abcabcabcabcabc"
        print(gsub(test,"ab","AB"))
        print(gsub(test,"ab","AB",3))
        print(gsub(test,"xy","AB",3))

  lpeg.Cmt() does a compile-time match and it's here that we track the
number of matches.  I also added the second return (number of successful
matches) to match string.gsub().

  -spc