Формальные грамматики и языки элементы теории трансляции

Формальные грамматики и языки элементы теории трансляции

Описание файла

Онлайн просмотр документа "И.А. Волкова, Т.В. Руденко — Формальные грамматики и языки. Элементы теории трансляции"

Текст из документа "И.А. Волкова, Т.В. Руденко — Формальные грамматики и языки. Элементы теории трансляции"

Московский государственный университет им. М.В.Ломоносова

Факультет вычислительной математики и кибернетики

Волкова И.А., Руденко Т.В.

Формальные грамматики и языки.

Элементы теории трансляции.

(издание второе, переработанное и дополненное)

Приводятся основные определения, понятия и алгоритмы теории формальных грамматик и языков, некоторые методы трансляции, а также наборы задач по каждой из рассматриваемых тем. Излагаемые методы трансляции проиллюстрированы на примере модельного языка.

Во втором издании исправлены неточности и ошибки первого издания, расширен набор задач: номера первого издания сохранены, но появились дополнительные пункты, отмеченные малыми латинскими буквами. Все новые или измененные задачи отмечены звездочкой.

Для студентов факультета ВМК в поддержку основного лекционного курса “Системное программное обеспечение” и для преподавателей, ведущих практические занятия по этому курсу.

Авторы выражают благодарность Пильщикову В.Н. за предоставленные материалы по курсу “Системное программное обеспечение”, ценные советы и замечания при подготовке пособия, а также благодарят Баландина К.А. за большую помощь в оформлении работы.

проф. Жоголев Е.А.

доц. Корухова Л.С.

Волкова И.А., Руденко Т.В. “Формальные грамматики и языки. Элементы теории трансляции. (учебное пособие для студентов II курса)” — издание второе
(переработанное и дополненное)

Издательский отдел факультета ВМиК МГУ

(лицензия ЛР №040777 от 23.07.96), 1998.-62 с.

Печатается по решению Редакционно-издательского Совета факультета вычислительной математики и кибернетики МГУ им. М.В.Ломоносова

Издательский отдел факультета вычислительной математики и кибернетики МГУ им. М.В.Ломоносова, 1999

Введение.

В этом разделе изложены некоторые аспекты теории формальных языков, существенные с точки зрения трансляции. Здесь введены базовые понятия и даны определения, связанные с одним из основных механизмов определения языков — грамматиками, приведена наиболее распространенная классификация грамматик (по Хомскому). Особое внимание уделяется контекстно-свободным грамматикам и, в частности, их важному подклассу — регулярным грамматикам. Грамматики этих классов широко используются при трансляции языков программирования. Здесь не приводятся доказательства сформулированных фактов, свойств, теорем, доказательства правильности алгоритмов; их можно найти в книгах, указанных в списке литературы.

Основные понятия и определения

Определение: алфавит — это конечное множество символов.

Предполагается, что термин "символ" имеет достаточно ясный интуитивный смысл и не нуждается в дальнейшем уточнении.

Определение: цепочкой символов в алфавите V называется любая конечная последовательность символов этого алфавита.

Определение: цепочка, которая не содержит ни одного символа, называется пустой цепочкой. Для ее обозначения будем использовать символ .

Более формально цепочка символов в алфавите V определяется следующим образом:

(1)  — цепочка в алфавите V;

(2) если  — цепочка в алфавите V и a — символ этого алфавита, то a — цепочка в алфавите V;

(3)  — цепочка в алфавите V тогда и только тогда, когда она является таковой в силу (1) и (2).

Определение: если  и  — цепочки, то цепочка  называется конкатенацией (или сцеплением) цепочек  и .

Например, если  = ab и  = cd, то  = abcd.

Для любой цепочки  всегда  =  = .

Определение: обращением (или реверсом) цепочки  называется цепочка, символы которой записаны в обратном порядке.

Обращение цепочки  будем обозначать  R .

Например, если  = abcdef, то  R = fedcba.

Для пустой цепочки:  =  R .

Определение: n-ой степенью цепочки  (будем обозначать  n ) называется конкатенация n цепочек .

 0 = ;  n =  n-1 =  n-1 .

Определение: длина цепочки — это число составляющих ее символов.

Например, если  = abcdefg, то длина  равна 7.

Длину цепочки  будем обозначать |  |. Длина  равна 0.

