【问题标题】:Lua pattern matching for extracting hard coded strings in code base用于在代码库中提取硬编码字符串的 Lua 模式匹配
【发布时间】:2011-07-04 23:13:57
【问题描述】:

我正在使用 C++ 代码库。现在我正在使用调用 lua 脚本的 C++ 代码来查看整个代码库,并希望返回程序中使用的所有字符串的列表。

有问题的字符串前面总是有一个名为 TRANS 的 JUCE 宏。以下是一些应该提取字符串的示例

TRANS("Normal")
TRANS ( "With spaces" )
TRANS("")
TRANS("multiple"" ""quotations")
TRANS(")")
TRANS("spans \
multiple \
lines")

而且我相信您可以想象在大型代码库中可能出现的其他一些可能的字符串变体。我正在制作一个自动工具来生成 JUCE 翻译格式的文件,以尽可能地自动化该过程

就目前而言,为了找到这些字符串,我已经做到了模式匹配。我已将源代码转换为 lua 字符串

path = ...

--Open file and read source into string
file = io.open(path, "r")
str = file:read("*all")

被叫

for word in string.gmatch(string, 'TRANS%s*%b()') do print(word) end

找到以 TRANS 开头的模式,具有平衡括号。这将为我提供完整的宏,包括括号,但从那里我认为很容易拆分我不需要的脂肪并保留实际的字符串值。

但这不适用于导致括号不平衡的字符串。 例如TRANS(")") 将返回TRANS("),而不是TRANS("(")

我将模式修改为

for word in string.gmatch(string, 'TRANS%s*(%s*%b""%s*') do print(word) end

其中,模式应以 TRANS 开头,然后是 0 或多个空格。然后它应该有一个 ( 字符后跟零个或多个空格。现在我们在括号内,我们应该有平衡数量的 "" 标记,然后是另一个 0 或多个空格,最后以 a 结尾。不幸的是,这在使用时不会返回单个值。但是...我认为即使它按我的预期工作...内部可能有一个\",这会导致支架不平衡。

对提取这些字符串有什么建议吗?我应该继续尝试找到模式匹配序列吗?还是我应该尝试直接算法...你知道为什么我的第二个模式没有返回字符串吗?任何其他建议!我不想涵盖所有可能性的 100%,但接近 100% 会很棒。谢谢! :D

【问题讨论】:

    标签: c++ lua juce


    【解决方案1】:

    我和其他人一样喜欢 Lua 模式,但你是在为枪战带来一把刀。这是您确实不想将解决方案编码为正则表达式的问题之一。要正确处理双引号和反斜杠转义,您需要一个真正的解析器,LPEG 会很好地满足您的需求。

    【讨论】:

    • LPEG 将如何为我提供优于典型 lua 模式的优势?有很多要读的,你能给我一些可能会感兴趣的具体功能吗?另外,你确定模式不够吗?我不需要涵盖 100% 我相信的所有边界条件......这对于我正在使用的工具的使用并不重要。现在我想知道尝试分步完成这个而不是单一模式是否是一个更好的主意......
    • LPEG 是一个完整的解析器系统。您将编写与您的 TRANS 宏实例、平衡括号和 C 字符串文字的完整语法(包括平衡 " 标记、反斜杠转义和隐式连接)匹配的语法。然后,LPEG 将允许您将语法应用于源文本,并提取您需要知道的内容。它是一个大包裹,但非常值得。可以将其视为为您提供 LEX 和 YACC 提供的一切以及更多。
    【解决方案2】:

    在第二种情况下,您忘记转义括号。试试

    for word in string.gmatch(str, 'TRANS%s*%(%s*(%b"")%s*%)') do print(word) end
    

    【讨论】:

    • 啊,我不知道您需要 ( 标记的转义字符。而且我喜欢您的答案以更好的格式提供字符串的方式,我以前有...不幸的是,这仍然失败对于诸如 TRANS("\"") 之类的字符串或任何带有引号的字符串...
    • @Colton,我不认为你能 100% 甚至接近它使用 Lua 模式。你需要一个真正理解 C 字符串规则的词法分析器。我建议使用定义为TRANS 的C 预处理器(cppgcc -E),这样可以更轻松地对结果进行后处理。我用#define TRANS(x) BEGIN x END 做了一个快速测试,它在你的例子上运行良好。
    • 我不确定您的回复是什么意思。我知道 C 预处理器宏是什么,因为这就是 TRANS,但我不知道您通过这个快速测试#define 得到什么。你能说得更详细些吗? :)
    • @Colton,我提出了一种完全不同的批处理方法来解决这个问题,但我想它不符合你在 C++ 应用程序中嵌入的要求。
    • 啊...是的,这个 C++ 应用程序基于我创建的这个名为 FileDigger 的开源项目。 code.google.com/p/file-digger/source/browse/… 因为我已经有了这个漂亮的文件递归操作接口,所以我认为在 Lua 中进行解析是一项非常容易的任务,并且是一个很好的学习练习。
    猜你喜欢
    • 2012-08-30
    • 2011-03-29
    • 1970-01-01
    • 2013-10-13
    • 1970-01-01
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    相关资源
    最近更新 更多