Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции Михеева.doc
Скачиваний:
21
Добавлен:
04.11.2018
Размер:
1.19 Mб
Скачать

1. Языки и грамматики. Обозначения, определения

И КЛАССИФИКАЦИЯ

Вначале дадим ряд определений.

Алфавит - это непустое конечное множество элементов. Элементы алфавита называются символами

Всякая конечная последовательность символов алфавита называется цепочкой. Так a, b, c, ab, aaca - цепочки в алфавите A = {a,b,c}.

Допустим существование пустой цепочки , не содержащей ни одного символа.

Важен порядок символов в цепочке. Цепочка ab отличается от ba.

Длина цепочки  равна количеству символов в цепочке. Так a=1, abc=3, =0.

Если и - цепочки, то их конкатенацией  является цепочка, полученная путем дописывания символов цепочки вслед за символами цепочки . Например, если ab, bc, то  abbc и  bcab. Поскольку - цепочка, не содержащая символов, то в соответствии с правилами конкатенации для любой цепочки можно записать

.

Обращением цепочки (обозначается R ) называется цепочка , записанная в обратном порядке, т.е. если = a1...an , где все ai - символы, то R= an... a1. Кроме того, R= .

Если  - цепочка, то - голова (префикс), а - хвост (суффикс) цепочки . При этом, - правильная голова, если - не пустая цепочка ( ), - правильный хвост, если . Таким образом, если abc, то , a, ab и abc - головы , и все они, кроме abc, - правильные головы.

Иногда удобнее и нагляднее писать

  вместо ,

если нас не интересует - остальная часть цепочки. Три точки "" будут обозначать любую возможную цепочку, включая пустую.

Языком L в алфавите A называется множество цепочек в A.

Это определение подходит почти для любого языка. Языки Паскаль, С, Модула-2, английский и русский охватываются этим понятием.

Рассмотрим простые примеры языков в алфавите A.

Пустое множество - это язык. Множество { }, содержащее только пустую цепочку, также является языком.

Заметим, что и { } - это два разных языка.

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

Например, если A бинарный алфавит {0,1}, то

A = { , 0, 1, 00, 01, 10, 11, 000, 001, 010, 011, 100, 101, 110, ...}.

Каждый язык в алфавите A является подмножеством множества A. Множество всех цепочек в A, за исключением , обозначим A +, то есть A= A+ .

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

1). - цепочка в A,

2). если цепочка в A и a A, то a - цепочка в A (a A),

3). - цепочка в A, тогда и только тогда, когда она является таковой в силу 1) или 2).

Цепочку, состоящую из i символов a будем обозначать a i, то есть a0=, a1= a, a2= aa, a3= aaa и т.д.

Итак язык L - это некоторое множество цепочек в некотором алфавите A. Как описать этот язык. Если L состоит из конечного числа цепочек, то самый очевидный способ состоит в составлении списка всех цепочек этого языка. Однако, для большинства языков нельзя или нежелательно устанавливать верхнюю границу длины самой длинной цепочки. Следовательно приходится рассматривать язык, содержащий сколь угодно много цепочек. Очевидно, их нельзя описать перечислением цепочек. Мы хотим, чтобы описание языка было конечным (имело конечный объем), хотя сам язык может быть и бесконечным. Известно несколько методов такого описания. Один из основных состоит в использовании порождающей системы, называемой грамматикой.

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

( ) ( ) ( ).

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

  

или

::=

что означает порождает (состоит из) .

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

S

где S - начальный символ, а  ( ) - любая цепочка.

В последующем, если не оговорено дополнительно, используем следующие обозначения. Грамматику языка обозначим через G, возможно с индексом, или G(S). Язык L, определяемый грамматикой G, обозначим L(G). Терминальные символы обозначим малыми буквами, а нетерминалы - прописными, или в виде текста в угловых скобках, например, <нетерминал>. Цепочки будем обозначать греческими буквами. Если в грамматике встречаются правила с одинаковыми левыми частями

::=1

::=2

..........

::=n ,

то будем писать

::=12 ... n

в виде одного правила, имеющего ряд альтернатив в правой части. Правило вида

::= 

можно представить

::= [ ]

где []-факультативный (необязательный) элемент. Последние обозначения используются в системе записи метаязыка Хомского, которая носит название Бэкусовой нормальной формы (БНФ) или формы Бэкуса-Наура. Она была предложена Д.Бэкусом в 1959 году и впервые применена П.Науром для описания языка Алгол-60. Напомним, что метаязыком называется язык, который используется для описания других языков.

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

Пример 1.1.

<предложение>::=<подлежащее><группа сказуемого>

<подлежащее>::=матьотец

<группа сказуемого>::=<сказуемое><дополнение>

<сказуемое>::=любитобожаетбоготворит

<дополнение>::=сынадочь

Если имеется множество правил, то ими можно воспользоваться для того, чтобы вывести или породить цепочку (предложение) по следующей схеме. Начнем с начального символа грамматики - <предложение>, найдем правило, в котором <предложение> слева от ::= , и подставим вместо <предложение> цепочку, которая расположена справа от ::=, т.е.

<предложение><подлежащее> <группа сказуемого>

Таким образом, мы заменяем синтаксическое понятие на одну из цепочек, из которых оно может состоять. Повторим процесс. Возьмем один из нетерминалов в цепочке <подлежащее> <группа сказуемого>, например <подлежащее>; найдем правило, где <подлежащее> находится слева от ::=, и заменим <подлежащее> в исходной цепочке на соответствующую цепочку, которая находится справа от ::=. Это дает

