Lua源代码操作:获取给定行的最内层函数()位置
我有一个语法正确的Lua5.1源代码文件 我在该文件中有一个位置(行和字符偏移) 我需要获取包含该位置的最里面的Lua源代码操作:获取给定行的最内层函数()位置,lua,Lua,我有一个语法正确的Lua5.1源代码文件 我在该文件中有一个位置(行和字符偏移) 我需要获取包含该位置的最里面的函数()主体的右括号的偏移量(以字节为单位)(或者找出该位置属于文件的主块) 即: 局部函数foo() ^结果 打印(“条”) ^输入 结束 本地foo=函数() ^结果 打印(“条”) ^输入 结束 本地foo=函数() 返回函数() ^结果 打印(“条”) ^输入 结束 结束 ……等等 我怎样才能有力地做到这一点呢?编辑:我最初的回答没有考虑到“最里面的”要求。我已经考虑到了这一点
函数()
主体的右括号的偏移量(以字节为单位)(或者找出该位置属于文件的主块)
即:
局部函数foo()
^结果
打印(“条”)
^输入
结束
本地foo=函数()
^结果
打印(“条”)
^输入
结束
本地foo=函数()
返回函数()
^结果
打印(“条”)
^输入
结束
结束
……等等
我怎样才能有力地做到这一点呢?编辑:我最初的回答没有考虑到“最里面的”要求。我已经考虑到了这一点 要使事情变得“健壮”,有几个考虑因素 首先,跳过字符串和注释内容非常重要,以避免在以下情况下输出错误:
foo = function()
print(" function() ")
-- function()
print("bar")
^ input
end
考虑到Lua的嵌套字符串和注释语法,这可能有点困难。例如,考虑输入以嵌套字符串或注释开始的情况:
foo = function()
print([[
bar = function()
print("baz")
^ input
end
]])
end
因此,如果您想要一个完全健壮的系统,在到达函数参数列表的末尾之前只能向后解析是不可接受的,因为您可能没有向后解析到足以使匹配无效的[
。因此,有必要将整个文件解析到您的位置(除非在这些奇怪的情况下你对不正确的匹配没有意见。如果这是一个编辑器插件,这些“不正确”的结果实际上可能是可取的,因为它们允许你编辑lua代码,该代码以字符串文字形式存储在使用相同插件的其他lua代码中)
由于您试图匹配的特定语法没有任何类型的“嵌套”,因此不需要一个完整的解析器。但是,您需要维护一个堆栈来跟踪作用域。考虑到这一点,您只需从一开始就逐个字符地对源文件进行检查,应用以下逻辑:
“
或”
时,忽略直到结束“
或”
为止的字符。小心处理像\“
和\
这样的转义--
时,请忽略注释结束换行符之前的字符。请注意,仅当注释不是多行注释时才这样做[[
,[=[
等)或多行注释符号(如-[[
或-[=[
等)时,忽略这些字符,直到最后的方括号中有适当数量的匹配等号为止结尾的块(例如,if
,while
,for
,function
,等等)。如果是这样,推动作用域堆栈上的位置。单词边界“在这种情况下,是不能用作lua标识符的任何字符(这是为了防止在类似abcfunction()
)的情况下进行匹配)。文件的开头也被视为单词边界
end
,则弹出堆栈的顶部元素。如果堆栈没有元素,则抱怨语法错误函数
作用域。从该位置向前一步到下一个)
,忽略注释中的)
(理论上可以在参数列表中找到,如果它跨越多行或包含内联--[]]
comments)。这个职位就是你的结果
这应该可以处理每种情况,包括使用函数
语法糖的情况,例如
function foo()
print("bar")
end
您的示例中没有包含但我想您仍然希望匹配的库。您可以使用什么样的库来实现这一点?您可能需要一个Lua解析器。无论我需要什么,只要它是正常的(最好不在GPL下)。实际上,在这种特定情况下,我认为仅使用regexps就可以实现(可能是在反向源代码上操作时)。但基于库的解决方案更可取。“我如何稳健地做到这一点?”您可以编写解析器。如果您想“稳健地”进行认真的源代码操作,你可以编写一个解析器。并不复杂。所以,只需获取你最喜欢的解析工具并编写一个。好吧,有几种Lua解析器。Metalua、luafish、Cheese、luapase、LuaInspect、Leg等等。
foo = function()
print(" function() ")
-- function()
print("bar")
^ input
end
foo = function()
print([[
bar = function()
print("baz")
^ input
end
]])
end
function foo()
print("bar")
end