Определение: язык в алфавите V — это подмножество цепочек конечной длины в этом алфавите.

Определение: обозначим через V * множество, содержащее все цепочки в алфавите V, включая пустую цепочку .

Определение: обозначим через V + множество, содержащее все цепочки в алфавите V, исключая пустую цепочку .

Следовательно, V * = V +  <>.

Ясно, что каждый язык в алфавите V является подмножеством множества V * .

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

Определение: декартовым произведением A  B множеств A и B называется множество < (a,b) | a  A, b  B>.

Определение: порождающая грамматика G — это четверка (VT, VN, P, S), где

VT — алфавит терминальных символов ( терминалов ),

VN — алфавит нетерминальных символов (нетерминалов), не пересекаю-
щийся с VT,

P — конечное подмножество множества (VT  VN) +  (VT  VN) * ; элемент (, ) множества P называется правилом вывода и записывается в виде   ,

S — начальный символ (цель) грамматики, S  VN.

Для записи правил вывода с одинаковыми левыми частями

будем пользоваться сокращенной записью

Каждое i , i = 1, 2, . ,n , будем называть альтернативой правила вывода из цепочки .

Пример грамматики: G1 = (<0,1>, , P, S), где P состоит из правил

Определение: цепочка   (VT  VN) * непосредственно выводима из цепочки   (VT  VN) + в грамматике G = (VT, VN, P, S) (обозначим   ), если  = 12,  = 12, где 1, 2,   (VT  VN) * ,   (VT  VN) + и правило вывода
   содержится в P.

Например, цепочка 00A11 непосредственно выводима из 0A1 в грамматике G1.

Определение: цепочка   (VT  VN) * выводима из цепочки
  (VT  VN) + в грамматике G = (VT, VN, P, S) (обозначим   ), если существуют цепочки , 1, . , n (n>=0), такие, что  =   1  .  n= .

Определение: последовательность , 1, . , n называется выводом длины n.

Например, S  000A111 в грамматике G1 (см. пример выше), т.к. существует вывод S  0A1  00A11  000A111. Длина вывода равна 3.

Определение: языком, порождаемым грамматикой G = (VT, VN, P, S), называется множество L(G) = <  VT * | S  >.

Другими словами, L(G) — это все цепочки в алфавите VT, которые выводимы из S с помощью P.

Определение: цепочка   (VT  VN) * , для которой S  , называется сентенциальной формой в грамматике G = (VT, VN, P, S).

Таким образом, язык, порождаемый грамматикой, можно определить как множество терминальных сентенциальных форм.

Определение: грамматики G1 и G2 называются эквивалентными, если
L(G1) = L(G2).

P1: S  0A1 P2: S  0S1 | 01

эквивалентны, т.к. обе порождают язык L(G1) = L(G2) = <0 n 1 n | n>0>.

Определение: грамматики G1 и G2 почти эквивалентны, если
L(G1)  <>= L(G2)  <>.

Другими словами, грамматики почти эквивалентны, если языки, ими порождаемые, отличаются не более, чем на .

P1: S  0A1 P2: S  0S1 | 

почти эквивалентны, т.к. L(G1)=<0 n 1 n | n>0>, а L(G2)=<0 n 1 n | n>=0>, т.е. L(G2) состоит из всех цепочек языка L(G1) и пустой цепочки, которая в L(G1) не входит.

Классификация грамматик и языков по Хомскому

(грамматики классифицируются по виду их правил вывода)

Грамматика G = (VT, VN, P, S) называется грамматикой типа 0, если на правила вывода не накладывается никаких ограничений (кроме тех, которые указаны в определении грамматики).

Грамматика G = (VT, VN, P, S) называется неукорачивающей грамматикой, если каждое правило из P имеет вид   , где   (VT  VN) + ,   (VT  VN) + и
|  | + ; 1,2  (VT  VN) * .

Грамматику типа 1 можно определить как неукорачивающую либо как контекстно-зависимую.

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

Грамматика G = (VT, VN, P, S) называется контекстно-свободной ( КС ), если каждое правило из Р имеет вид A  , где A  VN,   (VT  VN) + .

Грамматика G = (VT, VN, P, S) называется укорачивающей контекстно-свободной ( УКС ), если каждое правило из Р имеет вид A  , где A  VN,
  (VT  VN) * .

