Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

СПО

.pdf
Скачиваний:
41
Добавлен:
31.05.2015
Размер:
2.9 Mб
Скачать

<A>$, <D> 0 | 1 | ... | 9,

<C> a | d | c | ... | z }.

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

Г1. 22 : R = { <I> <C> <A1>, <A1> <C> <B>, <A1> <D> <B>, <B> <C>,

<B> <D>, <D> 0 | 1 | ... | 9,

<C> a | d | c | ... | z }.

8.4.5.5. Грамматики для арифметических выражений

Условимся рассматривать арифметические выражения, использующие только знаки сложения и умножения. Вначале построим грамматику для выражений без скобок. Такие выражения представляют собой цепочки, которые можно рассматривать как списки с разделителями, в которых роль разделителей выполняют знаки операций. В соответствии с этой аналогией получаем схему грамматики, в которой символ <I> обозначает идентификатор, определение которого приведено выше.

Г1. 23 : R = { <H> <I> <R>, <R> <W> <I> <R>, <R>$,

<W> +, <W>* }.

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

Г1. 25
Г1. 24

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

: R = { <G> <H> <Q>, <G> (<H>) <Q>,

<Q> <W> <G>, <Q> $ }.

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

: R = { <E> <G> <P>, <E> (<E>) <P>,

<P> <W> <E>, <P> $ }.

8.4.5.6. Грамматика для описаний

Пусть требуется построить грамматику для описания целых и вещественных переменных. Описание переменных определенного типа должно начинаться указателем типа 'real' или 'int'. В полном тексте описания переменных определенного типа могут повторяться.

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

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

Г1. 26

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

Схема грамматики рассматриваемого вида может быть записана так:

: R = { <Z> <A2>, <A2> <B1> <C1>,

<C1> ; <B1> <C1>, <C1> $,

<B1> 'real' <L>, <B1> 'int' <L>, <L> <I> <K>,

<K> , <I> <K>, <K> $ }

8.4.5.7. Грамматика, задающая последовательность операторов присваивания

Допустим, что в правой части оператора присваивания могут быть использованы только выражения без скобок, описываемые грамматикой Г1.24. В качестве разделителя операторов в последовательности примем точку с запятой. Учитывая, что последовательность операторов соответствует списку с разделителями в виде точки с запятой, и, используя определенную ранее конструкцию идентификатора, получаем искомую схему грамматики в виде:

Г1. 27 : R = { <U> <A3>, <A3> <S> <R1>,

<R1> ; <S> <R1>, <R1> $,

<S> <I> <B2>, <B2> := <H1>, <H1> <I> <R2>, <R2> + <I> <R2>,

Г1. 28

<R2>* <I> <R2>, <R2>$}

8.4.5.8.Грамматики, описывающие условные операторы

иоператоры цикла

Допустим, что рассматриваются условные операторы, аналогичные используемым в языке Паскаль, с разделителями 'if', 'then', 'else'. В качестве условия в таких операторах разрешается использовать отношения, состоящие из двух идентификаторов, соединенных знаками = и <. Структура такого оператора определяется двумя видами последовательностей фиксированной длины, для описания которых можно воспользоваться простым перечислением компонентов. Первая последовательность определяет полный и сокращенный условные операторы, а вторая - конструкцию "отношение". Схема грамматики, задающая эти последовательности, может быть изображена так:

: R = { <V> .if. <R4> <C2>, <C2> .then. <S> <C3>, <C3> .else. <S>,

<C3>$, <R4> <I> <R3>, <R3> < <I>, <R3> = <I> } .

В этой грамматике <S> определяется схемой грамматики Г1.27 . Рассмотрим описание операторов цикла, подобных используемым в языке Паскаль, с разделителями 'while', 'do', 'repeat', 'until'. Каждый оператор может быть описан в виде простой последовательности ограниченной длины, в которой используются построенные ранее грамматика Г1.28 и грамматика Г1.27 . На практике часто встречаются ситуации, когда удобнее работать с грамматикой, правая часть правил которой начинается терминальным символом. Построение подобных

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

Г1. 29: R = { <W> .while. <R4> <C4>, <C4> .do. <S> }

Г1. 30: R = { <W1> .repeat.<S> <C5>, <C5> .until.<R4> }.

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

Эта задача относится к классу эвристических задач, не имеющих общих алгоритмов решения.

На практике поиск решения выполняется с применением структурного анализа заданных цепочек.

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

8.4.5.9. Бесскобочные выражения

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

Существуют формы записи арифметических выражений

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

8.4.5.10. Префиксная польская запись

Определение. Префиксную польскую запись (ПрПЗ) определим так:

1) Если инфиксное выражение Е представляет собой один операнд а, то ПрПЗ выражение Е - это просто а.

2)Если инфиксное выражение Е12, где * - знак операции,а Е1 и Е2 инфиксные выражения для операндов, то ПрПЗ этого выражения – это *Е1'E2',где E1', E2' - ПрПЗ выражений Е1

иЕ2.

3)Если (Е) есть инфиксное выражение, то ПрПЗ этого

