Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
LoSWS_L_07_Error_Restore.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
138.24 Кб
Скачать

Корректировка грамматики

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

Рассмотрим анализ составного оператора begin . . . end

----------┐

>--- begin ---│ operator │-┬------------------------┬--- end >

----------┘ ^ │

│ │

│┌----------┐ │

└│ operator │< semicolon ┘

----------┘

if sym = begin

then

begin

getsym;

operator;

while sym = semicolon do

begin

getsym;

operator

end;

if sym = end

then getsym

else error(17)

end

else обработка другого оператора

Если будет пропущена точка с запятой между операторами, то анализатор будет проверять наличие терминального символа end и в его отсутствии выдавать ошибку с кодом 17 - "Требуется точка с запятой или end"

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

Сначала проверяется может ли входная последовательность быть оператором, путем обращения к процедуре operator. Для нормального окончания процедуры, ей передается множество внешних символов – [semicolon, end] и множество символов возобновления fsys = [point] + declbegsys + ststbegsys , передаваемых и дополняемых транзитом от самой внешней процедуры. Здесь для групп символов даны следующие названия:

declbegsys = [const, var]

statbegsys = [begin, if, while]

facbegsys = [id, number, lparent]

Далее необходимо проверить нет ли символа "точки с запятой". Но в данном случае список символов, указывающий, что составной блок еще не закончен, расширен. В этот список включены ключевые слова – begin, if, while. Таким образом программа как бы «вставляет» пропущенные точки с запятой перед ключевыми словами. Множество, называемое statbegsys, есть множество начальных символов конструкции «оператор».

if sym = begin

then

begin

getsym;

operator([semicolon, end] + fsys);

while sym in [semicolon]+ statbegsys do

begin

if sym = semicolon

then getsym

else error(10);

operator([semicolon, end] + fsys)

end;

if sym = end

then getsym

else error(17)

end

else обработка другого оператора

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

----------┐

>--- begin ---│ operator │-┬------------------------┬--> end -

----------┘ ^

│ │

│┌----------┐ │

└│ operator< semicolon

----------┘<-----------┘

О том, насколько успешно эта программа обнаруживает синтаксические ошибки и справляется с необычными ситуа­циями, можно судить по программе ПЛ/0 (5.20). Ее распе­чатка является результатом работы программы 5.5, а в табл. 5.3 перечислены возможные сообщения об ошибках, со­ответствующие номерам ошибок в программе 5.5.

Таблица 5.3. Сообщения об ошибках, выдаваемые транслятором с ПЛ/0

1. = вместо :=

2. Нет числа после =

3. Нет = после идентификатора

4. Нет идентификатора после const. var, procedure

5. Пропущена запятая или точка с запятой

6. Неверный символ после описания процедуры

7. Нет оператора

8. Неверный символ после операторной части блока

9. Нет многоточия

10. Пропущена точка с запятой между операторами

11. Неописанный идентификатор

12. Недопустимое присваивание константе или процедуре.

13. Требуется :=

14. Нет идентификатора после call

15. Вызов константы или переменной вместо процедуры

16. Требуется then

17. Требуется точка с запятой или end

18. Требуется do

19. Неверный символ после оператора

20. Требуется сравнение

21. Выражение содержит идентификатор процедуры

22. Отсутствует правая скобка

23. Неверный символ после множителя

24. Неверный символ в начале выражения

30. Слишком большое число

Все же ясно, что никакая схема, которая достаточно эф­фективно транслирует правильные предложения, не сможет так же эффективно справляться со всеми возможными не­правильными конструкциями. Да и как может быть иначе!

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

1. Никакая входная последовательность не должна приводить к катастрофе.

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

3. Ошибки, встречающиеся довольно часто и действительно являющиеся ошибками программиста (вызванными недо­смотром или недопониманием), должны правильно диагно­стироваться и не вызывать каких-либо дальнейших откло­нений в работе транслятора — сообщений о так называе­мых наведенных ошибках.

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

Синтаксис языка

<program> ::= <block> point

<block> ::= <declare> <operator>

<block> ::= <operator>

<declare> ::= <declare> semicolon <dcl_const>

<declare> ::= <declare> semicolon <dcl_var>

<declare> ::= <dcl_const> semicolon

<declare> ::= <dcl_var> semicolon

<dcl_const> ::= const <list_const>

<list_const> ::= <list_const> comma id equal number

<list_const> ::= id equal number

<dcl_var> ::= var <list_var>

<list_var> ::= <list_var> comma id

<list_var> ::= id

<operator> ::= id become <expr>

<operator> ::= if log_expr then <operator>

<operator> ::= while log_expr do <operator>

<operator> ::= begin <list_oper> end

<list_oper> ::= <list_oper> semicolon <operator>

<list_oper> ::= <operator>

<log_expr> ::= <expr> rel <expr>

<expr> ::= <expr> plus <add>

<expr> ::= <expr> minus <add>

<expr> ::= <add>

<add> ::= <add> mult <factor>

<add> ::= <add> div < factor>

<add> ::= <factor>

<factor> ::= id

<factor> ::= lparent <expr> rparent

Таблица 5.2. 1 Начальные и внешние символы в ПЛ/0

.

Нетерминальный символ S

Начальные символы L(S)

Внешние символы F(S)

blok

Блок

const var id if begin while

point

Оператор

id call begin if while

point semicolon end

log_expr

Условие

lparent id number

then do

expr

Выражение

lparent id number

point. semicolon rparent rel end then do

add

Слагаемое

lparent id number

point. semicolon rparent rel end then do

factor

Множитель

id number lparent

semicolon rparent rel plus minus mult div

end then do

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]