Грамматику типа 2 можно определить как контекстно-свободную либо как укорачивающую контекстно-свободную.

Возможность выбора обусловлена тем, что для каждой УКС-грамматики существует почти эквивалентная КС-грамматика.

Грамматика G = (VT, VN, P, S) называется праволинейной, если каждое правило из Р имеет вид A  tB либо A  t, где A  VN, B  VN, t  VT.

Грамматика G = (VT, VN, P, S) называется леволинейной, если каждое правило из Р имеет вид A  Bt либо A  t, где A  VN, B  VN, t  VT.

Грамматику типа 3 (регулярную, Р-грамматику) можно определить как праволинейную либо как леволинейную.

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

Соотношения между типами грамматик:

(1) любая регулярная грамматика является КС-грамматикой;

(2) любая регулярная грамматика является УКС-грамматикой;

(3) любая КС-грамматика является КЗ-грамматикой;

(4) любая КС-грамматика является неукорачивающей грамматикой;

(5) любая КЗ-грамматика является грамматикой типа 0.

любая неукорачивающая грамматика является грамматикой типа 0.

Замечание: УКС-грамматика, содержащая правила вида A  , не является КЗ-грамматикой и не является неукорачивающей грамматикой.

Определение: язык L(G) является языком типа k, если его можно описать грамматикой типа k.

Соотношения между типами языков:

(1) каждый регулярный язык является КС-языком, но существуют КС-языки, которые не являются регулярными ( например, L = 0>).

(2) каждый КС-язык является КЗ-языком, но существуют КЗ-языки, которые не являются КС-языками ( например, L = 0>).

каждый КЗ-язык является языком типа 0.

Замечание: УКС-язык, содержащий пустую цепочку, не является КЗ-языком.

Замечание: следует подчеркнуть, что если язык задан грамматикой типа k, то это не значит, что не существует грамматики типа k’ (k’>k), описывающей тот же язык. Поэтому, когда говорят о языке типа k, обычно имеют в виду максимально возможный номер k.

Например, КЗ-грамматика G1 = (<0,1>, , P1, S) и

КС-грамматика G2 = (<0,1>, , P2, S), где

P1: S  0A1 P2: S  0S1 | 01

описывают один и тот же язык L = L(G1) = L(G2) = < 0 n 1 n | n>0>. Язык L называют КС-языком, т.к. существует КС-грамматика, его описывающая. Но он не является регулярным языком, т.к. не существует регулярной грамматики, описывающей этот язык [3].

Примеры грамматик и языков.

Замечание: если при описании грамматики указаны только правила вывода Р, то будем считать, что большие латинские буквы обозначают нетерминальные символы, S — цель грамматики, все остальные символы — терминальные.

1) Язык типа 0: L(G) = | n >= 1>

Мотивация

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

Этот текст задуман как популярное введение в теорию формальных языков и грамматик. Эта теория считается (и, надо сказать, справедливо) довольно сложной и запутанной. На лекциях студенты обычно скучают и экзамены тем более не вызывают энтузиазма. Поэтому и в науке не так много исследователей в этой тематике. Достаточно сказать, что за все время, с зарождения теории формальных грамматик в середине 50-х годов прошлого века и до наших дней, по этому научному направлению было выпущено всего две докторских диссертации. Одна из них была написана в конце 60-х годов Алексеем Владимировичем Гладким, вторая уже на пороге нового тысячелетия — Мати Пентусом.

Далее в наиболее доступной форме описаны два основных понятия теории формальных языков: формальный язык и формальная грамматика. Если тест будет интересен аудитории, то автор дает торжественное обещание разродиться еще парой подобных опусов.

Формальные языки

Коротко говоря, формальный язык — это математическая модель реального языка. Под реальным языком здесь понимается некий способ коммуникации (общения) субъектов друг с другом. Для общения субъекты используют конечный набор знаков (символов), которые проговариваются (выписываются) в строгом временном порядке, т.е. образуют линейные последовательности. Такие последовательности обычно называют словами или предложениями. Таким образом, здесь рассматривается только т.н. коммуникативная функция языка, которая изучается с использованием математических методов. Другие функции языка здесь не изучаются и, потому, не рассматриваются.