<подлежащее> < группа сказуемого > мать < группа сказуемого >

Символ "" означает, что один символ слева от  в соответствии с правилом грамматики заменяется цепочкой, находящейся справа от . Полный вывод одного предложения будет таким:

<предложение><подлежащее> <группа сказуемого>

мать < группа сказуемого >

мать <сказуемое> <дополнение>

мать любит <дополнение>

мать любит сына

Этот вывод предложения запишем сокращенно, используя новый символ +

<предложение> + мать любит сына

На каждом шаге можно заменить любой нетерминал. В приведенном выше выводе всегда заменялся самый левый из них.

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

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

мать любит сына мать обожает сына мать боготворит сына

мать любит дочь мать обожает дочь мать боготворит дочь

отец любит сына отец обожает сына отец боготворит сына

отец любит дочь отец обожает дочь отец боготворит дочь

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

Рассмотрим еще один пример полезной грамматики

Пример 1.2. Грамматики целого числа без знака содержат следующие 13 правил

(1) <число>::=<чс> S A

(2) <чс>::=<цифра><чс> A AB

(3) <чс>::=<цифра> A B

(4) <цифра>::=0 B 0

(5) <цифра>::=1 B 1

(6) <цифра>::=2 B 2

(7) <цифра>::=3 B 3

(8) <цифра>::=4 B 4

(9) <цифра>::=5 B 5

(10) <цифра>::=6 B 6

(11) <цифра>::=7 B 7

(12) <цифра>::=8 B 8

(13) <цифра>::=9 B 9

Заметим, что грамматики G(<число>) и G(S) определяют один и тот же язык и отличаются только именами нетерминалов и вторым правилом 

А теперь продолжим наши определения.

Пусть G - грамматика. Будем говорить, что цепочка непосредственно порождает цепочку , и обозначим

  ,

если для некоторых цепочек и можно написать

  U

  

где

U

правило грамматики G. Будем также говорить, что непосредственно выводима из или что непосредственно приводится (редуцируется, сворачивается) к .

Цепочки и , конечно, могут быть пустыми. Следовательно, для любого правила A грамматики G имеет место A . На рис. 1.1 даны некоторые примеры непосредственных выводов для грамматики G(<число>) из примера 1.2 и обозначений предыдущего определения.

Будем говорить, что порождает или приводится к и записывать + , если существует последовательность непосредственных выводов

  0 1 2  n ,

где n>0. Эта последовательность называется выводом длины n. Будем писать , если + или .

Если просмотреть все строки рис 1.1 то мы получим

<число> <чс> <цифра> <чс> 2 <чс> 2 <цифра> 25

Таким образом, <число> + 22 и длина вывода равна 5. (Если длина вывода известна можно записывать в явном виде <число> 5 22 )

Заметим, что пока в цепочке есть хотя бы один нетерминал, из нее можно вывести новую цепочку, Однако если нетерминальные символы отсутствуют, то вывод завершен. Неслучайно "терминалом" (terminal - заключительный, конечный) называют символ, который не встречается в левой части ни одного из правил. Исключение составляют нетерминалы-тупики, которые будут рассмотрены в разделе 4.2.

Попробуем еще раз определить язык.

Пусть G(S) = {,,,S} - грамматика. Цепочка называется сентенциальной формой, если выводима из начального символа S, т.е. если

S.

Цепочка языка - это сентенциальная форма, состоящая только из терминалов.

Язык L(G(S)) - это множество цепочек:

L(G)={ S и }

т.е. язык - это подмножество множества всех терминальных цепочек .

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

Пусть G(S) - грамматика. И пусть  - сентенциальная форма. Тогда называется фразой сентенциальной формы для нетерминального символа U, если S U и U + ; и далее, называется простой фразой, если S U и U .

Тот факт, что U + , вовсе не означает, что является фразой сентенциальной формы ; необходимо также иметь S U. Значит ли в примере 1.2, что <чс> является фразой сентенциальной формы 1 <чс>, если существует правило <число>::=<чс> ? Конечно, нет, поскольку невозможен вывод цепочки 1 <число> из начального символа грамматики <число>. Каковы же фразы сентенциальной формы 1 <чс> ? Имеет место вывод

<число> <чс> <цифра><чс> 1<чс>

Таким образом,

(1) <число> <чс> и <чс> +1<чс>

(2) <число> <цифра><чс> и <цифра> +1

Следовательно, 1<чс> и 1 - фразы, простой же фразой будет только 1.

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

Грамматики G(<число>) и G(S) из примера 1.2 описывают бесконечный язык, т.е. язык, состоящий из бесконечного числа цепочек. Это обусловлено тем, что правило <чс>::=<цифра><чс> (AAB) содержит <чс> (A) и в левой, и в правой частях, т.е. в некотором смысле символ <чс> (A) сам себя определяет.

В общем случае, если U +...U..., то говорят, что грамматика рекурсивна по отношению к U. Если U + U..., то имеет место левая рекурсия, а если U +...U, то - правая рекурсия. Соответствующие правила называют лево- (право)рекурсивными. Если язык бесконечен, то определяющая его грамматика должна быть рекурсивной.

Ниже представлен пример грамматики, которая включает правило с двухсторонней рекурсией.

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

S AB

A a A b

.............................

A y A z

B BB B

B A B 0

..............................

B 9.