Мне нужен инструмент для разбора таблиц Lua, предпочтительно на Ruby или Java.

Мне нужен инструмент для разбора табличных выражений 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" = {... } } и т. д. Этот (надеюсь, окончательный) обходной путь, вероятно, заставит его работать... Сообщу еще раз. ;)


person dimitarvp    schedule 03.03.2010    source источник
comment
Всегда ли ключи и значения будут строками и числами? Или они тоже могут быть выражениями? Ниже приведена допустимая таблица Lua: function foo() return 1 end table = {[2-foo()] = 't'..'wo'}, но ее будет сложнее (правильно) проанализировать, чем пример, который вы разместили.   -  person Bart Kiers    schedule 03.03.2010
comment
Извините, что не уточнил, я в принципе ничего не знаю о Lua на данный момент. И да, фрагмент, который я вставил, в основном представляет собой то, как все это будет выглядеть. Variable1 = ‹вложенные ассоциативные таблицы, как указано выше› Variable2 = ‹вложенные ассоциативные таблицы, как указано выше› ...   -  person dimitarvp    schedule 03.03.2010
comment
Хорошо, и каков ваш вклад? Файл с таблицами и прочим текстом в нем или только таблицы? И после определения таблиц в файле, какова ваша цель?   -  person Bart Kiers    schedule 03.03.2010
comment
Ввод - это то, что я вставил: просто присвоение переменных этим вложенным структурам. Конечная цель — использовать эту информацию в приложении Rails; поэтому данные должны быть переведены в JSON или XML, и с этого момента миссия выполнена.   -  person dimitarvp    schedule 03.03.2010
comment
Какой аддон WoW дает такой результат?   -  person Jonas Elfström    schedule 04.03.2010
comment
Все из семейства EQDKP. Я также изучаю вывод XML из одного из них (модифицированный третьей стороной), и вчера вечером я наконец получил вариант XML, который может сделать всю тему бесполезной. Нет, не совсем — я многому научился из отзывов людей.   -  person dimitarvp    schedule 04.03.2010


Ответы (9)


Пропуск первой строки, а затем некое специальное преобразование в 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"}}}
person Jonas Elfström    schedule 03.03.2010
comment
Собираюсь попробовать это очень скоро, а также! Я тоже полагал, что регулярные выражения должны быть подходящими, но мне нужны были жестко запрограммированные знания. Спасибо! Отчитаюсь, когда получу реальные результаты. :) - person dimitarvp; 03.03.2010
comment
Я показал немного измененную версию в разделе EDIT #1 исходного поста. - person dimitarvp; 04.03.2010
comment
В конце концов, это ответ на мою проблему. Хотя это немного рискованно и требует некоторой доводки, это подход, который в конечном итоге требует наименьших усилий и времени для выполнения работы. Я провел не менее 10 различных тестов, и модифицированная цепочка регулярных выражений + код Ruby теперь надежно потребляют информацию. Огромное спасибо! :) - person dimitarvp; 05.03.2010

Я, вероятно, констатирую очевидное, но Lua определенно может анализировать таблицы Lua. И вы можете "встроить" Lua практически в любой основной язык, включая Java и Ruby (прокрутите вниз ссылку на привязки Java и Ruby). Под встраиванием я подразумеваю анализ исходных файлов, вызов функций Lua и изучение таблиц, возможно, даже вызов функций, написанных на вашем основном языке, из Lua. Возможно, эти библиотеки привязки требуют больше работы, чем экспорт ваших таблиц в XML/JSON, но хотя бы взглянуть на них стоит.

Редактировать: уровень 70? Это последнее десятилетие ;)

person sbk    schedule 03.03.2010

Написать программу на Lua, выводящую таблицы в XML, просто, но это зависит от того, как вы хотите отформатировать XML. См. также LuaXML, в котором есть xml.save (но написан на C) и этот вопрос.

person lhf    schedule 03.03.2010
comment
Это мое последнее средство. ;) Однако может оказаться лучшим решением. - person dimitarvp; 03.03.2010
comment
Если бы вы могли указать формат XML, который вам нужен, я могу опубликовать код Lua для преобразования. Я хочу сказать, что самый простой способ разобрать файлы данных Lua — это загрузить их в Lua. - person lhf; 03.03.2010
comment
Ну, на данный момент у меня нет 100% ясности точной схемы данных (хотя я гуглил как сумасшедший), однако что не так с рекурсией вложенных ассоциативных массивов и выдачей правильного XML по пути? - person dimitarvp; 03.03.2010
comment
Ничего плохого, но точный XML зависит от того, что вы хотите вывести. - person lhf; 03.03.2010
comment
Имея в виду, что схема в значительной степени не существует (или, по крайней мере, не может быть обнаружена Google), я бы предпочел сначала провести слепое преобразование, а затем я проверю XML, чтобы узнать, как я должен его использовать. - person dimitarvp; 04.03.2010

