Что такое транслятор, компилятор, интерпретатор?
Трансляторы реализуются в виде компиляторов или интерпретаторов. С точки зрения выполнения работы компилятор и интерпретатор существенно различаются.
Компилятор (англ. compiler — составитель, собиратель) читает всю программу целиком, делает ее перевод и создает законченный вариант программы на машинном языке, который затем и выполняется.
Интерпретатор (англ. interpreter — истолкователь, устный переводчик) переводит и выполняет программу строка за строкой.
После того, как программа откомпилирована, ни сама исходная программа, ни компилятор более не нужны. В то же время программа, обрабатываемая интерпретатором, должна заново переводиться на машинный язык при каждом очередном запуске программы.
Откомпилированные программы работают быстрее, но интерпретируемые проще исправлять и изменять. |
Каждый конкретный язык ориентирован либо на компиляцию, либо на интерпретацию — в зависимости от того, для каких целей он создавался. Например, Паскаль обычно используется для решения довольно сложных задач, в которых важна скорость работы программ. Поэтому данный язык обычно реализуется с помощью компилятора. С другой стороны, Бейсик создавался как язык для начинающих программистов, для которых построчное выполнение программы имеет неоспоримые преимущества. Иногда для одного языка имеется и компилятор, и интерпретатор. В этом случае для разработки и тестирования программы можно воспользоваться интерпретатором, а затем откомпилировать отлаженную программу, чтобы повысить скорость ее выполнения. |
2.1. Языки программирования, трансляторы
Что такое системы программирования?
Система программирования — это система для разработки новых программ на конкретном языке программирования. |
Современные системы программирования обычно предоставляют пользователям мощные и удобные средства разработки программ. В них входят:
· компилятор или интерпретатор;
· интегрированная среда разработки;
· средства создания и редактирования текстов программ;
· обширные библиотеки стандартных программ и функций;
· отладочные программы, т.е. программы, помогающие находить и устранять ошибки в программе;
· «дружественная» к пользователю диалоговая среда;
· многооконный режим работы;
· мощные графические библиотеки; утилиты для работы с библиотеками
· встроенная справочная служба;
· другие специфические особенности.
Популярные системы программирования – Turbo Basic, Quick Basic, Turbo Pascal, Turbo C.
В последнее время получили распространение системы программирования, ориентированные на создание Windows-приложений:
Borland Delphi 3.0
· пакет Borland Delphi (Дельфи) — блестящий наследник семейства компиляторов Borland Pascal, предоставляющий качественные и очень удобные средства визуальной разработки. Его исключительно быстрый компилятор позволяет эффективно и быстро решать практически любые задачи прикладного программирования.
Урок 1. Краткая история языков программирования. Трансляторы
· пакет Microsoft Visual Basic — удобный и популярный инструмент для создания Windows-программ с использованием визуальных средств. Содержит инструментарий для создания диаграмм и презентаций.
· пакет Borland C++ — одно из самых распространённых средств для разработки DOS и Windows приложений.
Ниже для иллюстрации приведены на языках Бейсик, Паскаль и Си программы решения одной и той же простой задачи — вычисления суммы S элементов одномерного массива A=(a1, a2, . an).
Язык Бейсик был создан в 1965 г. Дж. Кемени и Т.Курцем как язык для начинающих, облегчающий написание простых программ. Существуют сотни различных версий Бейсика – от очень простых до усовершенствованных, содержащих множество дополнительных языковых конструкций. Бейсик очень популярный язык программирования. | Программа на Бейсике 10 INPUT «N = «; N 20 DIM A(N) 30 FOR I = 1 TO N 40 PRINT «A(«; I; «) =»; 50 INPUT A(I) 60 NEXT I 70 S = 0 80 FOR I = 1 TO N 90 S = S + A(I) 100 NEXT I 110 PRINT «Сумма =»; S |
Программа на Паскале Program Summa; Type Mas = Array [1..100] of Real; Var A : Mas; i, n: Integer; S : Real; BEGIN ReadLn(n); For i : = 1 To 10 Do ReadLn(A[i]); S : = 0; For i : = 1 To 10 Do S : = S + A[i]; WriteLn(‘S = ‘, S:8:2); END. | Язык Паскаль был разработан в 1970г. Никласом Виртом как язык обучения студентов программированию. Паскаль вырабатывает навыки соблюдения хорошего строгого стиля программирования (называемого структурным программированием), упрощающего разработку сложных программ. В своем первоначальном виде Паскаль имел довольно ограниченные возможности, но расширенный вариант этого языка – Turbo Pascal, является очень мощным языком программирования. |
Язык Си (разработан Деннисом Ритчи в 1972 г.) соединяет свойства языка высокого уровня с возможностями эффективного использования ресурсов компьютера, которые обычно достигаются только при программировании на языке Ассемблера. Си не очень прост в изучении и требует тщательности в программировании, но позволяет создавать сложные и весьма эффективные программы. | Программа на СИ # include main() |
Для чего нужны инструментальные программы?
Инструментальные программные средства — это программы, которые используются в ходе разработки, корректировки или развития других прикладных или системных программ. |
По своему назначению они близки системам программирования. К инструментальным программам, например, относятся:
· средства компоновки программ;
· отладочные программы, т.е. программы, помогающие находить и устранять ошибки в программе;
· вспомогательные программы, реализующие часто используемые системные действия;
· графические пакеты программ и т.п.
Инструментальные программные средства могут оказать помощь на всех стадиях разработки ПО.
Что такое текстовый редактор?
Текстовый редактор — это программа, используемая специально для ввода и редактирования текстовых данных. |
Этими данными могут быть программа или какой-либо документ или же книга. Редактируемый текст выводится на экран, и пользователь может в диалоговом режиме вносить в него свои изменения.
Текстовые редакторы могут обеспечивать выполнение разнообразных функций, а именно:
· редактирование строк текста;
· возможность использования различных шрифтов символов;
· копирование и перенос части текста с одного места на другое или из одного документа в другой;
· контекстный поиск и замена частей текста;
· задание произвольных межстрочных промежутков;
· автоматический перенос слов на новую строку;
· автоматическая нумерацию страниц;
· обработка и нумерация сносок;
· выравнивание краев абзаца;
· создание таблиц и построение диаграмм;
· проверка правописания слов и подбор синонимов;
· построение оглавлений и предметных указателей;
· распечатка подготовленного текста на принтере в нужном числе экземпляров и т.п.
Возможности текстовых редакторов различны — от программ, предназначенных для подготовки небольших документов простой структуры, до программ для набора, оформления и полной подготовки к типографскому изданию книг и журналов (издательские системы).
Рис. 6.5. Окно редактора Microsoft Word
Наиболее известный текстовый редактор — Microsoft Word.
Полнофункциональные издательские системы — Microsoft Publisher, Corel Ventura и Adobe PageMaker. Издательские системы незаменимы для компьютерной верстки и графики. Значительно облегчают работу с многостраничными документами, имеют возможности автоматической разбивки текста на страницы, расстановки номеров страниц, создания заголовков и т.д. Создание макетов любых изданий — от рекламных листков до многостраничных книг и журналов — становится очень простым, даже для новичков.
Источник: infopedia.su
ТРАНСЛЯ́ТОР
ТРАНСЛЯ́ТОР, переводчик (лат. translator, букв. – переносчик; переводчик) в информатике, класс компьютерных программ, которые осуществляют преобразование символьной записи программ из одной формы в другую. Символьные формы записи программ образуют континуум от языков высокого уровня через разл. формы промежуточных представлений (как с возможностью использования программы интерпретатор , так и без возможности интерпретации) вплоть до машинного кода конкретного процессора (вычислит. системы). Использование такой формы символьного представления полностью зависит от удобства проведения манипуляций с программой на каждом этапе её жизненного цикла. Термин «Т.» в информатике трудно отличим от понятия компилятор ; их можно считать взаимозаменяемыми. Однако Т. исторически появился раньше компилятора, поэтому принято считать, что Т. и компилятор относятся друг к другу как общее к частному.
Источник: bigenc.ru
Трансляция программ
Современные ОС — широко распространенные системы — во многом похожи друг на друга. Прежде всего это определяется требованием переносимости программного обеспечения. Именно для обеспечения этой переносимости был принят POSIX (Portable OS Interface based on uniX) — стандарт, определяющий минимальные функции по управлению файлами, межпроцессному взаимодействию и т.д., которые должна уметь выполнять система.
Кроме того, за четыре с лишним десятилетия, прошедших с момента разработки первых ОС, сообщество программистов достигло определенного понимания того, что: — при разработке ОС возникает много стандартных проблем и вопросов; — для большинства из этих проблем и вопросов существует набор стандартных решений; — некоторые из этих решений намного лучше, чем все альтернативные.
По современным представлениям, ОС должна уметь делать следующее:
· Обеспечивать загрузку пользовательских программ в оперативную память и их исполнение.
· Обеспечивать работу с устройствами долговременной памяти, такими как магнитные диски, ленты, оптические диски и т.д. Как правило, ОС управляет свободным пространством на этих носителях и структурирует пользовательские данные.
· Предоставлять более или менее стандартный доступ к различным устройствам ввода/вывода, таким как терминалы, модемы, печатающие устройства.
· Предоставлять некоторый пользовательский интерфейс. Слово некоторый здесь сказано не случайно — часть систем ограничивается командной строкой, в то время как другие на 90% состоят из средств интерфейса пользователя.
Существуют ОС, функции которых этим и исчерпываются. Одна из хорошо известных систем такого типа — дисковая операционная система MS DOS.
Более развитые ОС предоставляют также следующие возможности:
· Параллельное (точнее, псевдопараллельное, если машина имеет только один процессор) исполнение нескольких задач.
· Распределение ресурсов компьютера между задачами.
· Организация взаимодействия задач друг с другом.
· Взаимодействие пользовательских программ с нестандартными внешними устройствами.
· Организация межмашинного взаимодействия и разделения ресурсов.
· Защита системных ресурсов, данных и программ пользователя, исполняющихся процессов и самой себя от ошибочных и зловредных действий пользователей и их программ.
Трансляция программы — преобразование программы, представленной на одном из языков программирования, в программу на другом языке и, в определённом смысле, равносильную первой.
Транслятор — программа или техническое средство, выполняющее трансляцию программы. Транслятор обычно выполняет также диагностику ошибок, формирует словари идентификаторов, выдаёт для печати тексты программы и т.д.
Язык, на котором представлена входная программа, называется исходным языком, а сама программа — исходным кодом. Выходной язык называется целевым языком или объектным кодом.
Цель трансляции — преобразовать текст с одного языка на другой, который понятен адресату текста. В случае программ-трансляторов, адресатом является техническое устройство (процессор) или программа-интерпретатор.
Язык процессоров (машинный код) обычно является низкоуровневым. Существуют платформы, использующие в качестве машинного язык высокого уровня (например, iAPX-432[5]), но они являются исключением из правила в силу сложности и дороговизны.
Транслятор, который преобразует программы в машинный язык, принимаемый и исполняемый непосредственно процессором, называется компилятором.
Процесс компиляции как правило состоит из нескольких этапов: лексического, синтаксического и семантического анализов, генерации промежуточного кода, оптимизации и генерации результирующего машинного кода. Помимо этого, программа как правило зависит от сервисов, предоставляемых операционной системой и сторонними библиотеками (например, файловый ввод-вывод или графический интерфейс), и машинный код программы необходимо связать с этими сервисами.
Достоинство компилятора: программа компилируется один раз и при каждом выполнении не требуется дополнительных преобразований. Соответственно, не требуется наличие компилятора на целевой машине, для которой компилируется программа. Недостаток: отдельный этап компиляции замедляет написание и отладку и затрудняет исполнение небольших, несложных или разовых программ.
В случае, если исходный язык является языком ассемблера (низкоуровневым языком, близким к машинному языку), то компилятор такого языка называется ассемблером.
Противоположный метод реализации — когда программа исполняется с помощью интерпретатора вообще без трансляции. Интерпретатор программно моделирует машину, цикл выборки-исполнения которой работает с командами на языках высокого уровня, а не с машинными командами. Такое программное моделирование создаёт виртуальную машину, реализующую язык. Этот подход называется чистой интерпретацией.
Достоинство чистого интерпретатора: отсутствие промежуточных действий для трансляции упрощает реализацию интерпретатора и делает его удобнее в использовании, в том числе в диалоговом режиме. Недостаток — интерпретатор должен быть в наличии на целевой машине, где должна исполняться программа. А свойство чистого интерпретатора, что ошибки в интерпретируемой программе обнаруживаются только при попытке выполнения команды (или строки) с ошибкой, можно признать как недостатком, так и достоинством.
Трансляция и интерпретация — разные процессы: трансляция занимается переводом программ с одного языка на другой, а интерпретация отвечает за исполнение программ. Однако, поскольку целью трансляции как правило является подготовка программы к интерпретации, то эти процессы обычно рассматриваются вместе. Например, языки программирования часто характеризуются как «компилируемые» или «интерпретируемые», в зависимости от того, преобладает при использовании языка компиляция или интерпретация. Причём практически все языки программирования низкого уровня и третьего поколения, вроде ассемблера, Си или Модулы-2, являются компилируемыми, а более высокоуровневые языки, вроде Python или SQL, — интерпретируемыми.
С другой стороны, существует взаимопроникновение процессов трансляции и интерпретации: интерпретаторы могут быть компилирующими (в том числе с динамической компиляцией), а в трансляторах может требоваться интерпретация для конструкций метапрограммирования (например, для макросов в языке ассемблера, условной компиляции в Си или для шаблонов в C++).
Более того, один и тот же язык программирования может и транслироваться, и интерпретироваться, и в обоих случаях должны присутствовать общие этапы анализа и распознавания конструкций и директив исходного языка. Это относится и к программным реализациям, и к аппаратным — так, процессоры семейства x86 перед исполнением инструкций машинного языка выполняют их декодирование, выделяя в опкодах поля операндов (регистров, адресов памяти, непосредственных значений), разрядности и т. п., а в процессорах Pentium с архитектурой NetBurst машинный код перед сохранением во внутреннем кэше вообще транслируется в последовательность микроопераций.
Источник: studopedia.ru
Пишем свой язык программирования, часть 3: Архитектура транслятора. Разбор языковых структур и математических выражений
Приветствую вас, заинтересованные читающие разработчики на не важно каких языках, на которых я ориентирую эти статьи и чьи поддержку и мнения я ценю.
Для начала, по устоявшимся традициям, я приведу ссылки на предыдущие статьи:
Для формирования в вашей голове полного понимания того, что в этих статьях мы пишем, вам стоит заранее ознакомиться с предыдущими частями.
Также мне стоит разместить сразу ссылку на статью о проекте, который был написан мной ранее и на основе которого идет весь этот разбор полётов: Клац сюды. С ним пожалуй стоит ознакомиться первым делом.
И немного о проекте:
Ну и также скажу сразу, что все написано на Object Pascal, а именно — на FPC.
Принцип работы большинства трансляторов
Первым делом, стоит понимать что я не смог бы ничего путного написать, предварительно не ознакомившись с кучей теоретического материала и рядом статеек. Опишу основное в паре слов.
Задача транслятора первым делом — подготовить код к анализу (например удалить из него комментарии) и разбить код на токены (токен — минимальный значащий для языка набор символов).
Далее нужно путем анализа и преобразований разобрать код в некое промежуточное представление и затем уже собрать готовое к выполнению приложение или… Что там ему в общем нужно собрать.
Да, этой кучей текста я ничего толком то и не сказал, однако — сейчас задача разбита на несколько подзадач.
Пропустим то, как код подготавливается к выполнению, т.к. это слишком скучный для описания процесс. Предположим, что мы имеем уже готовый к анализу набор токенов.
Анализ кода
Вы могли слышать о построении дерева кода и его анализа или ещё более заумные вещи. Как всегда — это не более чем загромождение простого страшными терминами. Под анализом кода я понимаю гораздо более простой набор действий. Задача — пробежаться по списку токенов и разобрать код, каждую его конструкцию.
Как правило, в императивных языках код уже представлен в виде своеобразного дерева из конструкций.
Согласитесь, не приемлемо допустим начинать цикл «A» в теле цикла «B», а заканчивать — вне тела цикла «B». Код представляет собой структуру, состоящую из набора конструкций.
А что есть у каждой конструкции? Правильно — начало и конец (и возможно ещё что-то посередине, но не суть).
Соответственно, разбор кода можно сделать однопроходным, толком без построения дерева.
Для этого нужен цикл, который будет пробегать по коду и большущий switch-case, который будет выполнять основной разбор кода и анализ.
Т.е. пробегаем по токенам, перед нами токен (например пусть будет. ) «if» — очень уж сомневаюсь, что такой токен может стоять в коде просто так -> это начало конструкции if..then[..else]..end!
Выполняем разбор всех последующих токенов, соответствующим образом для конструкции условий в нашем языке.
Немного об ошибках в коде
На этапе разбора конструкций и пробега по коду, на обработку ошибок лучше не забивать. Это полезный функционал транслятора. Если в ходе разбора конструкции возникает ошибка, то логично — конструкция построена не должным образом и следует уведомить об этом разработчика.
Теперь о Mash. Как происходит разбор языковых конструкций?
Выше я описал обобщенный концепт устройства транслятора. Теперь настало время поговорить о моих наработках.
По сути транслятор получился очень даже похожим на описанное выше. Но у меня он не разбивает код на кучу токенов для дальнейшего анализа.
Перед началом разбора код приводится в более красивый вид. Удаляются комментарии и все конструкции соединяются в длинные строки, если они описаны в несколько строк.
Таким образом, в каждой отдельно взятой строке находится языковая конструкция либо её часть. Это классно, теперь мы можем разбирать каждую строку в нашем большом switch-case, вместо поиска этих конструкций в наборе токенов. Также плюсом тут выступает то, что строка имеет конец и значит определять ошибки в конструкции с таким подходом проще.
Соответственно разбор отдельных конструкций происходит отдельными методами, которые возвращают промежуточное представление кода конструкций или её частей.
П.с. в предыдущей статье я описал построение транслятора с промежуточного языка в байткод для ВМ. Собственно — этот промежуточный язык и является промежуточным представлением.
Стоит понимать, что конструкции могут состоять из нескольких более простых конструкций. Т.к. у нас разбор каждой конструкции описан отдельными методами, то мы можем без проблем вызывать их друг из друга при разборе каждой конструкции.
Разминочная пробежка по коду
Для начала транслятору стоит бегло ознакомиться с кодом, пробежавшись по нему и уделив внимание некоторым конструкциям.
На этом этапе можно разобраться с глобальными переменными, uses конструкциями, а также импортами, процедурами interface uses Classes, SysUtils; type TBlockEntryType = (btProc, btFunc, btIf, btFor, btWhile, btUntil, btTry, btClass, btSwitch, btCase); TCodeBlock = class(TObject) public bType: TBlockEntryType; mName, bMeta, bMCode, bEndCode: string; constructor Create(bt: TBlockEntryType; MT, MC, EC: string); end; implementation constructor TCodeBlock.Create(bt: TBlockEntryType; MT, MC, EC: string); begin inherited Create; bType := bt; bMeta := MT; bMCode := MC; bEndCode := EC; end; end.
Ну и стек — простой TList, изобретать велосипед тут просто глупо.
Таким образом, разбор конструкции, допустим того же while цикла выглядит так:
function ParseWhile(s: string; varmgr: TVarManager): string; var WhileNum, ExprCode: string; begin Delete(s, 1, 5); //»while» Delete(s, Length(s), 1); //»:» s := Trim(s); //Циклов в коде много, а в промежуточном представлении структуры кода нету. //Нужно точки входа все же отличать как то 🙂 WhileNum := ‘__gen_while_’ + IntToStr(WhileBlCounter); Inc(WhileBlCounter); //Номер очередной конструкции while в коде //Метод проверяет, является ли строка логическим или математическим выражением if IsExpr(s) then ExprCode := PreprocessExpression(s, varmgr) else ExprCode := PushIt(s, varmgr); //Теперь в ExprCode лежит промежуточное представление выражения //Результат после выполнения будет лежать в вершине стека //Проверка условия перед итерацией //(промежуточное представление ставится на место начала конструкции) Result := WhileNum + ‘:’ + sLineBreak + ‘pushcp ‘ + WhileNum + ‘_end’ + sLineBreak + ExprCode + sLineBreak + ‘jz’ + sLineBreak + ‘pop’; //Ну и соответственно генерация кода на завершение конструкции //Последний аргумент — название точки входа на выход из цикла //нужен для генератора break BlockStack.Add(TCodeBlock.Create(btWhile, », ‘pushcp ‘ + WhileNum + sLineBreak + ‘jp’ + sLineBreak + WhileNum + ‘_end:’, WhileNum + ‘_end’)); end;
Про математические выражения
Возможно вы могли этого не замечать, но математические/логические выражения — это тоже структурированный код.
Их разбор я реализовывал стековым путем. Сначала все отдельные элементы выражения ложатся в стек, затем в несколько проходов генерируется код промежуточного представления.
В несколько раз — т.к. есть приоритетные математические операции, такие как умножение.
Код тут приводить не вижу смысла, т.к. его много и он скучный.
П.с. /lang/u_prep_expressions.pas — тут он целиком и полностью выставлен на ваше обозрение.
Итоги
Итак, мы реализовали транслятор, который может преобразовать… Например такой вот код:
А теперь небольшой опрос (чтобы я смотрел на него и радовался значимости своих статей):
Источник: habr.com