I need a tool to parse Lua tables, preferably in Ruby or Java

I need a tool to parse Lua table expression expressions. If all else fails, I end up just encoding a small Lua module for converting tables to XML, but for now I'm interested in the Ruby library, but otherwise I would accept a tool in any language if I could look at its source.

Here is an example fragment (this is the output of a WoW addon):

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, }, ... 

The main idea is nested associative arrays. Any help or pointer will be considered, any idea appreciated.

EDIT #1

Due to controversy, let me clarify what I tried. I supplemented the string / regular expression replacement chain provided by one of the participants, for example:

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

I (1) added the removal of Lua comments, (2) replaced one of the regex replacers: when you have the last element in the object / array, it still has a comma after it, so it should be closed and the comma removed correctly.

Have you noticed the double opening braces? JSON does not like to have anonymous objects. It looks like this:

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

Basically, at the root level, we actually have a list / array of similar objects that have aaa and qqq sections to follow suit. However, in Lua, this is obviously allowed, but in JSON it is not. Since opening curly braces are treated as "start an object", but this object does not have a name.

I tried to detect this case with a regex and replace the curly braces with the pairs “[]”. While the resulting resulting time worked, the problem was the same: OK, we are defining an array of similar objects, but the declaration of the array is still nameless.

A possible solution would be instead of finding and replacing these curly braces with [] to baptize objects with indexes, for example: "0" = { "aaa" = {...} }, "1" = { "aaa" = {... } } etc. This (hopefully final) workaround is likely to make it work ... Will report back .;)

+4
source share
9 answers

Skipping the first line and then some ad hoc conversion to 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"}}} 
+3
source

I probably state the obvious, but Lua can, of course, parse Lua tables. And you can "embed" Lua in almost any main language , including Java and Ruby (scroll down the link to Java and Ruby bindings). Embedding, I mean parsing the source files, calling Lua functions and examining tables, maybe even calling functions written in your host language from Lua. These binding libraries may work more than exporting your tables to XML / JSON, but you should look at them at least.

Edit: level 70? This is so the last decade;)

+5
source

Just write a Lua program that outputs the tables in XML, but depends on how you want to format the XML. See Also LuaXML , which has xml.save (but written in C) and this question .

+3
source

It will probably be easier to use JSON than xml in this case.

Translation from lua tables is almost 1 to 1 (change = to :, and removes [and] from the keys). This is the JSON equivalent of your example:

 { "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 }, 

...

In addition, Rails has built-in JSON analysis (via JSON :: parse).

To read it from the ruby ​​application, you will need to do something similar to this:

 require 'json' # This is already included on Rails apps info = JSON::parse(File.read("PlayerInfos.json")) 

Then the player’s information will be available at:

 player_infos = info["PlayerInfos"] 

There is also a java JSON parser, but I have no experience with it.

+3
source

Try this code

 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) 
+2
source

You mentioned that you can only use Java, Ruby or PHP to parse this. The option is to use a tool like ANTLR to create a small parser for you.

Grammar 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();} ; 

generates a parser that can receive input, such as:

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

and convert it to:

alt text http://img59.imageshack.us/img59/7112/treef.png

(click here for full image resolution)

Writing XML from this tree structure is a child's play.

But, as I said, Lua tables can be very different from the grammar I wrote above: the lines can look like this:

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

keys and values ​​can consist of expressions. But if the trees always look the way you placed them, this might be an option for you.

Good luck

+1
source

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

https://github.com/mutantbob/jluadata

+1
source

Unverified code. And I just follow the Sbk link here, so I don't deserve any credit at all.

 require 'rubyluabridge' def lua_data_to_ruby_hash(data) luastate = Lua::State.new luastate.eval "d = #{data}" return luastate.d.to_hash end 
0
source

Can I point out that Lua does not have regular expression capabilities, it simply replaces the text with a pattern matching.

0
source

Source: https://habr.com/ru/post/1302964/


All Articles