Языки программирования и трансляторы.Обработка синтаксических ошибок. Восстановление

Страницы работы

6 страниц (Word-файл)

Фрагмент текста работы

внимание лишь то, что в данном месте объявляется некоторая функция) и попытаться проанализировать ее тело.

Кратко стратегию восстановления после ошибок можно описать следующим образом. Необходимо выделить некоторые блоки, которые легко отделяются друг от друга (например, специальным разделителем или группой разделителей). Если при анализе встречается ошибка внутри одного такого блока, необходимо пропустить все лексемы до разделителя, после чего просто начать анализ нового блока. Выбор таких блоков необходимо осуществлять отдельно для каждого языка. Например, для C++ это могут быть операторы и объявления (т.е. при обнаружении ошибки в операторе или объявлении пропускаются все лексемы до точки с запятой и начинается анализ новой конструкции).

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

Подобные вещи очень сложно формализовать и такая работа требует очень больших трудозатрат. Как правило, такие подробные описания требуются для промышленных компиляторов.

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

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


Практическая часть

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

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

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

Для обработки ошибок используем функцию handle_error, которая реализует данные эвристические правила:

void syntax_analyzer::handle_error(FILE *in){ //обработать ошибку

int type,b,c,i;

if(stack[0]!=0) //если стек не пуст, пропускаем текущий рассматриваемый нетерминал

{

state=stack[0]; //переходим к состоянию из стека

for(i=0;stack[i]!=0;i++)stack[i]=stack[i+1]; //обновляем стек

}

else

{

state=42; //выбрано исходя из специфики грамматики

}

if(strcmp(lexem,";\0")!=0)fscanf(in,"%d %d %d %s",&type,&b,&c,lexem

Информация о работе