4

我需要一个工具来解析 Lua 表表达式。如果一切都失败了,我最终只会编写一个小的 Lua 模块来将表转换为 XML,但目前,我对 Ruby 库感兴趣,但如果失败了,我会接受任何语言的工具,只要我可以看看它的来源。

这是一个示例片段(它是一个 WoW 插件输出):

CT_RaidTracker_RaidLog = {
{
    ["PlayerInfos"] = {
        ["Nyim"] = {
            ["race"] = "Orc",
            ["guild"] = "Excubitores Noctae",
            ["sex"] = 2,
            ["class"] = "HUNTER",
            ["level"] = 70,
        },
        ["Zyrn"] = {
            ["race"] = "BloodElf",
            ["guild"] = "Excubitores Noctae",
            ["sex"] = 2,
            ["class"] = "WARLOCK",
            ["level"] = 70,
        },
...

基本思想是嵌套关联数组。将检查任何帮助或指针,感谢任何想法。

EDIT #1

由于存在争议,让我澄清一下我尝试了什么。我补充了其中一位参与者提供的字符串/正则表达式替换链,如下所示:

str.gsub(/--.+$/, "").gsub("=", ":").gsub(/[\[\]]/,"").gsub('" :','":').gsub(/,\s*\n(\s*)}/, "\n\\1}")

我 (1) 添加了 Lua 注释的删除,(2) 替换了其中一个正则表达式替换器:当您在对象/数组中有最后一个元素时,它后面仍然有一个逗号,因此必须将其覆盖并正确删除逗号.

你注意到双开口花括号了吗?JSON 不喜欢匿名对象。它看起来像这样:

"xxx" = {
  {
    ["aaa"} = {
      ["bbb"] = {
        "ccc" = 7
        "ddd" = "a string"
        "eee" = "a date/time pattern"
      }
    },
    ["qqq"} = {
      "hm" = "something"
    }
  },
  {
    ["aaa"] = {
    -- ...
    },
    ["qqq"] = {
    -- ...
    }
  }
}

基本上在根级别,我们实际上有一个类似对象的列表/数组,都有“aaa”和“qqq”部分,以遵循示例。但是,在 Lua 中显然是允许的,而在 JSON 中则不允许。因为打开的花括号被视为“开始一个对象”,但该对象没有名称。

我试图用正则表达式检测这种情况,并用“[]”对替换花括号。虽然生成的正则表达式有效,但问题是一样的:好的,我们定义了一个相似对象的数组,但数组的声明仍然是无名的。

一个可能的解决方案不是用 [] 检测和替换这些大括号,而是用索引命名对象,例如:"0" = { "aaa" = {...} }, "1" = { "aaa" = {... } }等。(希望是最终的)解决方法可能会使其工作......将再次报告。;)

4

9 回答 9

5

我可能说的很明显,但 Lua 肯定可以解析 Lua 表。您可以将 Lua “嵌入”到几乎任何主流语言中,包括 Java 和 Ruby(向下滚动查看 Java 和 Ruby 绑定的链接)。通过嵌入,我的意思是解析源文件、调用 Lua 函数和探索表,甚至可能是从 Lua 调用用你的宿主语言编写的函数。这些绑定库可能比将表导出到 XML/JSON 更有效,但至少值得一看

编辑:70级?那是过去十年;)

于 2010-03-03T15:07:20.697 回答
3

编写一个以 XML 格式输出表的 Lua 程序很简单,但这取决于您希望如何格式化 XML。另请参阅LuaXML,它具有 xml.save (但用 C 编写)和这个问题

于 2010-03-03T10:09:17.130 回答
3

跳过第一行,然后对 JSON 进行一些临时转换。

s=File.readlines("test.luatable")[1..-1].join
JSON.parse(s.gsub("=", ":").gsub(/[\[\]]/,"").gsub('" :','":').gsub(/,\n(.+)\}/,"\n\\1}"))
=> {"PlayerInfos"=>{"Nyim"=>{"guild"=>"Excubitores Noctae", "class"=>"HUNTER",  
    "level"=>70, "sex"=>2, "race"=>"Orc"}, "Zyrn"=>{"guild"=>"Excubitores Noctae", 
    "class"=>"WARLOCK", "level"=>70, "sex"=>2, "race"=>"BloodElf"}}}
