- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания UNIX — универсальная среда программирования - Брайан Керниган
Шрифт:
Интервал:
Закладка:
Поскольку теперь программа hoc3 размещается не в одном, а в пяти файлах, makefile становится более сложным:
$ cat makefile
YFLAGS = -d # force creation of y.tab.h
OBJS = hoc.o init.o math.o symbol.o # abbreviation
hoc3: $(OBJS)
cc $(OBJS) -lm -o hoc3
hoc.o: hoc.h
init.o symbol.o: hoc.h y.tab.h
pr:
@pr hoc.y hoc.h init.c math.c symbol.c makefile
clean:
rm -f $(OBJS) y.tab.[ch]
$
Строка YFLAGS = -d добавляет флаг -d в командную строку запуска yacc, создаваемую make. Этот флаг предписывает yacc создать файл y.tab.h, содержащий операторы #define. Строка OBJS = ... вводит сокращение для записи конструкции, используемой последовательно несколько раз. Синтаксис здесь не такой, как для переменных интерпретатора, скобки обязательны. Флаг -lm указывает, что математические функции нужно искать в библиотеке libm.a.
Теперь программа hoc3 образуется из четырех файлов .о, причем некоторые из них в свою очередь зависят от файлов .h. "Зная" эти зависимости, make может рассчитать, какая требуется перетрансляция в случае изменения любого из указанных файлов. Если вы хотите выяснить действия make, не запуская процесс, то попробуйте ввести команду
$ make -n
С другой стороны, если необходимо установить временную согласованность файлов, с помощью флага -t (touch исправить) вы можете как бы модифицировать файлы, не производя перетрансляции.
Обратите внимание на то, что мы ввели не только множество зависимостей между исходными файлами, но и несколько полезных процедур, сконцентрировав их в одном файле. По умолчанию программа make выполняет первое действие, указанное в файле makefile. Однако если на первом месте окажется элемент, помечающий правило зависимости, такой, как symbol.o или pr, то выполняться будет он. Считается, что в случае "пустой" зависимости элемент всегда берется не из последней версии, поэтому при запросе он обязательно должен изменяться. Итак,
$ make pr | lpr
инициирует распечатку зависимостей файлов на принтере. (Появление символа @ в "@pr" подавляет эхо выполняемой команды, запущенной с помощью make.) Команда же
make clean
удаляет выходные файлы yacc, а также файлы .o.
Такой механизм пустых зависимостей в файле makefile часто оказывается более предпочтительным по сравнению с командным файлом как средство для концентрации в одном файле всех связанных операций. Область применения команды make не ограничивается только разработкой программ, она позволяет сгруппировать в единый набор все операции, имеющие временные зависимости.
Несколько замечаний относительно lexПрограмма lex порождает лексические анализаторы аналогично тому, как yacc генерирует программы грамматического разбора: вы создаете описание лексических правил вашего языка с помощью регулярных выражений и фрагментов Си программ, которые будут выполняться при обнаружении строки, соответствующей шаблону. Программа lex строит по этой информации распознаватель. Программы lex и yacc взаимодействуют таким же образом, как и описанные выше лексические анализаторы. Мы не собираемся здесь детально рассматривать lex; наша цель — заинтересовать вас, а подробности вы найдете в справочном руководстве по UNIX (том 2B).
Вначале приведем lex-программу из файла lex.l, которая заменяет применявшуюся до сих пор функцию yylex:
$ cat lex.l
%{
#include "hoc.h"
#include "y.tab.h"
extern int lineno;
%}
%%
[ t] { ; } /* skip blanks and tabs */
[0-9]+.?][0-9]*.[0-9]+ {
sscanf(yytext, "%lf", &yylval.val);
return NUMBER;
}
[a-zA-Z][a-zA-Z0-9]* {
Symbol *s;
if ((s=lookup(yytext)) == 0)
s = install(yytext, UNDEF, 0.0);
yylval.sym = s;
return s->type == UNDEF ? VAR : s->type;
}
n { lineno++; return 'n'; }
/* everything else */
. { return yytext[0]; }
$
Каждое "правило" является регулярным выражением, как и те, что использовались в egrep или awk, однако в отличие от них lex распознает комбинации в стиле Си типа t и n. Действие заключено в фигурные скобки. Правила проверяются по порядку, а конструкции с символами * и + задают сколь угодно длинную строку. Если правило применимо к текущей части входного потока, то выполняется действие. Совпавшая с правилом входная строка доступна в lex-программе под именем yytext. Чтобы работать в lex, нужно изменить файл makefile: Программа make
$ cat makefile
YFLAGS = -d
OBJS = hoc.o lex.o init.o math.o symbol.o
hoc3: $(OBJS)
cc $(OBJS) -lm -ll -o hoc3
hoc.o: hoc.h
lex.o init.o symbol.o: hoc.h y.tab.h
...
$
"знает", как получить из файла .l настоящий файл .o; все, что требуется от нас, дать ей сведения о зависимостях. (Нужно добавить библиотеку lex -ll к списку каталогов, в которых ведет поиск команда сс, поскольку распознаватель, создаваемый lex, нуждается в дополнительных функциях.) Эффект получается весьма ощутимым, причем совершенно автоматически:
$ make
yacc -d hoc.y
conflicts: 1 shift/reduce
сс -с y.tab.c
rm y.tab.c
mv y.tab.o hoc.o
lex lex.l
сс -с lex.yy.c
rm lex.yy.c
mv lex.yy.o lex.o
сс -c init.c
сс -c math.c
сс -c symbol.c
cc hoc.o lex.o init.o math.o symbol.o -lm -ll -o hoc3
$
Если один файл изменится, достаточно единственной команды make для получения действующей версии:
$ touch lex.l Смена времени модификации файла lex.l
$ make
lex lex.l
cc -с lex.yy.c
rm lex.yy.c
mv lex.yy.o lex.o
cc hoc.o lex.o init.o math.o symbol.o -ll -lm -o hoc3
$
Некоторое время мы дебатировали о том, следует ли считать обсуждение программы lex отступлением от нашей темы и поэтому показать ее кратко, а затем перейти к другим вопросам или рассматривать ее как основное средство для лексического анализа, когда язык становится слишком сложным. У нас были аргументы "за" и "против". Затруднения в работе с lex (помимо того, что пользователь должен изучить еще один язык) связаны с тем, что замедляется выполнение программы, а распознаватели оказываются более объемными и медленными, чем эквивалентные версии на языке Си. К тому же возникают трудности с механизмом ввода в некоторых особых случаях, таких, как восстановление после ошибки, а также с вводом из файла. Ни одна из перечисленных проблем не является существенной для hoc. К сожалению, из-за ограниченного объема книги мы вынуждены вернуться в последующих лексических анализаторах к Си. Однако создание версии с lex будет для вас хорошей практикой.
Упражнение 8.9Сравните размеры двух версий hoc3. Подсказка: обратитесь к справочному руководству по size(1).
8.4 Этап 4: компиляция на машину
Мы постепенно приближаемся к созданию hoc5 — интерпретатора языка со структурами управления. Программа hoc4 является промежуточным звеном: она имеет те же операции, что и hoc3, но реализуется на базе интерпретатора, как hoc5. Мы действительно написали такую программу hoc4 и в результате получили две программы с одинаковыми возможностями, что ценно для отладки. По мере разбора входного потока hoc4 порождает код, рассчитанный на простую машину, а не выдает сразу результат. При определении конца оператора будет выполнен код, порожденный для вычисления нужного результата (т.е. произойдет "интерпретация").
Под простой машиной здесь подразумевается стековая машина: когда появляется операнд, он заносится в стек, точнее, создаются команды, заносящие операнд в стек). Большинство операций над операндами выполняется в вершине стека. Например, при обработке присваивания
x=2*y
создаются следующие команды:
constpush Записать в стек: константа … константа2
2
varpush Записать указатель на таблицу имен в стек
y … для переменной у
eval Вычислить: заменить указатель значением
mul Перемножить два верхних элемента; результат заменяет их
varpush Записать указатель на таблицу имен в стек
x … для переменной x
assign Записать значение в переменную, убрать указатель