Lua源代码操作:获取给定行的最内层函数()位置

时间:2013-08-27 21:36:16

标签: lua

我有一个语法正确的Lua 5.1源代码文件。

我在该文件中有一个位置(行和字符偏移)。

我需要在包含该位置的最内层function()主体的右括号中获取一个以字节为单位的偏移量(或者确定该位置属于该文件的主要块)。

即:

local function foo()
                    ^ result
  print("bar")
           ^ input
end
local foo = function()
                      ^ result
  print("bar")
           ^ input
end
local foo = function()
  return function()
                   ^ result
    print("bar")
             ^ input
  end
end

......等等。

我该如何强有力地做到这一点?

1 个答案:

答案 0 :(得分:0)

编辑:我原来的答案没有考虑到最里面的"需求。我考虑到了这一点

使事情变得健壮,"有一些考虑因素。

首先,重要的是跳过字符串和注释内容,以避免在以下情况下输出错误:

foo = function()
    print(" function() ")
    -- function()
    print("bar")
            ^ input
end

考虑到Lua的嵌套字符串和注释语法,这可能有点困难。例如,考虑输入以嵌套字符串或注释开始的情况:

foo = function()
    print([[
        bar = function()
            print("baz")
                    ^ input
        end
    ]])
end

因此,如果你想要一个完全健壮的系统,那么只能向后解析直到你到达函数参数列表的末尾是不可接受的,因为你可能没有向后解析得足够远以达到[[会使你的比赛无效。因此,有必要将整个文件解析到您的位置(除非您在这些奇怪的情况下不正确匹配。如果这是一个编辑器插件,这些"不正确&# 34;结果可能实际上是可取的,因为它们允许你使用相同的插件编辑以字符串文字形式存储在其他lua代码中的lua代码。

由于您尝试匹配的特定语法没有任何类型的"嵌套",因此不需要完整的解析器。但是,您需要维护一个堆栈以跟踪范围。考虑到这一点,您需要做的就是从头开始逐个字符地逐步执行源文件,应用以下逻辑:

  1. 每次遇到"'时,请忽略截至结束"'的字符。小心处理\"\\
  2. 之类的转义
  3. 每次遇到--时,请忽略评论结束换行符前的字符。如果评论不是多行注释,请注意这样做。
  4. 每次遇到多行字符串开头符号(例如[[[=[等),或遇到多行注释符号(例如--[[或{{1} }等等)忽略字符,直到结束方括号,它们之间有正确数量的匹配等号
  5. 遇到字边界时,请检查其后面的字符是否可以开始以--[=[结尾的块(例如endif,{{1} },while等。请勿包含for)。如果是这样,请按下示波器堆栈上的位置。 A"字边界"在这种情况下,任何不能使用lua标识符的字符(这是为了防止像function这样的情况下的匹配)。文件的开头也被视为单词边界。
  6. 如果遇到单词边界并且后跟repeat,则弹出堆栈的顶部元素。如果堆栈没有元素,则抱怨语法错误。
  7. 当你最后前进并达到你的输入"位置,从堆栈中弹出元素,直到找到abcfunction()范围。从该位置前进到下一个end,忽略评论中的function(如果它跨越多行或包含内联),理论上可以在参数列表中找到评论)。那个位置就是你的结果。

    这应该处理每一个案例,包括使用)句法糖的情况,比如

    --[[ ]]

    你没有在你的例子中包含但我想你仍然想要匹配。