Грамматики Perl 6. Простой разбор текста

Покопаемся в коде и разберем текст с помощью грамматик Perl 6.
2 минуты6983

В Perl 6  получил развитие мощный инструмент анализа и обработки текста – грамматики (Grammars). Они являются связующим звеном между регулярными выражениями и методами обработки их результатов. С точки зрения синтаксиса они основаны на суперклассе Grammar и для их объявления достаточно вместо ключевого слова «class» использовать Grammar. 
Регулярные выражения определенные в теле класса задают вершины дерева  соответствия (tree of Match objects). Тут могут быть определены операторы языков программирования, ключевые слова, выражения. При этом обязательно должна быть указана вершина дерева с именем «TOP»: правило, с применения которого начинается разбор текста.

grammar Sentences {

    #Вершина дерева разбора, предполагается, что текст состоит из предложений
    rule TOP {    [<sentence>]*   }

    #Предложение включает в себя основу и второстепенный член
   rule sentence { <basis> <minor> '.'   }
   
   #Основа предполагает наличие подлежащего(их) и сказуемого
   rule basis{<subjects>  <predicate>  }
       
   
   #Подлежащих может быть несколько и они разделены либо запятыми, либо союзом «и»
   rule subjects{ <subject> (',' <subject>)* ('и' <subject>)? }
     
    #Подлежащее
    rule subject{ <word> }
 
    #Сказуемое  
    rule predicate{ <word> }

    #Второстепенный член    
    rule minor{ <word> }

   rule word{ <:L>+ }
    
}

 

Для построения синтаксического дерева достаточно передать в метод «parse» данного класса анализируемый текст:

my $text="Аборигены нашли Кука.  
    Вирус порушил систему.
    Система и софт забили диск.";
    
Sentences.parse($text).say;

Результат:

Аборигены нашли Кука.  
    Вирус порушил систему.
    Система и софт забили диск.」
 sentence => 「Аборигены нашли Кука.  
    」
  basis => 「Аборигены нашли 」
   subjects => 「Аборигены 」
    subject => 「Аборигены 」
     word => 「Аборигены 」
   predicate => 「нашли 」
    word => 「нашли 」
  minor => 「Кука」
   word => 「Кука」
 sentence => 「Вирус порушил систему.
    」
  basis => 「Вирус порушил 」
   subjects => 「Вирус 」
    subject => 「Вирус 」
     word => 「Вирус 」
   predicate => 「порушил 」
    word => 「порушил 」
  minor => 「систему」
   word => 「систему」
 sentence => 「Система и софт забили диск.」
  basis => 「Система и софт забили 」
   subjects => 「Система и софт 」
    subject => 「Система 」
     word => 「Система 」
    1 => 「и софт 」
     subject => 「софт 」
      word => 「софт 」
   predicate => 「забили 」
    word => 「забили 」
  minor => 「диск」
   word => 「диск」 

Но на построении синтаксического дерева задача разбора не заканчивается. Путешествие по его ветвям также значительно упрощено, для его анализа можно подключить класс действий (Action class). В том случае, когда «срабатывает» правило, вызывается одноименный метод из класса действий. Если метода не существует — никаких действий не производится. В качестве параметра классу действий передается экземпляр класса "Match", содержащий соответствующую подстроку, разобранную с помощью регулярных выражений. При этом полученные в результате разбора подстроки доступны по именам, определенным  в грамматике.

class SentencesActions {
   
    method minor($/) {      $/.make: ~$/~" [свободный член]. " }
    
    method predicate($/) { $/.make: ~$/ ~" [сказуемое] "  }
        
    method subject($/) { $/.make: ~$/ }
    
    method subjects($/) {    $/.make: ~$/ ~" [подлежащее(ие)] " }
   
    method basis($/)  { $/.make: ~$<subjects>.ast ~$<predicate>.ast  }
    
    
method sentence($/) {
        $/.make: ~$<basis>.ast ~$<minor>.ast ~"\n"
        
    }

#Простой сбор результатов 
    method TOP($/) { $/.make: $<sentence>».ast  }
}

my  $res = Sentences.parse($text, :actions(SentencesActions)).ast;

for @$res -> $p {
    say ~$p;
}

Результат:

Аборигены [подлежащее(ие)] нашли [сказуемое] Кука [свободный член]. 

Вирус [подлежащее(ие)] порушил [сказуемое] систему [свободный член]. 

Система и софт [подлежащее(ие)] забили [сказуемое] диск [свободный член].

Грамматики позволяют объединять регулярные выражения так же, как классы позволяют объединять методы. Это позволяет создать более прозрачный, лучше структурированный код разбора текста.

 

Хотите стать программистом? Рекомендуем профессию «Веб-разработчик».

кодобучениеразвитиеitperl
Нашли ошибку в тексте? Напишите нам.
Спасибо,
что читаете наш блог!