Как стать автором
Обновить

Комментарии 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
Что ты думаешь на тему запилить библиотеку для комбинаторов парсеров?
А можно чуть более приземлёнными словами, делая скидку на то, что я дилетант в этой области? =)
ну вот пример на JS: github.com/jneen/parsimmon

под 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 не устраивает в этом случае

  1. медленно (комбинаоры парсеров будут не быстрее, в силу того что лексинг по сути будет работать аналогично — тупо preg_match по оффсету, но в целом функции можно подменять. Вот будет FFI в PHP и можно будет re2c юзать для генерации таблиц сравнения символов). Я пока ленюсь сделать бенчмарк и сравнить json парсер на написанном наколенке комбинаторе парсеров и hoa (хочется еще сравнить какой-нибудь PHP-Yacc или pacc.
  2. неудобно расширять грамматику (по сравнению с простой композицией функций). Как по мне для проектов типа Doctrine ORM это будет намного более интересной вещью нежели hoa.
  3. стильно модно молодежно.

набросать грамматику для PHP

вот тут помогут фичи типа нэймспейсов для лексем, в силу того что у php таки контекстно зависимый лексер.


через LL будет сложно нормально приоритеты операторов распарсить

да там как бы не только в этом вопрос.

медленно (комбинаоры парсеров будут не быстрее, в силу того что лексинг по сути будет работать аналогично — тупо preg_match по оффсету, но в целом функции можно подменять. Вот будет FFI в PHP и можно будет re2c юзать для генерации таблиц сравнения символов).

Тут проблем ну вообще никаких нет. 600к токенов в секунду, вполне достаточно для моментальной токенизации даже мегабайтных файлов:image

И прошу заметить — это обычный домашний ПК под виндой, а не сервер. Да и места под дальнейший тюнинг тоже километр, например 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 грамматика, изначально спроектированная для этого, не уступает по удобству композиции функций. Пока аргументов с твоей стороны в эту сторону не было. Так что предлагаю начать с этого. ;)
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.