Чтобы лучше разобраться в том, как именно изучаются формальные языки, необходимо сначала понять, в чем заключаются особенности математических методов изучения. Согласно Колмогорову и др. (Александров А.Д., Колмогоров А.Н., Лаврентьев М.А. Математика. Ее содержание, методы и значение. Том 1. М.: Издательство Академии Наук СССР, 1956.), математический метод, к чему бы он ни применялся, всегда следует двум основным принципам:

  1. Обобщение (абстрагирование). Объекты изучения в математике — это специальные сущности, которые существуют только в математике и предназначены для изучения математиками. Математические объекты образуются путем обобщения реальных объектов. Изучая какой-нибудь объект, математик замечает только некоторые его свойства, а от остальных отвлекается. Так, абстрактный математический объект «число» может в реальности обозначать количество гусей в пруду или количество молекул в капле воды; главное, чтобы о гусях и о молекулах воды можно было
    говорить как о совокупностях. Из такой «идеализации» реальных объектов следует одно важное свойство: математика часто оперирует бесконечными совокупностями, тогда как в реальности таких совокупностей не существует.
  2. Строгость рассуждений. В науке принято для выяснения истинности того или иного рассуждения сверять их результаты с тем, что существует в действительности, т.е. проводить эксперименты. В математике этот критерий проверки рассуждения на истинность не работает. Поэтому выводы не проверяются экспериментальным путем, но принято доказывать их справедливость строгими, подчиняющимися определенным правилам, рассуждениями. Эти рассуждения называются доказательствами и доказательства служат единственным способом обоснования верности того или иного утверждения.

Таким образом, чтобы изучать языки с помощью математических методов, необходимо сначала выделить из языка его свойства, которые представляются важными для изучения, а затем эти свойства строго определить. Полученная таким образом абстракция будет называться формальным языком — математической моделью реального языка. Содержание конкретной математической модели зависит от того, какие свойства важны для изучения, т.е. что планируется в данный момент выделить и изучать.

В качестве известного примера такой математической абстракции можно привести модель, известную под неблагозвучным для русского уха названием «мешок слов». В этой модели исследуются тексты естественного языка (т.е. одного из тех языков, которые люди используют в процессе повседневного общения между собой). Основной объект модели мешка слов — это слово, снабженное единственным атрибутом, частотой встречаемости этого слова в исходном тексте. В модели не учитывается, как слова располагаются рядом друг с другом, только сколько раз каждое слово встречается в тексте. Мешок слов используется в машинном обучении на основе текстов в качестве одного из основных объектов изучения.

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

Алфавит представляет собой конечное непустое множество элементов. Эти элементы будем называть символам. Для обозначения алфавита обычно будем использовать латинское V, а для обозначения символов алфавита — начальные строчные буквы латинского алфавита. Например, выражение V = обозначает алфавит из двух символов a и b.

Цепочка представляет собой конечную последовательность символов. Например, abc — цепочка из трех символов. Часто при обозначении цепочек в символах используют индексы. Сами цепочки обозначают строчными символами конца греческого алфавита. Например, omega = a1. an — цепочка из n символов. Цепочка может быть пустой, т.е. не содержать ни одного символа. Такие цепочки будем обозначать греческой буквой эпсилон.

Наконец, формальный язык L над алфавитом V — это произвольное множеств цепочек, составленных из символов алфавита V. Произвольность здесь означает тот факт, что язык может быть пустым, т.е. не иметь ни одной цепочки, так и бесконечным, т.е. составленным из бесконечного числа цепочек. Последний факт часто вызывает недоумение: разве имеются реальные языки, которые содержат бесконечное число цепочек? Вообще говоря, в природе все конечно. Но мы здесь используем бесконечность как возможность образования цепочек неограниченной длины. Например, язык, который состоит из возможных имен переменных языка программирования C++, является бесконечным. Ведь имена переменных в C++ не ограничены по длине, поэтому потенциально таких имен может быть бесконечно много. В реальности, конечно, длинные имена переменных не имеют для нас особого смысла т.к. к концу чтения такого имени уже забываешь его начало. Но в качестве потенциальной возможности задавать неограниченные по длине переменные, это свойство выглядит полезным.

