  lua-l archive

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

• Subject: Re: Can someone convert this POSIX regex to a Lua regex?
• From: David Manura <dm.lua@...>
• Date: Thu, 22 Oct 2009 02:04:44 -0400

```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.

```