hoc2: floating point exception near line 5
...
В самом деле, для PDP-11 требуются вполне конкретные меры, чтобы обнаружить переполнение вещественного, но на большинстве других машин hoc2
действует так, как показано выше.
Упражнение 8.3
Обеспечьте возможность запоминания последнего вычисленного значения, чтобы его не приходилось вводить снова для последовательности связанных вычислений. Одним из решений может быть использование какой-либо переменной, например 'p'
, в качестве "предыдущего" (previous) значения.
Упражнение 8.4
Измените программу hoc
так, чтобы можно было использовать символ ';'
как разделитель выражений наравне с символом перевода строки.
8.3 Этап 3: переменные с произвольными именами; встроенные функции
В версию hoc3
добавлено несколько новых средств, из-за чего увеличился текст программы. Основное нововведение возможность обращения к встроенным функциям:
sin cos atan exp log log10 sqrt int abs
Введена также дополнительно операция возведения в степень '^'
(право ассоциативная с наивысшим приоритетом).
Поскольку лексический анализатор должен справляться с встроенными именами длиной более чем в один символ, не так уж много усилий придется приложить, чтобы допустить переменные с именами произвольной длины. Для хранения информации об этих переменных нужна довольно сложная таблица имен, но если мы ее создаем, то можно заранее задать в ней вместе с именами значения некоторых полезных констант:
PI |
3.14159265358979323846 |
Число π |
E |
2.71828182845904523536 |
Основание натурального логарифма |
GAMMA |
0.57721566490153286060 |
Константа Эйлера-Маскерони |
DEG |
57.2957795130823208768 |
Отношение градуса к радиану |
PHI |
1.61803398874989484820 |
Золотое сечение |
В результате получим полезный калькулятор:
$ hoc3
1.5^2.3
2.5410306
exp(2*3*log(1.5))
2.5410306
sin(PI/2)
1
atan(1)*DEG
45
Несколько улучшилась и работа распознавателя. В hoc2
присваивание x = expr
не только вызывало присваивание, но и приводило к печати значения, поскольку все выражения печатаются:
$ hoc2
x=2*3.14159
6.28318
В случае присваивания переменной значение печатается
В программе hoc3
проводится различие между присваиваниями и выражениями; значения печатаются только для выражений:
$ hoc3
x=2*3.14159
Присваивание: значение не печатается
x
Выражение:
6.28318
Значение печатается
Получившаяся в результате всех этих изменений программа настолько велика (около 250 строк текста), что для простоты редактирования и ускорения компиляции лучше разбить ее на отдельные файлы. Итак, теперь мы имеем пять файлов вместо одного:
hoc.y |
грамматика, main , yylex (как и прежде); |
hoc.h |
глобальные структуры данных для включения в другие файлы; |
symbol.c |
функции, работающие с таблицей имен: lookup , install ; |
unit.c |
встроенные функции и константы; init ; |
math.c |
функции для вызова стандартных математических функций: Sqrt , Log и т.д. |
Необходимо более детально познакомиться с работой Си программы, состоящей из нескольких файлов, и программы make
, чтобы переложить на нее часть своих обязанностей.
Вернемся снова к программе make
и рассмотрим вначале структуру таблицы имен. Поименованный объект имеет имя, тип ( VAR
или BLTIN
) и значение. Так, объект типа VAR
имеет значение double
; если объект является встроенным, то его значением служит указатель на функцию, возвращающую double
. Данная информация используется в hoc.y
, symbol.c
и init.c
. Ее можно размножить в трех экземплярах, но тогда легко ошибиться или забыть исправить один из экземпляров при внесении изменений. Вместо этого мы поместили общую информацию в файл макроопределений hoc.h
, который можно включить при необходимости в любой файл. (Окончание .h
традиционно, но не контролируется никакими программами.) В файл makefile
также добавлены сведения о зависимости исходных файлов от hoc.h
, чтобы при изменении hoc.h
была проведена требуемая перекомпиляция.
$ cat hoc.h
typedef struct Symbol { /* symbol table entry */
char *name;
short type; /* VAR, BLTIN, UNDEF */
Читать дальше
Конец ознакомительного отрывка
Купить книгу