Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Теория языков программирования методов трансляции.-1.pdf
Скачиваний:
13
Добавлен:
05.02.2023
Размер:
1.36 Mб
Скачать

228

Ошибка в виде пропуска или неправильного употребления, допущенная на более раннем этапе, может проявиться совсем в другом месте программы. Это можно проиллюстрировать следующим примером.

while x>y ; begin something end.

Никакого сообщения об ошибке при встрече «;» на данной стадии синтаксический анализатор не выдаст. Последствия ее могут появиться на более поздней фазе анализа.

Сообщив о синтаксической ошибке, анализатор в большинстве случаев постарается продолжить разбор. Для этого ему понадобится исключить какие-либо символы, включить какие-либо символы или изменить их. Существует ряд стратегий исправления ошибок. Практически все они хорошо срабатывают в одних случаях и плохо – в других. «Хорошая» стратегия заключается в том, чтобы обнаружить как

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

от знания исходного языка и от того, как он употребляется.

11.5. Методы исправления синтаксических ошибок

Режим переполоха

Один их наиболее распространенных методов исправления синтаксических ошибок носит названиережим переполоха. При появлении недопустимого символа весь последующий исходный текст, вплоть до соответствующего ограничителя (например «;» или end), игнорируется. Ограничитель заканчивает какую-то конструкцию языка, и элементы удаляются из стека разбора до тех пор, пока не встретится адрес возврата. Этот элемент тоже удаляется из стека, а разбор продолжается, начиная с адреса в таблице разбора, содержащего следующий входной символ. Такой метод довольно легко реализуется, но имеет серьезный недостаток: длинные последовательности кода, соответствующие игнорируемым символам, не анализируются.

Исключение символов

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

c := d+3; end,

229

где «;» является недопустимой, исправление ошибки – идеальное. Однако исключение скобок обычно разрушает блочную структуру и приводит к дальнейшим синтаксическим ошибкам.

Включение символов

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

равдано исправление программ путем подстановки одного из таких символов перед недопустимым символом, который вызвал ошибку. Например, последовательность

end begin

никогда не будет допустимой. Однако включение «;» между end begin позволит анализатору продолжить работу.

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

Правила для ошибок

Одним из способов исправления некоторых типов синтаксических ошибок заключается в расширении синтаксиса языка за счет включения в него программ, содержащих типичные ошибки. Это не значит, что ошибки пройдут незамеченными, так как в грамматику могут быть включены сообщения о них. Но анализатор не будет считать такой вход недопустимым и не потребует никаких исправлений. Так можно обращаться, например, с ошибками типа«;» перед end или пропуск «;». Дополнительные правила, включенные в грамматику, обычно называются правилами для ошибок. Они неизбежно приводят к увеличению грамматики, и поэтому включать их следует только для наиболее часто встречающихся ошибок программирования. При этом надо следить за тем, чтобы при включении этих правил грамматика не стала неоднозначной.

11.6. Предупреждения

Наряду с сообщениями о синтаксических ошибках анализатор может выдавать предупреждения, когда ему встретилась допустимая, но маловероятная последовательность символов, например

; do

Еще чаще такие ситуации возникают, когда в таблице идентификаторов содержится переменная, но ссылки в программе на нее нет. Для

230

выдачи сообщений о таких ситуациях в грамматику вводятся действия, идентифицирующие их.

11.7. Сообщения о синтаксических ошибках

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

SYNTAX ERROR IN LINE 22.

Или местоположение ошибки может описываться полнее

LINE 22 SYMBOL 4.

В любом случае пользователь может быть недоволен тем, что сообщение не вполне ясное, так как не указывается, в чем заключается ошибка программиста. На практике фактическая ошибка программирования могла произойти гораздо раньше, анализатор же сообщает об ошибке только тогда, когда ему встречается недопустимый символ. Если программист представляет анализатору программу, имеющую синтаксическую ошибку, компилятор, естественно, не сможет решить, какую программу программист должен был написать. Единственное, что компилятор смог бы сделать, это принять решение о «ремонте» на минимальном расстоянии, т.е. о ремонте, требующем минимальное число включений символов в текст программы и исключений из него, дающем синтаксически правильную программу. Цель ремонта – обеспечить анализатору условия для продолжения анализа программы.

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

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

231

была допущена, он может исправить программу для последующих проходов.

Для исправления программы (но не ремонта) необходимо знать истинные намерения программиста. В общем случае это невозможно, однако для КС-языков многие типы ошибок можно локализовать достаточно точно.

11.8. Контекстно-зависимые ошибки

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

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

IDENTIFIER xyz NOT DECLARED TYPE NOT COMPATIBLE ASSIGNMENT

Так как сам анализатор ошибку не обнаружил, никакого исправления не требуется. Однако, если не принять соответствующие меры, то одна ошибка может повлечь за собой лавину сообщений об ошибках. Во избежание этого при первом же появлении неописанного идентификатора он должен включаться в таблицу символов. В таблицу также должен помещаться тип, соответствующий неописанному идентификатору. Компилятор в этом случае обладает недостаточной информацией, чтобы решить какой тип идентификатора предполагается, поэтому многие компиляторы принимают стандартный типint или real. Лучше всего иметь для этого специальный типsptype, который будет ассоциироваться с такими идентификаторами; sptype обладает следующими свойствами:

1)его можно приводит к любому типу/виду;

2)если значение типа sptype оказывается операндом, знак операции идентифицируется с помощью другого операнда, причем любая неоднозначность разрешается произвольно;

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