Типы ключевых слов (kwtype)

Все мы знаем детский стишок Маршака про воробья:

(11) — Где обедал, воробей?

— В зоопарке у зверей.

Пообедал я сперва

За решеткою у льва.

Подкрепился у лисицы.

У моржа попил водицы.

Ел морковку у слона.

С журавлем поел пшена.

Погостил у носорога,

Отрубей поел немного.

Побывал я на пиру

У хвостатых кенгуру.

Был на праздничном обеде

У мохнатого медведя.

А зубастый крокодил

Чуть меня не проглотил.

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

Для такой грамматики нам потребуется не только грамматическая, но и семантическая информация о словах из текста. Для этого нам надо построить мини-словарь.

Мы сталкивались со словарем в самом начале, когда создавали корневой файл mydic.gzt. Теперь рассмотрим этот формат подробнее.

Словарь в Томите называется газеттиром и пишется в отдельном файле с расширением gzt. Как и любой словарь, газеттир состоит из статей. Создадим файл animals_dict.gzt и напишем в нем простейшую статью, в которой перечислим некоторых животных:

encoding "utf8";
TAuxDicArticle “животные”
{
    key = "собака" | "кот" | "лошадь" | "корова" | "лев" | "слон" | "волк" | 
          "кенгуру" | "крокодил" 
}

В этом примере TAuxDicArticle – тип статьи, «животные» — ее название, а в поле key мы перечисляем все слова, входящие в эту статью.

Созданный словарь обязательно надо импортировать в корневой словарь. Для этого в файле mydic.gzt надо добавить следующую строчку:

import "animals_dict.gzt";

Теперь на созданную статью можно ссылаться из грамматики. Для этого используются пометы kwtype и kwset, в качестве значения которых выступает тип или имя статьи. Тип TAuxDicArticle является типом по умолчанию и используется во многих статьях, поэтому мы ссылаемся на название, которое уникально:

#encoding "utf-8"
S -> 'у' (Adj<gnc-agr[1]>) Noun<kwtype='животные', gram='род', rt, gnc-agr[1]>;
S -> 'с' (Adj<gnc-agr[1]>) Noun<kwtype='животные', gram='твор', rt, gnc-agr[1]>;

Если мы запустим эту грамматику на стишке про воробья, мы получим следующие подцепочки:

у лев
у слон
у хвостатый кенгуру

Естественно, полнота результата напрямую зависит от полноты словаря: в нашем примере у нас выделились только те животные, которых мы включили в словарь.

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

TAuxDicArticle “животные”
{
    key = { "animals.txt" type=FILE }
}

В поле key указывается название текстового файла и тип ключа — FILE. Соответственно, в файле animals.txt перечислены названия животных:

собака
кот
лошадь
корова
лев
слон
волк
кенгуру
крокодил

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

TAuxDicArticle "млекопитающие"
{
    key = "собака" | "кот" | "лошадь" | "корова" | "лев" | "слон" | "волк" | 
          "кенгуру" | "морж" | "лисица" | "носорог" | "медведь" 
}
TAuxDicArticle "птицы"
{
    key = "воробей" | "журавль" | "павлин"
}
TAuxDicArticle "рептилии"
{
    key = "черепаха" | "крокодил"
}

Чтобы сохранить информацию о том, что все млекопитающие, птицы и рептилии являются животными, целесообразно вместо стандартного типа статьи TAuxDicArticle использовать свой — например, animal. Типы статей описываются в специальном формате в отдельном файле. Создадим файл kwtypes.proto и запишем туда следующее:

import "base.proto";
import "articles_base.proto";
message animal : TAuxDicArticle {}

Первые две строчки импортируют встроенные в парсер файлы base.proto и article_base.proto аналогично тому, как это делается в корневом словаре, а в последней описывается тип статьи animal, производный от базового типа TAuxDicArticle. Все типы статей должны быть производными от TAuxDicArticle. Создание пользовательских типов статей позволяет объединить несколько статей в группу, чтобы в дальнейшем можно было бы использовать их все, указав только их тип при помощи пометы kwtype (например, kwtype=animal), но не перечисляя каждую в отдельности.

Теперь мы можем переписать газеттир с использованием нового класса:

encoding "utf-8";
import "kwtypes.proto"; //импортируем файл, в котором описаны используемые в словаре типы статей
animal "млекопитающие"
{
    key = "собака" | "кот" | "лошадь" | "корова" | "лев" | "слон" | "волк" |
          "кенгуру" | "морж" | "лисица" | "носорог" | "медведь" 
}
animal "птицы"
{
    key = "воробей" | "журавль" | "павлин"
}
animal "рептилии"
{
    key = "черепаха" | "крокодил"
}