于 2010-03-03T15:50:04.287 回答
3

在这种情况下,使用JSON可能比使用 xml 更简单。

lua 表的转换几乎是一对一的(将 = 更改为 :,并从键中删除 [ 和 ])。这是您的示例的 JSON 等价物:

{
  "PlayerInfos": {
    "Nyim": {
      "race": "Orc",
      "guild": "Excubitores Noctae",
      "sex": 2,
      "class": "HUNTER",
      "level": 70
    },
    "Zyrn": {
      "race": "BloodElf",
      "guild": "Excubitores Noctae",
      "sex": 2,
      "class": "WARLOCK",
      "level": 70
    },

...

此外,Rails 有内置的 JSON 解析(通过 JSON::parse)。

为了从 ruby​​ 应用程序中读取它,您必须执行类似的操作:

require 'json' # This is already included on Rails apps

info = JSON::parse(File.read("PlayerInfos.json"))

然后玩家信息将在以下位置可用:

player_infos = info["PlayerInfos"]

还有一个 java JSON 解析器,但我没有这方面的经验。

于 2010-03-03T11:10:27.683 回答
2

试试这个代码

function toxml(t,n)
        local s=string.rep(" ",n)
        for k,v in pairs(t) do
                print(s.."<"..k..">")
                if type(v)=="table" then
                        toxml(v,n+1)
                else
                        print(s.." "..v)
                end
                print(s.."</"..k..">")
        end
end

toxml(CT_RaidTracker_RaidLog,0)
于 2010-03-04T14:13:00.880 回答
1

I needed to do this in Java, so I wrote a small library:

https://github.com/mutantbob/jluadata

于 2013-03-26T20:52:21.757 回答
1

您提到您只能使用 Java、Ruby 或 PHP 来解析它。一种选择是使用像 ANTLR 这样的工具为您生成一个小解析器。

ANTLR 语法:

grammar Test;

parse
  :  Identifier '=' table EOF
  ;

table
  :  '{' (entry (',' entry)* ','?)? '}'
  ;

entry
  :  key ('=' value)?
  |  String
  |  Number
  ;

key
  :  '[' (String | Number) ']'
  |  Identifier
  ;

value
  :  String 
  |  Number
  |  Identifier
  |  table
  ;

Identifier
  :  ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*
  ;

String
  :  '"' ~'"'* '"'
  ;

Number
  :  '0'..'9'+
  ;

Space
  :  (' ' | '\t' | '\r' | '\n') {skip();}
  ;

生成一个可以接受如下输入的解析器:

Table = {
  ["k1"] = "v1",
  ["k2"] = {["x"]=1, ["y"]=2},
  ["k3"] = "v3"
}

并将其转换为:

替代文字 http://img59.imageshack.us/img59/7112/treef.png

(点击这里查看图片的完整分辨率)

从该树结构编写 XML 是小菜一碟。

但就像我说的,Lua 表可能看起来与我上面发布的语法完全不同:字符串可能看起来像:

'a string'
[===[ also ]==] a string ]===]

键和值可以由表达式组成。但是,如果树木看起来总是像您发布的那样,那么它可能是您的一个选择。

祝你好运!

于 2010-03-03T15:19:54.673 回答
0

我可以指出 Lua 没有正则表达式功能,只是模式匹配的文本替换。

于 2010-03-04T10:37:22.947 回答
0

未经测试的代码。而且,我只是在这里关注 Sbk 的链接,所以我根本不值得任何信任。

require 'rubyluabridge'

def lua_data_to_ruby_hash(data)
    luastate = Lua::State.new
    luastate.eval "d = #{data}"
    return luastate.d.to_hash
end
于 2010-03-03T16:39:34.337 回答