Алгоритм Кока-Янгера-Касами.




Алгоритм Рутенхаузера.

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

Выражение должно быть записано в полной скобочной структуре. Например, формула a+b*c запишется в виде a+(b*c).

Обрабатывая выражение с полной скобочной структурой, алгоритм Рутенхаузера присваивает каждому символу Si из строки с формулой число Ni, согласно алгоритму, приведённому ниже. Здесь S(j) – j-й символ, а N(j) – j-е число и используется переменная содержащая самое большое присвоенное N(j) значение.

Алгоритм: Присвоить.

Присвоить 1: N(0)0; J0

Присвоить 2: JJ+1; Если конец строки, то N(J)0 и выход;

Присвоить 3: Если S(J) это «(» или «операнд», то N(J)N(J-1)+1; перейти к Присвоить 2;

Присвоить 4: Иначе N(J)N(J-1)-1; перейти к Присвоить 2;

Первый символ S(0) является пробелом, являющимся фактически началом строки. Заметим, что конечное значение J на единицу больше длины строки. Например, пусть задана цепочка a+(b*c) тогда присвоение чисел будет происходить согласно следующей таблице:

J                  
S(J)   A + ( b * c )  
N(J)                  

 

Далее транслятор ищет наибольшее значение N(J). Это значение, назовем его K, появляется в структуре вида N(J): … (K-1) K (K-1) K (K-1) … Рассматриваемая структура соответствует последовательности символов следующего вида: Z операнд1 Θ операнд2 R.

Символ Z – либо левая скобка, либо левый конец выражения.

Точно также R – это правая скобка или правый конец выражения.

Символ Θ представляет ОПЕРАЦИЮ.

При обнаружении такой структуры значение двуместного выражения вычисляется и запоминается во временной ячейке Ti. Тройка Ti <= операнд1 Θ операнд2 фиксируется. Обработанные три символа вместе с Z и R (если последние являются скобками) удаляются, а на их место помещается Ti со значением N=(K-1). Если Z и R – концы строки, процесс завершен. В противном случае алгоритм повторяет поиск наибольшего числа N. Приведенный выше пример после однократной обработки имеет такой вид:

S(J)   A + Ti  
N(J)          

 

 

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

Более сложный пример применения метода Рутенхаузера, обрабатывающий арифметическое выражение (((a + b)*c) + d)¸(e + (a¸f)).

 

Генерация тройки Выражение
  T1=a+b (((a + b) * c) + d) ¸ (e + (a ¸ f)) 0 1 2 3 4 3 4 3 2 3 2 1 2 1 0 1 2 1 2 3 2 3 2 1 0
  T1=T1*c ((T1 * c) + d) ¸ (e + (a ¸ f)) 0 1 2 3 2 3 2 1 2 1 0 1 2 1 2 3 2 3 2 1 0
  T2=a – f (T1 + d) ¸ (e + (a – f)) 0 1 2 1 2 1 0 1 2 1 2 3 2 3 2 1 0
  T1=T1 + d (T1 + d) ¸ (e + T2) 0 1 2 1 2 1 0 1 2 1 2 1 0
  T2=e+T2 T1 ¸ (e + T2 ) 0 1 0 1 2 1 2 1 0
  T1=T1¸T2 T1 ¸ T2 0 1 0 1 0
  T1 0 1 0

Стековые методы

Бауэр и Замельзон. Основные его компоненты СТЕК и таблица ПЕРЕХОДОВ. Анализатор использует два стека: один стек используется непосредственно при трансляции выражения, а второй стек – во время исполнения.

Стек транслятора имеет метку Т, а исполнительный – метку Е.

Транслятор прочитывает выражение один раз слева на право и вырабатывает последовательность команд двух видов:

KI (I – есть идентификатор) является командой «Выбрать число по имени I и заслать его в стек Е »

K§ (§ - операция) является командой «Выбрать два верхних операнда из стека Е, произвести над ними операцию § и занести результат в вершину стека Е ».

Когда при просмотре входной строки считываемый символ является ОПЕРАНДОМ выдается команда KI и транслятор переходит к следующему символу.

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

В таблице переходов указывается, какие действия должен выполнять транслятор. В этой таблице каждой операции соответствует СТРОКА и СТОЛБЕЦ.

Элементами таблицы являются директивы транслятору.

Возможны 4 действия транслятора после прочтения операции § (операция в вершине стека Т обозначается h):

I: Заслать § в Т; читать следующий символ
II: Генерировать Кh; заслать § в Т. Читать следующий символ
III: Читать из Т; Читать следующий символ (используется для удаления скобок)
IV: Генерировать Кh; Читать из Т; Повторить с тем же самым входным символом.

Имеется еще две специальные команды: Конец процесса и Ошибка, которые приказывают транслятору остановится и выдать соответствующую команду. ПРОЦЕССОР выбирает элементы таблицы, используя в качестве одного индекса h, верхнюю операцию стека Т, и в качестве второго, §, операцию, прочитанную последней из входной строки. Таблицу мы приведем для трансляции с языка простых арифметических выражений. В этой таблице L обозначает символ пробела, или пустую строку. Если стек Т пуст или пуста входная строка, то считается что прочитано L § - входной символ h - вершина стека Т.

Таблица переходов для простых алгебраических выражений.

Стек T\Строка L ( + - * / )
L Конец I I I I I Ошибка
( Ошибка I I I II II III
+ IV I II II I I IV
- IV I II II I I IV
* IV I IV IV II II IV
/ IV I IV IV II II IV

 

Применим этот процесс к конкретному выражению (a*b+c*d)/(a-d)

Т Прочитанный символ Действие Выдать
L ( I  
( a   Ka
( * I  
(* b   Kb
(* + IV K*
( Повторить I  
(+ c   Kc
(+ * I  
(+* d   Kd
(+* ) IV K*
(+ Повторить IV K+
( Повторить III  
L / I  
/ ( I  
/( a   Ka
/( - I  
/(- d   Kd
/(- ) IV K-
/( Повторить III  
/ + IV K/

Получается последовательность команд, имеющая вид:

Ka, Kb, K*, Kc, Kd, K*, K+, Ka, Kd, K -, K/

Более простая запись получается, если опустить все скобки и использовать польскую запись (польский математик Лукасевич): ab*cd*+ad-/bc*+

Исполняющая программа использует стек Е и читает польскую запись слева направо.

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

Алгоритм Кока-Янгера-Касами.

Обсуждаемый алгоритм предназначен для разбора методом «снизу-вверх» слов любой контекстно-свободной грамматики, т.е. это – универсальный метод. Для его применения грамматика должна быть преобразована к нормальной форме Хомского (т.е. правила имеют вид: A®a или A®BC). Этот алгоритм имеет сложность O(n3) по времени и O(n2) по памяти. На первом этапе алгоритм строит треугольную таблицу с элементами tik, в каждую клетку которой помещается множество нетерминалов, из которых можно вывести отрезок слова начинающийся с символа ai и длиной k.

Формально: tik = {A | A ai…ai+k-1}. Очевидно, что множества tik формально (рекурсивно) можно определить так:

ti1 = {A | A®ai - правило грамматики},

tij = {A | A®BC - правило грамматики и $k, 1£k<j такое, что BÎtik Ù CÎti+k,j-k}.

Если в t1n есть S, то слово Î языку.

t16          
t15 t25        
t14 t24 t34      
t13 t23 t33 t43    
t12 t22 t32 t42 t52  
t11 t21 t31 t41 t51 t61
a1 a2 a3 a4 a5 a6

Пусть заполнены все строки таблицы до j-1 включительно. Рассмотрим tij.

Эта ячейка соответствует фрагменту слова <ai…ai+j-1>. Разбиваем этот фрагмент на пары слов всеми способами. Каждому варианту разбиения соответствует пара клеток таблицы, в которых стоят нетерминалы, из которых могут быть выведены соответствующие строки. Пусть это пара (t¢,t²). В tij поместим нетерминал A, если есть правило A®BC и BÎt¢, CÎt².

Пример. Рассмотрим неоднозначную грамматику: G = ({S,L,R}, {(,)}, {S®SS | LR, L®(, R®)}, S). Пусть задано слово ()()(). Построим таблицу.

S16          
           
S14   S34      
           
S12   S32   S52  
L11 R21 L31 R41 L51 R61
( ) ( ) ( )

На втором этапе восстанавливаем дерево вывода.

Это можно выполнить с помощью следующей рекурсивной процедуры:

GEN(i,j,A)

| 1. Если j=1 Ù A®ai – правило с номером m, то выдать m.

| 2. Если j>1. Пусть k – наименьшее из чисел, для которых $ BÎtik CÎti+k,j-k и A®BCÎR

| имеет номер m. Выбрать это правило, выдать m и выполнить последовательно:

| GEN(i,k,B)???

ë GEN(i+k,j-k,C)???

Старт: GEN(1,n,S)

Замечание. Описанный алгоритм существенно опирается на то, что грамматика имеет форму Хомского.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2017-12-12 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: