Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Обработка ошибок при трансляции




В рассмотренном примере обработка ошибок выполнялась с помощью процедуры Error, которая после выдачи сообщения прекращала работу всей программы. Такой способ реакции на ошибку упрощает синтаксический анализатор, но далеко не идеален. Рассмотрим способ его усовершенствования: завершение работы распознавателя (транслятора) после обнаружения первой ошибки без прерывания работы вызвавшей его программы.

Проблема при обработке ошибок состоит в том, чтобы после обнаружения ошибки завершить все процедуры, цепочка вызова которых привела к процедуре, обнаружившей ошибку. Это можно сделать, если процедура Error установит признак ошибки и прочитает текст до конца. Текущим символом станет «конец текста». Поскольку этот символ не может встретиться в тексте, он будет отвергнут всеми частями анализатора, который завершит свою работу без прерывания программы в целом. В качестве признака ошибки будем использовать номер ошибочного символа (обозначим ErrPos), ненулевое значение которого соответствует наличию ошибки и несет информацию о ее местоположении. Исправленные процедуры выглядят следующим образом.

procedure Error(Message: string);

var

    e: integer;

begin

    if ErrPos = 0 then begin

              WriteLn(‘^’: Pos);

              WriteLn (‘Синтаксическая ошибка: ‘, Message);

              e:=Pos;

              while Ch <> EOT do NextCh;

              ErrPos:=e;

    end;

end;

Процедура Error «самоблокируется», проверяя значение ErrPos и обходя выдачу сообщений при повторных вызовах.

Процедура NextCh после обнаружения ошибки всегда возвращает «конец текста».

procedure NextCh;

begin

    if ErrPos <> 0 then

              Ch := EOT

    else

              …

end;

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

procedure Power (var p: integer);

begin

    if Ch = ‘^’ then begin

              NextCh;

              Number(p);  

              if p>nmax then begin

                       Error (‘Слишком большая степень’);

                       p:=0; {Степень не должна остаться слишком большой}

              end

              end

    else

              p:=1;   

end;

Требуется еще одно уточнение. Поскольку при завершении работы распознавателя, обнаружившего ошибку, текущим символом станет EOT, его проверка уже не будет достаточным условием успешного окончания анализа. Использовавшееся завершение:

if Ch <> EOT then

    Error (‘Ожидается конец текста’)

else

    WriteLn (‘Правильно’);

 

должно быть заменено следующим:

if (ErrPos = 0) and (Ch = EOT) then

    WriteLn (‘Правильно’)

else

    Error (‘Ожидается конец текста’);

Табличный LL(1) – анализатор

 

Рассматривая автоматные языки, мы использовали детерминированный конечный автомат в роли эффективного универсального распознавателя. Один из вариантов его реализации – программная интерпретация таблицы переходов автомата. На похожих принципах может быть построен и распознаватель для LL(1) – грамматик, который будет представлять собой реализацию определенного подкласса МП – автоматов.

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

Таблица 1.

Состояние

Символ

Цифра Не цифра
1 2 E
2 2 K
E E E
K    

Здесь E означает состояние ошибки, а K – конечное состояние автомата. Теперь будем модифицировать таблицу. Символы запишем во втором столбце, а состояние, в которое переходит автомат при совпадении входного символа и символа в таблице, - в третьем. В четвертом столбце будем отмечать, возникает ли ошибка, если входной символ не совпадает с символом, записанным в таблице для данного состояния. Если в данном столбце записано «Нет», то при совпадении символов автомат переходит в следующее по порядку состояние.

Таблица 2.

Состояние Символ Переход Ошибка
10 Цифра 11 Да
11 Цифра 11 Нет
12 Любой 0 Нет

Распознаватель целого для данного примера начинается с состояния 10 (нумерация не с единицы, чтобы подчеркнуть, что данный распознаватель составляет не законченный автомат, а только его часть). Переход в состояние 0, который переходит при получении автоматом, находящимся в состоянии 12, любого символа (например, символа «конец текста») означает завершение его работы с принятием (части) входной цепочки.

Данный автомат можно применить при построении автомата, распознающего многочлен в целом. Начнем с автомата, распознающего степень. Построим таблицу переходов (табл. 3). Пусть состояния этого автомата начинаются с 20.

Таблица 3.

Состояние Символ Переход Ошибка Вызов Читать
20 ^ 22 Нет Нет Да
21 Любой 0 Нет Нет Нет
22 Любой 10 Нет Да Нет
23 Любой 0 Нет Нет Нет

В таблице добавилось два столбца. Столбец «Читать» управляет чтением следующего символа: если в этом столбце стоит «Да», то при совпадении входного символа и символа, записанного во втором столбце для данного состояния, читается следующий символ входной цепочки. Распознавание начинается, когда автомат находится в состоянии 20. Если текущим символом является «^», автомат переходит в состояние 22, считывая следующий символ. Если первый символ не равен «^», автомат переходит в состояние 21 и принимает часть входной цепочки, за которую он отвечает – запись степени в этом случае пуста.

Попав в состояние 22, автомат ожидает целое число, поэтому в данном состоянии запрограммирован переход в состояние 10. Но это не обычный переход, а переход с возвратом. По окончании распознавания целого должен произойти возврат из состояния 12 в состояние 23. Чтобы отметить особенность таких переходов, в таблицу введена графа «Вызов», в которой записывается «Да», если происходит переход с возвратом.

Значение 0 в графе «Переход» следует воспринимать, как возврат в состояние, следующее за тем, из которого произошел вызов.

 

 










Последнее изменение этой страницы: 2018-05-31; просмотров: 212.

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