Операторы

Возьмем другое предложение (5) и применим к нему правило S -> Adj Word<h-reg1>, обсуждавшееся в предыдущем разделе.

(5) Многоуважаемый Константин Иванович Деревяшкин сначала категорически воспретил ругаться в рупор и даже топнул ногой, но потом, после некоторого колебания, увлеченный этой идеей, велел позвать из соседнего дома бывшего черноморца - отчаянного ругателя и буяна.

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

S -> Adj Word<h-reg1>;                            // "изнеженный Чичиков"
S -> Adj Word<h-reg1> Word<h-reg1>;               // "новоявленный Аль Капоне"
S -> Adj Word<h-reg1> Word<h-reg1> Word<h-reg1>;  // "многоуважаемый Константин Иванович Деревяшкин"

К счастью, эту грамматику можно сократить до одного правила при помощи оператора “+”, обозначающего, что терминал или нетерминал может встретиться в цепочке один или более раз. В результате грамматика будет выглядеть так:

S -> Adj Word<h-reg1>+;

Знак «+» и другие операторы описаны в Руководстве пользователя в разделе Операторы.

Далее стоит учесть, что прилагательных может быть больше одного, и они могут разделяться запятой или сочинительным союзом или не разделяться ничем:

(6) В центре большого персидского ковра поставили объемистую вазу с крюшоном, а вокруг нее радиусами разлеглась вся компания, не исключая и Яблоньки, которой пылкий влюбленный Новакович смастерил царственное ложе: шкура белого медведя, на шкуре плюшевый плед, а на пледе ― Яблонька, положившая круглый алебастровый подбородок на огромную пушистую голову страшного зверя.

(7) Но прокурор, по-прежнему минуя оружейный магазин, катил каждое утро к зданию судебных установлений, с грустью поглядывая на фигуру Фемиды, державшей весы, в одной чашке которых он явственно видел себя санкт-петербургским прокурором, а в другой ― розового и наглого Воробьянинова.

(8) В спальную вошла толстая, краснощекая Розалия Карловна и остановилась в ожидательной позе.

Для разбора примера под номером 6 нам необходимо добавить к терминалу Adj уже известный нам оператор “+”. Чтобы справиться с примерами 7 и 8 потребуется дописать несколько дополнительных правил:

AdjCoord -> Adj;                                      // вырожденный случай, когда цепочка прилагательных - однородных членов
                                                      // состоит из одного прилагательного
AdjCoord -> AdjCoord<gnc-agr[1]> ',' Adj<gnc-agr[1]>; // прилагательные - однородные члены могут быть записаны через запятую
AdjCoord -> AdjCoord<gnc-agr[1]> 'и' Adj<gnc-agr[1]>; // или через сочинительный союз 'и'

Помета gnc-agr означает, что отмеченные ею слова должны быть согласованы по роду, числу и падежу. Подробнее об этом будет написано чуть позже в этом руководстве и в справочнике.

Теперь вспомним о том, что человек может обозначаться не только именем собственным, но и непосредственно словом «человек» и добавим его к терминалу, обозначающему имя собственное, с помощью оператора дизъюнкции: “|”.

Наконец, между именем собственным и определяющим его прилагательным нередко появляется форма обращения – товарищ, господин, мистер и т.д. Чтобы указать, что элемент цепочки является факультативным (может быть, а может и нет), его ставят в круглые скобки.

В итоге мы получаем такую грамматику:

#encoding "utf-8"
#GRAMMAR_ROOT S
ProperName ->  Word<h-reg1>+;                         // задание имени собственного
Person -> ProperName | 'человек';                     // человек может обозначаться именем собственным
                                                      // или словом “человек”
FormOfAddress -> 'товарищ' | 'мистер' | 'господин';   // перечисление возможных форм обращения
AdjCoord -> Adj;                                      // вырожденный случай, когда цепочка прилагательных - однородных членов
                                                      // состоит из одного прилагательного
AdjCoord -> AdjCoord<gnc-agr[1]> ',' Adj<gnc-agr[1]>; // прилагательные - однородные члены могут быть записаны через запятую
AdjCoord -> AdjCoord<gnc-agr[1]> 'и' Adj<gnc-agr[1]>; // или через сочинительный союз 'и'
S -> Adj+ (FormOfAddress) Person;                     // для случаев, когда прилагательные идут друг за другом
S -> AdjCoord (FormOfAddress) Person;                 // для случаев, когда прилагательные разделены запятой
                                                      // или сочинительным союзом

Если применить эту грамматику к примерам 6-8, Томита-парсер выделит 3 цепочки:

Мы видим, что в первую цепочку попало лишнее слово – которой. Это произошло потому, что оно является местоимением-прилагательным, а значит, удовлетворяет правилу S -> Adj+ (FormOfAddress) Person;

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

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

В синтаксисе Томита-парсера это записывается следующим образом:

S -> Adj<gnc-agr[1]>+ (FormOfAddress) Person<gnc-agr[1]>;

gnc-agr расшифровывается как GenderNumberCase-Agreement (т.е. согласование по роду, числу и падежу), а в квадратных скобках стоит идентификатор согласования, который указывает, какие элементы правой части правила согласуются между собой.

Обратите внимание, что в одном правиле можно использовать несколько разных согласований с разными идентификаторами. Например, в правиле S -> Participle<gnc-agr[2]> Adj<gnc-agr[1]> Noun<gnc-agr[1], gram=’тв’> Noun<gnc-agr[2], gram=’им’, rt>; требуется согласование между первым и четвертым терминалами и между вторым и третьим терминалами. Такое правило будет корректно обрабатывать цепочку « обожаемый местным населением напиток ». Используемые в этом примере пометы gram='тв' и gram='им' означают, что слова должны стоять в указанных падежах (творительном и именительном). Подробно об этой помете написано в следующих разделах и в справочнике.

Добавим согласование в нашу грамматику:

#encoding "utf-8"
ProperName ->  Word<h-reg1>+; 
Person -> ProperName | ‘человек’;
FormOfAddress -> ‘товарищ’ | ‘мистер’ | ‘господин’; 
AdjCoord -> Adj;
AdjCoord -> AdjCoord<gnc-agr[1]> ',' Adj<gnc-agr[1]>;
AdjCoord -> AdjCoord<gnc-agr[1]> 'и' Adj<gnc-agr[1]>;
S -> Adj<gnc-agr[1]>+ (FormOfAddress) Person<gnc-agr[1]>; 
S -> AdjCoord<gnc-agr[1]> (FormOfAddress) Person<gnc-agr[1]>;

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