lua-users home
lua-l archive

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


Roberto Ierusalimschy a écrit :
so, to have patt{n,m}, can we write
  patt^n * patt^(n - m)

This is not correct. Remember that patt^n is actually "at least n". So,
patt^n will always consume as many patt as possible, leaving no one to
patt^(n - m) (which will always fail).

Ah, my newbie error...

? Is it possible to express this without writing the pattern twice? (or is it a non-issue?)

I am not sure whether {n,m} is that common to deserve primitive support.

I don't ask that much, an elegant workaround would have been enough (like the 1 - p for "any char but the pattern"). {n,m} isn't used that much, but {n} is more often used (eg. parsing telephone numbers, zip codes, social security numbers, credit card numbers, etc.).

But it should be easy to write a function to build that kind of patterns.
Something like this (untested!):

function rep (p, n, m)
  local r = lpeg.P""
  for i = 1, n do r = r * p end    -- at least n
  if not m then m = 0
  else m = n - m     -- assuming that n > m
  end
  return r * p^m
end

If I am not mistaken, your comment should be "assuming that n < m"...
At least, that's how I interpret these parameters. And m must be negative to work OK, anyway (at most -m occurences, right?).
Mmm, there should be a test for n = m, returning only r.

-- emulates {n,m} syntax of REs:
-- {n,} n or more repeats
-- {n} exactly n repeats
-- {n,m} at least n repeats, at most m
function rep (p, n, m)
  local r = lpeg.P""
  for i = 1, n do r = r * p end    -- at least n
  if m == nil or m <= 0 then m = 0 -- {n,}
  elseif m <= n then return r      -- {n,n} or {n}
  else m = n - m                   -- m is negative
  end
  return r * p^m
end

As untested as your...

That's the point of composability. (We could have a library of these
auxiliary functions.)

Indeed. That's nice.
I still think that having some opcode to exact number of matching could be interesting (consuming less memory, faster) but it is not obvious to fit it in your syntax.
Unless having a lpeg.Rep(p, n, m)... (or just lpeg.Rep(p, n)).

Thanks, I will try to compile this for Windows to be able to test it.

--
Philippe Lhoste
--  (near) Paris -- France
--  http://Phi.Lho.free.fr
--  --  --  --  --  --  --  --  --  --  --  --  --  --