Lua 源代码转换:根据近似位置剥离函数调用

我有一堆 Lua 5.1 文件,里面有这样(或类似)的结构:

...
local alpha,
      beta
      = FUNCTION "gamma"
      {
        'delta',
        'epsilon'
      }
...

也就是调用返回函数返回一些值的FUNCTION,这些值被分配给在该处声明的一些本地变量。

精确代码可能会有所不同,无论是风格(比如说,所有东西可能在同一行上),还是内容(比如第二次函数调用可能不传递任何参数)。但总是以“local”开始,并以两个链接的函数调用结束。

我有一个FUNCTION调用的行号。我需要找到最后一个函数调用在链中的结束(这个特别的,可能会在文件的更远的位置有更多的FUNCTION调用),并删除从那一点开始的所有文件内容。

也就是说,在:

print("foo") -- 01
local alpha = FUNCTION 'beta' -- 02
{ "gamma" } -- 03
print("bar") -- 04

之前:

print("foo") -- 01
local alpha = FUNCTION 'beta' -- 02
{ "gamma" } -- 03
print("bar") -- 04

之后:

 -- 03
print("bar") -- 04

有什么线索可以解决这个问题吗?


更新:

为了更清楚为什么简单的正则表达式方法行不通,以下是一个真实的例子:

local alpha
      = FUNCTION ( -- 我的行号指向这里
          FUNCTION 'beta' { 'gamma' } ()
            and 'epsilon'
             or 'zeta'
        )
      {
        'eta'
      } -- 结果应该被从这里和以上截掉
点赞
用户1847592
用户1847592

主要思路:搜索相邻的括号()()

local line_no = 12
local str = [[
print("foo")
local nif_nif
      = FUNCTION (
          FUNCTION 'beta' { 'gamma' } ()
            and 'epsilon'
             or 'zeta'
        )
      {
        'eta'
      }
local nuf_nuf
      = FUNCTION (      -- 这是第12行
          FUNCTION 'beta' { 'gamma' } ()
            and 'epsilon'
             or 'zeta'
        )
      {
        'eta'
      }                 -- 从这里开始应该被剪掉
local naf_naf
      = FUNCTION (
          FUNCTION 'beta' { 'gamma' } ()
            and 'epsilon'
             or 'zeta'
        )
      {
        'eta'
      }
print("bar")
]]

-- 剪掉目标 "local" 关键字之前的所有文本
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)

输出:

                 -- 从这里开始应该被剪掉
local naf_naf
      = FUNCTION (
          FUNCTION 'beta' { 'gamma' } ()
            and 'epsilon'
             or 'zeta'
        )
      {
        'eta'
      }
print("bar")
2013-08-27 19:07:31