Синтаксис грамматик

Файл грамматики состоит из двух частей: блока с директивами, влияющими на работу грамматики в целом, и множества правил.

Директивы

Директивы начинаются со знака # и заканчиваются переносом строки. Некоторые директивы совпадают по смыслу с аналогичными директивами препроцессора языка C++.

#encoding

Указывает кодировку данного файла с грамматикой. Кодировка по умолчанию: utf-8. Кодировка указывается в кавычках.

#encoding “windows-1251”

#include

Включает в данную грамматику текст другой грамматики. При этом фильтры грамматик суммируются, а корень включаемой грамматики (см. #grammar_root) игнорируется. Называние включаемой грамматики указывается в кавычках.

#include “small_grammar.cxx”

#GRAMMAR_ROOT

Директива #GRAMMAR_ROOT указывает нетерминал, который является корнем данной грамматики. Корень грамматики можно не задавать явно, если в грамматике есть только один нетерминал, который ни разу не встречается в правой части правил грамматики.

#GRAMMAR_ROOT MainRule

#GRAMMAR_KWSET

Директива #GRAMMAR_KWSET позволяет явно указать имена или типы статей из газеттира, чьи найденные в предложении ключи должны передаваться парсеру в качестве терминалов. C точки зрения текущей грамматики, эти цепочки становятся multiword-ами (см. п. 2 алгоритма работы парсера). В частности директива #GRAMMAR_KWSET может использоваться для уточнения значения пометы kwtype=none. Пример использования см. тут.

Синтаксис описания статей аналогичен синтаксису пометы kwset: перечисления в квадратных скобках [ ] через запятую.

#GRAMMAR_KWSET [“котики”, cat_types];

#filter

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

Фильтр записывается как последовательность терминалов. Предложение проходит фильтр если в нем в указанном порядке встретились слова описываемые этими терминалами. Расстояние между словами может быть любым.

Перед названиями терминалов в фильтрах ставится амперсанд &. У терминалов могут быть их обычные пометы: kwtype, wff и другие. Операторы (+, * и другие) в фильтрах использовать нельзя. Между терминалами может быть указано максимально допустимое расстояние в квадратных скобках [].

Если в грамматику включается другая грамматика директивой #include, то фильтры включаемой грамматики тоже учитываются.

#filter &Word<kwtype=fio> &AnyWord<wff=".*\d.*",h-reg1> [10] &Hyphen;

Объявление подстановки: #define, #undef

Директива #define также используется для реализации подстановок. В этом случае у директивы два аргумента: имя подстановки и ее значение. Именем подстановки может быть любая последовательность из букв, цифр и символа подчеркивания, первый символ имени подстановки не может быть цифрой. Значением подстановки может быть любое завершенное выражение, в синтаксисе, разрешенном в правой части правил грамматики: список граммем, цепочка нетерминалов с ограничениями и интерпретациями и т.п. Знак переноса строки означает конец значения переменной.

После объявления имя подстановки можно использовать с помощью синтаксиса в фигурных скобках со знаком доллара перед ним: ${ … }. Между знаком $, фигурными скобками и именем подстановки пробелы не допускаются.

Следует понимать, что подстановка «подставляется» не буквально (как, например, в языке C++), а сама по себе является сложным токеном в тексте грамматики. Поэтому подстановки нельзя использовать внутри строкового литерала (там она просто не будет распознана), а также внутри идентификаторов и других длинных токенов.

#define ALL_CASES [nom,acc,gen,dat,ins,loc]
BetterStatus -> PostStatusCoord<gnc-agr[1]> 
                FIO<rt,gnc-agr[1],GU=${ALL_CASES}>;
BetterStatus -> PostStatusCoord<gram='им'>
                FIO<rt,GU=&${ALL_CASES}>;
#undef ALL_CASES
#define HERO_WITH_INTERP Hero<rt,gram='ед,им'> interp (HeroMaybe.Fio from Fio)
Maybe -> ${HERO_WITH_INTERP} 
         TellVerb<gram='3л,ед'> ToSomeone Word;
Maybe -> ${HERO_WITH_INTERP} 
         ToSomeone TellVerb<gram='3л,ед'> Word;
#undef HERO_WITH_INTERP

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

#NO_INTERPRETATION

Вводит запрет на интерпретацию в рамках текущей грамматики. Все операторы interp перестают срабатывать.