Reputation: 41443
I have a bunch of Lua 5.1 files that have this (or similar) construct inside:
... local alpha, beta = FUNCTION "gamma" { 'delta', 'epsilon' } ...
That is, a call to the FUNCTION
that returns a function that returns some values, that are assigned to some local variables, declared at the spot.
Exact code may vary somewhat — both in style (say, everything may be on the same line), and in content (say, there can be zero arguments passed to the second function call). But always things start with local
, and end with two chained function calls.
I've got a line number for FUNCTION
call. I need to find the end of the last function call in the chain (this particular one; there can be more FUNCTION
calls somewhere further in the file), and remove all file content upwards from that point.
I.e., before:
print("foo") -- 01 local alpha = FUNCTION 'beta' -- 02 { "gamma" } -- 03 print("bar") -- 04
after:
-- 03 print("bar") -- 04
Any clues on how to approach this?
Update:
To be more clear on why naïve regexp approach wouldn't work, a real life example:
local alpha = FUNCTION ( -- my line number points here FUNCTION 'beta' { 'gamma' } () and 'epsilon' or 'zeta' ) { 'eta' } -- should be cut from here and above as a result
Upvotes: 0
Views: 220
Reputation: 23757
Main idea: search for adjacent tits ()()
!
local line_no = 12
local str = [[
print("foo")
local nif_nif
= FUNCTION (
FUNCTION 'beta' { 'gamma' } ()
and 'epsilon'
or 'zeta'
)
{
'eta'
}
local nuf_nuf
= FUNCTION ( -- this is line#12
FUNCTION 'beta' { 'gamma' } ()
and 'epsilon'
or 'zeta'
)
{
'eta'
} -- should be cut from here
local naf_naf
= FUNCTION (
FUNCTION 'beta' { 'gamma' } ()
and 'epsilon'
or 'zeta'
)
{
'eta'
}
print("bar")
]]
-- cut all text before target "local" keyword
str = str:gsub('\n','\0',line_no):gsub('^.*(local.-%z)','%1'):gsub('%z','\n')
-- enclose string literals and table constructors into temporary parentheses
str = str:gsub('%b""','(\0%0\0)')
:gsub("%b''",'(\0%0\0)')
:gsub("%b{}",'(\0%0\0)')
-- replace text in parentheses with links to it
local n, t = 0, {}
str = str:gsub('%b()', function(s) n=n+1 t[n..'']=s return'<\0'..n..'>' end)
-- search for first chained function call and cut it out
str = str:gsub('^.-<%z%d+>%s*<%z%d+>', '')
repeat
local ctr
str, ctr = str:gsub('^%s*<%z%d+>', '')
until ctr == 0
-- replace links with original text
t, str = nil, str:gsub('<%z(%d+)>', t)
-- remove temporary parentheses
str = str:gsub('%(%z', ''):gsub('%z%)', '')
print(str)
Output:
-- should be cut from here
local naf_naf
= FUNCTION (
FUNCTION 'beta' { 'gamma' } ()
and 'epsilon'
or 'zeta'
)
{
'eta'
}
print("bar")
Upvotes: 1