Поддержка макросов

Примечание: В этом разделе рассматриваются продвинутые функциональные возможности, полезные при написании больших и сложно организованных правил. Его можно пропустить и перейти к следующим разделам без ущерба для понимания. Макросы стоит использовать, когда в коде многократно повторяется одно и то же (или почти одно и то же) правило или поисковый запрос. Чтобы не писать идентичные правила, можно объявить макрос, который содержит повторяющиеся фрагменты, и вызывать его при необходимости. Использование макросов позволяет менять код только в одном месте: сделанные в макросе изменения затронут и другие правила, где используется этот макрос.

Синтаксис объявления макроса

macro: имя_макроса(аргумент_1, аргумент_2…​)
{
/* здесь можно записать xpdl-правила или pdl-запрос */
}

Объявление макроса начинается с ключевого слова macro:, после идет имя макроса и взятый в скобки список аргументов, перечисленных через запятую. Если у макроса нет аргументов, в скобках можно ничего не указывать. Тело макроса заключается в фигурные скобки. Имя макроса задается пользователем, оно может содержать любые число-буквенные символы и знак нижнего подчеркивания (специальные символы и пунктуация, например, знак процента, коммерческое at, точка, запятая, пробел, скобки и т.д. недопустимы).

Если макрос содержит PDL-запрос, допускается упрощенное объявление макроса:

macro: имя_макроса(аргумент_1, аргумент_2…​) = PDL-запрос

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

Объявление макроса должно предшествовать вызову макроса.

Синтаксис вызова макроса

macro(имя_макроса, аргумент_1, аргумент_2…​)

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

Обратите внимание, что макросы сокращают не время выполнения правил, а время их написания. Они помогают избежать повторения одинаковых фрагментов правил, что облегчает чтение.

Пример. Найти названия компаний и их аббревиатуры

Рассмотрим правила на Изображении 1, которые извлекают названия компаний.

xpdl macros comp 1 rus
Изображение 1. Пример правила, извлекающего названия компаний
Фрагмент правила
 rule: full_company_names
 // например, Ульяновский авиастроительный завод "Авиастар СП", Батыр Мальсагов, владелец группы компаний "Акрополь"
 {
 query: {phrase(0, char(quote), {phrase(0, case(mixed_title upper, lemma(noun|adjective)), repeat(1, 3, lemma(noun|adjective)))}:comp, char(quote))}:comp_whole

 rule_filter: business_context
 // оставляем только контексты, в которых может встретиться название компании (например, после слова "компания")
 {
 query: phrase(0, orn(госкомпания, директор, завод, компания, предприятие, работник, фабрика), $comp_whole)

 result: Компания = $comp_whole: comp
 }
}

 rule: company_after_type
 // например, ЗА0 "Гражданские самолеты Сухого"
 {
 query: {phrase(0, orn(ooo, пао, зао, оао), char (quote),
 {phrase(0, case(mixed_title upper, lemma(noun|adjective)), repeat(1, 3, lemma(noun|adjective)))}:comp, char(quote))}:comp_whole

 result: Компания = $comp_whole:comp
 }

Первое правило («full_company_names») извлекает названия компаний в кавычках, после которых идет существительное или прилагательное в смешанном, заглавном или верхнем регистре, а затем от 1 до 3 повторяющихся существительных или прилагательных. Например, «Авиатор СП», «Курорты Северного Кавказа». Вложенное фильтрующее правило необходимо, чтобы находить название компании только в правильных контекстах, например, после слов «компания», «директор», «завод», «предприятие».

Второе правило ищет названия компаний после типа компании (например, ЗАО «Гражданские самолеты Сухого»).

На следующем этапе можно извлечь аббревиатуры компании, часто следующие за названием. Лучше делать это отдельным правилом, чтобы не перегружать правило, извлекающее названия.

Как показано на Изображении 2, правило, извлекающее аббревиатуры, нужно добавить как в правило «full_company_names», так и в правило «company_after_type».

