UNIX — универсальная среда программирования
Шрифт:
Упражнение 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 */
union {
double val; /* if VAR */
double (*ptr); /* if BLTIN */
} u;
struct Symbol *next; /* to link to another */
} Symbol;
Symbol *install, *lookup;
$
Тип
UNDEF
обозначает VAR
, которой пока не присвоили значения. Объекты связаны в список с помощью элемента next
в записи Symbol
. Сам список является локальным для symbol.c
, доступ к нему возможен только посредством функций lookup
и install
. Это позволяет в случае необходимости легко менять структуру таблицы имен (что мы уже сделали однажды). Функция lookup
отыскивает в списке заданное имя и возвращает указатель на Symbol
, если имя найдено, и 0 в противном случае. Таблица имен рассчитана на линейный поиск, что вполне допустимо для диалогового калькулятора, поскольку поиск имен выполняется не во время его работы, а в процессе разбора. Функция install
вносит переменную и связанные с ней тип и значение в начало списка. Функция emalloc
обращается к стандартной функции размещения malloc
(см. справочное руководство по malloc(3)
) и проверяет результат. Указанные три функции составляют содержимое файла symbol.c
. Файл y.tab.h
создается при выполнении команды yacc -d
; он содержит операторы #define
, порождаемые yacc
для лексем NUMBER
, VAR
, BLTIN
и т.д.
$ cat symbol.c
#include "hoc.h"
#include "y.tab.h"
static Symbol *symlist = 0; /* symbol table: linked list */
Symbol *lookup(s) /* find s in symbol table */
char *s;
{
Symbol *sp;
for (sp = symlist; sp != (Symbol*)0; sp = sp->next)
if (strcmp(sp->name, s) == 0)
Поделиться:
Популярные книги
Свадьба по приказу, или Моя непокорная княжна
Любовные романы:
любовно-фантастические романы
5.57
рейтинг книги
Сборник коротких эротических рассказов
Любовные романы:
эро литература
love action
7.25
рейтинг книги
Отец моего жениха
Любовные романы:
современные любовные романы
7.79
рейтинг книги
Вадбольский
1. Вадбольский
Фантастика:
попаданцы
5.00
рейтинг книги
Бастард Императора. Том 7
7. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Повелитель механического легиона. Том VIII
8. Повелитель механического легиона
Фантастика:
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
В зоне особого внимания
12. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Таня Гроттер и магический контрабас
1. Таня Гроттер
Фантастика:
фэнтези
8.52
рейтинг книги
Бастард Императора. Том 2
2. Бастард Императора
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга ХI
11. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Третий
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Возвышение Меркурия. Книга 16
16. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 9
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Потусторонний. Книга 1
1. Господин Артемьев
Фантастика:
фэнтези
попаданцы
5.00