Вероятно, в этом случае будет проще использовать JSON, чем xml.

Перевод из таблиц lua почти 1-к-1 (измените = на : и удалите [ и ] из ключей). Это эквивалент 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, но у меня нет с ним опыта.

person kikito    schedule 03.03.2010
comment
Очень хорошая идея, приятель, я тоже об этом думал, только одна проблема -- я должен придумать замену на основе RegExp, конечно, что само по себе несложно, но на данный момент мне не удалось найти краткое описание формата таблиц Lua (однако все варианты TLDR исчерпаны). - person dimitarvp; 03.03.2010
comment
Вероятно, будет еще проще использовать сам lua для разбора исходного файла и создания json-файла. - person kikito; 03.03.2010
comment
Дело в том, что я могу легко сделать это дома, но на хостинге, на котором я это поставлю, нет Lua. :/ Таким образом, мне нужен Ruby (или Java, или даже PHP) для этого.. - person dimitarvp; 03.03.2010

Попробуйте этот код

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)
person lhf    schedule 04.03.2010
comment
Извините за добавление нового ответа, но форматированный код не допускается в комментариях. - person lhf; 04.03.2010
comment
Насколько я знаю, я мог бы в конечном итоге делать это вручную дома и периодически загружать в веб-сервис. Спасибо, попробую сегодня-завтра, когда будет время. - person dimitarvp; 04.03.2010

Вы упомянули, что можете использовать только 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 ]===]

а ключи и значения могут состоять из выражений. Но если деревья всегда выглядят так, как вы их разместили, это может быть вариантом для вас.

Удачи!

person Bart Kiers    schedule 03.03.2010
comment
Вот это да. Пойду пробовать а-а-а-а. :) Я полагаю, смогу ли я обойтись без ANTLR и вычесть жестко закодированные функции в Ruby для выполнения этой работы, но, вероятно, лучший способ — создать сгенерированный ANTLR синтаксический анализатор, а затем попытаться перекодировать его самостоятельно (если это вообще необходимо ). Недурно! - person dimitarvp; 03.03.2010
comment
Это огромная работа для чего-то, что могло бы быть крошечной программой на Lua. И Lua очень легко подобрать. - person Shadowfirebird; 03.03.2010
comment
Я, конечно, люблю ANTLR и анализ текста... но я думаю, что это немного перебор. Более того, если ОП сможет установить ANTLR на сервер, он также сможет установить lua ... и использовать сам lua для экспорта. - person kikito; 03.03.2010
comment
@egarcia, вы ошибаетесь (или я не понимаю, что вы имеете в виду): вам не нужно устанавливать ANTLR. Вы используете ANTLR для генерации парсера только один раз. Этот сгенерированный парсер может иметь различные целевые языки, поддерживаются как Java, так и Ruby, оба из которых Димитко указал в исходном вопросе, который он мог использовать. - person Bart Kiers; 03.03.2010
comment
@Shadowfirebird, конечно, Lua простой, но, цитируя dimitko: .. но на хостинге, на который я его поставлю, нет Lua. :/ Значит, мне нужен Ruby или Java.... Как я упоминал в своем предыдущем замечании: ANTLR может создать парсер как для Ruby, так и для Java. Что касается вашего замечания большой объем работы: я не согласен, грамматика, которую я разместил выше, - это все, что вам нужно для создания синтаксического анализатора, который без каких-либо хлопот обрабатывает рекурсивно вложенную таблицу. Я могу ошибаться, но полагаю, вы никогда не работали с ANTLR, чтобы прийти к такому выводу. Я говорю это не для того, чтобы вас унизить, но как только вы немного познакомитесь с ANTLR, ... t.b.c. - person Bart Kiers; 03.03.2010
comment
... вы увидите, что это не просто инструмент для анализа сложных языков, он идеально подходит для анализа простых языков (с рекурсивной природой) и выполнения некоторого рода перевода с одного языка на другой: табличная структура в XML в Это дело. - person Bart Kiers; 03.03.2010
comment
@bart - я могу ошибаться, но вам все равно нужно установить среду выполнения ANTLR - сгенерированный парсер зависит от библиотек, которые должны быть установлены на сервере. - person kikito; 03.03.2010
comment
@egarcia, да, хорошая мысль. Вам действительно нужен один (или несколько) файлов .rb на сервере. Обратите внимание, что вам не нужно их устанавливать: достаточно просто скопировать их по FTP. - person Bart Kiers; 03.03.2010
comment
Необходимо проверить время выполнения ANTLR для Ruby/PHP. Я бы, конечно, отдал первый приоритет правильному синтаксическому анализатору, плюс я знаю, что сообщество ANTLR безумно полезно, плюс, очень вероятно, что кто-то там уже решил эту проблему. Хотя использование замены цепочек-регулярных выражений очень умно и заставляет вас чувствовать себя сильным, умным и все такое, у меня достаточно опыта в качестве разработчика на 3 языках, чтобы сначала попытаться найти подходящие реализации. - person dimitarvp; 04.03.2010
comment
Немного изучил его, и мне кажется, что приведенная выше грамматика может быть неполной - и, поскольку я не эксперт Lua, я не рискну. Я мог бы успешно сгенерировать код Ruby для разбора ЛЮБОГО Lua, но это кажется слишком большой проблемой производительности. Поэтому я буду придерживаться рискованного подхода с заменой регулярного выражения цепочки. - person dimitarvp; 05.03.2010
comment
@dimitko, он определенно неполный, как я уже сказал в своем ответе. Все зависит от того, какой именно ввод может быть. Но когда вы идете по пути регулярных выражений, помните, что у него есть некоторые недостатки. Вы не сможете правильно обрабатывать запись таблицы, такую ​​как ["k[e]y"] = 123 (обратите внимание на квадратные скобки внутри строкового литерала), если назвать только один недостаток. - person Bart Kiers; 05.03.2010
comment
Я прекрасно знаю об этом, приятель. К сожалению, это предприятие должно было быть коротким, и, начав его копать, на самом деле потребовалось немало усилий. Поэтому, имея в виду, что на самом деле я буду обрабатывать небольшое подмножество возможного синтаксиса таблицы Lua, я, вероятно, пока просто буду жить с возможными рисками. - person dimitarvp; 05.03.2010

