Студопедия КАТЕГОРИИ: АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
Обработка ошибок при трансляции
В рассмотренном примере обработка ошибок выполнялась с помощью процедуры 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.
Здесь E означает состояние ошибки, а K – конечное состояние автомата. Теперь будем модифицировать таблицу. Символы запишем во втором столбце, а состояние, в которое переходит автомат при совпадении входного символа и символа в таблице, - в третьем. В четвертом столбце будем отмечать, возникает ли ошибка, если входной символ не совпадает с символом, записанным в таблице для данного состояния. Если в данном столбце записано «Нет», то при совпадении символов автомат переходит в следующее по порядку состояние. Таблица 2.
Распознаватель целого для данного примера начинается с состояния 10 (нумерация не с единицы, чтобы подчеркнуть, что данный распознаватель составляет не законченный автомат, а только его часть). Переход в состояние 0, который переходит при получении автоматом, находящимся в состоянии 12, любого символа (например, символа «конец текста») означает завершение его работы с принятием (части) входной цепочки. Данный автомат можно применить при построении автомата, распознающего многочлен в целом. Начнем с автомата, распознающего степень. Построим таблицу переходов (табл. 3). Пусть состояния этого автомата начинаются с 20. Таблица 3.
В таблице добавилось два столбца. Столбец «Читать» управляет чтением следующего символа: если в этом столбце стоит «Да», то при совпадении входного символа и символа, записанного во втором столбце для данного состояния, читается следующий символ входной цепочки. Распознавание начинается, когда автомат находится в состоянии 20. Если текущим символом является «^», автомат переходит в состояние 22, считывая следующий символ. Если первый символ не равен «^», автомат переходит в состояние 21 и принимает часть входной цепочки, за которую он отвечает – запись степени в этом случае пуста. Попав в состояние 22, автомат ожидает целое число, поэтому в данном состоянии запрограммирован переход в состояние 10. Но это не обычный переход, а переход с возвратом. По окончании распознавания целого должен произойти возврат из состояния 12 в состояние 23. Чтобы отметить особенность таких переходов, в таблицу введена графа «Вызов», в которой записывается «Да», если происходит переход с возвратом. Значение 0 в графе «Переход» следует воспринимать, как возврат в состояние, следующее за тем, из которого произошел вызов.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Последнее изменение этой страницы: 2018-05-31; просмотров: 212. stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда... |