yandex / tomita-parser

Other
495 stars 112 forks source link

Помогите разобраться новичку с частью кода #129

Closed 515 closed 3 years ago

515 commented 3 years ago

Есть код, который мне написал пользователь Victor Bocharov за что ему огромное спасибо. Но я к сожалению не могу до конца понять как именно он работает Исходник: при сотрудниках Мамыкиной А. В. , Поликарповой Е. Н.,

#encoding "utf-8"
PersonStatusLight -> 'директор' | 'управляющий' | 'авминистратор';
PersonStatusLight1 -> 'продавец' | 'кладовщик' | 'охранник' | 'кассир';
Helper -> Word<kwtype=helper>; //Здесь подтягивается слово "заместитель"
PersonStatus2 -> PersonStatusLight1;
PersonStatus0 -> (Helper) PersonStatusLight;
PersonStatus1 -> PersonStatus0 interp (Person.Status) AnyWord AnyWord "г." AnyWord;
PersonStatus -> PersonStatusLight;
PersonName -> Word<kwtype="имя"> ( Word<wff="^.$"> );
PersonEnumInit_ -> PersonStatus | PersonStatus1 | PersonStatus2;
PersonEnumInit -> PersonEnumInit_ interp(Person.Status);
PersonEnumItem -> PersonName interp(Person.Name);
PersonEnumEnd -> "и" PersonEnumItem;
PersonEnumItems_ -> PersonEnumItem;
PersonEnumItems_ -> PersonEnumItem Comma PersonEnumItems_;
PersonEnumItems -> PersonEnumItems_ ( PersonEnumEnd );
PersonEnum -> PersonEnumInit PersonEnumItems;

Если кто-то поможет с объяснением буду благодарен.

  1. Что значит строка PersonEnumEnd -> "и" PersonEnumItem;?
  2. Не совсем понятно как работает эта строка - PersonEnumItems -> PersonEnumItems_ ( PersonEnumEnd );?
victorbocharov commented 3 years ago
  1. На приведённом примере, мне кажется, не работает, т.к. в списках слов-статусов нет слова "сотрудник".

  2. PersonEnumEnd обозначает последний элемент перечисления, который, обычно, идёт с союзом, а не с запятой, как предыдущие элементы.

  3. Элемент правой части в скобках - опционален. Это правило эквивалентно вот такой конструкции:

PersonEnumItems -> PersonEnumItems_ PersonEnumEnd ;
PersonEnumItems -> PersonEnumItems_;

Эта, не совсем очевидная конструкция, с разными PersonEnum* нужна для обработки цепочек вида "А, Б, В, Г и Д" без ограничения по длине. У неё есть начало (Init), повторящийся элемент (Item), несколько повторяющихся элементов (Items) и опциональный хвост (End).

victorbocharov commented 3 years ago

Если в конфиге включить PrintTree = "файл для отладочной печати", то он запишет в этот файл вот такое:

coverage: 7, weight: 0.34
PersonEnum  ->  PersonEnumInit[*сотрудниках]  PersonEnumItems[Мамыкиной_А._В. , Поликарповой_Е._Н.] :: 0.35
|   
|__ PersonEnumInit  ->  PersonEnumInit_[*сотрудниках] :: 0.66666666
|       PersonEnumInit_  ->  PersonStatus2[*сотрудниках] :: 0.66666666
|           PersonStatus2  ->  PersonStatusLight1[*сотрудниках] :: 0.66666666
|               PersonStatusLight1  ->  сотрудник[*сотрудниках] :: 0.66666666
|                   сотрудник  ->  сотрудниках :: 1
|   
|__ PersonEnumItems  ->  PersonEnumItems_[*Мамыкиной_А._В. , Поликарповой_Е._Н.] :: 0.36666666
        PersonEnumItems_  ->  PersonEnumItem[*Мамыкиной_А._В.]  Comma[,]  PersonEnumItems_[Поликарповой_Е._Н.] :: 0.36666666
        |   
        |__ PersonEnumItem  ->  PersonName[*Мамыкиной_А._В.] :: 0.66666666
        |       PersonName  ->  Word[*Мамыкиной_А._В.]<kwt=имя> :: 0.66666666
        |           Word  ->  Мамыкиной_А._В. :: 1
        |   
        |__ Comma  ->  , :: 1
        |   
        |__ PersonEnumItems_  ->  PersonEnumItem[*Поликарповой_Е._Н.] :: 0.66666666
                PersonEnumItem  ->  PersonName[*Поликарповой_Е._Н.] :: 0.66666666
                    PersonName  ->  Word[*Поликарповой_Е._Н.]<kwt=имя> :: 0.66666666
                        Word  ->  Поликарповой_Е._Н. :: 1

DROPPED OCCURRENCE, coverage: 4, weight: 0.35
PersonEnum  ->  PersonEnumInit[*сотрудниках]  PersonEnumItems[Мамыкиной_А._В.] :: 0.43333333
|   
|__ PersonEnumInit  ->  PersonEnumInit_[*сотрудниках] :: 0.66666666
|       PersonEnumInit_  ->  PersonStatus2[*сотрудниках] :: 0.66666666
|           PersonStatus2  ->  PersonStatusLight1[*сотрудниках] :: 0.66666666
|               PersonStatusLight1  ->  сотрудник[*сотрудниках] :: 0.66666666
|                   сотрудник  ->  сотрудниках :: 1
|   
|__ PersonEnumItems  ->  PersonEnumItems_[*Мамыкиной_А._В.] :: 0.66666666
        PersonEnumItems_  ->  PersonEnumItem[*Мамыкиной_А._В.] :: 0.66666666
            PersonEnumItem  ->  PersonName[*Мамыкиной_А._В.] :: 0.66666666
                PersonName  ->  Word[*Мамыкиной_А._В.]<kwt=имя> :: 0.66666666
                    Word  ->  Мамыкиной_А._В. :: 1

Тут видны все варианты дерева от корневого нетерминала, которые парсеру удалось собрать. Факты сгенерированы по верхнему варианту.