Вход/Регистрация
UNIX — универсальная среда программирования
вернуться

Керниган Брайан Уилсон

Шрифт:

Лексический анализатор распознает имена переменных, находит их в таблице имен и определяет, относятся ли они к переменным (

VAR
) или к встроенным функциям (
BLTIN
). Функция
yylex
возвращает один из указанных типов. Заметим, что определенные пользователем переменные и предопределенные переменные типа
PI
относятся к
VAR
.

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

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

Ниже приводится измененная часть функции

yylex
:

yylex /* hoc3 */

{

 ...

 if (isalpha(c)) {

Symbol *s;

char sbuf[100], *p = sbuf;

do {

*p++ = c;

} while ((c=getchar) != EOF && isalnum(c));

ungetc(c, stdin);

*p = '\0';

if ((s=lookup(sbuf)) == 0)

s = install(sbuf, UNDEF, 0.0);

yylval.sym = s;

return s->type == UNDEF ? VAR : s->type;

 }

 ...

В функции

main
добавлена еще одна строка, в которой вызывается процедура инициации
init
для занесения в таблицу имен встроенных и предопределенных имен типа
PI
:

main(argc, argv) /* hoc3 */

 char *argv[];

{

 int fpecatch;

 progname = argv[0];

 init;

 setjmp(begin);

 signal(SIGFPE, fpecatch);

 yyparse;

}

Теперь остался только файл

math.с
. Для некоторых стандартных математических функций требуется обработка ошибок для диагностики и восстановления, например, стандартная функция по умолчанию возвращает 0, если аргумент отрицателен. Функции из файла
math.с
используют контроль ошибок, описанный в разд. 2 справочного руководства по UNIX (см. гл. 7). Это более надежный и переносимый вариант, чем введение своих проверок, так как, вероятно, конкретные ограничения функций полнее учитываются в "официальной" программе. Файл макроопределений
<math.h>
содержит описания типов для стандартных математических функций, а файл
<errno.h>
— определения фатальных ошибок:

$ cat math.с

#include <math.h>

#include <errno.h>

extern int errno;

double errcheck;

double Log(x)

 double x;

{

 return errcheck(log(x), "log");

}

double Log10(x)

 double x;

{

 return errcheck(log10(x), "log10");

}

double Sqrt(x)

 double x;

{

 return errcheck(sqrt(x), "sqrt");

}

double Exp(x)

 double x;

{

 return errcheck(exp(x), "exp");

}

double Pow(x, y)

 double x, y;

{

 return errcheck(pow(x,y), "exponentiation");

}

double integer(x)

 double x;

{

 return (double)(long)x;

}

double errcheck(d, s) /* check result of library call */

 double d;

 char *s;

{

 if (errno == EDOM) {

errno = 0;

execerror(s, "argument out of domain");

 } else if (errno == ERANGE) {

errno = 0;

execerror(s, "result out of range");

 }

 return d;

}

Любопытная, хотя грамматически неясная, диагностики появится при запуске yacc с новой грамматикой:

$ yacc hoc.y

  • Читать дальше
  • 1
  • ...
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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