Помня о том, какое бурление вызвало сравнение скорости Лиспа с другими языками в прошлом номере ПФП, прошу помощи зала не допустить несправедливости. Я сейчас доделываю сравнение скорости разных методов парсинга, сделал вариант на Хаскеле на базе Parsec2, и получившаяся скорость мне совсем не нравится. До этого на Хаскеле не писал, поэтому
(
Read more... )
Comments 41
Reply
Сейчас готовы цифры по таким вариантам:
OcamlYacc, классические парсер-комбинаторы на Окамле, их модификация без списков, оптимизирующие парсер-комбинаторы на Окамле (это тема статьи), C#/System.Xml, Haskell/Parsec2.
Планируется еще добавить Boost.Spirit. Если есть еще предложения - буду рад услышать.
Reply
Reply
http://thedeemon.livejournal.com/15606.html
Reply
Reply
Reply
Reply
Reply
Reply
Reply
Вот собсно код http://www.everfall.com/paste/id.php?br3cu0ui8ere
(61 строка). Собиралось 10м экспрессом (в пустой проект добавить этот файл и все 4 файлика пуги. Время работы релиза со статикой ~0.17 сек. Результат практически такой же ( другая точность распечатки плавучки ) и я поленился на мессаджи :)
Reply
Reply
Кстати, в Haskell можно работать со структурами аналогично OCaml:
update_lat lat bnd = bnd {
minlat = min lat (minlat bnd),
maxlat = max lat (maxlat bnd)
}
Reply
Про структуры спасибо за хинт, поправлю.
Reply
Reply
Документация говорит, что комбинатор альтернативы не делает сам откат в случае неудачи первого варианта, а для корректной работы откаты эти нужны, поэтому я в непоследние альтернативы повставлял try.
Reply
Проблема в том, что в ленивом языке комбинатор, аналогичный <|>, в случае удачи с первой альтернативой должен идти дальше и возвращаться к следующими альтернативам в случаях обломов. Для этого он должен все помнить. Что бы избежать этой проблемы, <|> находит первый сработавший парсер и забывает про остальные.
"Идеологически правильное" поведение можно востановить с помощью try (как именно уже не помню), но нужно это сравнительно редко.
Reply
Возьмем простой пример. Файл состоит из XML тэгов, тэг может быть node, а может быть какой-то другой, нам не интересный. Сейчас это описано как
try p_node <|> p_tag
Если убрать try, то парсер попробует разобрать очередной тэг как node, и если не получилось, то с _текущей_ позиции будет пытаться разбирать tag, но часть символов (как минимум открывающая скобка) уже будет съедена, что приведет к ошибке. Т.е. нужно вернуться на начало тэга, для этого и try. Или я все неправильно понял?
По идее, try можно убрать из тех мест, где начала альтернатив точно не пересекаются, например при разборе флоатов. Попробую.
Reply
Leave a comment