Выбрать главу

Интуитивное понимание подобное описанному может быть необыкновенно действенным. Рассматриваемый код был написан в течение приблизительно 90 минут, был работоспособен при первом запуске и с тех пор в течение многих лет оставался стабильным (единственный сбой произошел при обработке исключительной ситуации в присутствии действительного перекоса версий). Данный код содержит менее 40 строк и великолепно прост. Не существует способа, при котором примитивный подход полного создания второго синтаксического анализатора мог бы привести к созданию такого же удобства сопровождения, такой же надежности или компактности. Повторное использование кода, упрощение, обобщение, ортогональность — Дзэн операционной системы Unix в действии.

В главе 10 рассматривается синтаксис файла конфигурации fetchmail в качестве примера стандартного shell-подобного метаформата для конфигурационных файлов. В главе 14 fetchmailconf используется как пример, демонстрирующий мощность языка Python в быстрой разработке GUI-интерфейсов.

9.2. Генерация специального кода

Операционная система Unix оснащена несколькими мощными генераторами кода специального назначения, предназначенного для таких целей, как создание лексических анализаторов (tokenizers) и синтаксических анализаторов; они рассматриваются в главе 15. Однако существуют более простые, легковесные виды генераторов кода, которые можно использовать для облегчения работы программиста и не требуют знания теории компиляторов или написания процедурной логики (подверженной ошибкам).

Ниже приводится два иллюстративных учебных примера.

9.2.1. Учебный пример: генерация кода для ascii-дисплеев

Запущенная без аргументов программа ascii генерирует экран справочной информации по использованию, подобный распечатке, приведенной в примере 9.5.

Данный экран достаточно тщательно спроектирован, чтобы уместиться в 23 строки и 79 колонок, поэтому он помещается в терминальном окне 24×80.

Таблицу можно было бы создавать во время выполнения, т.е. на лету. Подгонка десятичных и шестнадцатеричных столбцов была бы достаточно простой. Однако существует достаточно необычных, делающих код крайне неудобным, случаев от перенесения строк таблицы в нужных местах до вывода таких неотображаемых символов, как NUL, вместо обычных символов. Более того, столбцы понадобилось бы неравномерно заполнять пробелами, чтобы заставить таблицу уместиться в 79 колонках. Но любой Unix-программист автоматически выражал бы таблицу как блок данных, прежде чем обнаружил бы данные проблемы.

Самым примитивным способом создания справочного экрана было бы помещение каждой строки в C-инициализатор в исходном коде ascii.с, а затем заставить код, проходящий через инициализатор, выписывать строки. Проблема такого метода заключается в том, что дополнительные данные в формате C-инициализатора (завершающие разделители строк, строковые кавычки, запятые) удлиняли бы строки более 79 символов. Это привело бы к переносу строк и усложнило бы преобразование внешнего вида кода к внешнему виду вывода, что, в свою очередь, усложнило бы редактирование справочного дисплея, который и без этого сложно было уместить в экран на 24×80 растровых ячеек.

Более сложный метод использования режима вставки строк в препроцессоре ANSI С приводит к другому варианту той же проблемы. По существу, любой способ явного включения в код справочного экрана задействовал бы пунктуацию в начале и конце строки, для которой не было места[94]. А копирование на экран таблицы из файла во время выполнения выглядело ненадежно. В конце концов, файл мог быть утерян.

Пример 9.5. Справка по использованию программы ascii

Usage: ascii [-dxohv] [-t] [char-alias...]

 -t = one-line output -d = Decimal table -o = octal table -x = hex table

 -h = This help screen -v = version information

Prints all aliases of an ASCII character. Args may be chars, C \-escapes,

English names, ^-escapes, ASCII mnemonics, or numerics in decimal/octal/hex.

Dec Hex     Dec Hex     Dec Hex  Dec Hex   Dec Hex   Dec Hex   Dec Hex   Dec Hex

0   00  NUL 16  10  DLE 32  20   48  30  0 64  40  @ 80  50  P 96  60  ` 112 70 p

1   01  SOH 17  11  DC1 33  21 ! 49  31  1 65  41  A 81  51  Q 97  61  a 113 71 q

2   02  STX 18  12  DC2 34  22 " 50  32  2 66  42  B 82  52  R 98  62  b 114 72 r

вернуться

94

Языки сценариев часто решают данную проблему более изящно, чем С. Для того чтобы понять, как именно они это делают, следует изучить методику потоковых документов (here documents) в shell и конструкцию тройных кавычек в Python.