Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции СисПО.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
731.14 Кб
Скачать

2.3. Грамматики

2.3.1. Формальное определение грамматики

Для нас наибольший интерес представляет одна из систем генерации языков – грамматики. Понятие грамматики изначально было формализовано лингвистами при изучении естественных языков. Предполагалось, что это может помочь при их автоматической трансляции. Однако наилучшие результаты в этом направлении достигнуты при описании не естественных языков, а языков программирования. Примером может служить способ описания синтаксиса языков программирования при помощи БНФ – формы Бэкуса­Наура, которая предполагает использование в качестве нетерминальных символов комбинаций слов естественного языка, заключенных в угловые скобки, а в качестве разделителя - специального знака, состоящего из двух двоеточий и равенства. Например, если правила <L><L> и <L><E> записаны в символической форме, и символ <L> соответствует синтаксическому понятию "список", а символ <E> - "элемент списка", то их можно представить в форме Наура-Бэкуса так:

<список>::= <элемент списка><список>, <список>::= <элемент списка>.

Чтобы сократить описание схемы грамматики, в БНФ разрешается объединять правила c одинаковой левой частью в одно правило, правая часть которого должна включать правые части объединяемых правил, разделенные вертикальной чертой. Используя объединение правил, для рассматриваемого примера получаем:

<список>::=<элемент списка><список>|<элемент списка>.

Декартовым произведением A B множеств A и B называется множество {(a,b) | a  A, b  B}.

Порождающая грамматика G - это четверка (VT, VN, P, S), где

VT - алфавит терминальных символов (терминалов), то есть множество таких символов, которые считаются известным и не требуют определения;

VN - алфавит нетерминальных символов (нетерминалов), не пересекающийся с VT, то есть множество таких символов, которые требуют определения в грамматике;

P - это конечное подмножество множества (VT  VN)+  (VT  VN)*;

Р является множеством правил или продукций (то есть способов определения нетерминальных символов) вида {   } (из некоторой цепочки  следует цепочка ), где  образована из терминальных или нетерминальных символов, а также может быть пустой:   ( VTVN )*, а  - цепочка, которая в общем случае содержит как терминалы, так и нетерминалы, но в ней обязательно должен быть один нетерминал.

Элемент (, ) множества P называется правилом вывода и записывается в виде   ,

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

Мы будем использовать большие латинские буквы для обозначения нетерминальных символов, малые латинские буквы из начала алфавита для обозначения терминальных символов, малые латинские буквы из конца алфавита для обозначения цепочек из VT* и, наконец, малые греческие буквы для обозначения цепочек из ( VTVN )*.

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

  1   2 ...   n

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

  1 | 2 |...| n.

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

Пример 2.3

1) Грамматика G1 = ({0,1}, {A,S}, P, S),

где P состоит из правил Р={ S  0A1, 0A  00A1, A  }

Применяя последовательно правила (S  0A1  00A11  0011), получаем цепочку 0011.

Эта грамматика порождает язык L(G1) = {0n 1n |n > 0}.

2) Грамматика G2 = ({a, b, c}, {S, B, C}, P, S),

P = {S  aSBC, S  aBC, CB  BC, aB  ab, bB  bb, bC  bc, cC  cc}.

Эта грамматика порождает язык L(G2) = {an bn cn |n > 0}.

Действительно, применяем n - 1 раз правило 1 и получаем an-1 S(BC)n-1 , затем один раз правило 2 и получаем an (BC)n , затем n(n - 1)/2 раз правило 3 и получаем anBnCn. Затем используем правило 4, получаем anbBn-1Cn . Затем применяем n – 1 раз правило 5 и получаем anbnCn. Затем применяем правило 6 и n - 1 раз правило 7 и получаем anbncn. Можно показать, что язык L(G2) состоит из цепочек только такого вида.

3) Грамматика G3 = ({0, 1},{S}, {S  0S1, S  01}, S).

Легко видеть, что цепочка 000111  L(G), так как существует вывод

S  0S1  00S11  00111

Нетрудно показать, что грамматика порождает язык L(G3) = {0n 1n |n > 0}.

  1. Грамматика

G4 = ({0, 1},{S, A}, {S  0S, S  0A, A  1A, A  1}, S)

порождает язык L(G4) = {0n 1m |n,m > 0}, что нетрудно показать.

Цепочка   (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) (обозначим   ), если существуют цепочки 0, 1, ... , n (n0), такие, что  = 0  1  ...  n= .

Последовательность 0, 1, ... , n называется выводом длины n.

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

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

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

Например, L(G1) = {0n1n | n>0}.

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

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

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

Пример 2.4

Грамматики G1 = ({0,1}, {A,S}, P1, S) и G2 = ({0,1}, {S}, P2, S), где

P1={ S  0A1, 0A  00A1, A   P2={S  0S1 | 01}

эквивалентны, так как обе порождают язык

L(G1) = L(G2) = {0n1n | n>0}.

Грамматики G1 и G2 называются почти эквивалентными, если

L(G1)  { = L(G2)  {.

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

Пример 2.5

Грамматики G1 = ({0,1}, {A,S}, P1, S) и G2 = ({0,1}, {S}, P2, S), где

P1={ S  0A1, 0A  00A1, A   P2={ S  0S1 | 

являются почти эквивалентными, так как

L(G1)={0n1n | n>0}, а L(G2)={0n1n | n0}, то есть L(G2) состоит из всех цепочек языка L(G1) и пустой цепочки, которая в L(G1) не входит.