lua-users home
lua-l archive

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


On Tue, Oct 20, 2009 at 4:13 PM, Duncan Cross  wrote:
> On Tue, Oct 20, 2009 at 7:41 PM, Linus Sjögren wrote:
>> Here's the regex in question:
'^(?:(?:ceil|abs|floor|mod|exp|log|pow|sqrt|acos|asin|atan|cos|sin|tan|deg|rad|random)\\(|pi|\\(|\\)|-|\\+|\\*|/|\\d|\\.|\\^|\\x2C|
>> )+$'
>
> Lua's string patterns are not full regular expressions, and simply
> don't support many constructs like (pattern1|pattern2) or (pattern)+....
> However, if you'd like to see what a "pure-Lua" solution would look
> like, here is one.

I've updated the pure-Lua "xpattern" library:

  http://lua-users.org/wiki/ExPattern

So, one can now write a quasi-Lpeg like test as such:

  local m = (
    P'^' * ( ( P'ceil'+P'abs' +P'floor'+P'mod' +P'exp'+P'log'+P'pow'+
               P'sqrt'+P'acos'+P'asin' +P'atan'+P'cos'+P'sin'+P'tan'+
               P'deg' +P'rad' +P'random'
             ) * P'%('
             + P'[0-9%(%)%-%+%*%/%.%,]' + P'pi'
            )^1 * P'$'
  ):compile()
  assert(m'cos(1+pi)' == 'cos(1+pi)')
  assert(m'cos(1+p)' == nil) -- 'p'
  assert(m'cos(12.3/2)+mod(2,3)' == 'cos(12.3/2)+mod(2,3)')
  assert(m'cos(12.3/2)+mod(2,3) ' == nil) -- ' '
  assert(m' cos(12.3/2)+mod(2,3)' == nil) -- ' '
  assert(m'cos(12.3/2)+mod+2' == nil) -- no '('

And it code generates this Lua code:

local match = ...  -- string.match
return function(s,pos)
  local pos1=pos or 1
  local pos2
  pos2 = match(s, "^()", pos1)
  if pos2 then
    do
      local pos3=pos2
      pos2 = nil
      while 1 do
        local pos4 = pos3
        local pos5 = pos3
        local pos6 = pos3
        local pos7 = pos3
        local pos8 = pos3
        local pos9 = pos3
        local pos10 = pos3
        local pos11 = pos3
        local pos12 = pos3
        local pos13 = pos3
        local pos14 = pos3
        local pos15 = pos3
        local pos16 = pos3
        local pos17 = pos3
        local pos18 = pos3
        local pos19 = pos3
        local pos20 = pos3
        local pos21 = pos3
        pos21 = match(s, "^ceil()", pos3)
        if not pos21 then
          pos21 = match(s, "^abs()", pos3)
        end
        pos20 = pos21
        if not pos20 then
          pos20 = match(s, "^floor()", pos3)
        end
        pos19 = pos20
        if not pos19 then
          pos19 = match(s, "^mod()", pos3)
        end
        pos18 = pos19
        if not pos18 then
          pos18 = match(s, "^exp()", pos3)
        end
        pos17 = pos18
        if not pos17 then
          pos17 = match(s, "^log()", pos3)
        end
        pos16 = pos17
        if not pos16 then
          pos16 = match(s, "^pow()", pos3)
        end
        pos15 = pos16
        if not pos15 then
          pos15 = match(s, "^sqrt()", pos3)
        end
        pos14 = pos15
        if not pos14 then
          pos14 = match(s, "^acos()", pos3)
        end
        pos13 = pos14
        if not pos13 then
          pos13 = match(s, "^asin()", pos3)
        end
        pos12 = pos13
        if not pos12 then
          pos12 = match(s, "^atan()", pos3)
        end
        pos11 = pos12
        if not pos11 then
          pos11 = match(s, "^cos()", pos3)
        end
        pos10 = pos11
        if not pos10 then
          pos10 = match(s, "^sin()", pos3)
        end
        pos9 = pos10
        if not pos9 then
          pos9 = match(s, "^tan()", pos3)
        end
        pos8 = pos9
        if not pos8 then
          pos8 = match(s, "^deg()", pos3)
        end
        pos7 = pos8
        if not pos7 then
          pos7 = match(s, "^rad()", pos3)
        end
        pos6 = pos7
        if not pos6 then
          pos6 = match(s, "^random()", pos3)
        end
        pos5 = pos6
        if pos5 then
          pos5 = match(s, "^%(()", pos5)
        end
        if not pos5 then
          pos5 = match(s, "^[0-9%(%)%-%+%*%/%.%,]()", pos3)
        end
        pos4 = pos5
        if not pos4 then
          pos4 = match(s, "^pi()", pos3)
        end
        pos3 = pos4
        if pos3 then
          pos2=pos3
        else break end
      end
    end
  end
  if pos2 then
    pos2 = match(s, "^()$", pos2)
  end

  if pos2 then return s:sub(pos1,pos2-1) end
end

It's currently somewhat experimental, so fix it up if you're so inclined.