Реферат: Транслятор, компилятор, интерпретатор

Транслятор, компилятор, интерпретатор
Трансля́тор — программа или техническое средство, выполняющее трансляцию программы.

Транслятор обычно выполняет также диагностику ошибок, формирует словари идентификаторов, выдаёт для печати тексты программы и т. д.

Трансляция программы — преобразование программы, представленной на одном из языков программирования, в программу на другом языке и, в определённом смысле, равносильную первой.

Язык, на котором представлена входная программа, называется исходным языком, а сама программа — исходным кодом. Выходной язык называется целевым языком или объектным кодом.

Понятие трансляции относится не только к языкам программирования, но и к другим компьютерным языкам, вроде языков разметки, аналогичных HTML, и к естественным языкам, вроде английского или русского.

Трансляторы подразделяют:

Адресный. Функциональное устройство, преобразующее виртуальный адрес (англ. Virtual address) в реальный адрес.

Диалоговый. Обеспечивает использование языка программирования в режиме разделения времени.

Многопроходной. Формирует объектный модуль за несколько просмотров исходной программы.

Обратный. То же, что детранслятор. См. также: декомпилятор, дизассемблер.

Однопроходной. Формирует объектный модуль за один последовательный просмотр исходной программы.

Оптимизирующий. Выполняет оптимизацию кода в создаваемом объектном модуле.

Синтаксически-ориентированный (синтаксически-управляемый). Получает на вход описание синтаксиса и семантики языка и текст на описанном языке, который и транслируется в соответствии с заданным описанием.

Тестовый. Набор макрокоманд языка ассемблера, позволяющих задавать различные отладочные процедуры в программах, составленных на языке ассемблера.

Цель трансляции — преобразовать текст с одного языка на другой, который понятен адресату текста. В случае программ-трансляторов, адресатом является техническое устройство (процессор) или программа-интерпретатор.

Компиля́тор —

Программа или техническое средство, выполняющее компиляцию.

Машинная программа, используемая для компиляции.

Программа, переводящая текст программы на языке высокого уровня в эквивалентную программу на машинном языке.

Программа, предназначенная для трансляции высокоуровневого языка в абсолютный код или, иногда, в язык ассемблера. Входной информацией для компилятора (исходный код) является описание алгоритма или программа на проблемно-ориентированном языке, а на выходе компилятора — эквивалентное описание алгоритма на машинно-ориентированном языке(объектный код).

Программа выполняющая (после трансляции) компоновку программы.

Компиляция —

трансляция программы на язык, близкий к машинному, и последующая её компоновка.

трансляция программы, составленной на исходном языке, в объектный модуль (осуществляется компилятором) и последующая её компоновка в готовый к использованию программный модуль.

трансляция программы, составленной на исходном языке, и последующая её компоновка в программу на некоем машинонезависимом низкоуровневом интерпретируемом коде (как например в случае языка Java).

Компилировать — производить трансляцию машинной программы с проблемно-ориентированного языка на машинно-ориентированный язык и последующую компоновку программы в готовый к использованию программный модуль.

Векторизующий. Компилирует исходный код в машинный код для компьютеров, оснащённых векторным процессором.

Гибкий. Сконструирован по модульному принципу, управляется таблицами и запрограммирован на языке высокого уровня или реализован с помощью компилятора компиляторов.

Диалоговый

Инкрементальный. Повторно транслирует/компонует фрагменты программы и дополнения к ней без перекомпиляции всей программы.

Интерпретирующий (пошаговый). Последовательно выполняет независимую компиляцию каждого отдельного оператора(команды) исходной программы.

Компилятор компиляторов. Компилятор, воспринимающий формальное описание языка программирования и генерирующий компилятор для этого языка.

Отладочный. Устраняет отдельные виды синтаксических ошибок.

Резидентный. Постоянно находится в оперативной памяти и доступен для повторного использования многими задачами.

Самокомпилируемый. Написан на том же языке, с которого осуществляется компиляция.

Универсальный. Основан на формальном описании синтаксиса и семантики входного языка. Важными составными частями такого компилятора являются: ядро, синтаксический и семантический загрузчики.

Пакетная. Компиляция нескольких исходных модулей в одном пункте задания.

Построчная. То же, что и интерпретация.

