Введение

ML/1 (Macro Language/One) – мощный универсальный макропроцессор. Типичные области применения ML/1 включают: редактирование, изменение, исправление или переформатирование текстовых файлов; перевод исходного кода с одного языка программирования на другой; использование в качестве предпроцессора исходного кода, позволяющего пользователю добавлять новые синтаксические конструкции в существующий язык программирования; поддержка параметризации исходного кода программы (например, параметр может определять, следует ли включать отладочные операторы в исходный код программы, передаваемый компилятору).

ML/1 был разработан в 1966 году Питером Дж. Брауном в рамках докторской диссертации в Кембриджском университете в Англии. В 1984 году Роберт Д. Игер, один из коллег Питера Брауна в Университете Кента, переписал ML/I, сначала на BCPL в 1981 году, а затем на C в 1984 году, что повысило его переносимость. Следует отметить, что первоначальное название языка, данное Питером Брауном, было ML/I, где (как и в PL/I от IBM) последний символ – римская цифра "I", а не арабская цифра "1". Однако большинство последующих реализаций назывались ML/1 (где последний символ – арабская цифра "1"). С тех пор ML/1 был портирован на множество платформ и операционных систем, включая VMS, MVS, MS DOS, OS/2 и UNIX. В своих реализациях ML/1 Роберт Д. Игер добавил функции и возможности, помимо тех, что были изначально описаны в диссертации Питера Брауна. Эта версия доступна для различных платформ через веб-сайт ML/1: http://www.ml1.org.uk. На веб-сайте ML/1 представлена дополнительная информация о ML/1, а также документация (включая учебное пособие, простое руководство и полное руководство пользователя). Хотя общее количество пользователей ML/1 в мире невелико, они есть по всему миру, и Боб поддерживал связь с пользователями ML/1 в Соединенных Штатах, Канаде, Австралии, Новой Зеландии, Германии, Нидерландах и Индии. В статье 1976 года Эндрю С. Таненбаум описывает использование ML/I в качестве компилятора компиляторов.

Обзор

ML/I принимает входные данные в абсолютно произвольной форме, обрабатывая их как поток байтов, а не как последовательность строк или записей. Для указания на макрорасширение не требуется специальный флаг, что делает его особенно удобным для обработки произвольного текста. Замены текста могут быть простыми (например, замена "PIG" на "DOG") или сложными (например, замена элемента между третьей и четвертой запятыми после последней точки содержимым какого-либо счетчика). ML/I использовался для реализации нескольких компонентов переносимого программного обеспечения, включая сам ML/I. Изначально он был написан на специальном описательном языке, а затем преобразован в подходящий язык для каждой целевой системы. Это преобразование выполнялось с использованием самого ML/I. Существовали две различные формы этого описательного языка: высокого и низкого уровней. После этого преобразования ML/I часто использовался для реализации ЯСИ (языков реализации систем, таких как C) для нового поколения 16-битных мини-ЭВМ.

Как работает ML/1

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

Отличительные черты ML/1

Есть несколько способов, которыми ML/1 превосходит простые утилиты "поиск и замена". ML/1 не обрабатывает текст посимвольно, а по словам (или, в терминологии ML/1, "по атомам"). Для многих задач крайне полезно обрабатывать текст как последовательность атомов, а не символов. Например, предположим, что нам нужно перевести программу с языка программирования, использующего синтаксис DO END, на язык с синтаксисом BEGIN END. Следовательно, мы хотим заменить "DO" на "BEGIN". Если выполнить замену с помощью обычной утилиты поиска и замены, все вхождения строки "DO" будут заменены на "BEGIN", включая "DO", встроенные в слова, такие как "DOCUMENT" (которые превратятся в "BEGINCUMENT"). В отличие от этого, с ML/1 этого не произойдет, поскольку строка "DO" будет инициировать замену текста только при встрече в виде отдельного слова (то есть, когда ей предшествуют и следуют разделители, такие как пробелы, табуляции, переносы строк или знаки препинания). ML/1, в отличие от построчной обработки, распознает текстовые шаблоны, которые могут быть сложными, вложенными, с множеством разделителей и охватывать несколько строк. ML/1 может, например, обрабатывать шаблон, такой как распространенная структура языка программирования IF THEN ELSE ENDIF, которая охватывает несколько строк и содержит встроенный текст, который сам может включать вложенную структуру IF THEN ELSE ENDIF. ML/1 может распознавать встроенные комментарии и строковые литералы, защищая их от изменений. Обычные утилиты поиска и замены без разбора изменяют строки, независимо от того, являются ли они ключевыми словами, именами переменных, частью комментария или строковым литералом. Для работы с такими сложными шаблонами ML/1 должен быть полноценным языком программирования. Как и другие языки программирования, ML/1 поддерживает переменные и операторы присваивания, операторы GOTO и метки, условные операторы IF THEN и циклы. Эти возможности обеспечивают ML/1 необычайную мощность и гибкость.

Ограничения

ML/1 чувствителен к регистру, поэтому не поддерживает обработку текста без учета регистра.