выражения есть ПрПЗ Е.

Это определение определяет порядок построения ПрПЗ заданного инфиксного выражения.

Например для выражений (a + b) * (c - d) построение ПрПЗ можно выполнить так. Обозначим операнды первой выполняемой операции:

E1 = (a + b) и E2 = (c - d).

Согласно определению префиксная запись выражения Е12 - это *E1'E2', где Е1',Е2' -префиксные записи выражений Е1 и Е2. Выполняя построение постфиксных записей для этих выражений,

E1' = +ab, E2' = -cd,

окончательно получаем результат в виде:

*+ab-cd

8.4.5.11. Вычисление префиксных польских записей

Вычисление ПрПЗ можно представить следующим обра-

зом:

1.Просматриваем выражение слева направо, пока не найдем знак операции, за которым следуют два операнда.

2.Выполняем операцию и результат записываем на место выбранной тройки.

3.Повторяем пункт (1), пока не получим вместо выражения один результат.

Вычисление построчного префиксного выражения можно представить в следующем виде:

1.*+ab-cd

2.*R1-cd

3.*R1R2

4.R3

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

8.4.5.12. Постфиксная польская запись

Определение. Постфиксную польскую запись (ПоПЗ) определим так:

1.Если инфиксное выражение Е представляет собой один операнд а, то ПоПЗ выражения Е - это а.

2.Если инфиксное выражение Е12, где * - знак операции, E1, E2 - инфиксные выражения для операндов, то ПоПЗ этого выражения это - Е1'E2'*, где Е1',E2' - постфиксные выра-

жения Е12.

3. Если (Е) есть инфиксное выражение, то постфиксная запись этого выражения есть постфиксная запись Е.

Аналогично предыдущему примеру построим ПоПЗ выражения

(a + b) * (c - d).

Обозначая операнды внешней операции

E1 = (a + b) и E2 = (c - d),

найдем постфиксные записи операндов, которые имеют вид:

E1' = ab+ и E2' = cd-.

Подставляя полученные постфиксные записи в выраже-

ние

E1'E2'*,

окончательно получаем : ab+cd-* .

8.4.5.13. Вычисление постфиксных записей

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

1.Просматриваем выражение слева направо пока не найдем два стоящих рядом операнда, за которыми следует знак операции.

2.Выполняем операцию и записываем результат вместо выбранных операндов и операций.

3.Повторяем пункт (1) пока не получим вместо выражения единственный результат.

Вычисление построенного постфиксного выражения можно представить в следующем виде:

1.ab+cd-*

2.R1cd-*

3.R1R2*

4.R3

На практике вычисление постфиксных выражений реализуется с применением магазина. В этом случае вычисления выполняются по следующим правилам.

1.Прочитать очередной символ входной цепочки.

2.Если входной символ - операнд, то выполнить его запись в магазин.

3.Если входной символ - оператор, то прочитать два операнда из магазина, выполнить операцию и результат занести в магазин как операнд.

4.Повторять п.1, пока во входной цепочке не будут прочитаны все символы.

Последовательность вычислений продемонстрируем на примере входной цепочки

ab+cd-*

и изобразим ее в виде следующей схемы:

Вход

Магазин

Операция

ab+cd-*

 

 

1. b+cd-*

a

 

2. +cd-*

ab

 

3. cd-*

R1

a+b=R1

4. d-*

R1c

 

5. -*

R1cd

 

6. *

R1R2

c-d = R2

7. $

R3

R1*R2 = R3

8.5. Конечные автоматы и регулярные грамматики

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

Рис. 34. Схема работы конечного автомата

Конечный автомат состоит из конечного управления и входной ленты, разбитой на ячейки. В каждой ячейке записан один символ из входного алфавита Σ, и все они образуют конечную входную цепочку. Конечное управление первоначально находится в состоянии q0 и сканирует крайнюю левую ячейку ленты. По мере чтения входной цепочки слева направо автомат переходит в другие состояния из множества Q. Если, прочитав входную цепочку, автомат оказывается в некотором конечном состоянии из множества F, то говорят, что он принял ее. Множество цепочек, принимаемых конечным автома-

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

автоматом.

Конечные автоматы не могут распознавать все языки, порождаемые грамматиками, но языки, распознаваемые ими, являются в точности языками, порождаемыми грамматиками типа 3. В дальнейшем вместо термина ―конечный автомат‖ будем использовать аббревиатуру fa - finite automaton.

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

Определение. Конечным автоматом называется фор-

мальная система

M = (Q, Σ, δ, q0, F), где

Q - конечное непустое множество состояний;

Σ - конечный входной алфавит;

δ - отображение типа Q Σ → Q; q0 Q - начальное состояние;

F Q - множество конечных состояний.

Запись δ(q, a) = p, где q, p Q и a Σ, означает, что конечный автомат M в состоянии q, сканируя входной символ a, продвигает свою входную головку на одну ячейку вправо и переходит в состояние p.

Область определения отображения δ можно расширить до Q Σ* следующим образом:

δ(q, ) = q,