Грамматики Perl 6. Простой разбор текста
В 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;
}
Результат:
Аборигены [подлежащее(ие)] нашли [сказуемое] Кука [свободный член].
Вирус [подлежащее(ие)] порушил [сказуемое] систему [свободный член].
Система и софт [подлежащее(ие)] забили [сказуемое] диск [свободный член].
Грамматики позволяют объединять регулярные выражения так же, как классы позволяют объединять методы. Это позволяет создать более прозрачный, лучше структурированный код разбора текста.
Хотите стать программистом? Рекомендуем профессию «Веб-разработчик».