Eu preciso de uma ferramenta para analisar as mesas da Lua, de preferência em rubi ou java

StackOverflow https://stackoverflow.com/questions/2370153

Pergunta

Preciso de uma ferramenta para analisar expressões da tabela Lua. Se tudo mais falhar, acabarei codificando um pequeno módulo Lua para converter tabelas em XML, mas, por enquanto, estou interessado em uma biblioteca de rubi fazendo isso, mas, não, eu aceitaria a ferramenta em qualquer idioma, desde que eu pode olhar para sua fonte.

Aqui está um exemplo de snippet (é uma saída de addon 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,
        },
...

A idéia básica é, matrizes associativas aninhadas. Qualquer ajuda ou ponteiro será examinado, qualquer idéia é apreciada.

EDIT #1

Devido às disputas, deixe -me esclarecer o que eu tentei. Eu complementei a cadeia de String/Regex, fornecida por um dos participantes, como assim:

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

I (1) Adicionado a remoção de comentários da Lua, (2) substituía um dos substitutos regex: quando você tem o último elemento em um objeto/matriz, ele ainda tem uma vírgula depois dele, de modo que deve ser coberto e a vírgula removida corretamente .

Você percebe o Braces encaracolados de abertura dupla? JSON não gosta de ter objetos anônimos. Parece assim:

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

Basicamente, no nível da raiz, na verdade, temos uma lista/matriz de objetos semelhantes, com a seção "AAA" e "QQQ", para seguir o exemplo. No entanto, em Lua, isso é obviamente permitido, enquanto em JSON não é. Como os aparelhos de abertura de abertura são tratados como "Iniciar um objeto", mas esse objeto não tem um nome.

Tentei detectar esse caso com regex e substituir aparelhos encaracolados por pares [] []. Enquanto o Regex resultante funcionou, o problema era o mesmo: ok, definimos uma variedade de objetos semelhantes, mas a declaração da matriz ainda é sem nome.

Uma solução possível seria em vez de detectar e substituir esses aparelhos por [], para batizar os objetos com índices, como: "0" = { "aaa" = {...} }, "1" = { "aaa" = {... } }, etc. Isso (esperançosamente) a solução alternativa provavelmente fará com que funcione ... reportará novamente. ;)

Foi útil?

Solução

Pulando a primeira linha e depois alguma transformação ad hoc em 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"}}}

Outras dicas

Provavelmente estou afirmando o óbvio, mas Lua certamente pode analisar as mesas da Lua. E você pode "Incorporar" Lua em praticamente qualquer linguagem mainstream incluindo Java e Ruby (role para baixo no link para ligações Java e Ruby). Por incorporar, quero dizer analisar arquivos de origem, chamando as funções Lua e explorando tabelas, pode estar chamando funções escritas no seu idioma host da Lua. É possível que essas bibliotecas de ligação sejam mais trabalhos do que exportar suas tabelas para XML/JSON, mas vale a pena olhar para elas pelo menos

EDIT: Nível 70? Essa é a última década;)

É simples escrever um programa Lua que produz tabelas no XML, mas depende de como você deseja o formato XML. Veja também Luaxml, que tem xml.save (mas está escrito em c) e essa questão.

Provavelmente vai ser mais simples de usar JSON do que XML neste caso.

A tradução das tabelas Lua é quase 1 para 1 (altere = para: e remova [e] das teclas). Este é o equivalente a JSON do seu exemplo:

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

...

Além disso, o Rails possui JSON-PARSING (via JSON :: Parse).

Para lê -lo em um aplicativo Ruby, você teria que fazer algo semelhante a isso:

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

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

Então o jogador Infos estaria disponível em:

player_infos = info["PlayerInfos"]

Há também um analisador Java JSON, mas não tenho experiência com isso.

Experimente este código

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)

Você menciona que só pode usar Java, Ruby ou PHP para a análise disso. Uma opção é usar uma ferramenta como o ANTLR para gerar um pouco de analisador para você.

A gramática 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();}
  ;

gera um analisador que pode tomar informações como:

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

e transformá -lo em:

ALT TEXTO http://img59.imageshack.us/img59/7112/treef.png

(clique aqui Para uma resolução completa da imagem)

Escrever um XML dessa estrutura de árvore é a brincadeira de criança.

Mas, como eu disse, as mesas Lua podem parecer bem diferentes da gramática que publiquei acima: Strings podem parecer:

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

e chaves e valores podem consistir em expressões. Mas se as árvores sempre se parecerem com a forma como você as postou, pode ser uma opção para você.

Boa sorte!

Eu precisava fazer isso em Java, então escrevi uma pequena biblioteca:

https://github.com/mutantbob/jluadata

Código não testado. E estou apenas seguindo o link da SBK aqui, então não mereço nenhum crédito.

require 'rubyluabridge'

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

Posso ressaltar que o Lua não possui recursos REGEX, apenas a substituição de texto correspondente ao padrão.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top