UNIX — универсальная среда программирования
Шрифт:
typedef int (*Inst); /* machine instruction */
#define STOP (Inst)0
extern Inst prog[], *progp, *code;
extern eval, add, sub, mul, div, negate, power;
extern assign, bltin, varpush, constpush, print;
extern prexpr;
extern gt, lt, eq, ge, le, ne, and, or, not;
extern ifcode, whilecode;
$
Большая часть файла
code.c
также не изменилась, хотя, очевидно, здесь появилось много новых процедур для обработки операций
le
("less than equal to" меньше или равно).
le {
Datum d1, d2;
d2 = pop;
d1 = pop;
d1.val = (double)(d1.val <= d2.val);
push(d1);
}
He совсем тривиальными являются функции
whilecode
и ifcode
. Чтобы понять их, необходимо уяснить, что функция execute
последовательно обрабатывает команды до тех пор, пока не будет найдена команда STOP
, после чего происходит возврат из execute
. Процесс разбора построен таким образом, что команда STOP
завершает каждую последовательность команд, которую нужно обработать за одно обращение к execute
. Тело цикла while
, а также условие и фрагменты оператора if
после then
и else
обрабатываются с помощью рекурсивных обращений к execute
, возврат из которых по завершении обработки осуществляется в функцию execute
на один уровень вложенности выше. Управление этими рекурсивными обращениями обеспечивается в whilecode
и ifcode
. Последние и предназначены для обработки соответствующих операторов.
whilecode {
Datum d;
Inst *savepc = pc; /* loop body */
execute(savepc+2); /* condition */
d = pop;
while (d.val) {
execute(*((Inst **)(savepc))); /* body */
execute(savepc+2);
d = pop;
}
pc = *((Inst **)(savepc+1)); /* next statement */
}
Как уже отмечалось ранее, после операции
whilecode
размещается указатель на тело цикла, затем указатель на следующий оператор, а за ним команды условия. Когда вызывается whilecode
, значение указателя pc
уже увеличено, так что он содержит указатель на тело цикла. Таким образом, pc+1
настроен на следующий оператор, а pc+2
на команды условия. Функция
ifcode
аналогична предыдущей: при входе в нее pc
ссылается на фрагмент посте then
, pc+1
на фрагмент посте else
, pc+2
на следующий оператор, а pc+3
на условие.
ifcode
{
Datum d;
Inst *savepc = pc; /* then part */
execute(savepc+3); /* condition */
d = pop;
if (d.val)
execute(*((Inst **)(savepc)));
else if (*((Inst **)(savepc+1))) /* else part? */
execute(*((Inst **)(savepc+1)));
pc = *((Inst**)(savepc+2)); /* next stmt */
}
Программа
init.c
также немного увеличится за счет введения в нее таблицы ключевых слов, хранимых в таблице имен вместе с остальной информацией:
$ cat init.с
...
static struct { /* Keywords */
char *name;
int kval;
} keywords [] = {
"if", IF,
"else", ELSE,
"while", WHILE,
"print", PRINT,
0, 0,
};
...
Для занесения в таблицу имен ключевых слов нужно организовать еще один цикл в функции
init
:
...
for (i = 0; keywords[i].name; i++)
install(keywords[i].name, keywords[i].kval, 0.0);
...
Изменения в функциях, управляющих таблицей имен, не требуются; в файле
code.c
есть функция prexpr
, которая вызывается при выполнении оператора вида print
выраж.
prexpr /* print numeric value */
{
Datum d;
d = pop;
printf ('"%.8g\n", d.val);
}
Это не та функция печати, которая автоматически вызывается для вывода окончательного результата вычислений. Здесь выбирается число из стека и добавляется символ перевода строки к выходному потоку.
Теперь
hoc5
представляет собой вполне полезный калькулятор, хотя для серьезного программирования необходимы дополнительные средства. В приведенных ниже упражнениях предлагаются возможные решения. Упражнение 8.12
Добавьте для отладки к
hoc5
средство печати создаваемых машинных команд в понятной форме. Упражнение 8.13
Введите в свою программу операции присваивания из языка Си вида
+=
, *=
и т.п., а также операции инкремента и декремента ++
и – -
. Измените операции &&
и ||
так, чтобы обеспечить вычисление слева направо и условное вычисление, как в Си программах. Упражнение 8.14
Введите в
hoc5
оператор for
, как в Си-программах. Добавьте операторы break
и continue
. Упражнение 8.15
Как бы вы изменили грамматику или лексический анализатор
hoc5
(или и то, и другое), чтобы сделать программу более "терпимой" к использованию символов перевода строки? Каким образом можно ввести символ в качестве синонима символа перевода строки? Как ввести в язык примечания? Какой синтаксис, по вашему мнению, нужно использовать?
Поделиться:
Популярные книги
Отмороженный 8.0
8. Отмороженный
Фантастика:
постапокалипсис
рпг
аниме
5.00
рейтинг книги
Газлайтер. Том 14
14. История Телепата
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Ермак. Телохранитель
2. Ермак
Фантастика:
альтернативная история
7.00
рейтинг книги
Матабар IV
4. Матабар
Фантастика:
фэнтези
5.00
рейтинг книги
Сборник коротких эротических рассказов
Любовные романы:
эро литература
love action
7.25
рейтинг книги
Идеальный мир для Лекаря 19
19. Лекарь
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Дочь моего друга
2. Айдаровы
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Свет Черной Звезды
6. Катриона
Любовные романы:
любовно-фантастические романы
5.50
рейтинг книги
Кодекс Крови. Книга IV
4. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 22
22. Лекарь
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Попаданка в академии драконов 4
4. Попаданка в академии драконов
Любовные романы:
любовно-фантастические романы
7.47
рейтинг книги
Сердце Дракона. Том 12
12. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.29
рейтинг книги
Лолита
Проза:
классическая проза
современная проза
8.05
рейтинг книги
Сводный гад
2. Самбисты
Любовные романы:
современные любовные романы
эро литература
5.00