xpdl macros comp abbrev no macro rus
Изображение 2. Пример расширенного правила с Изображения 1
Фрагмент правила
 rule: full_company_names
 // например, Ульяновский авиастроительный завод "Авиастар СП", Батыр Мальсагов, владелец группы компаний "Акрополь"
 {
 query: {phrase(0, char(quote), {phrase(0, case(mixed_title upper, lemma(noun|adjective)), repeat(1, 3, lemma(noun|adjective)))}:comp, char(quote))}:comp_whole

 rule_filter: business_context
 // оставляем только контексты, в которых может встретиться название компании (например, после слова "компания")
 {
 query: phrase(0, orn(госкомпания, директор, завод, компания, предприятие, работник, фабрика), $comp_whole)

 result: Компания = $comp_whole:comp

  rule: abbreviations
  // Госкомпания "Курорты Северного Кавказа" /КСК/
  {
  query: {phrase($comp_whole, phrase(0, "(" or "/",  {length(2, 4, case(upper))}:abbr, ")" or "/"))}:comp_full

  result: Компания = $comp_full
  attribute: Аббревиатура = $comp_full:abbr
  }
 }
}

 rule: company_after_type
 // например, ЗА0 "Гражданские самолеты Сухого"
 {
 query: {phrase(0, orn(ooo, пао, зао, оао), char (quote),
 {phrase(0, case(mixed_title upper, lemma(noun|adjective)), repeat(1, 3, lemma(noun|adjective)))}:comp, char(quote))}:comp_whole

 result: Компания = $comp_whole:comp

 rule: abbreviations
 // Госкомпания "Курорты Северного Кавказа" /КСК/
 {
 query: {phrase($comp_whole, phrase(0, "(" or "/", {length(2, 4, case(upper))}:abbr, ")" or "/"))}:comp_full

 result: Компания = $comp_full
 attribute: Аббревиатура = $comp_full:abbr
 }
}

Уже на этом этапе правила выглядят громоздко и сложно, а при добавлении новых правил, после которых нужно будет искать аббревиатуры, правило увеличится еще больше.

Избавиться от повторяющихся фрагментов поможет макрос. На Изображении 3 показано, как объявить макрос с PDL-запросом.

xpdl macros comp macro query std rus
Изображение 3. Стандартное объявление макроса
Фрагмент правила
macro: abbrev_query()
{
 query: {phrase($comp, phrase(0, "(" or "/", {length(2, 4, case(upper))}:abbr, ")" or "/"))}:comp_full
}

На Изображении 3 показно стандартное объявление макроса. Так как макрос содержит только PDL-запрос, можно использовать упрощенный способ объявления макроса (см. Изображение 4).

xpdl macros comp macro query simpl rus
Изображение 4. Упрощенное объявление макроса
Фрагмент правила
macro: abbrev_query() = {phrase($comp, phrase(0, "(" or "/", {length(2, 4, case(upper))}:abbr, ")" or "/"))}:comp_full

После объявления макроса его можно вызвать в любом месте правила.

На Изображении 5 показано, как это можно сделать.

xpdl macros comp abbrev macro query dia rus
Изображение 5. Вызов макроса
Фрагмент правила
macro: abbrev_query()
{

{phrase($comp, phrase(0, "(" or "/", {length(2, 4, case(upper))}:abbr, ")" or "/"))}:comp_full

}

 rule: full_company_names
 // например, Ульяновский авиастроительный завод "Авиастар СП", Батыр Мальсагов, владелец группы компаний "Акрополь"
 {
 query: {phrase(0, char(quote), {phrase(0, case(mixed_title upper, lemma(noun|adjective)), repeat(1, 3, lemma(noun|adjective)))}:comp, char(quote))}:comp_whole

 rule_filter: business context
 // оставляем только контексты, в которых может встретиться название компании (например, после слова "компания")
 {
 query: phrase(0, orn(госкомпания, директор, завод, компания, предприятие, работник, фабрика), $comp_whole)

 result: Компания = $comp_whole:comp

   rule: abbreviations
   // Госкомпания "Курорты Северного Кавказа" /КСК/
   {
   query: macro(abbrev_query)

   result: Компания = $comp_full
   attribute: Аббревиатура = $comp_full:abbr
   }
 }
}

 rule: company_after_type
 // например, ЗАО "Гражданские самолеты Сухого"
 {
 query: {phrase(0, orn(ooo, пао, зао, оао), char (quote),
 {phrase(0, case(mixed_title upper, lemma(noun|adjective)), repeat(1, 3, lemma(noun|adjective)))}:comp, char(quote))}:comp_whole

 result: Компания = $comp_whole:comp

 rule: abbreviations
 // Госкомпания "Курорты Северного Кавказа" /КСК/
 {
 query: macro(abbrev_query)

 result: Компания = $comp_full
 attribute: Аббревиатура = $comp_full:abbr
 }
}

После удаления повторяющихся запросов правила легче читать. Можно еще больше их упростить, объявив макрос с XPDL-правилом, как показано на Изображении 6.

