УДК 519.6 О РЕАЛИЗАЦИИ ПОДХОДА К ГЕНЕРАЦИИ ВНУТРЕННЕГО ПРЕДСТАВЛЕНИЯ ПРОГРАММЫ НА ВХОДНОМ ЯЗЫКЕ ГАММА Т.М. Брагин*, М.Ф. Степанов**, А.М. Степанов*** * Саратовский государственный технический университет имени Гагарина Ю.А., Россия, Саратов, btm@sstu.ru ** Саратовский государственный технический университет имени Гагарина Ю.А., Россия, Саратов, mfs@sstu.ru ** Саратовский государственный технический университет имени Гагарина Ю.А., Россия, Саратов, ams@sstu.ru Аннотация. Рассматриваются вопросы создания лингвистического обеспечения, предоставляющего пользователям системы ГАММА-3 возможности решения задач в стиле Матлабподобных систем. При этом разрабатываемый входной язык, получивший название ГАММА является максимально приближенным к входному языку пакета Матлаб. Ключевые слова: лингвистическое обеспечение, внутреннее представление программы. ON THE APPROACH TO GENERATION OF INTERNAL REPRESENTATION OF THE PROGRAM IN THE INPUT LANGUAGE GAMMA T.M. Bragin*, M.F. Stepanov**, A.M. Stepanov*** * Yuri Gagarin Saratov state technical university of Saratov, Russia, Saratov, btm@sstu.ru ** Yuri Gagarin Saratov state technical university of Saratov, Russia, Saratov, mfs@sstu.ru ** Yuri Gagarin Saratov state technical university of Saratov, Russia, Saratov, ams@sstu.ru Abstract. In operation problems of creation of the lingware submitting the user of a system the GAMMA-3 of possibilities of problem solving in style of Matlab-like systems are considered. Thus the developed source language which has obtained a title the GAMMA is maximum approximate to the source language of Matlab package. Keywords: the lingware, Internal form of the program. В проектировании систем автоматического управления важнейшим является разработка алгоритмов управления. При этом в множестве решаемых задач выделяются проектные операции и проектные процедуры. Проектные операции, являющиеся процедуральным определением понятий теории управления, например, свойство «управляемость объекта управления», как правило, реализуются в виде встроенных команд среды автоматизации решения задач. Проектные процедуры представляют собой совокупность проектных операций и предназначены для решения задач синтеза или анализа законов управления. Проектные процедуры разрабатываются специалистами в теории управления. Для записи порядка следования операций в составе проектной процедуры обычно применяются проблемно-ориентированные языки, близкие к профессиональному языку специалистов в предметной области – проектировании систем управления. В теории автоматического управления широкое распространение получила матричная форма записи используемых уравнений. Поэтому язык описания процедур решения задач должен предоставлять такую возможность в сочетании с минимально необходимыми управляющими конструкциями (ветвления, циклы). Подобные возможности имеются во входном языке пакета Matlab. Поэтому подобные языки стали называть Matlabподобными. Система ГАММА-3 [1, 2] позволяет решать как декларативно (непроцедурно) поставленные задачи, так и задачи, для которых пользователь может указать порядок их решения (команду, процедуру). Последние называются «типовыми». В подсистеме решения типовых задач для записи процедур их решения используется Matlabподобный язык ГАММА. Предшественником системы ГАММА-3 является система ИНСТРУМЕНТ-3м-И [3], предназначенная, в основном, для решения непроцедурно поставленных задач. Входящая в состав интегрированной среды системы ИНСТРУМЕНТ-3м-И «Среда исследователя» предоставляет возможности создания моделей знаний, на основе которых «Среда инженера» позволяет решать задачи в непроцедурной постановке. Однако для решения типовых задач такие возможности не требуются, что и послужило мотивом создания системы ГАММА-3, сочетающей возможности решения как непроцедурно поставленных, так и типовых задач. К сожалению удобные для человека формы записи последовательности действий (программа) оказываются неэффективными для исполнения на вычислительной машине [4]. Поэтому исходную программу преобразуют во внутреннее представление, более удобное для машины. Работа посвящена изложению подходов к построению компонентов программного обеспечения, осуществляющего преобразование исходного текста программ на языке ГАММА во внутреннее представление. Разрабатываемое программное обеспечение включает лексический анализатор, синтаксический анализатор, а также интерпретатор внутреннего представления входной программы. Лексический анализатор строится как конечный автомат. В синтаксическом анализаторе используется метод «сдвиг-свёртка». Синтаксическое дерево далее используется интерпретатором в качестве внутреннего представления исходной программы. В связи с тем, что язык ГАММА является интерпретируемым языком, результаты синтаксического анализа могут непосредственно использоваться для интерпретации, т.е. выполнения предусмотренных пользовательской программой действий. Однако при этом эффективность собственно процесса интерпретации может оказаться весьма низкой. Критериями эффективности традиционно выступают время исполнения и объём используемой памяти. Поэтому целесообразно провести некоторую предварительную работу, которая в компиляторах выполняется на этапе генерации кода. Чтобы компилятор мог построить код результирующей программы для синтаксической конструкции входного языка, часто используется метод, называемый синтаксически управляемым переводом – СУ-переводом [4]. Для полного представления о типе и структуре найденной и разобранной синтаксической конструкции входного языка, в принципе, достаточно знать последовательность номеров правил грамматики, примененных для ее построения. Однако форма представления этой достаточной информации может быть различной в зависимости, как от реализации самого компилятора, так и от фазы компиляции. Эта форма называется внутренним представлением программы (иногда используются также термины «промежуточное представление» и «промежуточная программа»). Все внутренние представления программы обычно содержат две принципиально различные вещи – операторы и операнды. Различия между формами внутреннего представления заключаются лишь в том, как операторы и операнды соединяются между собой. Также операторы и операнды должны отличаться друг от друга, вне зависимости от того, в каком порядке они встречаются во внутреннем представлении программы. За различение операндов и операторов отвечает разработчик компилятора, который руководствуется семантикой входного языка. Известны следующие формы внутреннего представления программ: - связные списочные структуры, представляющие синтаксические деревья; - многоадресный код с явно именуемым результатом (тетрады); - многоадресный код с неявно именуемым результатом (триады); - обратная (постфиксная) польская запись операций; - ассемблерный код или машинные команды. Существуют три формы записи выражений – префиксная, инфиксная и постфиксная. При префиксной записи операция записывается перед своими операндами, при инфиксной – между операндами, а при постфиксной – после операндов. Общепринятая запись арифметических выражений является примером инфиксной записи. Запись математических функций и функций в языках программирования является префиксной (другие примеры префиксной записи – команды ассемблера, триады и тетрады). Триады представляют запись операций в форме из трех составляющих: операции и двух операндов. Например, триады могут иметь вид: <операция> (<операнд1>,<операнд2>). Особенностью триад является то, что один или оба операнда могут быть ссылками на другую триаду в том случае, если в качестве операнда данной триады выступает результат выполнения другой триады. Поэтому триады при записи последовательно нумеруют для удобства указания ссылок одних триад на другие (в реализации компилятора в качестве ссылок можно использовать не номера триад, а непосредственно ссылки в виде указателей — тогда при изменении нумерации и порядка следования триад менять ссылки не требуется). Триады представляют собой линейную последовательность команд. При вычислении выражения, записанного в форме триад, они вычисляются одна за другой последовательно. Каждая триада в последовательности вычисляется так: операция, заданная триадой, выполняется над операндами, а если в качестве одного из операндов (или обоих операндов) выступает ссылка на другую триаду, то берется результат вычисления той триады. Результат вычисления триады нужно сохранять во временной памяти, так как он может быть затребован последующими триадами. Если какой-то из операндов в триаде отсутствует (например, если триада представляет собой унарную операцию), то он может быть опущен или заменен пустым операндом (в зависимости от принятой формы записи и ее реализации). Порядок вычисления триад, как и тетрад, может быть изменен, но только если допустить наличие триад, целенаправленно изменяющих этот порядок (например, триады, вызывающие переход на несколько шагов вперед или назад при каком-то условии). Триады представляют линейную последовательность, а потому для них несложно написать тривиальный алгоритм, который будет преобразовывать последовательность триад в последовательность команд результирующей программы (либо последовательность команд ассемблера). В этом их преимущество перед синтаксическими деревьями. Однако здесь требуется также и алгоритм, отвечающий за распределение памяти, необходимой для хранения промежуточных результатов вычисления, так как временные переменные для этой цели не используются. В этом отличие триад от тетрад. Так же как и тетрады, триады не зависят от архитектуры вычислительной системы, на которую ориентирована результирующая программа. Поэтому они представляют собой машинно-независимую форму внутреннего представления программы. Триады требуют меньше памяти для представления, чем тетрады, они также явно отражают взаимосвязь операций между собой, что делает их применение удобным. Необходимость иметь алгоритм, отвечающий за распределение памяти для хранения промежуточных результатов, не является недостатком, так как удобно распределять результаты не только по доступным ячейкам временной памяти, но и по имеющимся регистрам процессора. Это дает определенные преимущества. Триады ближе к двухадресным машинным командам, чем тетрады, а именно эти команды более всего распространены в наборах команд большинства современных компьютеров. Поэтому в качестве внутреннего представления программы на языке ГАММА используются триады. В синтаксическом графе у каждой вершины, соответствующей некоторому нетерминальному символу имеются дочерние вершины, количество которых определяется применённым на этапе синтаксического анализа правилом подстановки грамматики. Поскольку их количество, по определению, конечно, то конечным будет и количество шаблонов последовательности триад, некоторые из которых приведены в табл. 1. Таблица 1. Преобразование типовых узлов дерева вывода в последовательность триад Вид узла дерева assign oper1 oper2 assign oper1 Узел 2 assign Узел 2 oper2 assign Узел 2 Узел 3 Результирующий код i) assign (oper1,oper2) Примечание assign – тип триады oper1, oper2 — операнды (листья дерева) Узел 2 – нижележащий узел дерева вывода Code (Узел 2, i) –последовательность триад, порождаемая для Узла 2, начиная с триады с номером i, j — количество триад, порождаемых для Узла 2 Узел 2 — нижележащий узел дерева вывода Code (Узел 2, i) -последовательность триад, порождаемая для Узла 2, начиная с триады с номером i, j — количество триад, порождаемых для Узла 2 Узел 2, Узел 3 — нижележащие узлы дерева вывода i) Code (Узел 2, i) Code (Узел 2, i) –последовательность триад, порождаемая для Узла 2, i+j) Code (Узел 3,i+j) начиная с триады с номером i, j — количество триад, порождаемых i+j+k) assign (^i+j-1, для Узла 2 ^i+j+k-1) Code (Узел 3, i+j) –последовательность триад, порождаемая для Узла 3, начиная с триады с номером i+j, k – количество триад, порождаемых для Узла 3 i) Code (Узел 2, i) i+j) assign (oper1,^i+j-1) i) Code (Узел 2, i) i+j) assign (^i+j-1, oper2) При этом дочерние вершины дерева разбора, помеченные как «Узел 2» и «Узел 3» представляют собой корневые вершины поддеревьев разбора. К ним относятся, в частности: <формула>, <терм>, <элемент массива> и т.д. Поскольку они в дереве разбора могут встречаться многократно, то целесообразно, как это предусмотрено схемой СУ-перевода, осуществлять рекурсивный вызов генератора триад – функции makeTriadListOfSyntSymbol. При этом вначале осуществляется анализ правой части оператора присваивания, например, <формула>, для определения собственно присваиваемого значения, а затем – левой части, т.е. места памяти, в котором должно быть сохранено значение правой части оператора. Укрупнённый алгоритм приведён на рис. 1. Проиллюстрируем работу приведенного алгоритма на примере разбора фрагмента программы входном языке ГАММА (см. рис. 2-4). В качестве исходной программы рассматривается простейший код создания матрицы-строки вида: a = [0 1 2]. Несмотря на очень небольшой объем, приведенный фрагмент кода по смысловому содержанию достаточно емкий. Он включает: а) объявление трех числовых констант: 0, 1, 2; б) объявление массива чисел, являющегося матрицей-строкой; в) объявление идентификатора с именем “a”; г) задание оператора присваивания, осуществляющего соотнесение введенного идентификатора “a” и заданной матрицы-строки. Смысловое назначение приведенного оператора присваивания заключается в именовании введенной матрицы-строки идентификатором “a”, позволяющим далее в программе предоставлять доступ к ней. начало Анализ типа правой части Идентификатор Число <элемент массива> <формула> <терм> <вызов_функции> <массив> Анализ типа левой части идентификатор <элемент массива> <список идентификаторов> конец Объединение списков триад Рис. 1. Укрупнённый алгоритм генерации триад оператора присваивания Рис. 3. Дерево операций, построенное в результате синтаксического анализа Рис. 2. Запись программы на языке ГАММА Рис. 4. Внутреннее представление исходной программы на языке ГАММА в виде триад Полученные результаты иллюстрируют целесообразность применения триад в качестве внутреннего представления программы. Использование схемы синтаксически управляемого перевода обеспечило эффективность созданного синтаксического анализатора. Интерпретация внутреннего представления программы осуществляется посредством выполнения программных модулей, реализующих функции операций, задаваемых триадами. Приведенные экранные формы редактора кода на языке ГАММА иллюстрируют этапы синтаксического разбора, вид внутреннего представления программы и предназначены для использования в качестве учебного материала в лабораторном практикуме по дисциплине «Системное программное обеспечение». Работа выполнена при финансовой поддержке РФФИ (грант 09-07-00200-а). Библиографический список 1. Александров А.Г., Михайлова Л.С., Степанов М.Ф., Брагин Т.М., Степанов А.М. О развитии концепции автоматического решения задач теории управления в системе ГАММА-3 // Мехатроника, автоматизация, управление. 2011. №9. С.14-19. 2. Александров А.Г., Михайлова Л.С., Степанов М.Ф. Система ГАММА-3 и ее применение // Автоматика и телемеханика. 2011. № 10. С.19-27 3. Степанов М.Ф. Анализ и синтез систем автоматического управления в программной среде „ИНСТРУМЕНТ3М-И“ // Известия высших учебных заведений. Приборостроение. 2004. Т.47. №6. С. 27-30. 4. Ахо А., Ульман Дж. Теория синтаксического анализа, перевода и компиляции. В 2-х томах / Пер. с англ.; под ред. В.М. Курочкина. М.: Мир, 1978.