Антон Евгеньевич Москаль (kouzdra) - Представление связи исходного и выходного текстов при автоматическом порождении текстов программ
Название: | Представление связи исходного и выходного текстов при автоматическом порождении текстов программ | |
Автор: | Антон Евгеньевич Москаль (kouzdra) | |
Жанр: | Базы данных | |
Изадано в серии: | неизвестно | |
Издательство: | неизвестно | |
Год издания: | - | |
ISBN: | неизвестно | |
Отзывы: | Комментировать | |
Рейтинг: | ||
Поделись книгой с друзьями! Помощь сайту: донат на оплату сервера |
Краткое содержание книги "Представление связи исходного и выходного текстов при автоматическом порождении текстов программ"
Опубликовано в сборнике СПбГУ
Читаем онлайн "Представление связи исходного и выходного текстов при автоматическом порождении текстов программ". Главная страница.
- 1
- 2
- 3
- . . .
- последняя (4) »
А. Е. Москаль
ПРЕДСТАВЛЕНИЕ СВЯЗИ ИСХОДНОГО
И ВЫХОДНОГО ТЕКСТОВ ПРИ
АВТОМАТИЧЕСКОМ ПОРОЖДЕНИИ
ТЕКСТОВ ПРОГРАММ
Введение
При использовании макропроцессоров существует проблема представления связи
порожденного текста с исходным. Такая привязка необходима для корректной выдачи
диагностики об ошибках, работы отладчика, browser'a и т. п.
Следует отметить, что автоматическая генерация текста программы является очень
распространенным механизмом, используемым не только в макропроцессорах в собственном
смысле этого слова. Аналогичные проблемы возникают во многих других системах, например в
широко известной системе построения трансляторов YACC [1]. Кроме того, близкие проблемы
возникают в системах с расширяемым синтаксисом [2, 3], в системах для автоматического
построения кодогенераторов ([4] и другие).
Хотя проблема является общей для всех макропроцессоров, рассмотрение будет
производиться на примере макропроцессора языка C [5], который является наиболее известным.
Другие подходы к проблеме
Обычным решением проблемы является привязка текста с точностью до строки. Например, в
препроцессорах языка C она осуществляется при помощи вставки в порожденный текст
специальных операторов, задающих имя файла и номер строки в этом файле для каждой строки
порожденного текста (так называемый оператор #line1).
Это является удовлетворительным решением проблемы в случае языка C (имеющего крайне
слабые макровозможности, которые к тому же ориентированы на построчную обработку), но
гораздо менее приемлемо для более развитых макроязыков (например, для языка широко
используемого макропроцессора M4).
Даже в случае, если построчная привязка считается удовлетворительным решением
проблемы, при таком подходе трансляторы с языка С, как правило, неспособны точно указать
позицию в строке, приведшую к возникновению ошибки.
Однако кроме этих недостатков, существуют более серьезные. Рассмотрим следующий
фрагмент программы на языке C++:
#define for_all(ptr, list) \
for (List * ptr = list; \
ptr != NUL; ptr = ptr -> next)
int f (List * list)
{
int s = 0;
for_all (plist, lis)
s += plist -> info;
return s;
}
В данном примере содержится две ошибки: использование NUL вместо NULL и неверно
написанное имя переменной list в параметре макроса.
Обычно применяемый подход даст нам оба сообщения о неописанных именах, которые
будут привязаны к строке, содержащей вызов макроса. Если применительно к имени
переменной list это вполне разумная привязка, то для имени NUL это не слишком удачный
вариант.
1
Вставка этой информации непосредственно в порожденный текст не является необходимой. Того же результата
можно достичь, задав отдельно таблицу соответствия для строк выходного файла.
© А. Е. Москаль, 2000
В случае более сложного макроса поиск причины такой ошибки может быть источником
серьезных трудностей (особенно если ошибка имеет не столь очевидный характер, либо если в
одной строке вызывается несколько макросов).
Первый вариант, который приходит в голову, — это для каждого символа выходного текста
хранить указатель на байт в одном из исходных файлов, из которого он получен. Этот способ
даст удовлетворительные результаты в данном примере, но будет вести себя совершенно
неудовлетворительно, например, в таком случае:
#define isIdLetter(c)\
(isalpha (c) || (c) == '_')
Для корректной работы этого макроса должно быть доступно описание функции isaplha.
Если это не так, то данный подход приведет к привязке сообщения об ошибке в строке с
описанием макроса, тогда как причину ошибки следует искать в месте его использования. Более
того, при таком способе привязки место вызова макроса, приведшее к ошибке, установить почти
невозможно.
В случае работы browser'a или отладчика, а также в случае использования более развитых
макросредств (формирования новых идентификаторов, определения макросов внутри других
макросов и т. п.) проблемы только усугубляются.
Становится ясным, что попытка однозначной привязки позиции выходного текста к
исходному тексту является принципиально недостаточной. Разумным выходом представляется
хранение полной информации о происхождении каждого байта выходного файла, позволяющей
проследить историю его формирования.
Предлагаемая структура
Предлагаемое решение основывается на наблюдении, что порождаемый текст может быть
представлен как результат последовательности замен --">
ПРЕДСТАВЛЕНИЕ СВЯЗИ ИСХОДНОГО
И ВЫХОДНОГО ТЕКСТОВ ПРИ
АВТОМАТИЧЕСКОМ ПОРОЖДЕНИИ
ТЕКСТОВ ПРОГРАММ
Введение
При использовании макропроцессоров существует проблема представления связи
порожденного текста с исходным. Такая привязка необходима для корректной выдачи
диагностики об ошибках, работы отладчика, browser'a и т. п.
Следует отметить, что автоматическая генерация текста программы является очень
распространенным механизмом, используемым не только в макропроцессорах в собственном
смысле этого слова. Аналогичные проблемы возникают во многих других системах, например в
широко известной системе построения трансляторов YACC [1]. Кроме того, близкие проблемы
возникают в системах с расширяемым синтаксисом [2, 3], в системах для автоматического
построения кодогенераторов ([4] и другие).
Хотя проблема является общей для всех макропроцессоров, рассмотрение будет
производиться на примере макропроцессора языка C [5], который является наиболее известным.
Другие подходы к проблеме
Обычным решением проблемы является привязка текста с точностью до строки. Например, в
препроцессорах языка C она осуществляется при помощи вставки в порожденный текст
специальных операторов, задающих имя файла и номер строки в этом файле для каждой строки
порожденного текста (так называемый оператор #line1).
Это является удовлетворительным решением проблемы в случае языка C (имеющего крайне
слабые макровозможности, которые к тому же ориентированы на построчную обработку), но
гораздо менее приемлемо для более развитых макроязыков (например, для языка широко
используемого макропроцессора M4).
Даже в случае, если построчная привязка считается удовлетворительным решением
проблемы, при таком подходе трансляторы с языка С, как правило, неспособны точно указать
позицию в строке, приведшую к возникновению ошибки.
Однако кроме этих недостатков, существуют более серьезные. Рассмотрим следующий
фрагмент программы на языке C++:
#define for_all(ptr, list) \
for (List * ptr = list; \
ptr != NUL; ptr = ptr -> next)
int f (List * list)
{
int s = 0;
for_all (plist, lis)
s += plist -> info;
return s;
}
В данном примере содержится две ошибки: использование NUL вместо NULL и неверно
написанное имя переменной list в параметре макроса.
Обычно применяемый подход даст нам оба сообщения о неописанных именах, которые
будут привязаны к строке, содержащей вызов макроса. Если применительно к имени
переменной list это вполне разумная привязка, то для имени NUL это не слишком удачный
вариант.
1
Вставка этой информации непосредственно в порожденный текст не является необходимой. Того же результата
можно достичь, задав отдельно таблицу соответствия для строк выходного файла.
© А. Е. Москаль, 2000
В случае более сложного макроса поиск причины такой ошибки может быть источником
серьезных трудностей (особенно если ошибка имеет не столь очевидный характер, либо если в
одной строке вызывается несколько макросов).
Первый вариант, который приходит в голову, — это для каждого символа выходного текста
хранить указатель на байт в одном из исходных файлов, из которого он получен. Этот способ
даст удовлетворительные результаты в данном примере, но будет вести себя совершенно
неудовлетворительно, например, в таком случае:
#define isIdLetter(c)\
(isalpha (c) || (c) == '_')
Для корректной работы этого макроса должно быть доступно описание функции isaplha.
Если это не так, то данный подход приведет к привязке сообщения об ошибке в строке с
описанием макроса, тогда как причину ошибки следует искать в месте его использования. Более
того, при таком способе привязки место вызова макроса, приведшее к ошибке, установить почти
невозможно.
В случае работы browser'a или отладчика, а также в случае использования более развитых
макросредств (формирования новых идентификаторов, определения макросов внутри других
макросов и т. п.) проблемы только усугубляются.
Становится ясным, что попытка однозначной привязки позиции выходного текста к
исходному тексту является принципиально недостаточной. Разумным выходом представляется
хранение полной информации о происхождении каждого байта выходного файла, позволяющей
проследить историю его формирования.
Предлагаемая структура
Предлагаемое решение основывается на наблюдении, что порождаемый текст может быть
представлен как результат последовательности замен --">
- 1
- 2
- 3
- . . .
- последняя (4) »
Книги схожие с «Представление связи исходного и выходного текстов при автоматическом порождении текстов программ» по жанру, серии, автору или названию:
Другие книги автора «Антон Москаль»:
Антон Евгеньевич Москаль (kouzdra), Олег Анатольевич Плисс, Андрей Николаевич Терехов и др. - Обзор и сравнительный анализ языков программирования Жанр: Базы данных |