- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
UNIX — универсальная среда программирования - Брайан Керниган
Шрифт:
Интервал:
Закладка:
| пока усл опер все {
($1)[1] = (Inst) $3 /* тело цикла */
($1)[2] = (Inst) $4 /* все, если условие неверно */
}
Здесь $1 обозначает адрес команды whilecode, таким образом, ($1)[1] и ($1)[2] обозначают два следующих слова.
Рисунок, приведенный ниже, может прояснить ситуацию:
С оператором if дело обстоит аналогично, но резервируются три слова: для частей then и else, а также для оператора, следующего за if. Мы вскоре рассмотрим этот случай.
Лексический анализ теперь несколько удлиняется в основном из-за необходимости распознавания дополнительных операций:
yylex() /* hoc5 */
{
...
switch (с) {
case '>': return follow('=', GE, GT);
case '<': return follow('=', LE, LT);
case '=': return follow('=', EQ, '=');
case '!': return follow('=', NE, NOT);
case '|': return follow('|', OR, '|');
case '&': return follow('&', AND, '&');
case 'n': lineno++; return 'n';
default: return c;
}
}
Функция follow "смотрит" на один символ вперед и возвращает символ назад во входной поток с помощью ungetc, если он оказался не тем, который требовался:
follow(expect, ifyes, ifno) /* look ahead for >=, etc. */
{
int с = getchar();
if (c == expect)
return ifyes;
ungetc(c, stdin);
return ifno;
}
В файле hoc.h стало больше описаний функций, например всех отношений, но в общем его структура такая же, как и в hoc4. Ниже приведено несколько последних строк грамматики:
$ cat hoc.h
...
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 ('"%.8gn", d.val);
}
Это не та функция печати, которая автоматически вызывается для вывода окончательного результата вычислений. Здесь выбирается число из стека и добавляется символ перевода строки к выходному потоку.
Теперь hoc5 представляет собой вполне полезный калькулятор, хотя для серьезного программирования необходимы дополнительные средства. В приведенных ниже упражнениях предлагаются возможные решения.
Упражнение 8.12Добавьте для отладки к hoc5 средство печати создаваемых машинных команд в понятной форме.
Упражнение 8.13Введите в свою программу операции присваивания из языка Си вида +=, *= и т.п., а также операции инкремента и декремента ++ и --. Измените операции && и || так, чтобы обеспечить вычисление слева направо и условное вычисление, как в Си программах.
Упражнение 8.14Введите в hoc5 оператор for, как в Си-программах. Добавьте операторы break и continue.
Упражнение 8.15Как бы вы изменили грамматику или лексический анализатор hoc5 (или и то, и другое), чтобы сделать программу более "терпимой" к использованию символов перевода строки? Каким образом можно ввести символ в качестве синонима символа перевода строки? Как ввести в язык примечания? Какой синтаксис, по вашему мнению, нужно использовать?
Упражнение 8.16Добавьте к hoc5 средства обработки прерываний, чтобы некорректные вычисления можно было остановить без потери значений уже вычисленных переменных.
Упражнение 8.17Неудобно создавать программный файл, запускать его на выполнение, а затем редактировать с целью внесения небольших изменений. Как бы вы изменили hoc5, чтобы создать команду редактирования, которая автоматически вызывала бы редактор с уже считанной копией вашей hoc-программы? Подсказка: изучите текст функции.
8.6 Этап 6: функции и процедуры; ввод-вывод
На последнем из описываемых здесь этапе развития программа значительно разрастается: в нее добавляются процедуры и функции, средства печати строк символов наряду с числами и чтения чисел из стандартного входного потока. Кроме того, в язык hoc6 вводятся аргументы имен файлов, включая имя "-", обозначающее стандартный входной поток. Все эти изменения увеличивают программу на 235 строк, доводя ее общий размер до 810 строк. В результате hoc преобразуется из калькулятора в интерпретатор языка программирования. Полностью программа приводится в приложении 3.
В грамматике вызовы функции определяются как выражения, а вызовы процедур как операторы. И то, и другое детально поясняется в приложении 2, где дается еще несколько примеров. Так, определение и использование процедуры печати всех чисел Фибоначчи, меньших заданного параметра, происходят следующим образом:
$ cat fib
proc fib() {
a = 0
b = 1
while (b < $1) {
print b
с = b
b = a+b
a = с
}
print "n"
}
$ hoc6 fib -
fib(1000)
1 1 2 3 5 8 13 21 34.55 89 144 233 377 610 987
...
Здесь также показано использование файлов: имя файла "-" задает стандартный входной поток.

