Реализовать поддержку дублированных номеров подмасок в соответствии с PCRE

Issue #82 closed
Oleg Sychev repo owner created an issue

Originally reported on Google Code with ID 82 ``` Смотрим секцию DUPLICATE SUBPATTERN NUMBERS http://www.pcre.org/pcre.txt

Там хороший и подробный пример.

Вариант метода реализации: добавить новый тип скобок и перенумеровать в подмаски в парсере... ```

Reported by `oasychev` on 2011-12-30 16:12:33

Comments (7)

  1. Valeriy Streltsov

    ``` Поправил сканер и парсер. В сканере сохранился подсчет количества подмасок - он необходим для обработки обратных ссылок, но нумерации в сканере больше нет. За ненадобностью я закомментировал класс preg_lexem_subpatt. Нумерация переползет в regex_handler, так как необходимо иметь полностью построенное дерево.

    Теперь самое интересное - как лучше всего пронумеровать подмаски и обратные ссылки? Я пока что вижу один вариант - косвенная рекурсия. Одна функция будет нумеровать поддеревья обычным образом в порядке левого обхода, вторая функция будет осуществлять проход дерева волной вниз пока не встретит узлы подмасок, нумеровать их одним числом и вызывать первую функцию для этих узлов.

    Есть предложения, как это можно сделать проще? ```

    Reported by `vostreltsov` on 2012-01-13 20:43:01

  2. Oleg Sychev reporter

    ``` Я предлагал вам продолжать нумеровать подмаски в сканере, а в парсере - при встрече узла с двойной нумерацией подмасок - проходить под-дерево (оно к этому моменту готово) и перенумеровывает подмаски (и относительные обратные ссылки, если они там встречаются).

    Чем вам не нравится такой подход?

    P.S. Нас теперь волнует не столько общее количество подмасок, сколько количество нумерованных подмасок. Именованные считаются отдельно.... ```

    Reported by `oasychev` on 2012-01-14 05:57:07

  3. Valeriy Streltsov

    ``` Не все так просто с проходом поддерева. Узлы более высоких уровней влияют на нумерацию нижних. Если будет несколько вложенных (?|...), поддеревья будут перенумеровываться несколько раз, из-за того что верхний уровень собьет нумерацию нижнего. Если нумеровать после постройки дерева (а функция фактически останется такой же, но вызовется в другое время) - поддеревья не будут перенумеровываться дважды, и это будет проще для понимания. Хотя, может я не до конца что-то понимаю...

    И вот на счет нумерации именованных подмасок: Named capturing parentheses are still allocated numbers as well as names, exactly as if the names were not present. The PCRE API provides function calls for extracting the name-to-number translation table from a compiled pattern. There is also a convenience function for extracting a captured substring by name. ```

    Reported by `vostreltsov` on 2012-01-14 20:35:35

  4. Oleg Sychev reporter

    ``` Наличие вложенных узлов не проблема - их можно сохранять в дереве и обрабатывать как угодно. Надо только проверить (возможно экспериментом) как PCRE обрабатывает вложенность (?|...)

    Если нумеровать позже, будет больше проблем с относительными ссылками. Так проблемы доставят только те, что находятся прямо внутри (?|...) - их положительные номера может заменить та же функция, что и перенумеровывает подмаски. А если делать обход после построения всего дерева, надо перенумеровывать относительные подмаски глобально, все расположенные после (?|

    Я что-то не понимаю что вы собрались делать. Поле зачем-то ввели в узел альтернативы - непонятно, где вы эту информацию собрались определять и зачем в объекте сохранять. Альтернативы верхнего уровня элементарно определяются рекурсивным обходом, так что по идее все это должно быть локальными переменными в функции обхода.

    По именованным подмаскам: хорошо, это может даже удобнее. Тогда, получается, нужно иметь две копии совпадения - с доступом по имени и по номеру. Или соответствие имя-номер. Как думаете реализовать? ```

    Reported by `oasychev` on 2012-01-15 18:24:25

  5. Valeriy Streltsov

    ``` Дублированные номера подмасок разрешаются только для альтернатив, и это уже определяется в сканере.

    Для именованных подмасок удобнее организовать соответствие номер-имя.

    Я, кстати, додумал идею на счет стека и спешу ей поделиться: - хранить текущий номер подмаски который будет присваиваться (), и максимальный номер подмасок отдельно, причем максимум может только инкрементироваться, а текущий номер может как угодно меняться; - в сканере завести стек, на который при встрече (?| класть текущий максимальный номер подмаски и число открытых скобок; - при встрече | если этот стек не пустой - сбрасывать текущее значение подмаски на значение с вершины стека. иначе инкрементировать максимальное значение подмаски, это будет новым текущим значением. - при встрече ) соответствующей (?| удалять значение с вершины стека. Соответствие отслеживать путем уравновешивания открытых скобками закрытыми, количество первых лежит на вершине стека, количество последних можно подсчитывать.

    С помощью стека легко решатся проблемы вложенности и относительных ссылок, поскольку мы храним номер текущей подмаски.

    Пример: (?|(a(b(c)))|(d))(e) Сначала кладем на стек значение 1 и количество открытых скобок = 1 В первом пути альтернативы мы встретим максимальный номер подмаски = 3 Когда встретим | увидим, что стек не пустой и положим текущее значение подмаски равным значению верхнего элемента стека = 1 Когда встретим закрывающую скобку для конструкции (?|...) - удалим верхнее значение стека, увидим что он пустой и положим текущее значение подмаски = инкременту максимального значения, т.е. 4. В случае если бы стек оставался непустым, приравняли бы текущее значение подмаски к верхнему элементу из стека, макс. значение осталось бы неизменным.

    Этот вариант мне кажется более предпочтительным, Дмитрий согласен. Что скажете? ```

    Reported by `vostreltsov` on 2012-01-15 20:55:22

  6. Oleg Sychev reporter

    ``` Спасибо ```

    Reported by `oasychev` on 2012-09-25 09:41:53 - Status changed: `Done`

  7. Log in to comment