Комментарии 14
Делали подобные штуки лет 5 назад, в самописе, и кажется использовали Go!, только аспекты накладывали через аннотации.
Пример в статье не очень удобен, потому, что он моментально сломается если метод переименуется или изменится список аргументов. А отслеживать такие вещи сложно ибо разработчик меняющий метод может быть не в курсе, что на него кто-то налажал аспект. И IDE такую связь не увидит. Особенно весело, если проблема вылезет на этапе слияния с другими фичами.
Аннотации дают более четкую связь метода и аспекта и не такую жёсткую связь как явное использование в методе.
Сейчас, в Symfony, подобные задачи можно решить через Doctrine Annotation.
Полностью вас поддерживаю. Отслеживать это будет невозможно. Либо использовать какие-то дополнительные техники чтобы оправдать АОП.
Как по мне нужно сначала определить на сколько огромное приложение, если речь идет о 2-6 "аспектах", например таких популярных как ACL и логгер, то хватит и того чтобы их оставить сквозными, ничего плохого не случится, куча cms тому пример. Если уже 6-25 аспектов, то основная проблема не потерять ни один из них при рефакторинге, и тут уже придется что-то использовать как например скрипты для проверки совместимости аспектов и/или интеграционные тесты, но и в этом случае хватит обычных декораторов, например в симфони контейнере можно объявить сервис декоратор, он отлично справится с такой задачей. А дальше веселее, если у вас 25-100+ аспектов, у рядового разработчика точно не будет понимания всей архитектуры и он фактически будет работать только с отдельными модулями, а тут чтобы оставить прозрачность и совместимость нужно использовать публичные интерфейсы между модулями, т.е. апи, и на роль этого апи отлично подходят ивенты, в вашем примере именно код модуля базы данных должен создавать ивенты (а с новыми версиями отмечать как устаревшие и добавлять новые) и все аспекты должны полагаться на ивенты и только в таком случае вы сократите риски при дальнейшей разработке.
Во-первых, в PHP нет встроенного парсера кода
Токенизацию можно даже на уровне скрипта посмотреть, ASP и опкод доступны через расширения. Или что-то другое имелось в виду?
Если генерацию кода еще можно посчитать простой, то исправление кода несколько сложнее. Во-первых, в PHP нет встроенного парсера кода, а во-вторых, очень мало библиотек, решающих проблемы парсинга PHP кода
Зато есть библиотеки, которые позволяют это делать не только с PHP кодом:
1) github.com/hoaproject/Compiler
2) И его форк: github.com/railt/parser
под PHP есть вот такая статейка: inviqa.com/blog/functional-programming-php-developers-guide-parser-combinators-phunkie
там же обзор библиотеки [phunkie](https://github.com/phunkie/phunkie), которая отдельно интересна.
ну вот пример на JS: github.com/jneen/parsimmon
Ну так это ж лексер обычный
под PHP есть вот такая статейка: inviqa.com/blog/functional-programming-php-developers-guide-parser-combinators-phunkie
Ну так ты кидал эту статью уже. Я просто чуток не понимаю что в конечном итоге хочется получить? Декларацию правил парсера а-ля Yay? Это же просто функциональный интерфейс для декларации грамматик и всё. Не?
Ну так это ж лексер обычный
нет, это именно парсер. Там на выходе AST. просто "лексемы" выделяются как листья дерева парсеров.
Декларацию правил парсера а-ля Yay?
именно так, yay пример комбинатора парсеров. И оно не "просто" а устраняет много нюансов описания контекстно-зависимых грамматик.
нет, это именно парсер. Там на выходе AST. просто «лексемы» выделяются как листья дерева парсеров.
А, да, вижу: github.com/jneen/parsimmon/blob/master/API.md#parsernodename
Интересная штука.
именно так, yay пример комбинатора парсеров. И оно не «просто» а устраняет много нюансов описания контекстно-зависимых грамматик.
А чем тебя BNF/EBNF не устраивает в этом случае, который позволяет генерить правила сабжевого парсера, что по ссылке в первом моём комменте?
А если в целом, то да, мне идея API в стиле yay нравится, т.к. с тестами просто упороться можно. Приходится руками составлять таблицу переходов, а потом не понятно, то ли в грамматике накосячил в тестах, то ли реально в самом LL парсере где бага.
P.S. Оффтоп: Можно, кстати, попробовать действительно набросать грамматику для PHP. Авось и кому понравится, в качестве альтерантивы nikic парсера. Но она всё же LALR, через LL будет сложно нормально приоритеты операторов распарсить =\
А чем тебя BNF/EBNF не устраивает в этом случае
- медленно (комбинаоры парсеров будут не быстрее, в силу того что лексинг по сути будет работать аналогично — тупо preg_match по оффсету, но в целом функции можно подменять. Вот будет FFI в PHP и можно будет re2c юзать для генерации таблиц сравнения символов). Я пока ленюсь сделать бенчмарк и сравнить json парсер на написанном наколенке комбинаторе парсеров и hoa (хочется еще сравнить какой-нибудь PHP-Yacc или pacc.
- неудобно расширять грамматику (по сравнению с простой композицией функций). Как по мне для проектов типа Doctrine ORM это будет намного более интересной вещью нежели hoa.
- стильно модно молодежно.
набросать грамматику для PHP
вот тут помогут фичи типа нэймспейсов для лексем, в силу того что у php таки контекстно зависимый лексер.
через LL будет сложно нормально приоритеты операторов распарсить
да там как бы не только в этом вопрос.
медленно (комбинаоры парсеров будут не быстрее, в силу того что лексинг по сути будет работать аналогично — тупо preg_match по оффсету, но в целом функции можно подменять. Вот будет FFI в PHP и можно будет re2c юзать для генерации таблиц сравнения символов).
Тут проблем ну вообще никаких нет. 600к токенов в секунду, вполне достаточно для моментальной токенизации даже мегабайтных файлов:
И прошу заметить — это обычный домашний ПК под виндой, а не сервер. Да и места под дальнейший тюнинг тоже километр, например pthreads заюзать.
Я пока ленюсь сделать бенчмарк и сравнить json парсер на написанном наколенке комбинаторе парсеров и hoa (хочется еще сравнить какой-нибудь PHP-Yacc или pacc.
Да какая разница в итоге-то? Это всего лишь разные API гейтвей к парсеру. А производительность зависит от реализации рантайма к которому применили сабжевую грамматику. И LL, очевидно, будет быстрее и проще LALR реализации того же yacc/bison.
неудобно расширять грамматику (по сравнению с простой композицией функций).
А вот тут ты не прав. Всё упирается в реализацию. В моём случае парсер стейтлесс и поддерживает переопределение именованных групп. А значит поверх базовой можно вполне класть и кастомную. Проблемы только в генерации конечного парсера через компилятор компиляторов. Ну т.е. при каждом изменении грамматики её надо будет заново считывать и генерировать конечный класс.
стильно модно молодежно.
А это уже грязные инсинуации, молодой человек. Хотя аргумент — железный :D
да там как бы не только в этом вопрос.
А в чём тогда?
например pthreads заюзать.
я думаю это тупиковая ветвь. Нет смысла. А раскидать парсинг нескольких файлов проще через простой proc open.
Ну и опять же, я говорю о контекстно зависимых лексерах и возможности УДОБНО писать парсеры. Есть интересные проекты на том же ocaml которые вроде как довольно быстрые, да и имея декларативное описание парсера из него можно сгенерить что-то более эффективное.
А вот тут ты не прав.
что может быть проще декорации/композиции функций?)
я думаю это тупиковая ветвь. Нет смысла. А раскидать парсинг нескольких файлов проще через простой proc open.
Нужен ресёрч. Прям так сказать сложно. Но в любом случае его можно без особого напряга заюзать для мультистейт лексеров (ну типа неймспейсы из Hoa).
что может быть проще декорации/композиции функций?)
Грамматика с возможностью ссылаться декларируемые правила до и после.
digit ::= "1" | "2" | "3" | "4" | "5" ...etc ;
int ::= digit ;
float ::= [digit] "." digit ;
sum :: = (int | float) "+" (int | float | sum) ; <== ага, я могу ссылаться сам на себя! Читер! =)
Во время композиции теряется возможность получить ссылку на набор правил задекларированных до или после.
НО. Это всё опять же зависит от проектировки API. Так что вполне возможно, как это, например, сделано в yay, но получится это довольно избыточным с текущим синтаксисом пыха.
Ну и опять же, я говорю о контекстно зависимых лексерах и возможности УДОБНО писать парсеры. Есть интересные проекты на том же ocaml которые вроде как довольно быстрые, да и имея декларативное описание парсера из него можно сгенерить что-то более эффективное.
А я повторюсь, что (E)BNF like грамматика, изначально спроектированная для этого, не уступает по удобству композиции функций. Пока аргументов с твоей стороны в эту сторону не было. Так что предлагаю начать с этого. ;)
Аспектно-ориентированное программирование на PHP