Поддерка модификаторов s,x

Issue #134 closed
Oleg Sychev repo owner created an issue

Originally reported on Google Code with ID 134

Модификатор означает что неэкскейпенные пробелы и переводы строк в регексе игнорируются,
а комментарии могут начинаться с # (неэскейпинного) и продолжаться до перевода строки.

Мы можем поддерживать его без особых проблем (не сделать ли в любом случае textarea
для ввода регексов? при длинных может быть удобно), и часть тестов PCRE - в т.ч. хитрых
- записана с ним.

Reported by oasychev on 2012-07-30 13:53:34

Comments (12)

  1. Valeriy Streltsov
    Думаю, стоит поддерживать не только модификатор X :)
    
    Предлагаю внести следующие изменения. В qtype_preg_node добавить соответствующие константы
    (равные 1, 2, 4, 8) и функцию парсинга строки в число, в котором они побитово объединены.
    Модификаторы хэндлеру передавать внутри опций сразу же числом (будет намного проще,
    чем всякие strpos), соответственно убрать параметр modifiers у конструктора. Затронутся
    собственно узлы, лексер, get_matcher и вроде бы всё.
    

    Reported by vostreltsov on 2013-04-30 13:31:50 - Status changed: InProgress

  2. Valeriy Streltsov
    Забыл: поле modifiers из хэндлера можно будет убрать, а также проверку поддержки модификаторов
    (это же ведь тоже акцептинг по сути, модификаторы применяются к узлам - там их и можно
    проверять, в accept() dst узлов). Если честно, вообще не очень понимаю, почему для
    модификаторов отдельный тип ошибки, а не обычный акцептинг.
    

    Reported by vostreltsov on 2013-04-30 13:57:59

  3. Oleg Sychev reporter
    Я вообще не хотел мешать все в одну кучу. i уже поддерживается. Другие - требуют отдельного
    обсуждения.
    
    Вот зачем вам все модификаторы в узлы записывать? Это какой дубляж информации, не говоря
    о проверках при аццептинге каждого узла? Чем меньше полей в узлах - тем лучше, а если
    надо - они должны быть как можно ниже по иерархии. Поле для i например только в листьях
    было, и то, возможно, не всем надо. С опциями матчинга могу согласиться, но с листьями
    вы тут явно погорячились.
    
    Тот же х - с которого все началось - влияет только на сканер - к узлам он отношения
    не имеет вообще. Его неплохо бы сделать побыстрее, т.к. главный выигрыш для нас от
    него - в кросс-тестере, он открывает набор тестов которые просто записаны в другой
    форме. И там нехилые тестики есть...
    
    s - тоже может обрабатываться сканером, просто генерировать разные узлы для точки в
    зависимости от него, и все. Например за узлом точки оставляем совпадение со всем, в
    т.ч. переводом строки, а без нее генерируем отрицательный символьный класс - без перевода
    строки (но сохраняя userinscription как точку).
    
    m - тоже может поддерживаться сканером путем замены ^ и $ на \a \z при определенных
    значениях опции так, чтобы они для узлов всегда имели одинаковое значение (сами разберетесь?).
    К нему логично добавить - PCRE_DOLLARENDONLY - все это часть #188 вообще-то, не мешайте
    все модификаторы в одну кучу.
    
    Думаю, что так: модификаторы переносим в опции хендлера (сохраняя название чтобы не
    путаться?), вместо аццептинга регекса вводим аццептинг опций. В опциях - и глобальных,
    и локальных в стеке сканера, не забывайте про них - используем флаги вместо символов
    в строке. Ошибка остается отдельной, т.к. сообщение должно генерироваться по другому
    - над ним надо еще поработать, когда будут готовы хоть несколько опций, чтобы оно было
    вразумительным для юзера; он то "модификаторов" не пишет и не видит. Можно унаследовать
    обе ошибки аццептинга от одного предка для упрощения проверок аццептинг это или нет...
    

    Reported by oasychev on 2013-05-04 09:13:41

  4. Oleg Sychev reporter
    Я так понимаю, дискуссию по реализации модификаторов пока ведем здесь.
    1. Не понял, почему функция преобразования модификаторов в строку - статическая, как
    и другие аналогичные ей. Почему ей не быть динамической при объекте опций? modifiers_to_pcre_string
    например... (строка  - она разная бывает) В каких местах она нужна отдельно от объекта
    опций?
    2. Я же писал - не нужно добавлять в узлы флаги по поводу точки (s).Узлов много, тут
    надо экономить - сами помните, как меняются затраты памяти на тестирование. Достаточно
    сделать так, чтобы базовый узел точки совпадал со всем, а при наличии модификатора
    s генерировать узел [^\n] прописывая точку в userinscription. В чем проблема с этим
    решением?
    3. Не понял, зачем вы удалили сброс ast в null в конструкторе хэндлера при отсутствии
    парсинга.
    4. Если делать сразу список, добавляйте уж DOLLARENDONLY - буква D в PHP, PCRE его
    только словом понимает - управляет поведением доллара в случае конца строки.
    5. В вопросе
    $modifiers = $modifiers | qtype_preg_handling_options::MODIFIER_CASELESS;
     Разве операции |= нет?
    6. Не нравится мне дублирование кода функций управлениями модификаторами (set_modifier
    и еще две) в лексере и опциях. Использовать функции опций, благо в стеке лексера именно
    они и хранятся... 
    7. php_preg_matcher наверное требует отдельной поддержки модификаторов. Они в PHP и
    PCRE несколько различаются...
    

    Reported by oasychev on 2013-05-04 15:26:36

  5. Valeriy Streltsov
    1. modifiers_to_string понадобилась в php_preg_matcher:
    $for_regexp .= qtype_preg_handling_options::modifiers_to_string($this->options->modifiers);
    
    2. Пофикшу, надо придумать как (пока что пусть хотя бы работает)
    3. ast_root инициализируется в null сразу при объявлении.
    4. Добавлю
    5. a |= b сокращение для a||b, а не a|b
    6. Знаю, надо придумать как это улучшить. По идее туда лучше засунуть объект опций,
    а не число $modifiers. Тогда можно будет юзать функции опций.
    7. Тут уж не знаю, предлагайте как можно это сделать.
    

    Reported by vostreltsov on 2013-05-04 16:14:59

  6. Oleg Sychev reporter
    1. И что? $this->options же объект опций, ну и вызывать из него как динамическую функцию.
    2. А чего придумывать? Я уже дважды выше описал, как это можно сделать...
    3. Ладно.
    6. А сейчас там разве не объекты опций лежат? Например строка 380 preg_lexer.lex
    $node->caseless = $stackitem->is_modifier_set(qtype_preg_handling_options::MODIFIER_CASELESS);
    

    Reported by oasychev on 2013-05-04 16:50:37

  7. Valeriy Streltsov
    2: пофиксил
    1 и 6 - в ближайшее время
    

    Reported by vostreltsov on 2013-05-04 18:33:00

  8. Oleg Sychev reporter
    Про 1 и 6 не забыли? Там тривиальные довольно вещи, чего их бросать на половине дороги?
    

    Reported by oasychev on 2013-05-05 13:01:06

  9. Valeriy Streltsov
    1: modifiers_to_string теперь динамическая; остальное - статическое: string_to_modifiers
    нужен при установке локальных модификаторов (там объекта нет), и он же цепляет за собой
    char_to_modifier; modifier_to_char нужен в лексере при поиске ошибок, полученный char
    подставляется в addinfo (там объекта тоже нет).
    6: пофиксил, дублирования кода больше нет. Есть, правда, похожая функция в лексере
    - is_modifier_set, но без нее нельзя. Она сначала проверяет опции на верхнем элементе
    стека скобок, а если стек пустой (синтаксическая ошибка) - берет уже опции самого лексера.
    Ну и удобнее с ней, чем каждый раз проверять что стек непустой и брать верхний элемент.
    

    Reported by vostreltsov on 2013-05-05 15:02:53 - Status changed: Fixed

  10. Oleg Sychev reporter
    6 - а может лучше всегда поддерживать на стеке какой-то "пустой" объект - либо объект
    с глобальными опциями, даже при наличии ошибки с излишним закрыванием скобок? Всего-то
    pop изменить, чтобы она последний объект не удаляла...
    

    Reported by oasychev on 2013-05-05 15:06:09

  11. Log in to comment