разбор PGN

Тема в разделе "Машинное отделение", создана пользователем krey, 23 ноя 2008.

  1. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    пытаюсь идумать какой-нибудт простой разбор PGN файлов. пишу на PHP. пытаюсь придумать какой-нибудь простой критерий разделения партий, но пока не выходит. может, есть у кого какие идеи?
  2. NS Нефёдов Сергей

    • Заслуженный
    • Ветеран
    • Старожил
    Рег.:
    02.05.2006
    Сообщения:
    6.811
    Симпатии:
    96
    Репутация:
    3
    Адрес:
    Санкт-Петербург
    Оффлайн
    "[Event" - это начало партии.
  3. Umpire Заслуженный

    • Заслуженный
    Рег.:
    14.03.2007
    Сообщения:
    439
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    :D NS, браво!
    Но, вообще говоря, начало партии - это "1.", поскольку pgn-файл может вовсе не содержать никаких тегов.
    P.S. С другой стороны, "1." может быть в тегах. Так что задача не простая. ;)
  4. NS Нефёдов Сергей

    • Заслуженный
    • Ветеран
    • Старожил
    Рег.:
    02.05.2006
    Сообщения:
    6.811
    Симпатии:
    96
    Репутация:
    3
    Адрес:
    Санкт-Петербург
    Оффлайн
    Ничего не простого не вижу. У нас стандартная процедура обхода скобочных выражений.
    Пока идут [* вне скобок - это заголовки, как только кончились заголовки - это текст партии.

    Начало партии - это не ходы, а заголовки. Если бы нужен был первый ход - то наверно так и надо ставить вопрос...
  5. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    проблема в другом, насколько обязателен тег заголовка [Event "..."]?
  6. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    вот. из стандарта цитата:
  7. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    да, в своё время я писал парсер на с++, но он мне не нравился. он споступал сл. образом - считывалась строка, убивались лидирующие пробелы. если полученная строка начинается с [, то это заголовок. если нет, то это ходы, когторые читаются до результата партии. но и в комментариях может быть написано что угодно...
  8. NS Нефёдов Сергей

    • Заслуженный
    • Ветеран
    • Старожил
    Рег.:
    02.05.2006
    Сообщения:
    6.811
    Симпатии:
    96
    Репутация:
    3
    Адрес:
    Санкт-Петербург
    Оффлайн
    У меня сделано немного не так.
    последовательности спецсимволов и пробелов заменяются одним пробелом,
    после этого пробел служит разделителем, а дальше разбираем скобочные выражения, то есть по каждой скобке передаем параметр - тип скобки (чтоб потом её закрыть), и считаем уровень вложенности (тоже параметр процедуры) ходы в партии - только на нулевом уровне вложенности, информация о партии - только на первом уровне вложенности, пока не начались ходы, с типом скобки "[".

    Описание скобочной рекурсивной процедуры -
    Skob(s:char;Level:Byte) - первый параметр тип скобки, второй уровень вложенности.
  9. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    вообще говоря, когда взялся писать парсер на php идея была использовать регулярные выражения. для каждой записи заголовка составить выражение, результат применения его к файлу - массив. сколько нужно данных из заголовка - столько и выражений. итая партия файла будет итыми элементами массивов. другое дело, что таким способом непонятно как выделить текст партии. шаблончик не строится :(
  10. NS Нефёдов Сергей

    • Заслуженный
    • Ветеран
    • Старожил
    Рег.:
    02.05.2006
    Сообщения:
    6.811
    Симпатии:
    96
    Репутация:
    3
    Адрес:
    Санкт-Петербург
    Оффлайн
    Не знаю что такое регулярные выражения, но просто разделить заголовки и текст партии (без парсинга самого текста) - это 20 строк кода...
  11. dt Новичок

    • Новичок
    Рег.:
    09.03.2007
    Сообщения:
    81
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    Есть такая идея - взять формальное описание синтаксиса из стандарта (http://www.chessclub.com/help/PGN-spec параграф 18), подсунуть его генератору парсеров (аля flex/bison) и получить полноценный парсер, грубо говоря, бесплатно. Но, как обычно бывает со всеми простыми идеями, это уже сделано до нас, в т.ч. и для комбинации PHP+PGN :)
    http://greg.chiaraquartet.net/archives/137-a-parser-generator-for-PHP-finally.html
  12. WinPooh В.М.

    • Команда форума
    Рег.:
    13.02.2006
    Сообщения:
    9.492
    Симпатии:
    3.122
    Репутация:
    95
    Адрес:
    Москва
    Оффлайн
    По стандарту, насколько, помню, обязательны семь тегов: White, Black, Result, Date, Event, Round, Site.
  13. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    хитрите, парниша! © естественно, первым делом я гуглил, перед открытием темы. и в данной ссылке человек высказал, что он вовсю работает над pgn-парсером. однако самого парсера не показал.
    я эти и выбрал для данных, добавил еще fen. правда, обязательное наличие тега round сомнительно.
  14. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    кстати, насчет флекса - это идея!
  15. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    нехорошие люди в стандарте не определили полностью EBNF. Не определены:
    move-number-indication
    SAN-move
    numeric-annotation-glyph
    первое определить несложно:
    move-number-indication ::= [0-9]+ '.'
    а вот дальше - сложнее... никто не знает где можно найти SAN EBNF?
  16. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    в общем, забил на нормальный парсер, написал через попочку, извините за выражение. Посчитал [Event за начало каждой партии.
    есть какие комментарии? :rolleyes:
  17. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    кстати, спасибо dt за yacpdb - без него я бы не взялся за то, что делаю :)
  18. dt Новичок

    • Новичок
    Рег.:
    09.03.2007
    Сообщения:
    81
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    Тогда ой. Я нашел эту страницу, когда искал генератор парсеров для PHP (т.е. без PGN в запросе, просто аналог lex/yacc) и счёл упоминание парсера именно для PGN знаком свыше. Для SAN, наверное, можно самому написать грамматику, но м.б. имелось в виду, что и SAN и FEN это самостоятельные сущности и для их разбора надо использовать отдельные модули?
    На здоровье, конечно! А чего ты делаешь, если не секрет?
  19. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    базу для этюдов. собственно, она уже есть, только надо её заполнять. для этого и нужен парсер pgn.
  20. Kirr Администратор

    • Команда форума
    Рег.:
    11.02.2006
    Сообщения:
    1.208
    Симпатии:
    22
    Репутация:
    8
    Оффлайн
    Парсю почти так же:
    Код:
    if (/^\[Event\s/) ...
    Работает нормально так как дело приходится иметь только с PGN файлами записанными оболочками.
  21. NS Нефёдов Сергей

    • Заслуженный
    • Ветеран
    • Старожил
    Рег.:
    02.05.2006
    Сообщения:
    6.811
    Симпатии:
    96
    Репутация:
    3
    Адрес:
    Санкт-Петербург
    Оффлайн
    Видимо у всех программистов мысль течет в одном направлении :)
    Парсер PGN (полный, вместе с текстом партии, с открытыми исходниками) есть на JAVA.
    Используется на сайте www.crestbook.com :)
  22. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    =0
    где?! как я его пропустить смог?!
  23. NS Нефёдов Сергей

    • Заслуженный
    • Ветеран
    • Старожил
    Рег.:
    02.05.2006
    Сообщения:
    6.811
    Симпатии:
    96
    Репутация:
    3
    Адрес:
    Санкт-Петербург
    Оффлайн
  24. NS Нефёдов Сергей

    • Заслуженный
    • Ветеран
    • Старожил
    Рег.:
    02.05.2006
    Сообщения:
    6.811
    Симпатии:
    96
    Репутация:
    3
    Адрес:
    Санкт-Петербург
    Оффлайн
  25. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    так это же не ява :) а javascript, и Crest этим не пользуется... но ты прав, это парсер. Не полный (варианты не парсит), но рабочий.
  26. NS Нефёдов Сергей

    • Заслуженный
    • Ветеран
    • Старожил
    Рег.:
    02.05.2006
    Сообщения:
    6.811
    Симпатии:
    96
    Репутация:
    3
    Адрес:
    Санкт-Петербург
    Оффлайн
    Да я знаю что скрипт. Сократил название языка :)
    У меня где-то парсеры валяются на Делфи - но мне их не найти, я свои исходники постоянно теряю... Спроси, может я Фрукту высылал исходники парсинга pgn для сбора статистики по проценту совпадения ходов программ.
  27. Fruit Александр

    • Заслуженный
    • Участник
    • Старожил
    Рег.:
    12.02.2006
    Сообщения:
    2.201
    Симпатии:
    64
    Репутация:
    3
    Оффлайн
    У меня только сама программка.
  28. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    а я у себя нашел ошибку в коде. конфликт с тегом "EventDate". Решается добавлением пробела в разбор "Event". Думаю, еще возможны такие ошибки и с другими тегами, потому везде надо повставлять пробелы.
  29. Tinefol Учаcтник

    • Участник
    Рег.:
    09.07.2008
    Сообщения:
    17
    Симпатии:
    1
    Репутация:
    0
    Оффлайн
    Полноценный парсер на javascript мною написан давно (в принципе они и на php есть написанные, например DHTML Chess).

    Вот такя я разделял игры:

    Код:
    commentaries = [];
            this.games = [];
            // IE uses \r\n, Gecko browsers use \n
            PGN = PGN.replace(/\r\n/g,"\n");
            // Replace bracket {} commentaries because the can mess up how we determine the game edges, store them in array
            PGN = PGN.replace(/\{([\W\w]*?)\}/g, function($1) {
                commentaries.push($1.substring(1, $1.length - 1));
                return "{" + (commentaries.length - 1) + "}";
            });
    
            // Replace strings (because they can contain the semicolon comments,
            // which could once again cripple our ability to parse the games correctly) and store them in array
            var tagStrings = [];
            PGN = PGN.replace(/"([^"\\\r\n]*(?:\\.[^"\\\r\n]*)*)"/g, function($1) {
                // Also attempt to replace back "nested" {} comments because they can appear inside these strings
                tagValue = $1.replace(/\{([\d]+)\}/g, function ($1) {
                    return commentaries[$1.substring(1, $1.length - 1)];
                });
                tagStrings.push(tagValue.substring(1, tagValue.length - 1));
                return "\"" + (tagStrings.length - 1) + "\"";
            });
    
            // Replace semicolon this.commentaries and store them in array
            PGN = PGN.replace(/(;[\W\w]*?)\n/, function($1) {
                // Also attempt to replace back "nested" {} comments because they can appear inside semicolon commentaries
                    commValue = $1.replace(/\{([\d]+)\}/g, function ($1) {
                    return "{" + commentaries[$1.substring(1, $1.length - 1)] + "}";
                });
                commentaries.push(commValue.substring(1, commValue.length));
                return "{" + (commentaries.length - 1) + "}\n";
            });
            
            // Split the Games
            gamesArray = PGN.match(/(\[[\W\w]*?(?:0-1|1-0|1\/2-1\/2|\*))(?:[\s]+|$)/g);
  30. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    интересно. для меня
    выглядит откровением. однако логично.
  31. TopicStarter Overlay

    krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн

Поделиться этой страницей