Вход/Регистрация
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;

 }

...

  • Читать дальше
  • 1
  • ...
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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