Условная. Компиляция, при которой транслируемый текст зависит от условий, заданных в исходной программе директивами компилятора. Так, в зависимости от значения некоторой константы, можно включать или выключать трансляцию части текста программы.

Большинство компиляторов компилирует (в том числе транслирует) программу с некоторого высокоуровневого языка программирования в машинный код, который может быть непосредственно выполнен центральным процессором. Как правило, этот код также ориентирован на исполнение в среде конкретной операционной системы, поскольку использует предоставляемые ею возможности (системные вызовы, библиотеки функций, API). Архитектура или платформа (набор программно-аппаратных средств), для которой производится компиляция, называется целевой машиной или, также, целевой платформой.

Некоторые компиляторы (например, Java) переводят программу не в машинный код, а в программу на некотором специально созданном низкоуровневом интрепретируемом языке. Такой язык — байт-код (в случае с Java Java-байт-код) — также можно считать языком машинных команд, поскольку в качестве его интерпретатором используется виртуальная машина. Байт-код не является машинным кодом какого-либо компьютера, т. е. машинным кодом в прямом смысле слова, и может переноситься на различные компьютерные архитектуры без перекомпиляции. Байт-код интерпретируется (исполняется) виртуальной машиной.

Например, для языка Java это JVM (язык виртуальной машины Java), или так называемый байт-код Java (вслед за ним все промежуточные низкоуровневые интрепретируемые языки стали называть байт-кодами). Для языков программирования на платформе.NET Framework (C#, Managed C++, Visual Basic .NET и другие) — это MSIL (Microsoft Intermediate Language).

Программа на байт-коде подлежит интерпретации виртуальной машиной, либо ещё одной компиляции уже в машинный код непосредственно перед исполнением. Последнее называется «Just-In-Time компиляция» (JIT), по названию подобного компилятора для Java. MSIL-код компилируется в код целевой машины также JIT-компилятором, а библиотеки .NET Framework компилируются заранее.

Для каждой целевой машины (IBM, Apple, Sun и т. д.) и каждой операционной системы или семейства операционных систем, работающих на целевой машине, требуется написание своего компилятора. Существуют также так называемые кросс-компиляторы, позволяющие на одной машине и в среде одной ОС генерировать код, предназначенный для выполнения на другой целевой машине и/или в среде другой ОС. Кроме того, компиляторы могут быть оптимизированы под разные типы процессоров из одного семейства (путём поддержки специфичных для этих процессоров машинных команд). Например, код, скомпилированный под процессоры семейства Pentium, может использовать специфичные для этих процессоров наборы инструкций — MMX, SSE, SSE2.

Также существуют компиляторы, переводящие программу с языка высокого уровня на язык ассемблера. (Правда такие компиляторы, вообще-то следовало бы называть трансляторами...)

Существуют программы, которые решают обратную задачу — перевод программы с низкоуровневого языка на высокоуровневый. Этот процесс называют декомпиляцией, а такие программы — декомпиляторами. (Яркий пример таких программ - дизассемблеры) Но поскольку компиляция — это процесс с потерями, точно восстановить исходный код, скажем, на C++, в общем случае невозможно. Более эффективно декомпилируются программы в байт-кодах — например, существует довольно надёжный декомпилятор для Flash. Разновидность декомпилирования является дизассемблирование машинного кода в код на языке ассемблера, который всегда выполняется успешно. Связано это с тем, что между кодами машинных команд и командами ассемблера имеется практически взаимно-однозначное соответствие.

Любой компилятор состоит из транслятора и компоновщика. Часто в качестве компоновщика компилятор использует внешний компоновщик, реализованный в виде самостоятельной программы, а сам выполняет лишь трансляцию исходного текста (по этой причине многие ошибочно считают компилятором разновидность транслятора). Компилятор может быть реализован и как своеобразная программа-менеджер, для трансляции программы вызвающая сооствествующий транслятор (трансляторы - если разные части программы написаны на разных языках программирования) и затем - для компоновки программы, - вызывающаякомпоновщик. Ярким примером такого компилятора является имеющаяся во всех UNIX-системах (и Linux-системах в том числе) утилита make (имеются реализации утилиты make и в других системах, в частности в Windows-системах).

Процесс компиляции состоит из следующих фаз:

Лексический анализ. На этой фазе последовательность символов исходного файла преобразуется в последовательность лексем.

В информатике лексический анализ — процесс аналитического разбора входной последовательности символов (например, такой как исходный код на одном из языков программирования) с целью получения на выходе последовательности символов, называемых «токенами» (подобно группировке букв в словах). Группа символов входной последовательности, идентифицируемая на выходе процесса как токен, называется лексемой. В процессе лексического анализа производится распознавание и выделение лексем из входной последовательности символов.

Как правило, лексический анализ производится с точки зрения определённого формального языка или набора языков. Язык, а точнее его грамматика, задаёт определённый набор лексем, которые могут встретиться на входе процесса.

Традиционно принято организовывать процесс лексического анализа, рассматривая входную последовательность символов, как поток символов. При такой организации, процесс самостоятельно управляет выборкой отдельных символов из входного потока.

Распознавание лексем в контексте грамматики обычно производится путём их идентификации (или классификации), согласно идентификаторам (или классам) токенов, определяемых грамматикой языка. При этом, любая последовательность символов входного потока (лексема), которая, согласно грамматике, не может быть идентифицирована как токен языка, обычно рассматривается как специальная токен-ошибка.

Каждый токен можно представить в виде структуры, содержащей идентификатор токена (или идентификатор класса токена) и, если нужно, последовательность символов лексемы выделенной из входного потока (строку, число и т. д.).

Цель такой конвертации обычно состоит в том, чтобы подготовить входную последовательность для другой программы, например, для грамматического анализатора, и избавить его от определения лексических подробностей в контекстно-свободной грамматике (что привело бы к усложнению грамматики).

Лексический анализатор (англ. lexical analyzer или коротко lexer) — это программа или часть программы, выполняющая лексический анализ. Лексический анализатор обычно работает в две стадии: сканирование иоценка.

На первой стадии, сканировании, лексический анализатор обычно реализуется в виде конечного автомата, определяемого регулярными выражениями. В нём кодируется информация о возможных последовательностях символов, которые могут встречаться в токенах . Например, токен «целое число» может содержать любую последовательность десятичных цифр. Во многих случаях первый непробельный символ может использоваться для определения типа следующего токена, после чего входные символы обрабатываются один за другим пока не встретится символ, не входящий во множество допустимых символов для данного токена. В некоторых языках правила разбора лексем несколько более сложные и требуют возвратов назад по читаемой последовательности.

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

Токен с типом и соответственно подготовленным значением передаётся на вход синтаксического анализатора.


Синтаксический (грамматический) анализ. Последовательность лексем преобразуется в древо разбора.

В информатике, синтакси́ческий ана́лиз (па́рсинг) — это процесс сопоставления линейной последовательности лексем (слов, токенов) языка с его формальной грамматикой. Результатом обычно является дерево разбора (синтаксическое дерево). Обычно применяется совместно с лексическим анализом. Синтаксический анализатор (парсер) — это программа или часть программы, выполняющая синтаксический анализ.



Пример разбора выражения в дерево

При парсинге исходный текст преобразуется в структуру данных, обычно — в дерево, которое отражает синтаксическую структуру входной последовательности и хорошо подходит для дальнейшей обработки.

Как правило, результатом синтаксического анализа является синтаксическая структура предложения, представленная либо в виде дерева зависимостей, либо в виде дерева составляющих, либо в виде некоторой комбинации первого и второго способов представления.

Всё что угодно, имеющее «синтаксис», поддается автоматическому анализу.

Языки программирования — разбор исходного кода языков программирования, в процессе трансляции (компиляции илиинтерпретации).

Структурированные данные — данные, языки их описания, оформления и т. д. Например, XML, HTML, CSS, ini-файлы, специализированные конфигурационные файлы и т. п.

SQL-запросы (DSL-язык)

математические выражения

регулярные выражения (которые, в свою очередь, могут использоваться для автоматизации лексического анализа)

формальные грамматики

Лингвистика — человеческие языки. Например, машинный перевод и другие генераторы текстов.

Нисходящий парсер (англ. top-down parser) — продукции грамматики раскрываются, начиная со стартового символа, до получения требуемой последовательности токенов.

LL-анализатор

Восходящий парсер (англ. bottom-up parser) — продукции восстанавливаются из правых частей, начиная с токенов и кончая стартовым символом.

LR-анализатор

GLR-парсер

Простейший способ реагирования на некорректную входную цепочку лексем — завершить синтаксический анализ и вывести сообщение об ошибке. Однако часто оказывается полезным найти за одну попытку синтаксического анализа как можно больше ошибок. Именно так ведут себя трансляторы большинства распространённых языков программирования.

Таким образом перед обработчиком ошибок синтаксического анализатора стоят следующие задачи:

он должен ясно и точно сообщать о наличии ошибок;

он должен обеспечивать быстрое восстановление после ошибки, чтобы продолжать поиск других ошибок;

он не должен существенно замедлять обработку корректной входной цепочки.

Ниже описаны наиболее известные стратегии восстановления после ошибок.

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

Иногда при обнаружении ошибки синтаксический анализатор может выполнить локальную коррекцию входного потока так, чтобы это позволило ему продолжать работу. Например, перед точкой с запятой, отделяющей различные операторы в языке программирования, синтаксический анализатор может закрыть все ещё не закрытые круглые скобки. Это более сложный в проектировании и реализации способ, однако в некоторых ситуациях, он может работать значительно лучше восстановления в режиме паники. Естественно, данная стратегия бессильна, если настоящая ошибка произошла до точки обнаружения ошибки синтаксическим анализатором.

Знание наиболее распространённых ошибок позволяет расширить грамматику языка продукциями, порождающими ошибочные конструкции. При срабатывании таких продукций регистрируется ошибка, но синтаксический анализатор продолжает работать в обычном режиме.

Семантический анализ. Древо разбора обрабатывается с целью установления его семантики (смысла) — например, привязка идентификаторов к их определениям, типам данным, проверка совместимости типов данных, определение результирующих типов данных выражений и т. д. Результат обычно называется «промежуточным представлением/кодом», и может быть дополненным древом разбора, новым древом, абстрактным набором команд или чем-то ещё, удобным для дальнейшей обработки.

Оптимизация. Удаляются избыточные команды и упрощается (где это возможно) код с сохранением его смысла, т. е. реализуемого им алгоритма (в том числе предвычисляются (т. е. вычисляются на фазе трансляции) выражения, результаты которых практически являются константами). Оптимизация может быть на разных уровнях и этапах — например, над промежуточным кодом или над конечным машинным кодом.

Оптимизация — модификация системы для улучшения её эффективности. Система может быть одиночной компьютерной программой, набором компьютеров или даже целой сетью, такой как Интернет.

Хотя целью оптимизации является получение оптимальной системы, истинно оптимальная система в процессе оптимизации достигается далеко не всегда. Оптимизированная система обычно является оптимальной только для одной задачи или группы пользователей: где-то может быть важнее уменьшение времени, требуемого программе для выполнения работы, даже ценой потребления большего объёма памяти; в приложениях, где важнее память, могут выбираться более медленные алгоритмы с меньшими запросами к памяти.

Более того, зачастую не существует универсального решения, которое работает хорошо во всех случаях, поэтому инженеры используют компромиссные (англ. tradeoff) решения для оптимизации только ключевых параметров. К тому же, усилия, требуемые для достижения полностью оптимальной программы, которую невозможно дальше улучшить, практически всегда превышают выгоду, которая может быть от этого получена, поэтому, как правило, процесс оптимизации завершается до того, как достигается полная оптимальность. К счастью, в большинстве случаев даже при этом достигаются заметные улучшения.

Оптимизация должна проводиться с осторожностью. Тони Хоар впервые произнёс, а Дональд Кнут впоследствии часто повторял известное высказывание: «Преждевременная оптимизация — это корень всех бед». Очень важно иметь для начала озвученныйалгоритм и работающий прототип.

Понятие «оптимизация» обычно подразумевает, что система сохраняет ту же самую функциональность. Однако, значительное улучшение производительности часто может быть достигнуто и с помощью удаления избыточной функциональности. Например, если допустить, что программе не требуется поддерживать более, чем 100 элементов при вводе, то возможно использовать статическое выделение памяти вместо более медленного динамического.

Оптимизация в основном фокусируется на одиночном или повторном времени выполнения, использовании памяти, дискового пространства, пропускной способности или некотором другом ресурсе. Это обычно требует компромиссов — один параметр оптимизируется за счёт других. Например, увеличение размера программного кеша чего-либо улучшает производительность времени выполнения, но также увеличивает потребление памяти. Другие распространённые компромиссы включают прозрачность кода и его выразительность, почти всегда ценой деоптимизации. Сложные специализированные алгоритмы требуют больше усилий по отладке и увеличивают вероятность ошибок.

В исследовании операций, оптимизация — это проблема определения входных значений функции, при которых она имеет максимальное или минимальное значение. Иногда на эти значения накладываются ограничения, такая задача известна какограниченная оптимизация.

В программировании, оптимизация обычно обозначает модификацию кода и его установок компиляции для данной архитектуры для производства более эффективного ПО.

Типичные проблемы имеют настолько большое количество возможностей, что программисты обычно могут позволить использовать только «достаточно хорошее» решение.

Для оптимизации требуется найти узкое место (англ. hotspot), иногда называемое бутылочным горлышком (англ. bottleneck): критическую часть кода, которая является основным потребителем необходимого ресурса. Улучшение примерно 20 % кода иногда влечёт за собой изменение 80 % результатов (см. также принцип Парето). Для поиска узких мест используются специальные программы — профайлеры. Утечка ресурсов (памяти, дескрипторов и т.д.) также может привести к падению скорости выполнения программы, для их нахождения также применяются специальные программы (например, BoundsChecker).

Архитектурный дизайн системы особенно сильно влияет на её производительность. Выбор алгоритма влияет на эффективность больше, чем любой другой элемент дизайна. Более сложные алгоритмы и структуры данные могут хорошо оперировать с большим количеством элементов, в то время как простые алгоритмы подходят для небольших объёмов данных — накладные расходы на инициализацию более сложного алгоритма могут перевесить выгоду от его использования.

Чем больше памяти использует программа, тем быстрее она обычно выполняется. Например, программа-фильтр обычно читает каждую строку, фильтрует и выводит эту строку непосредственно. Поэтому она использует память только для хранения одной строки, но её производительность обычно очень плохая. Производительность может быть значительно улучшена чтением целого файла и записью потом отфильтрованного результата, однако этот метод использует больше памяти. Кэширование результата также эффективно, однако требует большего количества памяти для использования.

Оптимизация по затратам процессорного времени особенно важна для расчетных программ, в которых большой удельный вес имеют математические вычисления. Здесь перечислены некоторые приемы оптимизации, которые может использовать программист при написании исходного текста программы.

Во многих программах какую-то часть объектов данных необходимо инициализировать, то есть присвоить им начальные значения. Такое присваивание выполняется либо в самом начале программы, либо, например, в конце цикла. Правильная инициализация объектов позволяет сэкономить драгоценное процессорное время. Так, например, если речь идет об инициализации массивов, использование цикла, скорее всего, будет менее эффективным, чем объявление этого массива прямым присвоением.

В том случае, когда значительная часть времени работы программы отводится арифметическим вычислениям, немалые резервы повышения скорости работы программы таятся в правильном программировании арифметических (и логических) выражений. Важно, что различные арифметические операции значительно различаются по быстродействию. В большинстве архитектур, самыми быстрыми являются операции сложения и вычитания. Более медленным является умножение, затем идёт деление. Например, вычисление значения выражения , где a — константа, для аргументов с плавающей точкой производится быстрее в виде , где  — константа, вычисляемая на этапе компиляции программы (фактически медленная операция деления заменяется быстрой операцией умножения). Для целочисленного аргумента x вычисление выражения 2x быстрее произвести в виде x + x(операция умножения заменяется операцией сложения) или с использованием операции сдвига влево (что обеспечивает выигрыш не на всех процессорах). Подобные оптимизации называются понижением силы операций. Умножение целочисленных аргументов на константу на процессорах семейства x86 может быть эффективно выполнено с использованием ассемблерных команд LEA, SHL иADD вместо использования команд MUL/IMUL:

Генерация кода. Из промежуточного представления порождается код на целевом языке (в том числе выполняется компоновка программы).

Кодогенерация — часть процесса компиляции, когда специальная часть компилятора, кодогенератор, конвертирует синтаксическикорректную программу в последовательность инструкций, которые могут выполняться на машине. При этом могут применяться различные, в первую очередь машинно-зависимые оптимизации. Часто кодогенератор является общей частью для множества компиляторов, каждый из которых генерирует промежуточный код, который подаётся на вход кодогенератору.

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

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

Дальнейшие этапы компиляции могут и не относиться к «генерации кода», в зависимости от того, насколько значительными будут изменения, вносимые ими. Так, локальная оптимизация вряд ли может называться «генерацией кода», однако сам генератор кода может включать в себя этап локальной оптимизации.

В дополнение к основной задаче — преобразованию кода из промежуточного представление в машинные инструкции — генератор кода обычно пытается оптимизировать создаваемый код теми или иными способами. Например, он может использовать более быстрые инструкции, использовать меньше инструкций, использовать имеющиеся регистры и предотвращать избыточные вычисления.

Некоторые задачи, которые обычно решают сложные генераторы кода:

Выбор инструкций: какие инструкции использовать

Планирование инструкций: в каком порядке размещать эти инструкции. Планирование — это оптимизация, которая может значительно влиять на скорость выполнения программы на конвейерных процессорах

Размещение в регистрах: размещение переменных программы в регистрах процессора.

Выбор инструкций обычно выполняется рекурсивным обходом абстрактного синтаксического дерева, в этом случае сравниваются части конфигураций дерева с шаблонами; например, дерево W:=ADD(X,MUL(Y,Z)) может быть преобразовано в линейную последовательность инструкций рекурсивной генерации последовательностей t1:=X и t2:=MUL(Y,Z), а затем инструкцией ADD W,t1,t2.

В компиляторах, использующих промежуточный язык, может быть две стадии выбора инструкций — одна для конвертирования дерева разбора в промежуточный код, а вторая (следует намного позже) — для преобразования промежуточного кода в инструкции целевой системы команд. Вторая стадия не требует обхода дерева: она может выполняться последовательно и обычно состоит из простой замены операций промежуточного языка соответствующим им кодами операций. На самом деле, если компилятор фактически является транслятором (например, один переводит Eiffel в C), то вторая стадия генерации кода может включать построение дерева из линейного промежуточного кода.

Когда генерация кода происходит во время выполнения программы, как в JIT, важно, чтобы весь процесс генерации кода был эффективен как по времени, так и по используемой памяти. Например, при интерпретации регулярных выражений, чаще создаются недетерминированные конечные автоматы, чем детерминированные, потому что они создаются быстрее и занимают меньше памяти. Несмотря на то, что создаётся, в общем, менее эффективный код, генерация кода в JIT может предоставить возможность профилирования информации, доступной только во время выполнения программы.

В конкретных реализациях компиляторов эти фазы могут быть разделены или, наоборот, совмещены в том или ином виде.

Важной исторической особенностью компилятора, отражённой в его названии (англ. compile — собирать вместе, составлять), являлось то, что он мог производить как трансляцию так и компоновку (то есть состоял из двух части — транслятора и компоновщика). Это связано с тем, что раздельные трансляция и компоновка как отдельная фазы компиляции выделились значительно позже появления компиляторов. В связи с этим, вместо термина «компилятор» иногда используют термин «транслятор» как его синоним, что, правда, терминологически неправильно: либо в старой литературе, либо когда хотят подчеркнуть его способность переводить программу в машинный код (и наоборот, используют термин «компилятор» для подчёркивания способности собирать из многих файлов один).

На заре развития компьютеров первые компиляторы (трансляторы) называли «программирующими программами»[6] (так как в тот момент программой считался только машинный код, а «программирующая программа» была способна из человеческого текста сделать машинный код, то есть запрограммировать ЭВМ).

Собственно, это отражает тот факт, что компилятор по своей сути являются одним из средств автоматизации процесса программирования компьютеров. Дело в том, что любая написанная нами программа на неком входном языке (например, на С++ или языке ассемблера) по сути есть скрипт-сценарий для компилятора - непосредственно выполняемая - интерпретируемая - компилятором программа в которой описывается:

какую программу компилятор должен построить ,

что и как создаваемая нами таким образом программа должна делать (в том числе какие данные и как обрабатывать).

И уже выполняя - интерпретируя - эту нашу программу на входном языке, компилятор и строит эквивалентную ей программу на машинном языке.

Язык процессоров (машинный код) обычно является низкоуровневым. Существуют платформы, использующие в качестве машинного язык высокого уровня (например, iAPX-432[5]), но они являются исключением из правила в силу сложности и дороговизны. Транслятор, который преобразует программы в машинный язык, принимаемый и исполняемый непосредственно процессором, называется компилятором.

Процесс компиляции как правило состоит из нескольких этапов: лексического, синтаксического и семантического анализов(англ. Semantic analysis), генерации промежуточного кода, оптимизации и генерации результирующего машинного кода. Помимо этого, программа как правило зависит от сервисов, предоставляемых операционной системой и сторонними библиотеками (например, файловый ввод-вывод или графический интерфейс), и машинный код программы необходимо связать с этими сервисами. Связывание со статическими библиотеками выполняется редактором связей или компоновщиком (который может представлять из себя отдельную программу или быть частью компилятора), а с операционной системой и динамическими библиотеками связывание выполняется при начале исполнения программы загрузчиком.

Достоинство компилятора: программа компилируется один раз и при каждом выполнении не требуется дополнительных преобразований. Соответственно, не требуется наличие компилятора на целевой машине, для которой компилируется программа. Недостаток: отдельный этап компиляции замедляет написание и отладку и затрудняет исполнение небольших, несложных или разовых программ.

Ассе́мблер (от англ. assembler — сборщик) — компьютерная программа, компилятор исходного текста программы, написанной наязыке ассемблера, в программу на машинном языке.

Как и сам язык (ассемблер), ассемблеры, как правило, специфичны конкретной архитектуре, операционной системе и варианту синтаксиса языка. Вместе с тем существуют мультиплатформенные или вовсе универсальные (точнее, ограниченно-универсальные, потому что на языке низкого уровня нельзя написать аппаратно-независимые программы) ассемблеры, которые могут работать на разных платформах и операционных системах. Среди последних можно также выделить группу кросс-ассемблеров, способных собирать машинный код и исполняемые модули (файлы) для других архитектур и ОС.

Ассемблирование может быть не первым и не последним этапом на пути получения исполнимого модуля программы. Так, многие компиляторы с языков программирования высокого уровня выдают результат в виде программы на языке ассемблера, которую в дальнейшем обрабатывает ассемблер. Также результатом ассемблирования может быть не исполнимый, а объектный модуль, содержащий разрозненные и непривязанные друг к другу части машинного кода и данных программы, из которого (или из нескольких объектных модулей) в дальнейшем с помощью программы-компоновщика («линкера») может быть скомпонованисполнимый файл.

Макроассемблер (от греч. μάκρος — большой, обширный) — макропроцессор, базовым языком которого является язык ассемблера.

Процесс трансляции программы на языке ассемблера в объектный код принято называть ассемблированием. В отличие откомпилирования, ассемблирование — более или менее однозначный и обратимый процесс. В языке ассемблера каждой мнемонике соответствует одна машинная инструкция, в то время как в языках программирования высокого уровня за каждым выражением может скрываться большое количество различных инструкций. В принципе, это деление достаточно условно, поэтому иногда трансляцию ассемблерных программ также называют компиляцией.

В случае, если исходный язык является языком ассемблера (низкоуровневым языком, который является мнемоническим представлением машинных комманд процессора), то компилятор такого языка называется ассемблером.

Интерпрета́тор (языка программирования) —

Программа или техническое средство, выполняющее интерпретацию.

Вид транслятора, осуществляющего пооператорную (покомандную) обработку и выполнение исходной программы или запроса (в отличие от компилятора, транслирующего всю программу без её выполнения).

Программа (иногда аппаратное средство), анализирующая команды или операторы программы и тут же выполняющая их.

Языковый процессор, который построчно анализирует исходную программу и одновременно выполняет предписанные действия, а не формирует на машинном языке скомпилированную программу, которая выполняется впоследствии.

Простой интерпретатор анализирует и тут же выполняет (собственно интерпретация) программу покомандно (или построчно), по мере поступления её исходного кода на вход интерпретатора. Достоинством такого подхода является мгновенная реакция. Недостаток — такой интерпретатор обнаруживает ошибки в тексте программы только при попытке выполнения команды (или строки) с ошибкой.

Интерпретатор компилирующего типа — это система из компилятора, переводящего исходный код программы в промежуточное представление, например, в байт-код или p-код, и собственно интерпретатора, который выполняет полученный промеж
еще рефераты
Еще работы по разное