Последовательности типа \w \d \s внутри символьных классов должны корректно обрабатываться
Originally reported on Google Code with ID 57 ``` У нас имеются проблемы их обработки: - многие последовательности заменяются на значения, хотя должны обрабатываться через функции - \w и \W приводят к одинаковым действиям сканера, хотя обозначают, по идее, противоположные вещи
Необходимо наладить их правильную работу. Это, помимо прочего, необходимое условие внедрения в наших курсах, т.к. наши вопросы такие штучки используют... ```
Reported by `oasychev` on 2011-11-20 21:41:51
Comments (25)
-
reporter -
reporter ``` Символьные классы описываются последовательностями: \d \D \h \H \s \S \v \V \w \W \N
\d \D \s \S \w \W должны быть реализованы через свойства preg_leaf_charser и поддерживаться через вызовы функций. \N эквивалентно точке (все кроме перевода строки). Остальные могут быть реализованы перечислением символов. Подробнее см. http://pcre.org/pcre.txt раздел Generic character types
Последовательности видов \a \cx \e \f \n \r \t представляют собой отдельные символы и должны переводится в таковые. См. Non-printing characters того же документа.
По идее надобность в preg_leaf_meta и сам класс должны исчезнуть.
Дмитрий, прошу не тянуть с проектом переделки... ```
Reported by `oasychev` on 2012-01-02 22:17:45
-
reporter ``` Точнее preg_leaf_meta останется для эпсилонов и их аналогов типа ENDREG. ```
Reported by `oasychev` on 2012-01-21 17:35:34
-
reporter ``` Ввел дополнительные поля для этого.
Юникод-свойства тоже надо в charset переводить... ```
Reported by `oasychev` on 2012-01-21 18:03:11
-
Account Deleted ``` Идея такая: чарсет будет иметь строку содержащую перечислимые символы и массив флагов соответствующих не перечислимым (\w например), ключи этого массива будут заданы константами класса и будут являться именами функций которые проверяют символ на соответствие данному требования. Тогда можно будет, просто перебирая, этот массив foreach'ем и вызывая функцию имя которой хранится в ключе проверить символ. Пересечение чарсетов это пересечение строк и флажковых массивов массивов. Но как пересечь флажки? Как пересечь из \w \d ? Получится \w && \D понятное дело, но ведь в чарсете между флажками (и строкой тоже) имеются отношения "ИЛИ", если же сделать их через "И" и принимать символ соответствующий всем, то как быть с ситуациями где нужно "ИЛИ", [a\w\d]? Либо получится иерархическая структура либо можно сделать фокус. Я предлагаю такой фокус: флажок \w рассматривать как символ слова, кроме цифры, а цифру отдельно, \w из регекса превращать в \w || \d. Тогда все флажки будут непересекающимися, т.е. никакие два флажка не смогут принять один и тот же символ. Строку с перечисленными символами можно избавить от пересечения с флажками удалив лишние символы, ведь нет разницы принят символ дважэды или один раз, [ab@%\w] превратить в [@%\w] тогда для пересечения/вычитания/сложения и чего угодно строка станет таким же флажком, массивы флажков пересечь легко. В коде: class charset extend leaf { protected $string; protected $flags;$flags[self::<flagname>] = true если флажок установлен const w = 'is_alpha'; и т.д. }; ```
Reported by `Xapuyc7` on 2012-03-11 18:15:42
-
reporter ``` Проблему И/ИЛИ понял, буду думать. Важный вопрос - возможно ли более одного пересечения (т.е. пересечение уже ранее пересеченных элементов). Возможно придется хранить выражение - например в ДНФ (массив массивов, элементы внутренних массивов объединяются по И, а внешнего - ИЛИ). Т.е. array (array(d, space), array(w)) означает \d && [:space:]
\w Можно запоминать, какие классы должны давать нулевое пересечение обязательно, это упростит дело....
Вариант с особой обработкой \d \w мало что решает - см. issue про POSIX - классы. И есть еще Unicode properties, которые тоже проверяются вызовом функции. Так что в общем случае уходить от проблемы нельзя. ```
Reported by `oasychev` on 2012-03-11 20:46:30
-
Account Deleted ``` Даже если возможно пересечение неограниченное количество раз, выражение состоящее из И/ИЛИ можно свести к двум уровням иерархии. Разве нет? На вскидку, да возможно. Мне кажется, что удобнее (для данного случая) использовать КНФ, т.е. объединять элементы внутренних массивов по ИЛИ а внешнего по И? И стоит ли делать двумерный массив или лучше выделить класс чарсета и класс пересечения чарсетов(но не пересечения пересечений)? О ДНФ/КНФ я тоже думал, мне показалось, что я нашел лучший вариант, показалось. ```
Reported by `Xapuyc7` on 2012-03-11 21:00:39
-
reporter ``` Два уровня можно получить при любом количестве пересечений.
ДНФ или КНФ удобнее проверить на алгоритмах построения пересечения/разности - выйдут ли они одинаковыми или в какой-то ситуации проще будет. Ну и определения совпадения тоже...
Я бы предпочел иметь один класс - или придется определять функцию пересечения пересечений, пересечения пересечения с чарсетом и т.д.). Гораздо удобнее иметь все одним классом, тем более что от двумерного массива в общем случае все равно не уйти видимо. ```
Reported by `oasychev` on 2012-03-11 21:18:30
-
Account Deleted ``` Если я правильно помню количество юникодовских свойств, то об разделении на уникальные подклассы и думать страшно, так что с "не уйти" я согласен. На счет лишних функций, оно конечно так, но на другой чаше весов лежит усложнение кода в меньшем кол-ве функций. ```
Reported by `Xapuyc7` on 2012-03-11 21:23:07
-
reporter ``` Я не думаю что налицо серьезное усложнение кода при уменьшении количества классов. Один флаг - вполне разумный частный случай ДНФ/КНФ и никакого специального алгоритма обработки не требует.
Единственное усложнение будет заключаться в том, что одиночный флаг будет записываться типа array(array(preg_leaf_charset::w)) - но это не так страшно, как дополнительные функции с дублированным кодом выполняющим одно и то же по сути действие.
Если быть точным, то поскольку в оригинале все добавляется через ИЛИ то добавление в ДНФ будет выглядеть типа $xx->flags[] = array(preg_leaf_charset::w); В КНФ, кстати, немного сложнее...
Единственно по хорошему для юнит-тестов нужно бы написать функцию эквивалентности чарсетов, с учетом разного порядка в ДНФ/КНФ....
P.S. У нас будут вводиться новые флаги и т.д. Может быть это подходящий случай подогнать иерархию узлов под стандарты Moodle, имея qtype_preg_leaf_charset и т.д.? Когда-нибудь это все равно придется сделать...е ```
Reported by `oasychev` on 2012-03-12 07:43:42
-
Account Deleted ``` Добавил проект нового чарсета, вся его структура есть, функции не реализованы (пишут implement before use!). Классов у меня все же получилось два: 1)класс одиночного флага, который получается так, что многое делает 2)класс чарсета, являющийся их контейнером. Одни и теже функции есть, но они будут делать разное: функции флага будут делать непосредственно свою работу, а функции контейнера будут обрабатывать их результаты в соответствии с ДНФ. Код в клоне. Таблицы пересечений и вычитаний составлю в ближайшее время. ```
Reported by `Xapuyc7` on 2012-03-24 15:52:54
-
Account Deleted ``` Составил таблицы пересечений и вычитаний. В таблице вычитания из флажка которому посвящена строка вычитается флажок которому посвящен стобец. ??? означает что я не знаю что из этого получится, можно безболезненно заменить на false. false означает что одним флажком это не объять. Таблицы получились большие, даже если исключить из них( и из чарсета) дублирующиеся флажки (\w and [:word:], например) все равно останется немало, хотя загнать массив и можно радоваться, ведь это позволит не только избежать чрезмерного разрастания пересечений, но и сразу обнуруживать чарсеты которые не примут ничего, и соответствеено не делать переходов по ним. ```
Reported by `Xapuyc7` on 2012-03-24 23:56:48
<hr>
-
Account Deleted ``` Отредактировал таблицу. 1) исключил из неё повторы (\w [:word:] например) 2) исключил отрицательные флажки из таблицы пересечений и таблицы вычитаний (\D\W\S) 3) составил таблицу пересечений негативных флажка с негативными, она понадобится как для случая пересечния двух негативных флажков, так и для случая вычитания из позитивного флажка из негативного, в сущности это один случай. Остальные случаи
преобразуются через таблицы пересечения позитивных флажков и вычитание позитивных
флажков.
В большей части случаев получается 1 флажок, реже то, что не может быть представлено одним флажком и пустое пересечение. Таким образом, считаю применение этих таблиц оправданым. ```
Reported by `Xapuyc7` on 2012-03-25 13:12:06
<hr>
- *Attachment: [chrflags2.ods](https://storage.googleapis.com/google-code-attachments/oasychev-moodle-plugins/issue-57/comment-13/chrflags2.ods)*
-
reporter ``` По коду: 1) а что, у нас charset кроме флагов, ничего уже не содержит? А куда просто символы девать? 2) все потомки preg_node рассчитывались на то, что они имеют открытые public - поля. Насчет флагов можно подумать, но если поля защищены - то в конструкторе они должны заполняться полностью. А так у вас и способа то нет им что-либо присвоить... 3)\w включает буквы, цифры и подчеркивания - а у вас, если не ошибаюсь, минус вместо подчеркивания... 4) add_flag - может быть добавить к названию как добавить, т.е. add_conjuncted_flag или add_disjuncted_flag или что-нибудь в этом роде... 5) юникод-свойство если уж хранить arg то наверное '/\p{'.$prop.'}/' А называть имя функции "value" - довольно странное занятие. Нужно конкретнее определиться со значением этих аргументов. 6) Еще должна быть функция consumes, которая вычисляется не совсем очевидным образом учитывая что ассерты тоже могут быть флагами... ```
Reported by `oasychev` on 2012-03-25 17:13:30
-
reporter ``` По таблице 1) не согласен с false для ascii Возьмите таблицу символов и посмотрите. Например цифры - разве они не все от 0 до 127? Или \s ? 2) Наборы символов, не являющиеся флагами, мы всегда сможем хранить просто набором (возможно негативным), или они тоже должны участвовать к ДНФ?
P.S. DNF - это плохой комментарий! Человек, незнакомый с нашими идеями, его не поймет. Напишите что логическая функция от флагов в ДНФ (не аббревиатурой, а словами) ```
Reported by `oasychev` on 2012-03-25 18:32:26
-
reporter ``` И еще таблица могла бы чаще использовать set. Например при пересечении xdigit с alpha - разве не ясно, какой будет set? ```
Reported by `oasychev` on 2012-03-25 18:33:26
-
Account Deleted ``` 1)просто символы это частный случай флага, ведь с ними можно обращаться как с флагом, а дополнительные возможности обращения с ними остаются классу флага, тогда как контейнер-чарсет не интересуется типом флага 2)Согласен, буду думать о конструкторах, сделать флаги пабликом, впринципе, можно, главное самим помнить о их сложности и не трогать без нужды, но протектид мне более симпатичен, в данном случае. 3)Ой! Шифт не нажался :) 4)возможно нужны две такие такие функции, добавить функцию не сложно, эту переименую, вторую добавлю если понадобится. 5)так ведь \p{<property>} прилетит из лексера, флагу останется окружить его / /, разве нет? value для случая набора символов там будет именно значение, а ведь валуе не используется для пропертей, только арг, так зачем две переменные? может их в одну свести и назвать её <пока не придумал как>, зачем классу лишнее свойство? 6)вычисляется она просто, но у неё будет три результата: да нет, может так и может сяк. Последнее не может образоваться ни придти из регекса ни образоваться при мержинге ассертов, и этого не будет при построении автомата, если смержить ассерты до построения. Его наверное стоит запретить. Можно всегда глотать символ, можно никогда не глотать символ, но нельзя решать это в момент матчинга.
1)0123456789 все лежат в аски, но мы ведь не делаем их перечислимыми именно потому что могут быть экзотические цифры. Где будут лежать экзотические цифры? до 127 или после? Я не знаю. 2)[^a1] & \D | [^ T] & \S, например, я не представляю, как отсюда вытащить единый набор символов, думаю, что должны учавствовать в ДНФ.
ПС) комментарии перепишу
И) xdigit это 0123456789abcdefABCDEF для любой локали? тогда зачем на xdigit? Перечислимый набор получается. ```
Reported by `Xapuyc7` on 2012-03-25 19:41:23
-
reporter ``` 1) а, у вас там во флаге путаница с полями. Давайте называть их по назначению, лучше лишнее поле завести чем писать многострочные списки комментариев, что обозначает данное поле при каком типе флага... Исправляем бардак. 5) я бы по из лексера передавал только property без \p{} потому как во первых, неизвестно зачем еще оно может пригодиться кроме матчинга, во-вторых - \P это, как обычно, отрицание, оно должно перейти в отдельное свойство. 6) надо исследовать, при какой ситуации возможно "и так и сяк". Пример ДНФ и как оно может образоваться. Ассерты будут участвовать в ДНФ при построении ДКА, иначе у вас корректно они не обработаются - если не будут смержены предварительно, хотя там тоже могут возникнуть проблемы... 7) по POSIX-классам в пересечении с ASCII http://en.wikipedia.org/wiki/Regular_expression#POSIX_character_classes xdigit может быть и не одинакова по локалям, но ASCII набор (0-127) от локали не меняется, локаль обычно меняет набор 128-255. Поэтому пересечения POSIX/ASCII определить можно, вот разность уже имеет риск быть зависимой от локали.
Обратите внимание что вполне возможны выражения типа [x-z[:digit:]] а также отрицания [:^alpha:] Собственно POSIX классы поддерживаются PCRE только внутри символьных классов... ```
Reported by `oasychev` on 2012-03-25 20:12:31
-
Account Deleted ``` 1)Ну лишнее так лишнее. 5)опять же, не проблема. 6)Пример ДНФ ^ | a. Если мержить ассерты до построения автомата, то образоваться не может никак, это наше спасение. Ведь "и так и сяк" просто в лоб нельзя ни мержить ни использовать, их можно было бы разбивать, но все равно проблемы с точки зрения ЧСК. 7)Допустим можно, каков риск запутаться в символах закорючках? Для не закорючных случаев можно. Сделаю.
[x-z[:digit:]] не проблема. :^alpha: или [^[:alpha:]]? хотя и то и то не есть проблема. Я ведь составил таблицы так, чтобы они покрыли все случаи пересеченипя ++ +- -+ --, а вычитание выражается через пересечение и отрицание. ```
Reported by `Xapuyc7` on 2012-03-25 20:36:35
-
reporter ``` 1) поля называть: charset, uniprop и т.д - чтобы по названию было ясно, что они содержат 6) А чем вам поможет мержинг? Там у вас все равно получится что-нибудь типа a при условии ^. Тогда вам смерженные ассерты нужно будет в состав индивидуального флага водить. Полностью извести можно только \b - и то с ограничениями... 7) Какой риск запутаться в закорючках копируя их из википедии? Ну зависит от степени внимательности...
Я не говорю что проблема, я просто напоминаю чтобы делая сканер вы это учитывали....
```
Reported by `oasychev` on 2012-03-28 09:38:25
-
reporter ``` И если оно все не проблема - то где хотя бы исправленные классы чарсета/флага? ```
Reported by `oasychev` on 2012-03-28 09:39:29
-
Account Deleted Reported by `Xapuyc7` on 2012-04-05 15:06:35
-
reporter ``` добавить кросс-тесты на \w \d \W и т.д. внутри символьного класса ```
Reported by `oasychev` on 2012-07-23 09:07:58
-
Reported by `vostreltsov` on 2012-07-24 10:44:06 - Status changed: `Fixed`
-
reporter Reported by `oasychev` on 2012-07-27 16:08:55 - Status changed: `Done`
- Log in to comment
``` Есть мнение, что \W \s и т.д. должны быть частью preg_leaf_charset, а не meta.
Это дает легкую обработку их как внутри, так и вне класса (усложняется код charset, но он то как раз не сильно сложный), а также значительно более простые операции над листами (пересечение любых charsetов даст charset, а не набор узлов как сейчас). ```
Reported by `oasychev` on 2011-11-29 08:09:18