Итак, формальные языки — это просто множества цепочек, составленных из символов некоторого конечного алфавита. Но возникает вопрос: как можно задать формальный язык? Если язык конечен, то можно просто выписать все его цепочки одну за другой (конечно, можно задуматься, имеет ли смысл выписывать цепочки языка, имеющего хотя бы десять тысяч элементов и, вообще, есть ли смысл в таком выписывании?). Что делать, если язык бесконечен, как его задавать? В этот момент на сцену выходят грамматики.

Формальные грамматики

Способ задания языка называет грамматикой этого языка. Таким образом, грамматикой мы называем любой способ задания языка. Например, грамматика L = (здесь n — натуральное число) задает язык L, состоящий из цепочек вида ab, aabb, aaabbb и т.д. Язык L представляет собой бесконечное множество цепочек, но тем не менее, его грамматика (описание) состоит всего из 10 символов, т.е. конечна.

Назначение грамматики — задание языка. Это задание обязательно должно быть конечным, иначе человек не будет в состоянии эту грамматику понять. Но каким образом, конечное задание описывает бесконечные совокупности? Это возможно только в том случае, если строение всех цепочек языка основано на единых принципов, которых конечное число. В примере выше в качестве такого принципа выступает следующий: «каждая цепочка языка начинается с символов a, за которыми идет столько же символов b». Если язык представляет собой бесконечную совокупность случайным образом набранных цепочек, строение которых не подчиняется единым принципам, то очевидно для такого языка нельзя придумать грамматику. И здесь еще вопрос, можно или нет считать такую совокупность языком. В целях математической строгости и единообразия подхода обычно такие совокупности языком считают.

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

Такие парадигмы описания грамматик называют синтаксическими теориями. Формальная грамматика — это математическая модель грамматики, описанная в рамках какой-то синтаксической теории. Таких теорий придумано довольно много. Самый известный метаязык для задания грамматик — это, конечно, порождающие грамматики Хомского. Но имеются и другие формализмы. Один из таких них — окрестностные грамматики, будет описан чуть ниже.

С алгоритмической точки зрения грамматики можно подразделить по способу задания языка. Имеются три основных таких способа (вида грамматик):

  • Распознающие грамматики. Такие грамматики представляют собой устройства (алгоритмы), которым на вход подается цепочка языка, а на выходе устройство печатает «Да», если цепочка принадлежит языку, и «Нет» — в противном случае.
  • Порождающие грамматики. Этот вид устройств используется для порождения цепочек языков по требованию. Образно говоря, при нажатии кнопки будет сгенерирована некоторая цепочка языка.
  • Перечисляющие грамматики. Такие грамматики печатают одну за другой все цепочки языка. Очевидно, что если язык состоит из бесконечного числа цепочек, то процесс перечисления никогда не остановится. Хотя, конечно его можно остановить принудительно в нужный момент времени, например, когда будет напечатана нужная цепочка.

Интересным представляет вопрос о преобразовании видов грамматики друг в друга. Можно ли, имея порождающую грамматику, построить, скажем, перечисляющую? Ответ — да, можно. Для этого достаточно генерировать цепочки, упорядочив их, скажем по длине и порядку символов. Но превратить перечисляющую грамматику в распознающую в общем случае нельзя. Можно использовать следующий метод. Получив на вход цепочку, запустить процесс перечисления цепочек и ждать, напечатает ли перечисляющая грамматика эту цепочку или нет. Если такая цепочка напечатана, то заканчиваем процесс перечисления и печатаем «Да». Если цепочка принадлежит языку, то она обязательно будет напечатана и, таким образом, распознана. Но, если цепочка не принадлежит языку, то процесс распознавания будет продолжаться бесконечно. Программа распознающей грамматики зациклится. В этом смысле мощность распознающих грамматик меньше мощности порождающих и перечисляющих. Это следует иметь ввиду, когда сравнивают порождающие грамматики Хомского и распознающие машины Тьюринга.

Окрестностные грамматики

В середине 60-х годов советский математик Юлий Анатольевич Шрейдер предложил простой способ описания синтаксиса языков на основе т.н. окрестностных грамматик. Для каждого символа языка задается конечное число его «окрестностей» — цепочек, содержащих данный символ (центр окрестности) где-то внутри. Набор таких окрестностей для каждого символа алфавита языка называется окрестностной грамматикой. Цепочка считается принадлежащей языку, задаваемому окрестностной грамматикой, если каждый символ этой цепочки входит в нее вместе с некоторой своей окрестностью.

