СПО
.pdf<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>* }.
Чтобы построить грамматику, допускающую использование в арифметических выражениях скобок без вложенности, представим структуру таких выражений в виде списка с разде-
лителями, элементами которого являются выражения без скобок или выражения без скобок, заключенные в скобки. Разделителями этого списка являются знаки операций. Такой структуре соответствует следующая схема грамматики:
: 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'. В полном тексте описания переменных определенного типа могут повторяться.
Например, полное описание может включать три разных описания переменных целого типа. Полное описание должно заканчиваться точкой. В качестве разделителя описаний переменных разных типов примем точку с запятой, а в качестве разделителя переменных одного типа - запятую.
Структуру полного описания можно представить в виде двух вложенных списков с разделителями. Внутренний список, рассматриваемый как элемент внешнего списка, представляет собой описание переменных одного типа. Он имеет заго-
ловок в виде указателя типа, за которым следует последовательность идентификаторов, разделенных запятыми. Внешний список использует в качестве разделителя точку с запятой.
Схема грамматики рассматриваемого вида может быть записана так:
: 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>,
<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)Если инфиксное выражение Е1*Е2, где * - знак операции,а Е1 и Е2 инфиксные выражения для операндов, то ПрПЗ этого выражения – это *Е1'E2',где E1', E2' - ПрПЗ выражений Е1
иЕ2.
3)Если (Е) есть инфиксное выражение, то ПрПЗ этого
выражения есть ПрПЗ Е.
Это определение определяет порядок построения ПрПЗ заданного инфиксного выражения.
Например для выражений (a + b) * (c - d) построение ПрПЗ можно выполнить так. Обозначим операнды первой выполняемой операции:
E1 = (a + b) и E2 = (c - d).
Согласно определению префиксная запись выражения Е1*Е2 - это *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.Если инфиксное выражение Е1*Е2, где * - знак операции, E1, E2 - инфиксные выражения для операндов, то ПоПЗ этого выражения это - Е1'E2'*, где Е1',E2' - постфиксные выра-
жения Е1,Е2.
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,