Мне нужно было сделать это на Java, поэтому я написал небольшую библиотеку:

https://github.com/mutantbob/jluadata

person Mutant Bob    schedule 26.03.2013
comment
Спасибо. Я проверю это. - person dimitarvp; 27.03.2013

Непроверенный код. И я просто перехожу по ссылке Sbk здесь, так что я вообще не заслуживаю похвалы.

require 'rubyluabridge'

def lua_data_to_ruby_hash(data)
    luastate = Lua::State.new
    luastate.eval "d = #{data}"
    return luastate.d.to_hash
end
person Shadowfirebird    schedule 03.03.2010
comment
Я понимаю, что у вас нет Lua на сервере, но на самом деле установить его несложно. Вы должны решить, хотите ли вы выполнять основную работу по синтаксическому анализу в Ruby, с большим количеством кода, или вы устанавливаете Lua. - person Shadowfirebird; 03.03.2010
comment
... или быстрый грязный синтаксический анализ с парой регулярных выражений в ruby ​​и синтаксический анализ JSON без установки. - person kikito; 03.03.2010
comment
@egarcia, нет, регулярное выражение не может анализировать вложенные таблицы. - person Bart Kiers; 03.03.2010
comment
@Bart K. Но они могут очень легко удалять и заменять символы :) - person kikito; 03.03.2010
comment
@egarcia, да, я с этим не спорю. Но произвольные вложенные структуры (например, эти таблицы Lua) — это не то, что регулярное выражение может анализировать/сопоставлять. - person Bart Kiers; 03.03.2010
comment
Как упоминалось в моем редактировании исходного поста, в конце концов я понял, что есть еще одна проблема, кроме простой замены и приведения его в соответствие с JSON, а именно тот факт, что Lua не возражает против рекурсивных определений объектов без указания имени перед открывающим фигурным скобка. Боюсь, это недопустимо в JSON. Кроме того, как вы хорошо знаете, ребята, хостинг — это не то, на что вы можете реально повлиять; они говорят, что у нас есть Ruby и 43 гема для него, у нас есть PHP с этими библиотеками и т. д. и т. д., и если они извиняются, у нас нет динамических библиотек Lua и привязок Ruby для них, это нет -нет. - person dimitarvp; 04.03.2010

Могу ли я указать, что Lua не имеет возможностей регулярных выражений, просто замена текста с сопоставлением с шаблоном.

person Squidly    schedule 04.03.2010
comment
Мне не нужно, чтобы у Lua были возможности регулярных выражений. Мне нужен код Ruby, который может распознавать таблицы Lua и экспортировать их в структурированный и хорошо поддерживаемый формат, такой как XML и YAML. С этого момента мой код Ruby может считывать данные и обрабатывать их соответствующим образом. - person dimitarvp; 04.03.2010