Чтение онлайн

на главную - закладки

Жанры

UNIX — универсальная среда программирования
Шрифт:

 | VAR '=' expr { $$ = mem[$1] = $3; }

 | expr '+' expr { $$ = $1 + $3; }

 | expr '-' expr { $$ = $1 - $3; }

 | expr '*' expr { $$ = $1 * $3; }

 | expr '/' expr {

if ($3 == 0.0)

execerror("division by zero", "");

$$ = $1 / $3;

 }

 | '(' expr ')' { $$ = $2; }

 | '-' expr %prec UNARYMINUS { $$ = -$2; }

 ;

%%

/* end of grammar */

...

Из описания

%union
следует, что элементы стека содержат или число с двойной точностью (обычный случай), или целое, являющееся индексом в массиве
mem
. В описании
%token
дополнительно указывается тип значения. В описании
%type
есть сведения о том, что выраж является элементом объединения
<val>
, т.е.
double
. Информация о типе позволяет
yacc
обращаться к нужному элементу объединения. Обратите внимание:
"="
представляет собой правоассоциативную операцию, тогда как другие операции — левоассоциативные.

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

execerror
. Второй этап заключается в перехвате сигнала "переполнение вещественного" ("floating point exception"), который возникает при переполнении вещественного числа. Сигнал устанавливается в функции
main
. Последний шаг восстановления после ошибки заключается в добавлении к грамматике правила вывода для ошибки. В грамматике
yacc
слово
error
зарезервировано; оно дает возможность анализатору осознать синтаксическую ошибку и восстановиться после нее. Если произойдет ошибка,
yacc
в конце концов использует это правило, распознает ошибку как грамматически "правильную" конструкцию и, таким образом, восстановится. Действие
yyerrok
заключается в установке признака в анализаторе, который позволяет вернуться ему назад в состояние осмысленного разбора. Восстановление после ошибки сложная проблема для всех анализаторов. Мы показали вам здесь лишь самые элементарные приемы и только обозначили возможности
yacc
.

В грамматике

hoс2
произошли незначительные изменения. Ниже приведена функция
main
, дополненная обращением к
setjmp
. Оно позволяет запомнить то нормальное состояние, которое будет использовано при восстановлении после ошибки. В функции
execerror
происходит соответствующее обращение к
longjmp
. (Описание
setjmp
и
longjmp
см. в разд. 7.5.)

...

#include <stdio.h>

#include <ctype.h>

char *progname;

int lineno = 1;

#include <signal.h>

#include <setjmp.h>

jmp_buf begin;

main(argc, argv) /* hoc2 */

 char *argv[];

{

 int fpecatch;

 progname = argv[0];

 setjmp(begin);

 signal(SIGFPE, fpecatch);

 yyparse;

}

execerror(s, t) /* recover from run-time error */

 char *s, *t;

{

 warning(s, t);

 longjmp(begin, 0);

}

fpecatch /* catch floating point exceptions */

{

 execerror("floating point exception", (char*)0);

}

В целях отладки мы сочли удобным, чтобы функция

execerror
вызывала
abort
(см. справочное руководство по
abort(3)
), что приведет к распечатке содержимого памяти, которую затем смогут использовать программы
adb
и
sdb
. Когда разработка программы полностью завершится, обращение к
abort
будет заменено на
longjmp
.

В программе

hoc2
лексический анализатор несколько иной. В нем учтено различие строчных и прописных букв, а поскольку теперь
yyval
является объединением, нужно выбрать подходящий элемент перед выходом из
yylex
. Ниже показаны измененные фрагменты:

yylex /* hoc2 */

{

 ...

 if (с == '.' || isdigit(c)) { /* number */

ungetc(c, stdin);

scanf("%lf", &yylval.val);

return NUMBER;

 }

 if (islower(c)) {

yylval.index = с - 'a'; /* ASCII only */

return VAR;

 }

...

Еще раз отметим, что тип лексемы (т.е.

NUMBER
) не совпадает с ее значением (например, 3.1416).

Продемонстрируем новые возможности

hoc2
переменные и способность восстановления после ошибки:

$ hoc2

x = 355

355

y = 113

113

p = x/z
z не определено, а значит, равно 0

hoc2: division by zero near line 4
Восстановление после ошибки

x/y

3.1415929

1е30 * 1е30
Переполнение

hoc2: floating point exception near line 5

...

В самом деле, для PDP-11 требуются вполне конкретные меры, чтобы обнаружить переполнение вещественного, но на большинстве других машин

hoc2
действует так, как показано выше.

Упражнение 8.3

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

'p'
, в качестве "предыдущего" (previous) значения.

Поделиться:
Популярные книги

Я все еще барон

Дрейк Сириус
4. Дорогой барон!
Фантастика:
боевая фантастика
5.00
рейтинг книги
Я все еще барон

Кодекс Охотника. Книга XXXIX

Сапфир Олег
39. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
боевая фантастика
5.00
рейтинг книги
Кодекс Охотника. Книга XXXIX

Убивая маску

Метельский Николай Александрович
13. Унесенный ветром
Фантастика:
боевая фантастика
5.75
рейтинг книги
Убивая маску

Младший сын

Балашов Дмитрий Михайлович
1. Государи московские
Научно-образовательная:
история
8.50
рейтинг книги
Младший сын

Вино грез

Дик Филип Киндред
Фантастика:
научная фантастика
6.25
рейтинг книги
Вино грез

Защитник

Кораблев Родион
11. Другая сторона
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Защитник

Дважды одаренный. Том II

Тарс Элиан
2. Дважды одаренный
Фантастика:
городское фэнтези
альтернативная история
аниме
5.25
рейтинг книги
Дважды одаренный. Том II

Диверсант

Вайс Александр
2. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
Диверсант

Облава на волка

Серегин Михаил Георгиевич
Детективы:
боевики
5.00
рейтинг книги
Облава на волка

Ваше Сиятельство

Моури Эрли
1. Ваше Сиятельство
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Ваше Сиятельство

Книга драконов

Страуд Джонатан
Фантастика:
фэнтези
героическая фантастика
юмористическая фантастика
7.50
рейтинг книги
Книга драконов

Ермак. Регент

Валериев Игорь
10. Ермак
Фантастика:
попаданцы
альтернативная история
4.75
рейтинг книги
Ермак. Регент

Лекарь Империи 3

Карелин Сергей Витальевич
3. Лекарь Империи
Фантастика:
городское фэнтези
аниме
дорама
фэнтези
попаданцы
5.00
рейтинг книги
Лекарь Империи 3

Изгнанник Ардена

Анри Софи
Фантастика:
фэнтези
готический роман
историческое фэнтези
5.00
рейтинг книги
Изгнанник Ардена