В качестве примера рассмотрим язык A = . Этот язык представляет собой простейшую модель языка арифметических выражений, где роль чисел играет символ «a», а роль операций — символ "+". Составим для этого языка окрестностную грамматику. Зададим окрестности для символа «a». Символ «a» может встречаться в цепочках языка A в трех синтаксических контекстах: вначале, между двумя символами "+" и в конце. Для обозначения начала и конца цепочки введем псевдосимвол "#". Тогда окрестности символа «a» будут следующими: #a+, +a+, +a# . Обычно для выделения центра окрестности этот символ в цепочке подчеркивается (ведь в цепочке могут быть и другие такие символы, которые не являются центром!), здесь этого делать не будем за неимением простой технической возможности. Символ "+" встречается только между двух символов «a», поэтому для него задается одна окрестность, цепочка a+a .

Рассмотрим цепочку a+a+a и проверим, принадлежит ли она языку. Первый символ «a» цепочки входит в нее вместе с окрестностью #a+ . Второй символ "+" входит в цепочку вместе с окрестностью a+a . Подобное вхождение можно проверить и для остальных символов цепочки, т.е. данная цепочка принадлежит языку, как и следовало ожидать. Но, например, цепочка a+aa языку A не принадлежит, поскольку последний и предпоследний символы «a» не имеют окрестностей, с которыми они входят в эту цепочку.

Не всякий язык может быть описан окрестностной грамматикой. Рассмотрим, например, язык B, цепочки которого начинаются либо с символа «0», либо с символа «1». В последнем случае далее в цепочке могут идти символы «a» и «b». Если же цепочка начинается с нуля, то далее могут идти только символы «a». Нетрудно доказать, что для этого языка нельзя придумать никакой окрестностной грамматики. Легитимность вхождения символа «b» в цепочку обусловлена ее первым символом. Для любой окрестностной грамматики, в которой задается связь между символами «b» и «1» можно будет подобрать достаточно длинную цепочку, чтобы всякая окрестность символа «b» не доставала до начала цепочки. Тогда в начало можно будет подставить символ «0» и цепочка будет принадлежать языку A, что не отвечает нашим интуитивным представлениям о синтаксическом строении цепочек этого языка.

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

Можно сказать, что шрейдеровские языки задают одно простое синтаксическое отношение — «быть рядом» или отношение непосредственного предшествования. Отношение дальнего предшествования (которое, очевидно, присутствует в языке B) окрестностной грамматикой задано быть не может. Но, если визуализировать синтаксические отношения в цепочках языка, то для диаграмм отношений, в которые превращаются такие цепочки, можно придумать окрестностную грамматику.

Формальная грамматика или просто грамматика в теории формальных языков — способ описания формального языка, то есть выделения некоторого подмножества из множества всех слов некоторого конечного алфавита. Различают порождающие и распознающие (или аналитические) грамматики — первые задают правила, с помощью которых можно построить любое слово языка, а вторые позволяют по данному слову определить, входит ли оно в язык или нет.

Содержание

Термины [ править | править код ]

  • Терминал (терминальный символ) — объект, непосредственно присутствующий в словах языка, соответствующего грамматике, и имеющий конкретное, неизменяемое значение (обобщение понятия «буквы»). В формальных языках, используемых на компьютере, в качестве терминалов обычно берут все или часть стандартных символов ASCII — латинские буквы, цифры и спецсимволы.
  • Нетерминал (нетерминальный символ) — объект, обозначающий какую-либо сущность языка (например: формула, арифметическое выражение, команда) и не имеющий конкретного символьного значения.

Порождающие грамматики [ править | править код ]

Словами языка, заданного грамматикой, являются все последовательности терминалов, выводимые (порождаемые) из начального нетерминала по правилам вывода.

Чтобы задать грамматику, требуется задать алфавиты терминалов и нетерминалов, набор правил вывода, а также выделить в множестве нетерминалов начальный.

