Инструментальные программные средства. Трансляторы и их типы
Трансляторы реализуются в виде компиляторов или интерпретаторов. С точки зрения выполнения работы компилятор и интерпретатор существенно различаются.
Компилятор (англ. compiler - составитель, собиратель) читает всю программу целиком , делает ее перевод и создает законченный вариант программы на машинном языке, который затем и выполняется.
Интерпретатор (англ. interpreter - истолкователь, устный переводчик) переводит и выполняет программу строка за строкой .
После того, как программа откомпилирована, ни сама исходная программа, ни компилятор более не нужны. В то же время программа, обрабатываемая интерпретатором, должна заново переводиться на машинный язык при каждом очередном запуске программы.
Каждый конкретный язык ориентирован либо на компиляцию, либо на интерпретацию - в зависимости от того, для каких целей он создавался. Например, Паскаль обычно используется для решения довольно сложных задач, в которых важна скорость работы программ. Поэтому данный язык обычно реализуется с помощью компилятора . С другой стороны, Бейсик создавался как язык для начинающих программистов, для которых построчное выполнение программы имеет неоспоримые преимущества. Иногда для одного языка имеется и компилятор , и интерпретатор . В этом случае для разработки и тестирования программы можно воспользоваться интерпретатором, а затем откомпилировать отлаженную программу, чтобы повысить скорость ее выполнения. |
Что такое системы программирования?
Современные системы программирования обычно предоставляют пользователям мощные и удобные средства разработки программ. В них входят:
· компилятор или интерпретатор;
· интегрированная среда разработки;
· средства создания и редактирования текстов программ;
· обширные библиотеки стандартных программ и функций;
· "дружественная" к пользователю диалоговая среда;
· многооконный режим работы;
· мощные графические библиотеки; утилиты для работы с библиотеками
· встроенный ассемблер;
· встроенная справочная служба;
· другие специфические особенности.
Популярные системы программирования – Turbo Basic , Quick Basic , Turbo Pascal , Turbo C .
В последнее время получили распространение системы программирования, ориентированные на создание Windows-приложений :
Borland Delphi 3.0
· пакет Borland Delphi (Дельфи) - блестящий наследник семейства компиляторов Borland Pascal, предоставляющий качественные и очень удобные средства визуальной разработки. Его исключительно быстрый компилятор позволяет эффективно и быстро решать практически любые задачи прикладного программирования.
· пакет Microsoft Visual Basic - удобный и популярный инструмент для создания Windows-программ с использованием визуальных средств. Содержит инструментарий для создания диаграмм и презентаций .
· пакет Borland C++ - одно из самых распространённых средств для разработки DOS и Windows приложений.
Ниже для иллюстрации приведены на языках Бейсик, Паскаль и Си программы решения одной и той же простой задачи - вычисления суммы S элементов одномерного массива A=(a 1 , a 2 , ..., a n).
Для чего нужны инструментальные программы?
По своему назначению они близки системам программирования. К инструментальным программам, например, относятся:
· редакторы;
· средства компоновки программ;
· отладочные программы, т.е. программы, помогающие находить и устранять ошибки в программе;
· вспомогательные программы, реализующие часто используемые системные действия;
· графические пакеты программ и т.п.
Инструментальные программные средства могут оказать помощь на всех стадиях разработки ПО.
Что такое текстовый редактор?
Этими данными могут быть программа или какой-либо документ или же книга. Редактируемый текст выводится на экран, и пользователь может в диалоговом режиме вносить в него свои изменения.
Текстовые редакторы могут обеспечивать выполнение разнообразных функций, а именно:
· редактирование строк текста;
· возможность использования различных шрифтов символов;
· копирование и перенос части текста с одного места на другое или из одного документа в другой;
· контекстный поиск и замена частей текста;
· задание произвольных межстрочных промежутков;
· автоматический перенос слов на новую строку;
· автоматическая нумерацию страниц;
· обработка и нумерация сносок;
· выравнивание краев абзаца;
· создание таблиц и построение диаграмм;
· проверка правописания слов и подбор синонимов;
· построение оглавлений и предметных указателей;
· распечатка подготовленного текста на принтере в нужном числе экземпляров и т.п.
Возможности текстовых редакторов различны - от программ, предназначенных для подготовки небольших документов простой структуры, до программ для набора, оформления и полной подготовки к типографскому изданию книг и журналов (издательские системы).
Рис. 6.5. Окно редактора Microsoft Word
Наиболее известный текстовый редактор - Microsoft Word .
Полнофункциональные издательские системы - Microsoft Publisher , Corel Ventura и Adobe PageMaker . Издательские системы незаменимы для компьютерной верстки и графики. Значительно облегчают работу с многостраничными документами, имеют возможности автоматической разбивки текста на страницы, расстановки номеров страниц, создания заголовков и т.д. Создание макетов любых изданий - от рекламных листков до многостраничных книг и журналов - становится очень простым, даже для новичков.
МИНИСТЕРСТВО СЕЛЬСКОГО ХОЗЯЙСТВА РОССИЙСКОЙ ФЕДЕРАЦИИ
ФГБОУ ВПО «Воронежский государственный аграрный университет имени императора Петра I»
Кафедра информационного обеспечения
И моделирования агроэкономических систем
Контрольная работа
По дисциплине
«Экономическая информатика»
Выполнил: студент ЭПс-1
заочного отделения
Мамычев Д.А.
Шифр УЭэко-15126
Проверил:_________________
Воронеж 2016
1. Инструментальные программные средства. Трансляторы и их типы. Системы программирования.
2. Пакеты обработки графической информации.
3. Глобальная компьютерная сеть internet: основные понятия.
4. Список литературы.
Инструментальные программные средства. Трансляторы и их типы. Системы программирования.
Инструментальные программные средства – программы позволяющие модифицировать мультимедийные файлы и создавать мультимедийные приложения.
Инструментальные программные средства – это пакеты программ для создания мультимедийных приложений:
− редакторы неподвижных графических изображений,
− средства создания анимированных GIF-файлов,
− средства аудио- и видеомонтажа,
− средства создания презентаций,
− средства распознавания текстов, введенных со сканера,
− средства создания обучающих программ,
− системы создания приложений виртуальной реальности и другие.
Инструментальные средства существенно расширяют возможности управления мультимедийными устройствами по сравнению с теми, которые предоставляют системные средства, но это всегда платные продукты и некоторые из них стоят очень дорого, например профессиональные системы видеомонтажа.
Трансляторы и их типы.
Поскольку текст, записанный на языке программирования, непонятен компьютеру, то требуется перевести его на машинный код. Такой перевод программы с языка программирования на язык машинных кодов называется трансляцией, а выполняется она специальными программами – трансляторами.
Транслятор - обслуживающая программа, преобразующая исходную программу, предоставленную на входном языке программирования, в рабочую программу, представленную на объектном языке.
В настоящее время трансляторы разделяются на три основные группы: ассемблеры, компиляторы и интерпретаторы.
Ассемблер - системная обслуживающая программа, которая преобразует символические конструкции в команды машинного языка. Специфической чертой ассемблеров является то, что они осуществляют дословную трансляцию одной символической команды в одну машинную. Таким образом, язык ассемблера (еще называется автокодом) предназначен для облегчения восприятия системы команд компьютера и ускорения программирования в этой системе команд. Программисту гораздо легче запомнить мнемоническое обозначение машинных команд, чем их двоичный код.Вместе с тем, язык ассемблера, кроме аналогов машинных команд, содержит множество дополнительных директив, облегчающих, в частности, управление ресурсами компьютера, написание повторяющихся фрагментов, построение многомодульных программ. Поэтому выразительность языка намного богаче, чем просто языка символического кодирования, что значительно повышает эффективность программирования.
Компилятор - это обслуживающая программа, выполняющая трансляцию на машинный язык программы, записанной на исходном языке программирования. Также как и ассемблер, компилятор обеспечивает преобразование программы с одного языка на другой (чаще всего, в язык конкретного компьютера). Вместе с тем, команды исходного языка значительно отличаются по организации и мощности от команд машинного языка. Существуют языки, в которых одна команда исходного языка транслируется в 7-10 машинных команд. Однако есть и такие языки, в которых каждой команде может соответствовать 100 и более машинных команд (например, Пролог). Кроме того, в исходных языках достаточно часто используется строгая типизация данных, осуществляемая через их предварительное описание. Программирование может опираться не на кодирование алгоритма, а на тщательное обдумывание структур данных или классов. Процесс трансляции с таких языков обычно называется компиляцией, а исходные языки обычно относятся к языкам программирования высокого уровня (или высокоуровневым языкам). Абстрагирование языка программирования от системы команд компьютера привело к независимому созданию самых разнообразных языков, ориентированных на решение конкретных задач. Появились языки для научных расчетов, экономических расчетов, доступа к базам данных и другие.
Интерпретатор - программа или устройство, осуществляющее пооператорную трансляцию и выполнение исходной программы. В отличие от компилятора, интерпретатор не порождает на выходе программу на машинном языке. Распознав команду исходного языка, он тут же выполняет ее. Как в компиляторах, так и в интерпретаторах используются одинаковые методы анализа исходного текста программы. Но интерпретатор позволяет начать обработку данных после написания даже одной команды. Это делает процесс разработки и отладки программ более гибким. Кроме того, отсутствие выходного машинного кода позволяет не "захламлять" внешние устройства дополнительными файлами, а сам интерпретатор можно достаточно легко адаптировать к любым машинным архитектурам, разработав его только один раз на широко распространенном языке программирования. Поэтому, интерпретируемые языки, типа Java Script, VB Script, получили широкое распространение. Недостатком интерпретаторов является низкая скорость выполнения программ. Обычно интерпретируемые программы выполняются в 50-100 раз медленнее программ, написанных в машинных кодах.
Любой транслятор выполняет следующие основные задачи:
Анализирует транслируемую программу, в частности определяет, содержит ли она синтаксические ошибки;
Генерирует выходную программу (ее часто называют объектной) на языке машинных команд;
Распределяет память для объектной программы.
Системы программирования.
Системы программирования – это комплекс инструментальных программных средств, предназначенных для работы с программами на одном из языков программирования. Системы программирования представляют сервисные возможности программистам для разработки их собственных компьютерных программ.
В настоящее время разработка любого системного и прикладного программного обеспечения осуществляется с помощью систем программирования, в состав которых входят:
Трансляторы с языков высокого уровня;
Средства редактирования, компоновки и загрузки программ;
Макроассемблеры (машинно-ориентированные языки);
Отладчики машинных программ.
Системы программирования, как правило, включают в себя:
Текстовый редактор (Edit), осуществляющий функции записи и редактирования исходного текста программы;
Загрузчик программ(Load), позволяющий выбрать из директория нужный текстовый файл программы;
Запускатель программ (Run), осуществляющий процесс выполнения программы;
Компилятор (Compile), предназначенный для компиляции или интерпретации исходного текста программы в машинный код с диагностикой синтаксических и семантических (логических) ошибок;
Отладчик (Debug), выполняющий сервисные функции по отладке и тестированию программы;
Диспетчер файлов (File), предоставляющий возможность выполнять операции с файлами: сохранение, поиск, уничтожение и т.п.
2.Пакеты обработки графической информации.
Программные средства создания и обработки графической информации подразделяются на:
Графические редакторы, предназначенные преимущественно для создания и обработки плоскостных изображений;
Пакеты компьютерной графики для полиграфии, позволяющие дополнять текст иллюстрациями разного формата, создавать дизайн страниц и выводить полиграфическую продукцию на печать;
Программы двумерной анимации, используемые для создания динамических изображений и спецэффектов в кино;
Пакеты трехмерной анимации, используемые для создания рекламных и музыкальных клипов и кинофильмов.
Все компьютерные изображения разделяют на два типа: растровые и векторные.
Растровая графика. Растровые графические изображения формируются в процессе преобразования графической информации из аналоговой формы в цифровую.
Можно создать растровое графическое изображение и непосредственно на компьютере с использованием графического редактора, загрузить с CD-ROM или DVD-ROM дисков, или «скачать» из Интернета.
Растровое изображение хранится с помощью точек различного цвета (пикселей), которые образуют строки и столбцы. Каждый пиксель имеет определенное положение и цвет. Пиксель – это минимальный участок изображения, которому независимым образом можно задать цвет.
Качество растрового изображения зависит от размера изображения (количества пикселей по горизонтали и вертикали) и количества цветов, которые могут принимать пикселы. Хранение каждого пиксела требует определенного количества бит (глубина цвета), которое зависит от количества цветов в изображении.
Растровые графические изображения многоцветных фотографий и иллюстраций получают с помощью сканера. Такие изображения обычно имеют большой размер и большую глубину цвета (24 или 36 бит на точку). В результате файлы, хранящие растровые изображения, имеют большой информационный объем.
Растровые изображения очень чувствительны к масштабированию (увеличению или уменьшению). При уменьшении растрового изображения несколько соседних точек преобразуются в одну, поэтому теряется разборчивость мелких деталей изображения. При увеличении – увеличивается размер каждой точки и появляется ступенчатый эффект, который можно увидеть невооруженным глазом.
Векторная графика. Векторные графические изображения являются оптимальным средством для хранения высокоточных графических объектов (чертежи, схемы и т.д.), для которых имеет значение сохранение четких и ясных контуров. Системы компьютерного черчения и автоматизированного проектирования (САПР), программы обработки трехмерной графики базируются на векторной графике.
Векторные изображения формируются из объектов (точка, линия, окружность, прямоугольник и т.д.), которые хранятся в памяти компьютера в виде графических примитивов и описывающих их математических формул.
Достоинством векторной графики является то, что файлы, хранящие векторные графические изображения, имеют сравнительно небольшой объем. Важно также, что векторные графические изображения могут быть увеличены или уменьшены без потери качества. Это возможно, поскольку масштабирование изображений производится с помощью простых математических операций (умножения параметров графических примитивов на коэффициент масштабирования).
В зависимости от метода описания графических данных осуществляется и разбиение на типы графических редакторов.
Графический редактор – это программа, предназначенная для создания различного рода изображений, начиная с простейших и заканчивая видеоматериалами.
Растровые графические редакторы (PaintBrush, PhotoShop) основаны на битовом методе передачи изображений. Они обрабатывают достаточно подробные сканируемые образы. Выполняя ретуширование, изменение цветов, их оттенков и контрастов, растирание и штриховку, изменение направления тени и контуров. Длина битовых файлов велика из-за большого количества обрабатываемых экранных точек, что позволяет использовать большое количество цветов и детально редактировать изображение. Сканирование образа может быть осуществлено в черно-белом изображении, в серых оттенкахи тонах и цветным образом. Для растровых графических редакторов необходимо подобрать угол и тип растра (блочный, линейный, точечный и т.д.), разрешающую способность. Для цветных изображений регулируют яркость и контраст по каждому из цветов, составляющих гамму графического изображения. Готовые рисунки хранятся в отдельных файлах и могут быть доступны для использования.
Векторные графические редакторы (Adobe Fireworks, ConceptDraw PRO, CorelDRAW)
Для создания сложных рисунков с точными, сложными и четкими границами используют главным образом векторный редактор, одним из основных инструментов которого являются кривые Безье, позволяющие рисовать кривые (ломаные, прямые и гладкие) по сегментам с точным размещением узловых (опорных) точек и контролем над формой каждого сегмента. Кривую Безье можно представить как результат поступательной детализации формы многоугольника, выстраиваемого последовательным соединением определяющих форму контрольных точек. Кривая, направляясь от начальной точки многоугольника к ее конечной точке, притягивается, как магнитом к промежуточным, определяющим форму опорным точкам, через которые сама не проходит. Благодаря особым свойствам, простоте задания и возможности манипулировать, кривые Безье широко используются для моделирования гладких линий в компьютерной графике. В арсенале инструментов, которым обладает каждый редактор векторной графики, обязательно присутствуют "Заливка", "Текст", "Карандаш" и базовый набор геометрических фигур (т. н. примитивов), которые составляет основу большинства графических конструкций.
3.Глобальная компьютерная сеть internet: основные понятия.
Интернет (от англ. inter - «между» и net - «сеть, паутина») представляет собой совокупность компьютерных сетей, связывающих военные, правительственные, образовательные, коммерческие институты, а также отдельных граждан.
Сервером сети Интернет (web-сервером или http-сервером) называется программно-аппаратный комплекс, установленный на компьютере, подключенном к высокоскоростной магистрали Интернета. Такие компьютеры также называют серверами. Основная функция сервера - поиск и передача на пользовательский компьютер информации, запрашиваемой клиентскими программами, в частности браузерами.
Правомерно разное употребление термина сервер. Пользователи Интернета называют сервером большие web-узлы вместе с их информационным наполнением, web-дизайнеры и программисты понимают под сервером специальные программы для передачи данных из Интернета на пользовательский компьютер, системные администраторы и специалисты, обслуживающие локальные сети, - сами компьютеры, на которых установлены подобные программы.
Браузер представляет собой клиентскую программу для работы в Интернете, которая обращается к серверу, читает документ, сверстанный средствами HTML, интерпретирует полученную информацию и отображает содержание документа. Наиболее известными в России браузерами являются Internet Explorer, Opera, Google Chrome, Mozilla Firefox и др.
Web-сайт (от англ. site - «участок») - это набор web-страниц, связанных между собой ссылками и хранящихся на одном сервере. Набор Web-сайтов, которые связаны между собой ссылками и хранятся на разных серверах, называется Web-порталом.
Функционирование технологии сети Интернет напрямую зависит от протокола - набора правил, оговаривающих все, что связано с работой в сети. Технология передачи данных в Интернете базируется на протоколе TCP/IP (IP (Internet Protocol) - «протокол Интернета», TCP (Transmission Control Protocol) - «протокол управления передачей») - общепринятом стандарте, описывающем правила отправки и приема информации между несколькими подключенными к сети компьютерами.
TCP/IP для каждого работающего в Интернете компьютера определяет собственный IP-адрес, состоящий из четырех числовых последовательностей, разделенных точкой (например 195.85.105.160). В любой позиции каждое значение может изменяться от 0 до 255. Для удобства пользователей в Интернете разработана система доменных имен - DNS (Domain Name System). Служба доменных имен осуществляет преобразование доменного имени в числовой IP- адрес. Компьютеры, выполняющие такое преобразование, называются DNS- серверами.
Согласно спецификации DNS, все виртуальное пространство Интернета делится на домены - логические зоны, управляемые одним или несколькими специальными компьютерами. Иерархия доменных адресов может быть как региональной, так и в зависимости от вида деятельности хозяйствующего субъекта.Самые крупные единицы DNS называют доменами первого уровня, которые охватывают глобальные участки Интернета по следующим признакам:
Com, .biz - коммерческие предприятия;
Net - изначально присваивалось организациям, отвечающим за поддержку сети Интернет, сейчас также используются для коммерческих хозяйствующих субъектов;
Edu - образовательные учреждения;
Org - некоммерческие и общественные организации;
Gov - правительственные учреждения;
Mil - военные учреждения;
Int - международные организации, которые созданы на основании договоров или являются частью инфраструктуры Интернет;
Name - частные лица;
Info - не лимитируется;
Ru, .ua и др. - сокращения для стран, принятые комитетом по стандартам ISO.
Ступенью ниже в иерархии DNS стоят домены второго уровня, которые непосредственно зависят от домена первого уровня. Домены второго уровня принадлежат муниципальными или коммерческим организациям (например, spb.ru, ifmo.ru).
Домен второго уровня может содержать только 22 символа (буквы, числа и тире). При этом нельзя зарегистрировать уже существующее доменное имя.
Существуют также домены третьего уровня, входящие в состав вышестоящего домена, (например, условный домен name.spb.ru). Также можно встретить домены четвертого, пятого и т.д. уровней.
URL (Uniform Resource Locator) представляет собой универсальное обозначение местонахождения ресурса (например, www.ifmo.ru).
Таким образом, в Интернете используются несколько разновидностей адресов:
1) IP-адрес - основной сетевой адрес, который присваивается каждому компьютеру при входе в сеть. Это глобальная нумерация, так как компьютер, подключенный к Интернету, имеет свой уникальный IP-адрес. IP-адреса делятся на классы в соответствии с масштабом сети, к которой подключается пользователь.
2) доменный адрес. Перевод доменного адреса в IP-адрес происходит автоматически с помощью DNS системы.
3) URL-адрес - универсальный адрес, который применяется для обозначения имени каждого объекта хранения в Интернете.
Хостинг (от англ. hosting) - услуга по предоставлению дискового пространства для физического размещения информации на сервере, постоянно находящегося в сети. Как правило, в услугу хостинга входит предоставление места для почтовой корреспонденции, баз данных, DNS, файлового хранилища и т. п., а также поддержка функционирования соответствующих сервисов.
Электронные доски объявлений (BBS - Bulletin Board System) создают специализированные сетевые службы, деятельность которых посвящена определенной теме. BBS обычно содержит файлы с информацией, представляющей интерес для определенных групп пользователей, а также средства, позволяющие пользователям доски объявлений обмениваться информацией по интересующим их вопросам. Через BBS осуществляется техническое обслуживание: пользователи посылают вопросы, а персонал отвечает на них.
Web-сообщества пользуются финансовой поддержкой различных компаний и представляют собой сайты, члены которых обмениваются мнениями по интересующим их вопросам по принципу общности круга интересов.
Электронная почта (от англ. E-mail, email, сокр. от electronic mail) - способ передачи информации в компьютерных сетях, широко использующийся в Интернете. Основная особенность электронной почты заключается в том, что информация отправляется получателю не напрямую, а через промежуточное звено - электронный почтовый ящик, который представляет собой место на сервере, где сообщение хранится, пока его не запросит получатель. В большинстве случаев для доступа к почтовому ящику требуется наличие пароля. Доступ к почтовому серверу может предоставляться как через специальные почтовые программы (Microsoft Outlook, The Bat и др.), так и через web-интерфейс.
ICQ (акроним от англ. I seek you - «я ищу тебя») - служба, которая позволяет пользователям сети обмениваться сообщениями в реальном масштабе времени, а также организовывать чат, передавать файлы и др. Программа работает по протоколу OSCAR, который обеспечивает обмен мгновенными и оффлайновыми текстовыми сообщениями. В настоящее время служба принадлежит инвестиционному фонду Mail.ru Group (российская инвестиционная группа, специализирующаяся на инвестициях в интернет-проекты).
IRC (от англ. Internet Relay Chat - «ретранслируемый интернет-чат») - служба, в которой обмен сообщениями ведется без задержек.
IP-телефония - это технология, позволяющая использовать Интернет или любую другую IP-сеть в качестве средства организации и ведения телефонных разговоров.
Skype - бесплатное проприетарное программное обеспечение с закрытым кодом, обеспечивающее шифрованную голосовую связь через Интернет между компьютерами, а также платные услуги для связи с абонентами обычной телефонной сети. Создателями Skype являются Никлас Зеннстрём (Niklas Zennstrom) и Янус Фриис (Janus Friis). Первый релиз программы и сайт появились в сентябре 2003 года.
Таблица 1. Расчет прибыли фирмы
№ п/п | Показатели | Год | Итого за год | |||
1 кв. | 2 кв. | 3 кв. | 4 кв. | |||
Торговые доходы | ||||||
Торговые расходы | ||||||
Валовая прибыль | ||||||
Расходы на зарплату | ||||||
Расходы на рекламу | ||||||
Накладные расходы | ||||||
Общие затраты | ||||||
Производственная прибыль | ||||||
Удельная валовая прибыль | 0,099010177 | 0,118613565 | 0,074808144 | 0,121404967 | 0,4138369 |
Таблица 2. Структура затрат фирмы
Диаграмма 1. Структура затрат фирмы
Список используемой литературы:
1. Интернет ресурс http://eclib.net/
2. Интернет ресурс https://ru.wikipedia.org/
3. Интернет ресурс http://studopedia.ru/
4. Основные принципы построения трансляторов. Трансляторы, компиляторы и интерпретаторы – общая схема работы. Современные компиляторы и интерпретаторы.
Основные принципы построения трансляторов.
Трансляторы, компиляторы, интерпретаторы – общая схема работы.
Определение транслятора, компилятора, интерпретатора
Для начала дадим несколько определений - что же все-таки такое есть уже многократно упоминавшиеся трансляторы и компиляторы.
Формальное определение транслятора
Транслятор - это программа, которая переводит входную программу на исходном (входном) языке в эквивалентную ей выходную программу на результирующем (выходном) языке. В этом определении слово «программа» встречается три раза, и это не ошибка и не тавтология. В работе транслятора, действительно, участвуют всегда три программы.
Во-первых, сам транслятор является программой 1 - обычно он входит в состав системного программного обеспечения вычислительной системы. То есть транслятор - это часть программного обеспечения (ПО), он представляет собой набор машинных команд и данных и выполняется компьютером, как и все прочие программы в рамках операционной системы (ОС). Все составные части транслятора представляют собой фрагменты или модули программы со своими входными и выходными данными.
Во-вторых, исходными данными для работы транслятора служит текст входной программы - некоторая последовательность предложений входного языка программирования. Обычно это символьный файл, но этот файл должен содержать текст программы, удовлетворяющий синтаксическим и семантическим требованиям входного языка. Кроме того, этот файл несет в себе некоторый смысл, определяемый семантикой входного языка.
В-третьих, выходными данными транслятора является текст результирующей программы. Результирующая программа строится по синтаксическим правилам, заданным в выходном языке транслятора, а ее смысл определяется семантикой выходного языка. Важным требованием в определении транслятора является эквивалентность входной и выходной программ. Эквивалентность двух программ означает совпадение их смысла с точки зрения семантики входного языка (для исходной программы) и семантики выходного языка (для результирующей программы). Без выполнения этого требования сам транслятор теряет всякий практический смысл.
Итак, чтобы создать транслятор, необходимо прежде всего выбрать входной и выходной языки. С точки зрения преобразования предложений входного языка в эквивалентные им предложения выходного языка транслятор выступает как переводчик. Например, трансляция программы с языка С в язык ассемблера по сути ничем не отличается от перевода, скажем, с русского языка на английский, с той только разницей, что сложность языков несколько иная (почему не существует трансляторов с естественных языков - см. раздел «Классификация языков и грамматик», глава 9). Поэтому и само слово «транслятор» (английское: translator) означает «переводчик».
Результатом работы транслятора будет результирующая программа, но только в том случае, если текст исходной программы является правильным - не содержит ошибок с точки зрения синтаксиса и семантики входного языка. Если исходная программа неправильная (содержит хотя бы одну ошибку), то результатом работы транслятора будет сообщение об ошибке (как правило, с дополнительными пояснениями и указанием места ошибки в исходной программе). В этом смысле транслятор сродни переводчику, например, с английского, которому подсунули неверный текст.
Теоретически возможна реализация транслятора с помощью аппаратных средств. Автору встречались такого рода разработки, однако широкое практическое применение их не известно. В таком случае и все составные части транслятора могут быть реализованы в виде аппаратных средств и их фрагментов - вот тогда схема распознавателя может получить вполне практическое воплощение!
Определение компилятора.
Отличие компилятора от транслятора
Кроме понятия «транслятор» широко употребляется также близкое ему по смыслу понятие «компилятор».
Компилятор - это транслятор, который осуществляет перевод исходной программы в эквивалентную ей объектную программу на языке машинных команд или на языке ассемблера.
Таким образом, компилятор отличается от транслятора лишь тем, что его результирующая программа всегда должна быть написана на языке машинных кодов.или на языке ассемблера. Результирующая программа транслятора, в общем случае, может быть написана на любом языке - возможен, например, транслятор программ с языка Pascal на язык С. Соответственно, всякий компилятор является транслятором, но не наоборот - не всякий транслятор будет компилятором. Например, упомянутый выше транслятор с языка Pascal на С компилятором являться не будет 1 .
Само слово «компилятор» происходит от английского термина «compiler» («составитель», «компоновщик»). Видимо, термин обязан своему происхождению способности компиляторов составлять объектные программы на основе исходных программ.
Результирующая программа компилятора называется «объектной программой» или «объектным кодом». Файл, в который она записана, обычно называется «объектным файлом». Даже в том случае, когда результирующая программа порождается на языке машинных команд, между объектной программой (объектным файлом) и исполняемой программой (исполняемым файлом) есть существенная разница. Порожденная компилятором программа не может непосредственно выполняться на компьютере, так как она не привязана к конкретной области памяти, где должны располагаться ее код и данные (более подробно - см. раздел «Принципы функционирования систем программирования», глава 15) 2 .
Компиляторы, безусловно, самый распространенный вид трансляторов (многие считают их вообще единственным видом трансляторов, хотя это не так). Они имеют самое широкое практическое применение, которым обязаны широкому распространению всевозможных языков программирования. Далее всегда будем говорить о компиляторах, подразумевая, что выходная программа написана на
Естественно, трансляторы и компиляторы, как и все прочие программы, разрабатывает человек (люди) - обычно это группа разработчиков. В принципе они могли бы создавать его непосредственно на языке машинных команд, однако объем кода и данных современных компиляторов таков, что их создание на языке машинных команд практически невозможно в разумные сроки при разумных трудозатратах. Поэтому практически все современные компиляторы также создаются с помощью компиляторов (обычно в этой роли выступают предыдущие версии компиляторов той же фирмы-производителя). И в этом качестве компилятор является уже выходной программой для другого компилятора, которая ничем не лучше и не хуже всех прочих порождаемых выходных программ 2 .
Определение интерпретатора. Разница между интерпретаторами и трансляторами
Кроме схожих между собой понятий «транслятор» и «компилятор» существует принципиально отличное от них понятие интерпретатора.
Интерпретатор - это программа, которая воспринимает входную программу на исходном языке и выполняет ее.
В отличие от трансляторов интерпретаторы не порождают результирующую программу (и вообще какого-либо результирующего кода) - и в этом принципиальная разница между ними. Интерпретатор, так же как и транслятор, анализирует текст исходной программы. Однако он не порождает результирующей программы, а сразу же выполняет исходную в соответствии с ее смыслом, заданным семантикой входного языка. Таким образом, результатом работы интерпретатора будет результат, заданный смыслом исходной программы, в том случае, если эта программа правильная, или сообщение об ошибке, если исходная программа неверна.
Конечно, чтобы исполнить исходную программу, интерпретатор так или иначе должен преобразовать ее в язык машинных кодов, поскольку иначе выполнение программ на компьютере невозможно. Он и делает это, однако полученные машинные коды не являются доступными - их не видит пользователь интерпретатора. Эти машинные коды порождаются интерпретатором, исполняются и унич-
1 Следует особо упомянуть, что сейчас в современных системах программирования стали появляться компиляторы, в которых результирующая программа создается не на языке машинных команд и не на языке ассемблера, а на некотором промежуточном языке. Сам по себе этот промежуточный язык не может непосредственно исполняться на компьютере, а требует специального промежуточного интерпретатора для выполнения написанных на нем программ. Хотя в данном случае термин «транслятор» был бы, наверное, более правильным, в литературе употребляется понятие «компилятор», поскольку промежуточный язык является языком очень низкого уровня, будучи родственным машинным командам и языкам ассемблера.
Здесь возникает извечный вопрос «о курице и яйце». Конечно, в первом поколении самые первые компиляторы писались непосредственно на машинных командах, но потом, с появлением компиляторов, от этой практики отошли. Даже самые ответственные части компиляторов создаются, как минимум, с применением языка ассемблера - а он тоже обрабатывается компилятором. тожаются по мере надобности - так, как того требует конкретная реализа) интерпретатора. Пользователь же видит результат выполнения этих кодов -есть результат выполнения исходной программы (требование об эквивалент сти исходной программы и порожденных машинных кодов и в этом случае, (условно, должно выполняться).
Более подробно вопросы, связанные с реализацией интерпретаторов и их от чием от компиляторов, рассмотрены далее в соответствующем разделе.
Назначение трансляторов, компиляторов и интерпретаторов. Примеры реализации
Первые программы, которые создавались еще для ЭВМ первого поколения, сались непосредственно на языке машинных кодов. Это была поистине аде работа. Сразу стало ясно, что человек не должен и не может говорить на яз машинных команд, даже если он специалист по вычислительной технике. О; ко и все попытки научить компьютер говорить на языках людей успехов увенчались и вряд ли когда-либо увенчаются (на что есть определенные o6i тивные причины, рассмотренные в первой главе этого пособия).
С тех пор все развитие программного обеспечения компьютеров неразрывно i зано с возникновением и развитием компиляторов.
Первыми компиляторами были компиляторы с языков ассемблера или, как назывались, мнемокодов. Мнемокоды превратили «филькину грамоту» яз машинных команд в более-менее доступный пониманию специалиста язык ^ монических (преимущественно англоязычных) обозначений этих команд. (давать программы уже стало значительно проще, но исполнять сам мнемс (язык ассемблера) ни один компьютер неспособен, соответственно, возникла обходимость в создании компиляторов. Эти компиляторы элементарно про но они продолжают играть существенную роль в системах программировани сей день. Более подробно о языке ассемблера и компиляторах с него расска: далее в соответствующем разделе.
Следующим этапом стало создание языков высокого уровня. Языки высо] уровня (к ним относится большинство языков программирования) предста ют собой некоторое промежуточное звено между чисто формальными язык и языками естественного общения людей. От первых им досталась строгая с мализация синтаксических структуру предложений языка, от вторых - зн тельная часть словарного запаса, семантика основных конструкций и выражс (с элементами математических операций, пришедшими из алгебры).
Появление языков высокого уровня существенно упростило процесс програи рования, хотя и не свело его до «уровня домохозяйки», как самонадеянно п гали некоторые авторы на заре рождения языков программирования 1 . Снатаких языков были единицы, затем десятки, сейчас, наверное, их насчитывается более сотни. Процессу этому не видно конца. Тем не менее по-прежнему преобладают компьютеры традиционной, «неймановской», архитектуры, которые умеют понимать только машинные команды, поэтому вопрос о создании компиляторов продолжает быть актуальным.
Как только возникла массовая потребность в создании компиляторов, стала развиваться и специализированная теория. Со временем она нашла практическое приложение во множестве созданных компиляторов. Компиляторы создавались и продолжают создаваться не только для новых, но и для давно известных языков. Многие производители от известных, солидных фирм (таких, как Microsoft или Inprise) до мало кому знакомых коллективов авторов выпускают на рынок все новые и новые образцы компиляторов. Это обусловлено рядом причин, которые будут рассмотрены далее.
Наконец, с тех пор как большинство теоретических аспектов в области компиляторов получили свою практическую реализацию (а это, надо сказать, произошло довольно быстро, в конце 60-х годов), развитие компиляторов пошло по пути их дружественности человеку - пользователю, разработчику программ на языках высокого уровня. Логичным завершением этого процесса стало создание систем программирования - программных комплексов, объединяющих в себе кроме непосредственно компиляторов множество связанных с ними компонентов программного обеспечения. Появившись, системы программирования быстро завоевали рынок и ныне в массе своей преобладают на нем (фактически, обособленные компиляторы - это редкость среди современных программных средств). О том, что представляют собой и как организованы современные системы программирования, см. в главе «Современные системы программирования». Ныне компиляторы являются неотъемлемой частью любой вычислительной системы. Без их существования программирование любой прикладной задачи было бы затруднено, а то и просто невозможно. Да и программирование специализированных системных задач, как правило, ведется если не на языке высокого уровня (в этой роли в настоящее время чаще всего применяется язык С), то на языке ассемблера, следовательно, применяется соответствующий компилятор. Программирование непосредственно на языках машинных кодов происходит исключительно редко и только для решения очень узких вопросов. Несколько слов о примерах реализации компиляторов и интерпретаторов, а также о том, как они соотносятся с другими существующими программными средствами. Компиляторы, как будет показано далее, обычно несколько проще в реализации, чем интерпретаторы. По эффективности они также превосходят их - очевидно, что откомпилированный код будет исполняться всегда быстрее, чем происходит интерпретация аналогичной исходной программы. Кроме того, не каждый язык программирования допускает построение простого интерпретатора. Однако интерпретаторы имеют одно существенное преимущество - откомпилированный код всегда привязан к архитектуре вычислительной системы, на которую он ориентирован, а исходная программа - только к семантике языка программирования, которая гораздо легче поддается стандартизации. Этот аспект первоначально не принимали во внимание. Первыми компиляторами были компиляторы с мнемокодов. Их потомки - современные компиляторы с языков ассемблера - существую практически для всех известных вычислительных систем. Они предельно жестко ориентированы на архитектуру. Затем появились компиляторы с таких языков, как FORTRAN, ALGOL-68, PL/1. Они были ориентированы на большие ЭВМ с пакетной обработкой задач. Из вышеперечисленных только FORTRAN, пожалуй, продолжает использоваться по сей день, поскольку имеет огромное количество библиотек различного назначения . Многие языки, родившись, так и не получили широкого распространения - ADA, Modula, Simula известны лишь узкому кругу специалистов. В то же время на рынке программных систем доминируют компиляторы языков, которым не прочили светлого будущего. В первую очередь, сейчас это С и C++. Первый из них родился вместе с операционными системами типа UNIX, вместе с нею завоевал свое «место под солнцем», а затем перешел под ОС других типов. Второй удачно воплотил в себе пример реализации идей объектно-ориентированного программирования на хорошо зарекомендовавшей себя практической базе 1 . Еще можно упомянуть довольно распространенный Pascal, который неожиданно для многих вышел за рамки чисто учебного языка для университетской среды.
История интерпретаторов не столь богата (пока!). Как уже было сказано, изначально им не предавали существенного значения, поскольку почти по всем параметрам они уступают компиляторам. Из известных языков, предполагавших интерпретацию, можно упомянуть разве что Basic, хотя большинству сейчас известна его компилируемая реализация Visual Basic, сделанная фирмой Microsoft . Тем не менее сейчас ситуация несколько изменилась, поскольку вопрос о переносимости программ и их аппаратно-платформенной независимости приобретает все большую актуальность с развитием сети Интернет. Самый известный сейчас пример - это язык Java (сам по себе он сочетает компиляцию и интерпретацию), а также связанный с ним JavaScript. В конце концов, язык HTML, на котором зиждется протокол HTTP, давший толчок столь бурному развитию Всемирной сети, - это тоже интерпретируемый язык. По мнению автора, в области появления новых интерпретаторов всех еще ждут сюрпризы, и появились уже первые из них - например, язык С# («си-диез», но название везде идет как «Си шарп»), анонсируемый фирмой Microsoft.
Об истории языков программирования и современном состоянии рынка компиляторов можно говорить долго и много. Автор считает возможным ограничиться уже сказанным, поскольку это не является целью данного пособия. Желающие могут обратиться к литературе .
Этапы трансляции. Общая схема работы транслятора
На рис. 13.1 представлена общая схема работы компилятора. Из нее видно, что ъ целом процесс компиляции состоит из двух основных этапов - синтеза и анализа.
На этапе анализа выполняется распознавание текста исходной программы, создание и заполнение таблиц идентификаторов. Результатом его работы служит некое внутреннее представление программы, понятное компилятору.
На этапе синтеза на основании внутреннего представления программы и информации, содержащейся в таблице (таблицах) идентификаторов, порождается текст результирующей программы. Результатом этого этапа является объектный код.
Кроме того, в составе компилятора присутствует часть, ответственная за анализ и исправление ошибок, которая при наличии ошибки в тексте исходной программы должна максимально полно информировать пользователя о типе ошибки и месте ее возникновения. В лучшем случае компилятор может предложить пользователю вариант исправления ошибки.
Эти этапы, в свою Очередь, состоят из более мелких этапов, называемых фазами компиляции. Состав фаз компиляции приведен в самом общем виде, их конкретная реализация и процесс взаимодействия
Во-первых, он является распознавателем для языка исходной программы. То ее он должен получить на вход цепочку символов входного языка, проверить принадлежность языку и, более того, выявить правила, по которым эта цепоч была построена (поскольку сам ответ на вопрос о принадлежности «да» и. «нет» представляет мало интереса). Интересно, что генератором цепочек входи го языка выступает пользователь - автор входной программы.
Во-вторых, компилятор является генератором для языка результирующей пр граммы. Он должен построить на выходе цепочку выходного языка по опре; ленным правилам, предполагаемым языком машинных команд или языком i семблера. Распознавателем этой цепочки будет выступать уже вычислительн система, под которую создается результирующая программа.
Лексический анализ (сканер) - это часть компилятора, которая читает лите] программы на исходном языке и строит из них слова (лексемы) исходного яз ка. На вход лексического анализатора поступает текст исходной программ а выходная информация передаётся для дальнейшей обработки компилятор на этапе синтаксического разбора. С теоретической точки зрения лексическ анализатор не является обязательной, необходимой частью компилятора. Од1 ко существует причины, которые определяют его присутствие практически всех компиляторах. Более подробно см. раздел «Лексические анализаторы (а неры). Принципы построения сканеров».
Синтаксический разбор - это основная часть компилятора на этапе анализа. О выполняет выделение синтаксических конструкций в тексте исходной прогре мы, обработанном лексическим анализатором. На этой же фазе компиляц проверяется синтаксическая правильность программы. Синтаксический раз£ играет главную роль - роль распознавателя текста входного языка програмл рования (см. раздел «Синтаксические анализаторы. Синтаксически управл; мый перевод» этой главы).
Семантический анализ - это часть компилятора, проверяющая правильно* текста исходной программы с точки зрения семантики входного языка. Крс непосредственно проверки, семантический анализ должен выполнять преоб; зования текста, требуемые семантикой входного языка (такие, как добавлен функций неявного преобразования типов). В различных реализациях компи. торов семантический анализ может частично входить в фазу синтаксическ* разбора, частично - в фазу подготовки к генерации кода.
Подготовка к генерации кода - это фаза, на которой компилятором выполнят ся предварительные действия, непосредственно связанные с синтезом текста зультирующей программы, но еще не ведущие к порождению текста на вых ном языке. Обычно в эту фазу входят действия, связанные с идентификащ элементов языка, распределением памяти и т. п. (см. раздел «Семантическ анализ и подготовка к генерации кода», глава 14).
Генерация кода - это фаза, непосредственно связанная с порождением кома составляющих предложения выходного языка и в целом текст результируюи
Могут, конечно, различаться в зависимости от версии компилятора. Однако в том или ином виде все представленные фазы практически всегда присутствуют в каждом конкретном компиляторе .
Компилятор в целом с точки зрения теории формальных языков выступает в «двух ипостасях», выполняет две основные функции. программы. Это основная фаза на этапе синтеза результирующей программы. Кроме непосредственного порождения текста результирующей программы, генерация обычно включает в себя также оптимизацию - процесс, связанный с обработкой уже порожденного текста. Иногда оптимизацию выделяют в отдельную фазу компиляции, так как она оказывает существенное влияние на качество и эффективность результирующей программы (см. разделы «Генерация кода. Методы генерации кода» и « Оптимизация кода. Основные методы оптимизации», глава 14).
Таблицы идентификаторов (иногда - «таблицы символов») - это специальным образом организованные наборы данных, служащие для хранения информации об элементах исходной программы, которые затем используются для порождения текста результирующей программы. Таблица идентификаторов в конкретной реализации компилятора может быть одна, или же таких таблиц может быть несколько. Элементами исходной программы, информацию о которых нужно хранить в процессе компиляции, являются переменные, константы, функции и т. п. - конкретный состав набора элементов зависит от используемого входного языка программирования. Понятие «таблицы» вовсе не предполагает, что это хранилище данных должно быть организовано именно в виде таблиц или других массивов информации - возможные методы их организации подробно рассмотрены далее, в разделе «Таблицы идентификаторов. Организация таблиц идентификаторов».
Представленное на рис. 13.1 деление процесса компиляции на фазы служит скорее методическим целям и на практике может не соблюдаться столь строго. Далее в подразделах этого пособия рассматриваются различные варианты технической организации представленных фаз компиляции. При этом указано, как они могут быть связаны между собой. Здесь рассмотрим только общие аспекты такого рода взаимосвязи.
Во-первых, на фазе лексического анализа лексемы выделяются из текста входной программы постольку, поскольку они необходимы для следующей фазы синтаксического разбора. Во-вторых, как будет показано ниже, синтаксический разбор и генерация кода могут выполняться одновременно. Таким образом, эти три фазы компиляции могут работать комбинированно, а вместе с ними может выполняться и подготовка к генерации кода. Далее рассмотрены технические вопросы реализации основных фаз компиляции, которые тесно связаны с понятием прохода.
Понятие прохода. Многопроходные и однопроходные компиляторы
Как уже было сказано, процесс компиляции программ состоит из нескольких фаз. В реальных компиляторах состав этих фаз может несколько отличаться от рассмотренного выше - некоторые из них могут быть разбиты на составляющие, другие, напротив, объединены в одну фазу. Порядок выполнения фаз компиляции также может меняться в разных вариантах компиляторов. В одном случае компилятор просматривает текст исходной программы, сразу выполняет все фазы компиляции и получает результат - объектный код. В другом варианте он выполняет над исходным текстом только некоторые из фаз компиляции и получает не конечный результат, а набор некоторых промежуточных данных. Эти данные затем снова подвергаются обработке, причем этот процесс может повторяться несколько раз.
Реальные компиляторы, как правило, выполняют трансляцию текста исходной программы за несколько проходов.
Проход - это процесс последовательного чтения компилятором данных из внешней памяти, их обработки и помещения результата работы во внешнюю память. Чаще всего один проход включает в себя выполнение одной или нескольких фаз компиляции. Результатом промежуточных проходов является внутреннее представление исходной программы, результатом последнего прохода - результирующая объектная программа.
В качестве внешней памяти могут выступать любые носители информации - оперативная память компьютера, накопители на магнитных дисках, магнитных лентах и т. п. Современные компиляторы, как правило, стремятся максимально использовать для хранения данных оперативную память компьютера, и только при недостатке объема доступной памяти используются накопители на жестких магнитных дисках. Другие носители информации в современных компиляторах не используются из-за невысокой скорости обмена данными.
При выполнении каждого прохода компилятору доступна информация, полученная в результате всех предыдущих проходов. Как правило, он стремится использовать в первую очередь только информацию, полученную на проходе, непосредственно предшествовавшем текущему, но в принципе может обращаться и к данным от более ранних проходов вплоть до исходного текста программы. Информация, получаемая компилятором при выполнении проходов, недоступна пользователю. Она либо хранится в оперативной памяти, которая освобождается компилятором после завершения процесса трансляции, либо оформляется в виде временных файлов на диске, которые также уничтожаются после завершения работы компилятора. Поэтому человек, работающий с компилятором, может даже не знать, сколько проходов выполняет компилятор - он всегда видит только текст исходной программы и результирующую объектную программу. Но количество выполняемых проходов - это важная техническая характеристика компилятора, солидные фирмы - разработчики компиляторов обычно указывают ее в описании своего продукта.
Понятно, что разработчики стремятся максимально сократить количество проходов, выполняемых компиляторами. При этом увеличивается скорость работы компилятора, сокращается объем необходимой ему памяти. Однопроходный компилятор, получающий на вход исходную программу и сразу же порождающий результирующую объектную программу, - это идеальный вариант.
Однако сократить число проходов не всегда удается. Количество необходимых проходов определяется прежде всего грамматикой и семантическими правилами исходного языка. Чем сложнее грамматика языка и чем больше вариантов предполагают семантические правила - тем больше проходов будет выполнять компилятор (конечно, играет свою роль и квалификация разработчиков компилятора). Например, именно поэтому обычно компиляторы с языка Pascal работают быстрее, чем компиляторы с языка С - грамматика языка Pascal более проста, а семантические правила более жесткие. Однопроходные компиляторы - редкость, они возможны только для очень простых языков. Реальные компиляторы выполняют, как правило, от двух до пяти проходов. Таким образом, реальные компиляторы являются многопроходными. Наиболее распространены двух- и трехпроходные компиляторы, например: первый проход - лексический анализ, второй - синтаксический разбор и семантический анализ, третий - генерация и оптимизация кода (варианты исполнения, конечно, зависят от разработчика). В современных системах программирования нередко первый проход компилятора (лексический анализ кода) выполняется параллельно с редактированием кода исходной программы (такой вариант построения компиляторов рассмотрен далее в этой главе).
Интерпретаторы. Особенности построения интерпретаторов
Интерпретатор - это программа, которая воспринимает входную программу на исходном языке и выполняет ее. Как уже было сказано выше, основное отличие интерпретаторов от трансляторов и компиляторов заключается в том, что интерпретатор не порождает результирующую программу, а просто выполняет исходную программу.
Термин «интерпретатор» (interpreter), как и «транслятор», означает «переводчик». С точки зрения терминологии эти понятия схожи, но с точки зрения теории формальных языков и компиляции между ними большая принципиальная разница. Если понятия «транслятор» и «компилятор» почти неразличимы, то с понятием «интерпретатор» их путать никак нельзя.
Простейшим способом реализации интерпретатора можно было бы считать вариант, когда исходная программа сначала полностью транслируется в машинные команды, а затем сразу же выполняется. В такой реализации интерпретатор, по сути, мало бы чем отличался от компилятора с той лишь разницей, что результирующая программа в нем была бы недоступна пользователю. Недостатком такого интерпретатора было бы то, что пользователь должен был бы ждать компиляции всей исходной программы прежде, чем начнется ее выполнение. По сути, в таком интерпретаторе не было бы никакого особого смысла - он не давал бы никаких преимуществ по сравнению с аналогичным компилятором 1 . Поэтому подавляющее большинство интерпретаторов действует так, что исполняет исходную программу последовательно, по мере ее поступления на вход интерпретатора. Тогда пользователю не надо ждать завершения компиляции всей исходной программы. Более того, он может последовательно вводить исходную программу и тут же наблюдать результат ее выполнения по мере ввода команд .
При таком порядке работы интерпретатора проявляется существенная особенность, которая отличает его от компилятора, - если интерпретатор исполняет команды по мере их поступления, то он не может выполнять оптимизацию исходной программы. Следовательно, фаза оптимизации в общей структуре интер- претатора будет отсутствовать. В остальном же она будет мало отличаться от структуры аналогичного компилятора. Следует только учесть, что на последнем этапе - генерации кода - машинные команды не записываются в объектный файл, а выполняются по мере их порождения.
Отсутствие шага оптимизации определяет еще одну особенность, характерную для многих интерпретаторов: в качестве внутреннего представления программы в них очень часто используется обратная польская запись (см. раздел «Генерация кода. Методы генерации кода», глава 14). Эта удобная форма представления операций обладает только одним существенным недостатком - она плохо поддается оптимизации. Но в интерпретаторах именно это как раз и не требуется.
Далеко не все языки программирования допускают построение интерпретаторов которые могли бы выполнять исходную программу по мере поступления команд Для этого язык должен допускать возможность существования компилятора выполняющего разбор исходной программы за один проход. Кроме того, язык не может интерпретироваться по мере поступления команд, если он допускает по явление обращений к функциям и структурам данных раньше их непосредствен ного описания. Поэтому данным методом не могут интерпретироваться такш языки, как С и Pascal.
Отсутствие шага оптимизации ведет к тому, что выполнение программы с помо щью интерпретатора является менее эффективным, чем с помощью аналогично го компилятора. Кроме того, при интерпретации исходная программа должна за ново разбираться всякий раз при ее выполнении, в то время как при компиляци] она разбирается только один раз, а после этого всегда используется объектны] файл. Таким образом, интерпретаторы всегда проигрывают компиляторам в про изводительности.
Преимуществом интерпретатора является независимость выполнения програм мы от архитектуры целевой вычислительной системы. В результате компиляци: получается объектный код, который всегда ориентирован на определенную архн тектуру. Для перехода на другую архитектуру целевой вычислительной систем] программу требуется откомпилировать заново. А для интерпретации программ] необходимо иметь только ее исходный текст и интерпретатор с соответствующе го языка.
Интерпретаторы долгое время значительно уступали в распространенности коь пиляторам. Как правило, интерпретаторы существовали для ограниченного крз га относительно простых языков программирования (таких, например, как Basic Высокопроизводительные профессиональные средства разработки программш го обеспечения строились на основе компиляторов.
Новый импульс развитию интерпретаторов придало распространение глобал] ных вычислительных сетей. Такие сети могут включать в свой состав ЭВМ ра: личной архитектуры, и тогда требование единообразного выполнения на каждс из них текста исходной программы становится определяющим. Поэтому с разв] тием глобальных сетей и распространением всемирной сети Интернет появило
В современных системах программирования существуют реализации программного обеспечения, сочетающие в себе и функции компилятора, и функции интерпретатора - в зависимости от требований пользователя исходная программа либо компилируется, либо исполняется (интерпретируется). Кроме того, некоторые современные языки программирования предполагают две стадии разработки: сначала исходная программа компилируется в промежуточный код (некоторый язык низкого уровня), а затем этот результат компиляции выполняется с помощью интерпретатора данного промежуточного языка. Более подробно варианты таких систем рассмотрены в главе «Современные системы программирования».
Широко распространенным примером интерпретируемого языка может служить HTML (Hypertext Markup Language) - язык описания гипертекста. На его основе в настоящее время функционирует практически вся структура сети Интернет. Другой пример - языки Java и JavaScript - сочетают в себе функции компиляции и интерпретации. Текст исходной программы компилируется в некоторый промежуточный двоичный код, не зависящий от архитектуры целевой вычислительной системы, этот код распространяется по сети и выполняется на принимающей стороне - интерпретируется.
Трансляторы с языка ассемблера («ассемблеры»)
Язык ассемблера - это язык низкого уровня. Структура и взаимосвязь цепочек этого языка близки к машинным командам целевой вычислительной системы, где должна выполняться результирующая программа. Применение языка ассемблера позволяет разработчику управлять ресурсами (процессором, оперативной памятью, внешними устройствами и т. п.) целевой вычислительной системы на уровне машинных команд. Каждая команда исходной программы на языке ассемблера в результате компиляции преобразуется в одну машинную команду.
Транслятор с языка ассемблера всегда, безусловно, будет и компилятором, поскольку языком результирующей программы являются машинные коды. Транслятор с языка ассемблера зачастую просто называют «ассемблер» или «программа ассемблера».
Реализация компиляторов с языка ассемблера
Язык ассемблера, как правило, содержит мнемонические коды машинных команд. Чаще всего используется англоязычная мнемоника команд, но существуют и другие варианты языков ассемблера (в том числе существуют и русскоязычные варианты). Именно поэтому язык ассемблера раньше носил названия «язык мнемокодов» (сейчас это название уже практически не употребляется). Все возможные команды в каждом языке ассемблера можно разбить на две группы: в первую группу входят обычные команды языка, которые в процессе трансляции преобразуются в машинные команды; вторую группу составляют специальные команды языка, которые в машинные команды не преобразуются, но используются компилятором для выполнения задач компиляции (таких, например, как задача распределения памяти). Синтаксис языка чрезвычайно прост. Команды исходной программы записыв ются обычно таким образом, чтобы на одной строке программы располагала одна команда. Каждая команда языка ассемблера, как правило, может быть рг делена на три составляющих, следующих последовательно одна за другой: по метки, код операции и поле операндов. Компилятор с языка ассемблера обыч] предусматривает и возможность наличия во входной программе комментарш которые отделяются от команд заданным разделителем .
Поле метки содержит идентификатор, представляющий собой метку, либо явл ется пустым. Каждый идентификатор метки может встречаться в программе языке ассемблера только один раз. Метка считается описанной там, где она у посредственно встретилась в программе (предварительное описание меток требуется). Метка может быть использована для передачи управления на поь ченную ею команду. Нередко метка отделяется от остальной части команды сг циальным разделителем (чаще всего - двоеточием «:»).
Код операции всегда представляет собой строго определенную мнемонику одн из возможных команд процессора или также строго определенную команду (мого компилятора. Код операции записывается алфавитными символами вхс ного языка. Чаще всего его длина составляет 3-4, реже - 5 или 6 символов.
Поле операндов либо является пустым, либо представляет собой список из одг го, двух, реже - трех операндов. Количество операндов строго определено и: висит от кода операции - каждая операция языка ассемблера предусматривг жестко заданное число своих операндов. Соответственно, каждому из этих вар антов соответствуют безадресные, одноадресные, двухадресные или трехадресн команды (большее число операндов практически не используется, в совреме ных ЭВМ даже трехадресные команды встречаются редко). В качестве опер; дов могут выступать идентификаторы или константы.
Особенностью языка ассемблера является то, что ряд идентификаторов в н выделяется специально для обозначения регистров процессора. Такие идет фикаторы, с одной стороны, не требуют предварительного описания, но, с Д1 гой, они не могут быть использованы пользователем для иных целей. Набор эт идентификаторов предопределен для каждого языка ассемблера.
Иногда язык ассемблера допускает использование в качестве операндов оп] деленных ограниченных сочетаний обозначений регистров, идентификатор и констант, которые объединены некоторыми знаками операций. Такие соче ния чаще всего используются для обозначения типов адресации, допустим в машинных командах целевой вычислительной системы.
Например, следующая последовательность команд
Представляет собой пример последовательности команд языка ассемблера п; цессоров семейства Intel 80x86. Здесь присутствуют команда описания наб(данных (db), метка (loops), коды операций (mov, dec и jnz). Операндами яв. ются идентификатор набора данных (datas), обозначения регистров процессе
(Ьх и сх), метка (loops) и константа (4). Составной операнд datas отображает косвенную адресацию набора данных datas по базовому регистру Ьх со смещением 4.
Подобный синтаксис языка без труда может быть описан с помощью регулярной грамматики. Поэтому построение распознавателя для языка ассемблера не представляет труда. По этой же причине в компиляторах с языка ассемблера лексический и синтаксический разбор, как правило, совмещены в один распознаватель.
Семантика языка ассемблера целиком и полностью определяется целевой вычислительной системой, на которую ориентирован данный язык. Семантика языка ассемблера определяет, какая машинная команда соответствует каждой команде языка ассемблера, а также то, какие операнды и в каком количестве допустимы для того или иного кода операции.
Поэтому семантический анализ в компиляторе с языка ассемблера также прост, как и синтаксический. Основной его задачей является проверить допустимость операндов для каждого кода операции, а также проверить, что все идентификаторы и метки, встречающиеся во входной программе, описаны и обозначающие их идентификаторы не совпадают с предопределенными идентификаторами, используемыми для обозначения кодов операции и регистров процессора.
Схемы синтаксического и семантического анализа в компиляторе с языка ассемблера могут быть, таким образом, реализованы на основе обычного конечного автомата. Именно эта особенность определила тот факт, что компиляторы с языка ассемблера исторически явились первыми компиляторами, созданными для ЭВМ. Существует также ряд других особенностей, которые присущи именно языкам ассемблера и упрощают построение компиляторов для них.
Во-первых, в компиляторах с языка ассемблера не выполняется дополнительная идентификация переменных - все переменные языка сохраняют имена, присвоенные им пользователем. За уникальность имен в исходной программе отвечает ее разработчик, семантика языка никаких дополнительных требований на этот процесс не накладывает. Во-вторых, в компиляторах с языка ассемблера предельно упрощено распределение памяти. Компилятор с языка ассемблера работает только со статической памятью. Если используется динамическая память, то для работы с нею нужно использовать соответствующую библиотеку или функции ОС, а за ее распределение отвечает разработчик исходной программы. За передачу параметров и организацию дисплея памяти процедур и функций также отвечает разработчик исходной программы. Он же должен позаботиться и об отделении данных от кода программы - компилятор с языка ассемблера, в отличие от компиляторов с языков высокого уровня, автоматически такого разделения не выполняет. И в-третьих, на этапе генерации кода в компиляторе с языка ассемблера не производится оптимизация, поскольку разработчик исходной программы сам отвечает за организацию вычислений, последовательность машинных команд и распределение регистров процессора.
За исключением этих особенностей компилятор с языка ассемблера является обычным компилятором, но значительно упрощенным по сравнению с любым компилятором с языка высокого уровня. Компиляторы с языка ассемблера реализуются чаще всего по двухпроходной схеме. На первом проходе компилятор выполняет разбор исходной программы, ее преобразование в машинные коды и одновременно заполняет таблицу идентификаторов. Но на первом проходе в машинных командах остаются незаполненными адреса тех операндов, которые размещаются в оперативной памяти. На втором проходе компилятор заполняет эти адреса и одновременно обнаруживает неописанные идентификаторы. Это связано с тем, что операнд может быть описан в программе после того, как он первый раз был использован. Тогда его адрес еще не известен на момент построения машинной команды, а поэтому требуется второй проход. Типичным примером такого операнда является метка, предусматривающая переход вперед по ходу последовательности команд.
Макроопределения и макрокоманды
Разработка программ на языке ассемблера - достаточно трудоемкий процесс, требующий зачастую простого повторения одних и тех же многократно встречающихся операций. Примером может служить последовательность команд, выполняемых каждый раз для организации стекового дисплея памяти при входе в процедуру или функцию.
Для облегчения труда разработчика были созданы так называемые макрокоманды.
Макрокоманда представляет собой текстовую подстановку, в ходе выполнения которой каждый идентификатор определенного вида заменяется на цепочку символов из некоторого хранилища данных. Процесс выполнения макрокоманды называется макрогенерацией, а цепочка символов, получаемая в результате выполнения макрокоманды, - макрорасширением.
Процесс выполнения макрокоманд заключается в последовательном просмотре текста исходной программы, обнаружении в нем определенных идентификаторов и их замене на соответствующие строки символов. Причем выполняется именно текстовая замена одной цепочки символов (идентификатора) на другую цепочку символов (строку). Такая замена называется макроподстановкой .
Для того чтобы указать, какие идентификаторы на какие строки необходимо заменять, служат макроопределения. Макроопределения присутствуют непосредственно в тексте исходной программы. Они выделяются специальными ключевыми словами либо разделителями, которые не могут встречаться нигде больше в тексте программы. В процессе обработки все макроопределения полностью исключаются из текста входной программы, а содержащаяся в них информация запоминается для обработки при выполнении макрокоманд.
Макроопределение может содержать параметры. Тогда каждая соответствующая ему макрокоманда должна при вызове содержать строку символов вместо каждого параметра. Эта строка подставляется при выполнении макрокоманды в каждое место, где в макроопределении встречается соответствующий параметр. В качестве параметра макрокоманды может оказаться другая макрокоманда, тогда она будет рекурсивно вызвана всякий раз, когда необходимо выполнить подстановку параметра. В принципе макрокоманды могут образовывать последовательность
Рекурсивных вызовов, аналогичную последовательности рекурсивных вызовов процедур и функций, но только вместо вычислений и передачи параметров они выполняют лишь текстовые подстановки 1 .
Макрокоманды и макроопределения обрабатываются специальным модулем, называемым макропроцессором или макрогенератором. Макрогенератор получает на вход текст исходной программы, содержащий макроопределения и макрокоманды, а на выходе его появляется текст макрорасширения исходной программы, не содержащий макроопределений и макрокоманд. Оба текста являются только текстами программы, никакая другая обработка не выполняется. Именно макрорасширение исходного текста поступает на вход компилятора.
Синтаксис макрокоманд и макроопределений не является строго заданным. Он может различаться в зависимости от реализации компилятора с языка ассемблера. Но сам принцип выполнения макроподстановок в тексте программы неизменен и не зависит от их синтаксиса.
Макрогенератор чаще всего не существует в виде отдельного программного модуля, а входит в состав компилятора с языка ассемблера. Макрорасширение исходной программы обычно недоступно ее разработчику. Более того, макроподстановки могут выполняться последовательно при разборе исходного текста на первом проходе компилятора вместе с разбором всего текста программы, и тогда макрорасширение исходной программы в целом может и вовсе не существовать как таковое.
Например, следующий текст определяет макрокоманду push_0 в языке ассемблера процессора типа Intel 8086:
Хог ах,ах ■ push ax endm
Семантика этой макрокоманды заключается в записи числа «0» в стек через регистр процессора ах. Тогда везде в тексте программы, где встретится макрокоманда
Она будет заменена в результате макроподстановки на последовательность команд:
Хог ах,ах ■ push ax
Это самый простой вариант макроопределения. Существует возможность создавать более сложные макроопределения с параметрами. Одно из таких макроопределений описано ниже:
Глубина такой рекурсии, как правило, сильно ограничена. На последовательность рекурсивных вызовов макрокоманд налагаются обычно существенно более жесткие ограничения, чем на последовательность рекурсивных вызовов процедур и функций, которая при стековой организации дисплея памяти ограничена только размером стека передачи параметров. add_abx macro xl,x2
Push ax
endm
Тогда в тексте программы макрокоманда также должна быть указана с соответствующим числом параметров. В данном примере макрокоманда
Add_abx4,8 будет в результате макроподстановки заменена на последовательность команд:
Add ах,4 add bx.4 add ex,8 push ax
Во многих компиляторах с языка ассемблера возможны еще более сложные конструкции, которые могут содержать локальные переменные и метки. Примером такой конструкции может служить макроопределение:
Loop_ax macro xl,x2,yl
Хог bx.bx loopax: add bx.yl
Здесь метка 1 oopax является локальной, определенной только внутри данного макроопределения. В этом случае уже не может быть выполнена простая текстовая подстановка макрокоманды в текст программы, поскольку если данную макрокоманду выполнить дважды, то это приведет к появлению в тексте программы двух одинаковых меток 1 оорах. В таком варианте макрогенератор должен использовать более сложные методы текстовых подстановок, аналогичные тем, что используются в компиляторах при идентификации лексических элементов входной программы, чтобы дать всем возможным локальным переменным и меткам макрокоманд уникальные имена в пределах всей программы. Макроопределения и макрокоманды нашли применение не только в языках ассемблера, но и во многих языках высокого уровня. Там их обрабатывает специальный модуль, называемый препроцессором языка (например, широко известен препроцессор языка С). Принцип обработки остается тем же самым, что и для программ на языке ассемблера - препроцессор выполняет текстовые подстановки непосредственно над строками самой исходной программы. В языках высокого уровня макроопределения должны быть отделены от текста самой исходной программы, чтобы препроцессор не мог спутать их с синтаксическими конструкциями входного языка. Для этого используются либо специальные символы и команды (команды препроцессора), которые никогда не могут встречаться в тексте исходной программы, либо макроопределения встречаются
Внутри незначащей части исходной программы - входят в состав комментариев (такая реализация существует, например, в компиляторе с языка Pascal, созданном фирмой Borland). Макрокоманды, напротив, могут встречаться в произвольном месте исходного текста программы, и синтаксически их вызов может не отличаться от вызова функций во входном языке.
Следует помнить, что, несмотря на схожесть синтаксиса вызова, макрокоманды принципиально отличаются от процедур и функций, поскольку не порождают результирующего кода, а представляют собой текстовую подстановку, выполняемую прямо в тексте исходной программы. Результат вызова функции и макрокоманды может из-за этого серьезно отличаться.
Рассмотрим пример на языке С. Если описана функция
Int fKint a) { return a + а: } и аналогичная ей макрокоманда
#define f2(a) ((a) + (а)) то результат их вызова не всегда будет одинаков.
Действительно, вызовы j=fl(i) и j=f2(i) (где i и j - некоторые целочисленные переменные) приведут к одному и тому же результату. Но вызовы j=fl(++i) и j=f2(++i) дадут разные значения переменной j. Дело в том, что поскольку f2 - это макроопределение, то во втором случае будет выполнена текстовая подстановка, которая приведет к последовательности операторов j=((++i) + (++i)). Видно, что в этой последовательности операция ++i будет выполнена дважды, в отличие от вызова функции fl(++i), где она выполняется только один раз.
Так как текст программы, записанной на каком-нибудь языке программирования, не понятен компьютеру, то требуется перевести его на машинный язык. Перевод программы с языка программирования на язык машинных кодов называется трансляцией (translation - перевод), а выполняется он специальными программами – трансляторами .
Существуют два вида трансляторов: интерпретаторы, компиляторы.
Интерпретатором называется транслятор, производящий пооператорную (покомандную) трансляцию и последующее выполнение оттранслированного оператора исходной программы. Два недостатка метода интерпретации:
1. интерпретирующая программа должна находиться в памяти ЭВМ в течение всего процесса выполнения исходной программы, т.е занимать определенный объем памяти;
2. процесс трансляции одного и того же оператора повторяется столько раз, сколько раз должна исполняться эта команды в программе.
Компилятор – это программа, которая преобразует (транслирует) исходную программу в программу (модуль) на машинном языке. После этого программа записывается в память компьютера и только потом исполняется.
При компиляции процессы трансляции и выполнения разделены во времени: сначала исходная программа полностью переводится на машинный язык (после чего наличие транслятора в оперативной памяти не нужен), а затем оттранслированная программа может многократно исполняться.
Любой транслятор решает следующие основные задачи:
1. Анализирует транслируемую программу и определяет, содержит ли она синтаксические ошибки;
2. Генерирует выходную программу на языке команд ЭВМ;
3. Распределяет память для выходной программы, т.е. каждой переменной, константе, массивам и другим объектам отводится свой участок памяти.
Таким образом, Компилятор (англ. compiler - составитель, собиратель) читает всю программу целиком , делает ее перевод и создает законченный вариант программы на машинном языке, который затем и выполняется.
Интерпретатор (англ. interpreter - истолкователь, устный переводчик) переводит и выполняет программу строка за строкой .
После того, как программа откомпилирована, ни сама исходная программа, ни компилятор более не нужны. В то же время программа, обрабатываемая интерпретатором, должна заново переводиться на машинный язык при каждом очередном запуске программы.
Каждый конкретный язык ориентирован либо на компиляцию, либо на интерпретацию - в зависимости от того, для каких целей он создавался. Например, Паскаль обычно используется для решения довольно сложных задач, в которых важна скорость работы программ. Поэтому данный язык обычно реализуется с помощью компилятора . С другой стороны, Бейсик создавался как язык для начинающих программистов, для которых построчное выполнение программы имеет неоспоримые преимущества. Иногда для одного языка имеется и компилятор , и интерпретатор . В этом случае для разработки и тестирования программы можно воспользоваться интерпретатором, а затем откомпилировать отлаженную программу, чтобы повысить скорость ее выполнения. |
Поскольку текст, записанный на языке программирования, непонятен компьютеру, то требуется перевести его на машинный код. Такой перевод программы с языка программирования на язык машинных кодов называется трансляцией, а выполняется она специальными программами – трансляторами.
Транслятор - обслуживающая программа, преобразующая исходную программу, предоставленную на входном языке программирования, в рабочую программу, представленную на объектном языке.
В настоящее время трансляторы разделяются на три основные группы: ассемблеры, компиляторы и интерпретаторы.
Ассемблер - системная обслуживающая программа, которая преобразует символические конструкции в команды машинного языка. Специфической чертой ассемблеров является то, что они осуществляют дословную трансляцию одной символической команды в одну машинную. Таким образом, язык ассемблера (еще называется автокодом) предназначен для облегчения восприятия системы команд компьютера и ускорения программирования в этой системе команд. Программисту гораздо легче запомнить мнемоническое обозначение машинных команд, чем их двоичный код.
Вместе с тем, язык ассемблера, кроме аналогов машинных команд, содержит множество дополнительных директив, облегчающих, в частности, управление ресурсами компьютера, написание повторяющихся фрагментов, построение многомодульных программ. Поэтому выразительность языка намного богаче, чем просто языка символического кодирования, что значительно повышает эффективность программирования.
Компилятор - это обслуживающая программа, выполняющая трансляцию на машинный язык программы, записанной на исходном языке программирования. Также как и ассемблер, компилятор обеспечивает преобразование программы с одного языка на другой (чаще всего, в язык конкретного компьютера). Вместе с тем, команды исходного языка значительно отличаются по организации и мощности от команд машинного языка. Существуют языки, в которых одна команда исходного языка транслируется в 7-10 машинных команд. Однако есть и такие языки, в которых каждой команде может соответствовать 100 и более машинных команд (например, Пролог). Кроме того, в исходных языках достаточно часто используется строгая типизация данных, осуществляемая через их предварительное описание. Программирование может опираться не на кодирование алгоритма, а на тщательное обдумывание структур данных или классов. Процесс трансляции с таких языков обычно называется компиляцией, а исходные языки обычно относятся к языкам программирования высокого уровня (или высокоуровневым языкам). Абстрагирование языка программирования от системы команд компьютера привело к независимому созданию самых разнообразных языков, ориентированных на решение конкретных задач. Появились языки для научных расчетов, экономических расчетов, доступа к базам данных и другие.
Интерпретатор - программа или устройство, осуществляющее пооператорную трансляцию и выполнение исходной программы. В отличие от компилятора, интерпретатор не порождает на выходе программу на машинном языке. Распознав команду исходного языка, он тут же выполняет ее. Как в компиляторах, так и в интерпретаторах используются одинаковые методы анализа исходного текста программы. Но интерпретатор позволяет начать обработку данных после написания даже одной команды. Это делает процесс разработки и отладки программ более гибким. Кроме того, отсутствие выходного машинного кода позволяет не "захламлять" внешние устройства дополнительными файлами, а сам интерпретатор можно достаточно легко адаптировать к любым машинным архитектурам, разработав его только один раз на широко распространенном языке программирования. Поэтому, интерпретируемые языки, типа Java Script, VB Script, получили широкое распространение. Недостатком интерпретаторов является низкая скорость выполнения программ. Обычно интерпретируемые программы выполняются в 50-100 раз медленнее программ, написанных в машинных кодах.
Эмулятор - программа или программно-техническое средство, обеспечивающее возможность без перепрограммирования выполнять на данной ЭВМ программу, использующую коды или способы выполнения операция, отличные от данной ЭВМ. Эмулятор похож на интерпретатор тем, что непосредственно исполняет программу, написанную на некотором языке. Однако, чаще всего это машинный язык или промежуточный код. И тот и другой представляют команды в двоичном коде, которые могут сразу исполняться после распознавания кода операций. В отличие от текстовых программ, не требуется распознавать структуру программы, выделять операнды.
Эмуляторы используются достаточно часто в самых различных целях. Например, при разработке новых вычислительных систем, сначала создается эмулятор, выполняющий программы, разрабатываемые для еще несуществующих компьютеров. Это позволяет оценить систему команд и наработать базовое программное обеспечение еще до того, как будет создано соответствующее оборудование.
Очень часто эмулятор используется для выполнения старых программ на новых вычислительных машинах. Обычно новые компьютеры обладают более высоким быстродействием и имеют более качественное периферийное оборудование. Это позволяет эмулировать старые программы более эффективно по сравнению с их выполнением на старых компьютерах.
Перекодировщик - программа или программное устройство, переводящие программы, написанные на машинном языке одной ЭВМ в программы на машинном языке другой ЭВМ. Если эмулятор является менее интеллектуальным аналогом интерпретатора, то перекодировщик выступает в том же качестве по отношению к компилятору. Точно также исходный (и обычно двоичный) машинный код или промежуточное представление преобразуются в другой аналогичный код по одной команде и без какого-либо общего анализа структуры исходной программы. Перекодировщики бывают полезны при переносе программ с одних компьютерных архитектур на другие. Они могут также использоваться для восстановления текста программы на языке высокого уровня по имеющемуся двоичному коду.
Макропроцессор - программа, обеспечивающая замену одной последовательности символов другой. Это разновидность компилятора. Он осуществляет генерацию выходного текста путем обработки специальных вставок, располагаемых в исходном тексте. Эти вставки оформляются специальным образом и принадлежат конструкциям языка, называемого макроязыком. Макропроцессоры часто используются как надстройки над языками программирования, увеличивая функциональные возможности систем программирования. Практически любой ассемблер содержит макропроцессор, что повышает эффективность разработки машинных программ. Такие системы программирования обычно называются макроассемблерами.
Макропроцессоры используются и с языками высокого уровня. Они увеличивают функциональные возможности таких языков как PL/1, C, C++. Особенно широко макропроцессоры применяются в C и C++, позволяя упростить написание программ. Макропроцессоры повышают эффективность программирования без изменения синтаксиса и семантики языка.
Синтаксис - совокупность правил некоторого языка, определяющих формирование его элементов. Иначе говоря, это совокупность правил образования семантически значимых последовательностей символов в данном языке. Синтаксис задается с помощью правил, которые описывают понятия некоторого языка. Примерами понятий являются: переменная, выражение, оператор, процедура. Последовательность понятий и их допустимое использование в правилах определяет синтаксически правильные структуры, образующие программы. Именно иерархия объектов, а не то, как они взаимодействуют между собой, определяются через синтаксис. Например, оператор может встречаться только в процедуре, а выражение в операторе, переменная может состоять из имени и необязательных индексов и т.д. Синтаксис не связан с такими явлениями в программе как "переход на несуществующую метку" или "переменная с данным именем не определена". Этим занимается семантика.
Семантика - правила и условия, определяющие соотношения между элементами языка и их смысловыми значениями, а также интерпретацию содержательного значения синтаксических конструкций языка. Объекты языка программирования не только размещаются в тексте в соответствии с некоторой иерархией, но и дополнительно связаны между собой посредством других понятий, образующих разнообразные ассоциации. Например, переменная, для которой синтаксис определяет допустимое местоположение только в описаниях и некоторых операторах, обладает определенным типом, может использоваться с ограниченным множеством операций, имеет адрес, размер и должна быть описана до того, как будет использоваться в программе.
Синтаксический анализатор - компонента компилятора, осуществляющая проверку исходных операторов на соответствие синтаксическим правилам и семантике данного языка программирования. Несмотря на название, анализатор занимается проверкой и синтаксиса, и семантики. Он состоит из нескольких блоков, каждый из которых решает свои задачи. Более подробно будет рассмотрен при описании структуры транслятора.
Любой транслятор выполняет следующие основные задачи:
Анализирует транслируемую программу, в частности определяет, содержит ли она синтаксические ошибки;
Генерирует выходную программу (ее часто называют объектной) на языке машинных команд;
Распределяет память для объектной программы.