определение грамматики языка в программу на С, которая и занимается синтаксическим разбором языка. Язык С достаточно часто используется подобным образом -в качестве «языка ассемблера высокого уровня». Modula-З и C++ относятся к тем языкам общего назначения, для которых первые компиляторы создавали код на С, обрабатывавшийся затем уже стандартным компилятором.
У такого подхода есть ряд преимуществ — одним из главных является эффективность, поскольку получается, что в принципе программа может выполняться так же быстро, как и программы на С. Еще один плюс — переносимость: такие компиляторы могут быть перенесены на любую систему, имеющую компилятор С. Подобный подход сильно помог этим языкам на ранних стадиях их внедрения. В качестве еще одного примера возьмем графический интерфейс Visual Basic.
Он генерирует набор операторов присваивания Visual Basic для инициализации объектов. Этот набор пользователь выбирает из меню и располагает на экране с по’мощью мыши. Во множестве других языков есть «визуальная» среда разработки и «мастера» (wizard), которые синтезируют код пользовательского интерфейса по щелчку мыши.
Python на практике / Пишем 3 программы на Питон за 5 минут
Несмотря на мощь программ-генераторов и на большое количество примеров их удачного применения, этот подход еще не признан так широко, как он того заслуживает, и нечасто используется программистами. Однако существует уйма простых возможностей программного создания кода, и вы вполне можете использовать их преимущества. Ниже приведены несколько примеров генерации кода на С или C++. Операционная система Plan 9 генерирует сообщения об ошибках по заголовочному файлу, содержащему программные имена ошибок и комментарии к ним; эти комментарии механически конвертируются в строки, заключенные в кавычки, они помещаются в массив, который может быть индексирован перечислимым значением. В приведенном ниже фрагменте показана структура такого заголовочного файла: /* errors.h: стандартные сообщения об ошибках еnum < Eperm, /* Доступ запрещен */ Eio, /* Ошибка ввода/вывода */ Efile, /* Файл не существует */ Emem, /* Переполнение памяти */ Espace, /* Нет места для файла */ Egreg /* Гришина ошибка */ >; Имея такой фрагмент на входе, несложная программа сможет произнес* и следующий набор деклараций для сообщений об ошибках: /* machine-generated; do not edit. */ char *errs[] = < «Доступ запрещен», /* Eperm */ «Ошибка ввода/вывода», /* Eio */ «Файл не существует», /* Efile */ «Переполнение памяти», /* Emem */ «Нет места для файла», /* Espace */ «Гришина ошибка», /* Egreg */ >;
У такого подхода есть несколько достоинств. Во-первых, соотношение лежду значениями enum и строками, которые они представляют, получается самодокументированным, и его нетрудно сделать независимым от роднoro языка пользователя.
Во-вторых, информация хранится только в однтом месте, в одном «истинном месте», из которого генерируется весь эстальной код, так что и всё обновление информации выполняется лишь в одном месте. В случае, когда таких мест несколько, после ряда обновлений они неизбежно начнут друг другу противоречить.
Разнёс чужой код за 15 секунд. Часть 1 #код #айти #программирование #рефакторинг
И наконец, нетрудно сделать так, чтобы файлы программ на С создавались заново и перекомпилировались при каждом изменении заголовочного файла. Когда потребуется изменить сообщение об ошибке, все, что надо будет сделать, — это изменить заголовочный файл и компилировать таким способом операционную систему, и тогда сообщения автоматически обновятся.
Программа-генератор может быть написана на любом языке. Особенно просто это сделать на языке, специально предназначенном для обработки строк, таком как Perl: # enum.pl: генерирует строки сообщений no enurn + комментарии print «/* machine-generated; do not edit. */nn»; print «char *errs[] = ) I # удалить перевод строки if (/~s*(E[a-zO-9]+),?/) < » первое слово — Е. . . $name = $1; * сохранить имя s/ *\* *//; УДалить до /* s/ **///; удалить print «t»$_», /’•* $name */n»; >> print «>;n»; Опять в дело пошли регулярные выражения.
Выбираются строки, у которых первое поле выглядит как идентификатор, после которого стоит запятая. Первая замена удаляет все символы до первого непустого символа строки комментария, а вторая — символы конца комментария и все предшествующие им пробелы. Среди прочих способов для тестирования компилятора Энди Кёниг (Andy Koenig) разработал метод написания кода C++, позволяющий проверить, нашел ли компилятор ошибки в программе. Фрагменты кода, которые должны вызвать реакцию компилятора, снабжаются специальными комментариями, в которых описываются ожидаемые сообщения. Каждая строка такого комментария начинается с /// (чтобы их можно было отличить от обычных комментариев) и регулярного выражения, которое должно соответствовать диагностике компилятора, выдаваемой для этой строки. Таким образом, например, следующие два фрагмента кода должны вызвать реакцию компилятора: int f() <> /// warning.* non-void function .* should return a value void g() /// error.* void function may not return a value Если мы пропустим второй тест через компилятор C++, то он напечатает ожидаемое сообщение, вполне соответствующее регулярному выражению: % СС х.с