Поддержка шаблонов в инструментах авторинга
Originally reported on Google Code with ID 312
Нужно реализовать следующую функциональность:
Храним (в БД, а пока можно захардкодить) наборы соответствий типа
number - \d*\.\d* .
Соответственно некоторая запись в регексе с использованием комментариев (или другой
вариант - например flex использовал фигурные скобки, но тогда их эскейпить надо) будет
преобразовываться в содержимое шаблона - например (?#$$word$$)
Шаблоны могут содержать нумерованные плейсхолдеры - место, в котором может стоять любое
корректное регулярное выражение. Например в словаре шаблонов может быть описано типа
parens - ((?#$$1$$)|\((?R)\))
будет использовать плейсхолдер с номером 1.
В регулярном выражении при задании такого шаблона необходимо указать значение плейсхолдера.
Значение должно быть вне комментария, т.к. коммент закрывается любой скобкой. Здесь
вопрос как лучше. Вариант (но длинновато)
(?#$$parens$$)(?#$$1)abc(?#1$$)
Ваши предложения? Кто короче предложит вариант записи шаблона с плейсхолдером в регексе?
Нам необходима будет новая опция в режиме парсинга - учитывать ли шаблоны. И возможность
сгенерировать текст регекса при подстановке шаблона, а также возможность показать их
как узлы в инструментах авторинга - т.е. будут два новых типа preg-узла - preg_template_leaf
и preg_template_operator (они используются инструментами авторинга для отображения
шаблонов, матчер же их заменяет на реальные значения).
Решать надо срочно, т.к. желательно к релизу сделать хотя бы для захардкоденных шаблонов
(включая плейсхолдеры!) возможность вводить их и получать результирующий регекс.
Reported by oasychev
on 2014-12-03 21:51:31
Comments (39)
-
-
И чуть более короткий вариант для задания значения плейсхолдера - (?#$$1abc). То есть если видим запись (?#$$n то всё что до конца коммента - это регекс.
Reported by
vostreltsov
on 2014-12-06 10:19:30 -
reporter Смысл плейсхолдера - это та часть шаблона, которая задается не в описании шаблона, а в конкретном регексе. Параметризованный шаблон. Укорачивать и уточнять синтаксис плейсхолдеров нужно. Возможно по принципу функций в Си - круглая скобка вместе с названием, потом разделители-комменты (а не имена плейсхолдеров), потом закрывающая скобка. Причем именно скобки и разделители (запятые) должны быть комментами, значения плейсхолдеров между ними должны быть обычными регексами. Писать значение плейсхолдера в комменте нельзя категорически, т.к. коммент идет до первой закрывающей скобки, а значение - произвольный регекс. Более того - ваша мысль о подрядидущих шаблонах недостаточно страшна - они еще и вложенными будут (причем в случае с рекурсией и скобками это вполне рядовая юзерская ситуация) - внутри первого плейсхолдера parens может встретится снова шаблон parens со своим плейсхолдером и т.д. Синтаксис должен это выдерживать.
Reported by
oasychev
on 2014-12-07 22:51:49 -
Account Deleted оба синтаксиса какието очень нечитаемые. Есть 2 предложения: 1) Простые шаблоны: (?#<pattern_name>) Шаблоны с плейсхолдерами: (?#<pattern_name>inner_regex) Описание плейсхолдера при определении шаблона (?#<placeholder>) 2) json Простые шаблоны: (?#{name: "patternname"}) Шаблоны с плейсхолдерами: (?#{name: "patternname", placeholder1: "blablabla"}) Описание плейсхолдера при определении шаблона (?#{placeholder: "placeholder1"})
Reported by
TOPT.iiiii
on 2014-12-09 14:45:34 -
reporter Я уже писал почему нельзя размещать значение плейсхолдера (по сути - параметра функции) внутри коммента - оно нарушит синтаксис. Пока я вижу самое простое - использовать синтаксис функции - нумеровать плейсхолдеры и в скобках писать: (?#$$templatename()placeholder1_value(?#$$,)placehodler2_value(?#$$) * примечание - закрывающая круглая скобка я так понимаю не может быть частью коммента регекса, поэтому в последнем просто $$. Доллары нужны чтобы отличить специальные комменты шаблонов от обычных комментов. Плейсхолдер - это по сути параметр шаблона, т.е. при определении шаблона задается его номер (название) в нужных местах шаблона; а при вставке шаблона в регекс задается значение плейсхолдера в виде произвольного регулярного выражения.
Reported by
oasychev
on 2014-12-09 14:59:50 -
reporter Да, можно еще квадратные или фигурные скобки вместо круглых, тогда закрывающая тоже поместиться. Круглые скобки и запятые я взял по аналогиями с функциями С++, это универсальный синтаксис позволяющий внутри значения плейсхолдера вставлять новые шаблоны со своими плейсхолдерами.
Reported by
oasychev
on 2014-12-09 15:01:02 -
Account Deleted есть еще предложение - использовать квадратные скобки. То есть, в режиме использования шаблоном, мы говорим, что если первый символ символьного класса, например, # - то это уже не символьный класс а шаблон. Например [#patternname] [#patternname#placeholder1#placeholder2] или [#patternname[placeholder1][placeholder2]] это позволит избавиться от странностей вроде той, что в конце комментария может не быть круглой скобки. И это уменьшит размер шаблонов... *** Еще предложение в варианте (?#$$templatename()placeholder1_value(?#$$,)placehodler2_value(?#$$) не использовать доллары: (?##templatename()placeholder1_value(?##,)placehodler2_value(?##) (мне не нравятся доллары, кажется, они усложняют читаемость в миллиард раз)
Reported by
TOPT.iiiii
on 2014-12-10 16:11:55 -
reporter Манером с квадратными скобками вы нарушаете обратную совместимость - то, что раньше было корректными символьными классами становится чем-то непонятным; к тому же совершенно неясно какие правила эскейпинга применять к значениям плейсхолдеров - как внутри симв. класса (потому что внутри) или как обычно (потому что это обычный регекс, а вовсе не часть симв. класса). Очень проблемный подход. Использовать вместо доллара дублирование решетки можно, может быть три раза ее повторить. Общий смысл долларов или лишних решеток - сделать крайне маловероятным совпадение обычного коммента с шаблоном.
Reported by
oasychev
on 2014-12-10 21:00:12 -
reporter Новые узлы шаблонов для авторинга создаются, просьба всем оперативно написать их отображение в инструментах авторинга. Сначала каждый пишет здесь свои предложения по внешнему виду (граф/дерево) и необходимым строкам (описание, а также надписи в графе и тултипы в дереве); потом реализуем. Поскольку для релиза то надо сделать быстро - в течении недели...
Reported by
oasychev
on 2015-01-04 19:23:52 -
reporter Появился новый класс шаблона, который позволяет хранить их захардкоденными. Пахомову после общего обсуждения строк добавить туда поля для хранения строк с описаниями в естественном падеже. Посмотрите есть ли в Moodle filter/multilang или что-то подобное, там может быть способ записи строки с текстами на нескольких языках. Не использовать get_string здесь логично, ибо в будущем эти строки будет вводить пользователь. Только сначала согласовать строки, чтобы не повторяться а по максимум использовать те же для графа, тултипа дерева и описания.
Reported by
oasychev
on 2015-01-05 00:17:03 -
Еще пара моментов, которые надо уточнить. 1) Шаблонам нужны свои личные опции, потому что можно писать хоть в обычной, хоть в extended нотации, и так далее. Предлагаю строковое поле $options рядом с $regex. 2) Нужно ли уметь использовать шаблоны внутри описания шаблона? Именно описания, а не вложенных вызовов. Там тогда получается нужно кучу дополнительных проверок городить, и пока не совсем понятно как это вообще парсить.
Reported by
vostreltsov
on 2015-01-06 11:30:46 -
1) реализовано, 2) в первом приближении тоже Вот такой вопрос нумерации подвыражений. Допустим, есть: 'parens_req' => new qtype_preg\template('parens_req', '( \( (?:$$1|(?-1)) \) )', 'x', 1), 'parens_opt' => new qtype_preg\template('parens_opt', '$$1|(?###parens_req<)$$1(?###>)', '', 1), И простое использование: (?###parens_opt<)(a)(?###>) Правильно ли, номер 1 идет на левый операнд альтернативы, 2 - это обертка parens_req, 3 - это исходный (a) уже в качестве операнда вместо $$1? Просто получается, что записанное в строке в одном месте выражение размножается на несколько поддеревьев в разными номерами. Можно, конечно, решить этот конкретный случай вызовом подвыражения но как-то странно это всё равно.
Reported by
vostreltsov
on 2015-01-08 12:32:59 -
reporter Ну по логике вещей правильно. Другое дело что лучше в операндах таких шаблонов не использовать подвыражения без надобности. А использовать двойную нумерацию подвыражений тут невозможно? Если нет, то для именованных подвыражений можно точно добиться чтобы совпадение было с одинаковым ключом.
Reported by
oasychev
on 2015-01-09 18:17:36 -
Account Deleted добавил описания к шаблонам, и получение описания для текущего языка. Описания задаются в виде: array('код языка' => 'описание $$1', 'код языка' => 'описание $$1') $$1 выбрано для единообразия с синтаксисом шаблонов. Между $$ и цифрой можно указывать форму. Пример: new qtype_preg\template( 'parens_req', '( \( (?:$$1|(?-1)) \) )', 'x', array('en' => '$$1 in parens', 'ru' => '$$1 в скобках'), 1 )
Reported by
TOPT.iiiii
on 2015-01-11 09:42:20 -
Допустим, шаблон (x)(y)$$1|($$1) (?###template<)(a)(?###>) Допустим, мы проходим подряд по всем токенам, которые встречаем, и если это шаблон - сразу парсим его. Тогда у шаблона есть подвыражения 1,2,3. Операнд (a) получает номер 4 во время парсинга. Затем мы доходим до правила свёртки, и нужно подставить (a) вместо $$1. Вот этот момент мне и не ясен до конца. (x)(y) нужно оставить как есть, потом $$1 сделать номер 3, потом увеличить номер подвыражения из правой альтернативы, и снова увеличить номер правого $$1. И после всего этого лексеру нужно тоже увеличить счетчик для последующих скобок. Я пока не вижу четкого алгоритма, как оно должно работать. Может попробуем текстовый препроцессор сделать?
Reported by
vostreltsov
on 2015-01-12 18:17:23 -
Вот, предлагаю гораздо более простое решение с препроцессингом. Это будет одна-единственная функция, принимающая все токены из регекса и возвращающая строку, теперь уже без шаблонов. У нее есть стек открытых шаблонов - как при проверке открытых-закрытых скобок. Проходим по всем токенам, если встретили не-шаблон, дописываем к результату userinscription токена. Если шаблон, то добавляем его на стек. И так далее. Синтаксические ошибки обнаруживаются здесь же. По производительности я не думаю, что это будет медленее (а может и быстрее), чем каждый раз клонирование всех закэшированных шаблонов + многочисленные обходы для перенумерации.
Reported by
vostreltsov
on 2015-01-12 21:52:13 -
Еще забыл уточнить, что учет опций шаблона делается через (?x: ... ) в случае расширенной нотации, и т. п. Так что объект парсера будет создаваться всего один, только для финального парсинга. А лексера будет два - для первоначального и финального лексинга.
Reported by
vostreltsov
on 2015-01-12 21:58:00 -
reporter Честно говоря если подставлять прямо при лексинге основного регекса шаблоны, не понимаю какие могли бы быть проблемы - просто прибавлять количество подвыражений внутри шаблона и все, оно же слева направо работает. Но можно и препроцессором, надо только чтобы он режим preserveallnodes не испортил.
Reported by
oasychev
on 2015-01-15 18:46:33 -
reporter Пахомову вопрос - там слоформы описаний аргументов как-то поддерживаются? Или только именительный падеж везде?
Reported by
oasychev
on 2015-01-15 19:16:27 -
Account Deleted сейчас всё что есть - в именительном падеже. В описании шаблонов можно вместо $$1 использовать $$form1 для указания требуемой формы.
Reported by
TOPT.iiiii
on 2015-01-15 20:33:31 -
Account Deleted предлагаю в дереве отображать следующим образом - т.к. все стили форм уже были использованы ( http://www.graphviz.org/doc/info/attrs.html ), то выделить края новых узлов зеленым цветом. Для параметризованного шаблона так: 1) http://prntscr.com/5tp9lk 2) тултип на русском: шаблон с параметрами 3) тултип на английском: template with parameters Для шаблона без параметров так: 1) http://prntscr.com/5tozca 2) тултип на русском: шаблон без параметров 3) тултип на английском: template without parameters
Reported by
grvlter
on 2015-01-17 20:22:41 -
reporter Во-первых, если выделять цветом, то тогда уже форму делать для шаблона без параметров идентичную с листом-символом, прямоугольную. А с параметрами - как у операций. Как простые и сложные ассерты (мы, кстати и dashed и dotted ухитрились использовать?) Во-вторых, зеленый цвет вроде используется для выделения, может синий или оранжевый? В третьих, я уже писал выше - в качестве тултипа должно быть описание смысла шаблона на русском/английском языке, которое вводится в класс шаблона. Что этот конкретный шаблон означает, т.е. условно (над фразой надо подумать) "любое количество правильно открытых и закрытых скобок" а не просто "шаблон с параметрами". Использовать строки от описания Пахомова может получиться для шаблонов с параметрами если правильно продумать слова, которые в общем смысле характеризуют параметры.
Reported by
oasychev
on 2015-01-18 15:02:18 -
Account Deleted 1) Формы для шаблонов без параметров/с параметрами соответствуют формам операндов/операторов (прямоугольные/овалы) 2) синий цвет: http://prntscr.com/5ujazb оранжевый цвет: http://prntscr.com/5ujai8 Я за синий, он на вид заметнее. Прошу высказать остальных своё мнение.
Reported by
grvlter
on 2015-01-19 21:19:02 -
reporter Синий неплох, только у нас некоторые надписи внутри синим/голубым делались в других узлах, мешать не будет? В шаблонах вроде таких надписей быть не должно. И таки может их как-нибудь dotted/dashed - не могли же мы оба эти стиля использовать на ассерты? Тоже прошу всех высказаться...
Reported by
oasychev
on 2015-01-19 21:46:34 -
Я за синий. Кстати, если мне не изменяет память - в графе, дереве и описании выделения разными цветами были сделаны? Может стоит унифицировать?
Reported by
vostreltsov
on 2015-01-19 21:49:50 -
reporter В графе и дереве вроде одинаково - зеленым. В описании это фон (а не прямоугольник), так что унифицировать едва ли разумно.
Reported by
oasychev
on 2015-01-19 21:50:53 -
Account Deleted Значит оставляем синий. 3) тултипы: для word: "любое слово" "any word" для integer: "любое число, включая + или -" "any number including + or -" для parens_req: "подвыражение в скобках" "subexpression in parentheses" для parens_opt: "подвыражение в скобках или без" "subexpression in parentheses or without" для brackets_req: "подвыражение в квадратных скобках" "subexpression in square brackets" для brackets_opt: "подвыражение в квадратных скобках или без" "subexpression in square brackets or without" Что касается тултипов для пользовательских шаблонов: их должен описывать сам пользователь при создании шаблона так, как он хочет и на нужном ему языке или нужно генерировать краткое описание, подобно описаю самого регулярного выражения?
Reported by
grvlter
on 2015-01-20 21:45:36 -
reporter Я вот думаю, может быть к тултипам добавлять на первой строке слово "шаблон" а на второй уже описание? Мы так делали с символьными классами вроде. По скобкам - не надо пугать людей словом "подвыражение" - может "строка в скобках" или "текст в скобках"? Для круглых скобок - писать явно "в круглых скобках". Я бы еще и фигурные сделал. Может быть даже, для унификации с описанием, типа "в любом количестве круглых скобок" - а что именно будет в описании добавлено. Пользователь будет сам вводить для своих шаблонов описания, но это уже следующая версия.
Reported by
oasychev
on 2015-01-23 13:39:41 -
Account Deleted Добавил поддержку шаблонов в графе (репозиторий zlumyo-preg-28). Приму предложения по внешнему виду. На данный момент внешний вид такой: - простой шаблон выглядит как обычный узел в форме гексагона; - сложный как подмаска с подписью, что это собственного говоря шаблон типа "такого-то".
Reported by
ZluMYO
on 2015-01-25 11:28:32 -
Account Deleted 3) тултипы: для word: "любое слово" "any word" для integer: "любое число, включая + или -" "any number including + or -" для parens_req: "текст в круглых скобках" "text in round parentheses" для parens_opt: "текст в круглых скобках или без" "text in round parentheses or without" для brackets_req: "текст в квадратных скобках" "text in square brackets" для brackets_opt: "тект в квадратных скобках или без" "text in square brackets or without" "Пользователь будет сам вводить для своих шаблонов описания, но это уже следующая версия." - в таком случае предлагаю хранить тултипы на данном этапе в lang-файле
Reported by
grvlter
on 2015-01-25 18:33:58 -
reporter а) в графе сложный шаблон желательно отделить от подмасок/квантификаторов цветом или видом линии еще б) в lang файле можно, но с пользовательским это не пройдет. Есть еще такая штука для этих целей - в отличие от get_string работает и на пользовательских данных тоже https://github.com/moodle/moodle/tree/master/filter/multilang Вопрос только что ее надо проверять, если выключена - выдавать текст на одном каком-то языке, чтобы ужасов юзеру не показывать.
Reported by
oasychev
on 2015-01-25 21:43:55 -
Account Deleted Внешний вид сложного шаблона в графе довольно проблематично отделить от подмасок/квантификатором. Вот такие есть варианты отрисовки границ кластера: http://prntscr.com/5xcuam Если думать о цветовом выделении, то наиболее очевидные (и ярко выраженные) цвета уже используются в других местах графа. Или можно повториться?
Reported by
ZluMYO
on 2015-01-26 18:03:39 -
Account Deleted Для дерева вроде все сделал по шаблонам, прошу проверить
Reported by
grvlter
on 2015-01-26 21:38:13 -
Считаю, что и для дерева, и для описания, строки нужно делать прямо полями в самом классе шаблона. Юзер их будет вводить на своем родном языке сам, а сейчас пока захардкодим на английском. Не будет же он менять lang/en/qtype_preg.php!
Reported by
vostreltsov
on 2015-01-29 11:59:21 -
Account Deleted они сейчас (у меня по крайней мере) берут описания не из lang-файла а как параметр конструктора new qtype_preg\template( 'parens_req', '( \( (?:$$1|(?-1)) \) )', 'x', >>> array('en' => '$$1 in parens', 'ru' => '$$1 в скобках'), <<<<<<<<<<<<<<<<<<<<<< 1 ) расчет был на то, что в будущем появится форма вида: http://prntscr.com/5yhior и вся эта радость будет храниться в бд
Reported by
TOPT.iiiii
on 2015-01-29 12:13:47 -
Зачем мне вводить описание на английском, если я его всё равно не буду использовать?
Reported by
vostreltsov
on 2015-01-29 12:24:51 -
reporter По языкам и описаниям еще раз (см 31-й коммент) - "Есть еще такая штука для этих целей - в отличие от get_string работает и на пользовательских данных тоже https://github.com/moodle/moodle/tree/master/filter/multilang " Предлагаю проверять, включен ли - если проверять то вываливать описания на всех языках в соотв. тегах, если нет - на английском. Вообще по идее функция, возвращающая текущий язык интерфейса тоже есть. Валерий - про описание на английском не понял, хардкодить его точно надо.
Reported by
oasychev
on 2015-02-08 22:07:49 -
Account Deleted >> по идее функция, возвращающая текущий язык интерфейса тоже есть. Есть. Она используется уже
Reported by
TOPT.iiiii
on 2015-02-09 12:52:09 -
reporter Reported by
oasychev
on 2015-07-03 20:16:16 - Status changed:Done
- Log in to comment
Reported by
vostreltsov
on 2014-12-06 10:17:53