Итак, грамматика определяется следующими характеристиками:

  • Σ <displaystyle Sigma >— набор (алфавит) терминальных символов
  • N — набор (алфавит) нетерминальных символов
  • P — набор правил вида: «левая часть» → <displaystyle
    ightarrow >«правая часть», где:
  • «левая часть» — непустая последовательность терминалов и нетерминалов, содержащая хотя бы один нетерминал
  • «правая часть» — любая последовательность терминалов и нетерминалов
  • S — стартовый (или начальный) символ грамматики из набора нетерминалов.
  • Вывод [ править | править код ]

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

    Существование вывода для некоторого слова является критерием его принадлежности к языку, определяемому данной грамматикой.

    Типы грамматик [ править | править код ]

    По иерархии Хомского, грамматики делятся на 4 типа, каждый последующий является более ограниченным подмножеством предыдущего (но и легче поддающимся анализу):

    • тип 0. неограниченные грамматики — возможны любые правила
    • тип 1. контекстно-зависимые грамматики — левая часть может содержать один нетерминал, окруженный «контекстом» (последовательности символов, в том же виде присутствующие в правой части); сам нетерминал заменяется непустой последовательностью символов в правой части.
    • тип 2. контекстно-свободные грамматики — левая часть состоит из одного нетерминала.
    • тип 3. регулярные грамматики — более простые, эквивалентны конечным автоматам.

    Кроме того, выделяют:

    • Неукорачивающиеся грамматики. Каждое правило такой грамматики имеет вид α → β <displaystyle alpha
      ightarrow eta >, где | α | ⩽ | β | <displaystyle |alpha |leqslant |eta |>. Длина правой части правила не меньше длины левой [1] .
    • Линейные грамматики. Каждое правило такой грамматики имеет вид A → u B v <displaystyle A
      ightarrow uBv>, или A → u <displaystyle A
      ightarrow u>, то есть в правой части правила может содержаться не более одного вхождения нетерминала [2] .

    Применение [ править | править код ]

    • Контекстно-свободные грамматики широко применяются для определения грамматической структуры в грамматическом анализе.
    • Регулярные грамматики (в виде регулярных выражений) широко применяются как шаблоны для текстового поиска, разбивки и подстановки, в том числе в лексическом анализе.

    Пример — арифметические выражения [ править | править код ]

    Рассмотрим простой язык, определяющий ограниченное подмножество арифметических формул, состоящих из натуральных чисел, скобок и знаков арифметических действий. Стоит заметить, что здесь в каждом правиле с левой стороны от стрелки ⇒ <displaystyle Rightarrow > стоит только один нетерминальный символ. Такие грамматики называются контекстно-свободными.

    Выведем формулу (12+5) с помощью перечисленных правил вывода. Для наглядности, стороны каждой замены показаны попарно, в каждой паре заменяемая часть подчеркнута.

    ФОРМУЛА → 3 <displaystyle <stackrel <3>< o >>> (ФОРМУЛА) (ФОРМУЛА) → 1 <displaystyle <stackrel <1>< o >>> (ФОРМУЛА ЗНАК ФОРМУЛА) (ФОРМУЛА ЗНАК ФОРМУЛА) → 4 <displaystyle <stackrel <4>< o >>> (ФОРМУЛА + ФОРМУЛА) (ФОРМУЛА + ФОРМУЛА) → 2 <displaystyle <stackrel <2>< o >>> (ФОРМУЛА + ЧИСЛО) (ФОРМУЛА + ЧИСЛО) → 5 <displaystyle <stackrel <5>< o >>> (ФОРМУЛА + ЦИФРА) (ФОРМУЛА + ЦИФРА) → 7 <displaystyle <stackrel <7>< o >>> (ФОРМУЛА + 5) (ФОРМУЛА + 5) → 2 <displaystyle <stackrel <2>< o >>> (ЧИСЛО + 5) (ЧИСЛО + 5) → 6 <displaystyle <stackrel <6>< o >>> (ЧИСЛО ЦИФРА + 5) (ЧИСЛО ЦИФРА + 5) → 5 <displaystyle <stackrel <5>< o >>> (ЦИФРА ЦИФРА + 5) (ЦИФРА ЦИФРА + 5) → 7 <displaystyle <stackrel <7>< o >>> (1 ЦИФРА + 5) (1 ЦИФРА + 5) → 7 <displaystyle <stackrel <7>< o >>> (1 2 + 5)

    Аналитические грамматики [ править | править код ]

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

    Поделитесь ссылкой пожалуйста:
    Читайте также:  Как найти друзей в фотостране
    Ссылка на основную публикацию
    Adblock detector