Интерпретация
В начале мы сказали, что Томита выделяет подцепочки и интерпретирует их в разбитые по полям факты. До этого мы учились только выделять подцепочки, а теперь попробуем преобразовывать их факты.
Пусть у нас есть биография, и мы хотим извлечь из нее все даты. Для дальнейшей обработки даты удобнее извлекать не единой цепочкой, а сразу разбивать по полям: день недели, день, месяц, год. Для этого нам нужно создать факт «Дата» с перечисленными полями. Для описания фактов создаем отдельный файл — facttypes.proto. Его надо импортировать в корневой словарь — добавляем в файл mydic.gzt такую строчку:
import "facttypes.proto";
В сам файл facttypes.proto запишем следующее:
import "base.proto"; // описание protobuf-типов
import "facttypes_base.proto"; // описание protobuf-типа NFactType.TFact
message Date: NFactType.TFact
{
optional string DayOfWeek = 1;
optional string Day = 2;
optional string Month = 3;
optional string Year = 4;
}
В строке message Date: NFactType.TFact
Date
является названием типа факта, который мы описываем. Тип факта Date
наследуется от базового типа NFactType.TFact
, от которого нужно наследовать все типы фактов. Далее в фигурных скобках описываются поля факта Date
. Вначале указывается, обязательно ли поле должно быть заполнено (optional
- может быть пустым, required
- обязательно должно содержать значение, иначе факт не будет сформирован). Далее указан тип поля string
- это самый общий тип. В поля типа string
можно положить любые строки текста.
DayOfWeek
— название поля. Все поля нумеруются по порядку, начиная с единицы.
Также нам понадобится список дней недели и месяцев — для этого нужно создать соответствующие статьи в газеттире. Чтобы не создавать отдельный файл, их можно добавить прямо в корневой словарь:
TAuxDicArticle "месяц"
{
key = "январь" | "февраль" | "март" | "апрель" | "май" | "июнь" |
"июль" | "август" | "сентябрь" | "октябрь" | "ноябрь" | "декабрь"
}
TAuxDicArticle "день_недели"
{
key = "понедельник" | "вторник" | "среда" | "четверг" | "пятница" | "суббота" | "воскресенье"
}
Теперь напишем саму грамматику, выделяющую в тексте даты и интерпретирующую их в факты. Назовем ее date.cxx.
#encoding "utf-8"
DayOfWeek -> Noun<kwtype="день_недели">; // используем слова из статьи "день_недели"
Day -> AnyWord<wff=/([1-2]?[0-9])|(3[0-1])/>; // число от 1 до 31
Month -> Noun<kwtype="месяц">; // используем слова из статьи "месяц"
YearDescr -> "год" | "г. ";
Year -> AnyWord<wff=/[1-2]?[0-9]{1,3}г?\.?/>; // число от 0 до 2999 с возможным "г" или "г." в конце
Year -> Year YearDescr;
// день недели, запятая, число, месяц и год:
// "понедельник, 3 сентября 2012г."
Date -> DayOfWeek interp (Date.DayOfWeek) (Comma)
Day interp (Date.Day)
Month interp (Date.Month)
(Year interp (Date.Year));
// число, месяц и год: "10 января 2011"
Date -> Day interp (Date.Day)
Month interp (Date.Month)
(Year interp (Date.Year));
// месяц и год: "июнь 2009"
Date -> Month interp (Date.Month)
Year interp (Date.Year);
Чтобы интерпретировать желаемую подцепочку в факт, надо написать слово interp и после него в скобках указать имя факта и имя поля внутри этого факта, в которое должна попасть подцепочка.
Чтобы запустить эту грамматику, нам надо во-первых, добавить в корневой словарь новую статью:
TAuxDicArticle "дата"
{
key = { "tomita:date.cxx" type=CUSTOM }
}
Во-вторых, в файл config.proto, содержащий параметры запуска, надо добавить информацию о том, какие факты мы будем использовать в запускаемых грамматиках:
Facts = [
{ Name = "Date" }
]
Также можно добавить выходной файл, куда будут записываться факты (если этого не сделать, то они будут печататься прямо на экран):
Output = {
File = "facts.txt";
Format = text; // можно использовать следующие форматы:
// proto (Google Protobuf), xml, text
}
Факты будут сохранены в файл facts.txt (для последующей обработки программами), а также появятся в PrettyOutput.html в удобном для просмотра виде. Например, если мы дадим на вход грамматике отрывок биографии Гагарина:
(12) Юрий Алексеевич Гагарин родился в пятницу, 9 марта 1934 года. Согласно документам, это произошло в деревне Клушино Гжатского района Западной области РСФСР (ныне Гагаринский район Смоленской области), то есть по месту жительства (прописки) родителей. По происхождению является выходцем из крестьян: его отец, Алексей Иванович Гагарин (1902—1973), — плотник, мать, Анна Тимофеевна Матвеева (1903—1984), — работала на молочнотоварной ферме. Его дедушка, рабочий Путиловского завода Тимофей Матвеевич Матвеев, жил в Санкт-Петербурге, в Автове, на Богомоловской (ныне Возрождения) улице в конце XIX века. 1 сентября 1941 года Юрий пошел в школу, но 12 октября деревню заняли немцы, и его учеба прервалась. Почти полтора года деревня Клушино была оккупирована немецкими войсками. 9 апреля 1943 года деревню освободила Красная армия, и учеба в школе возобновилась.
В PrettyOutput.html мы увидим следующее:
Исходные файлы проекта tutorial4
tutorial4/config.proto | Конфигурационный файл парсера |
tutorial4/facttypes.proto | Описание типов фактов |
tutorial4/mydic.gzt | Корневой словарь |
tutorial4/date.cxx | Грамматика для дат |
tutorial4/test.txt | Текст «Юрий Алексеевич Гагарин родился в пятницу ...» |
tutorial4/config.proto | Конфигурационный файл парсера |
tutorial4/facttypes.proto | Описание типов фактов |
tutorial4/mydic.gzt | Корневой словарь |
tutorial4/date.cxx | Грамматика для дат |
tutorial4/test.txt | Текст «Юрий Алексеевич Гагарин родился в пятницу ...» |