xpdl macros comp abbrev macro dia rus
Изображение 6. Пример упрощения правила с Изображения 2 при помощи макроса
Фрагмент правила
macro: abbreviations()
 {
 rule: abbreviations
 // Госкомпания "Курорты Северного Кавказа" /КСК/
 {
 	query: {phrase($comp, phrase(0, "(" or "/", 	{length(2, 4, case(upper))}:abbr, ")" or "/"))}:comp_full

 	result: Компания = $comp_full
 	attribute: Аббревиатура = $comp_full:abbr
 }
}

 rule: full_company_names
 // например, Ульяновский авиастроительный завод "Авиастар СП", Батыр Мальсагов, владелец группы компаний "Акрополь"
 {
 query: {phrase(0, char(quote), {phrase(0, case(mixed_title upper, lemma(noun|adjective)), repeat(1, 3, lemma(noun|adjective)))}:comp, char(quote))}:comp_whole

 rule_filter: business_context
 // оставляем только контексты, в которых может встретиться название компании (например, после слова "компания")
 {
 query: phrase(0, orn(госкомпания, директор, завод, компания, предприятие, работник, фабрика), $comp_whole)

 result: Компания = $comp_whole:comp

 macro(abbreviations)
 }
}

 rule: company_after_type
 // например, ЗАО "Гражданские самолеты Сухого"
 {
 query: {phrase(0, orn(ooo, пао, зао, оао), char(quote),
 {phrase(0, case(mixed_title upper, lemma(noun|adjective)), repeat(1, 3, lemma(noun|adjective)))}:comp, char(quote))}:comp_whole

 result: Компания = $comp_whole: comp

 macro(abbreviations)
 }

Как передавать параметры в макрос

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

Рассмотрим немного измененное правило для извлечения названий компаний на Изображении 7.

macros addit info no macro dia rus
Изображение 7. Расширенное правило извлечения компаний
Фрагмент правила
rule: company_after type
 // например, ЗА0 "Гражданские самолеты Сухого"
 {
 query: {phrase(0, orn(ooo, пао, зао, оао), char(quote),
 {phrase(0, case(mixed_title upper, lemma(noun|adjective)), repeat(1, 3, lemma(noun|adjective)))}:comp, char(quote))}:comp_whole

 rule: abbreviations
 {
 query: {phrase($comp, phrase(0, "(" or "/", {length(2, 4, case(upper))}:abbr, ")" or "/"))}:comp_full

 result: Компания = $comp_full:comp
 attribute: Аббревиатура = $comp_full:abbr
 }

 rule: location
 {
 query: {phrase($comp, phrase(0, "(" or "/", {knownword(GeoAdministrative)}:location, ")" or "/"))}:comp_full

 result: Компания = $comp_full:comp
 attribute: Расположение = $comp_full:location
 }
}

Эти правила извлекают не только названия компаний, но и сопутствующую информацию, например, расположение компании, которое часто указывается в скобках после названия («ОАО «Аэропорт Кольцово» (Екатеринбург)»).

Расположение и аббревиатура выводятся в колонки «Расположение» и «Аббревиатура» соответственно.

Правило отрабатывает на следующем тексте:

macros addit info input rus

Результаты работы правила показаны на Изображении 8.

macros addit info output rus
Изображение 8. Результат работы правила на Изображении 7

Обратите внимание, что правила «abbreviation» и «location» отличаются только именем правила (они выделены красным на изображении выше), поисковой частью правила, которая находит информацию в скобках (выделено синим), и названием атрибутов (выделено зеленым). Эти части можно сделать параметрами макроса. При вызове макроса им будут присвоены разные значения. Измененный вариант правила, содержащего макрос с параметрами, представлен на Изображении 9.

Чтобы определить макрос, принимающий аргументы, при его объявлении после имени нужно перечислить параметры в скобках. Параметрами макроса могут быть имя правила, запрос, подзапрос, значение достоверности, результат, имя атрибута или значение.

При вызове макроса нужно перечислить в скобках все его аргументы. Количество аргументов, указанных при вызове макроса должно совпадать с количеством параметров, указанных при объявлении макроса. При выполнении правила каждый параметр в теле макроса заменяется значением соответствующего аргумента.

xpdl macros addit info macro rus
Изображение 9. Пример применения макроса в правиле, представленном на Изображения 7
Фрагмент правила
macro: additional_info(rule_name, info_in_bracket, attribute_name)
{

	rule: rule_name
	{

	query: {phrase($comp_phrase(0, "(" or "/", info_ in_bracket, ")" or "/"))}:comp_full

	result: Компания = $comp_full:comp
	attribute: attribute name = $comp_full:info
    }
}

rule: company_after type
 // например, ЗА0 "Гражданские самолеты Сухого"
 {
 query: {phrase(0, orn(ooo, пао, зао, оао), char(quote),
 {phrase(0, case(mixed_title upper, lemma(noun|adjective)), repeat(1, 3, lemma(noun|adjective)))}:comp, char(quote))}:comp_whole

 macro(additional_info, abbreviation, {length(2, 4, case(upper))}:info, Аббревиатура)
 macro(additional_info, location, {knownword GeoAdministrative }:info, Расположение)
}

На Изображении 10 подробно объясняется выполнение макроса.

xpdl macros addit info expansion rus
Изображение 10. Пошаговое описание работы макроса