|
Программирование >> Структурное программирование
ментом в стеке. Он выталкивается из стека и компилятор генерирует инструкцию ЯМП, присваивающую этот результат, хранящийся в этом адресе, той переменной, которая находится в левой части оператора let. Второй проход Второй проход компилятора выполняет две задачи: разрешение неразрешенных ссылок и вывод кода ЯМП в файл. Разрешение ссылок производится следующим образом: 1) В массиве flags ищется неразрешенная ссылка (т.е. элемент со значением, отличным от -1). 2) В массив symbolTable помещается объект, содержащий элемент, номер которого хранится в массиве flags (его тин L - номер строки). 3) Адрес из элемента location вставляется в инструкцию с неразрешенной ссылкой (вспомним, что у инструкций, содержащих неразрешенную ссылку, имеется операнд 00). 4) Шаги 1, 2 и 3 повторяются до тех пор, пока не будет достигнут конец массива flags. После того, как процесс разрешения ссылок завершен, весь массив, содержащий код ЯМП, выводится в файл на диске по одной инструкции ЯМП на строку. Этот файл может быть прочитан моделью Простотрона для выполнения (после модификации моделирующей программы, чтобы она читала свои входные данные из файла). Компиляция вашей первой программы на ЯП в файл программы на ЯМП и последующая обработка этого файла несомненно дадут вам удовлетворение. Итоговый пример Следующий пример иллюстрирует полное преобразование программы на ЯП в программу на ЯМП таким образом и в той последовательности, как это выполняется компилятором Простотрона. Допустим, что программа на ЯП вводит целое число и суммирует значения от 1 до этого целого. Программа и инструкции ЯМП, сгенерированные при первом проходе компилятора Простотрона, показаны на рис. 15.25. Таблица символических имен после первого прохода приведена на рис. 15.26. Большая часть операторов непосредственно преобразуется в команды ЯМП. Исключениями в этой программе являются операторы комментариев, оператор if/goto в строке 20 и операторы let. Комментарии не транслируются в машинный код. Однако, номер строки комментария помещается в таблицу символических имен на тот случай, если на этот номер будут ссылаться операторы goto или if/goto. В строке с номером 20 задается условие у == х, при выполнении которого происходит передача управления строке с номером 60. Поскольку строка с номером 60 появляется в программе позднее, то при первом проходе номер строки 60 не помещен в таблицу символических имен (номера строк операторов по- Глава 15 мещаются в таблицу символических имен только если они появляются в качестве первой лексемы в операторе). Следовательно, в этот момент невозможно установить операнд инструкции ЯМП передачи управления по нулю, помещаемой в ячейку 03 массива инструкций ЯМП. Компилятор помещает 60 в ячейку 03 массива flags, чтобы показать, что эту инструкцию должен завершить второй проход. Мы обязаны сохранить этот след адреса, поскольку нет взаимно-однозначаного соответствия между операторами Простотрона и инструкциями ЯМП. Например, оператор if/goto в строке с номером 20 компилируется в три инструкции ЯМП. Каждый раз, когда генерируется инструкция, мы должны увеличивать счетчик команд, указывающий следующую ячейку массива ЯМП. Заметим, что объем памяти Простотрона может создать проблему для программ на ЯП, содержахцих много операторов, переменных и констант. Возможно, что компилятор выйдет за пределы памяти. Чтобы проверять этот случай, следует включить в вашу программу счетчик данных для хранения адреса следующей переменной или константы в массиве ЯМП. Если значение счетчика команд больше значения счетчика данных, значит массив ЯМП полностью заполнен. В этом случае процесс компиляции должен завершиться и компилятор должен выдать сообщение об ошибке переполнения памяти во время компиляции. Следует отметить, что хотя компилятор освобождает программиста от забот о памяти, сам компилятор должен корректно вычислять местоположение команд и данных в памяти и обнаруживать такие ошибки, как отсутствие свободного места в памяти во время компиляции. Пошаговый анализ процесса компиляции Проанализируем весь процесс компиляции программы на ЯП, приведенной на рис. 15.25. Компилятор читает первую строку программы 5 rem sum 1 to х в память. Первая лексема в операторе (номер строки) определяется с помощью strtok (см. главы 5 и 16, в которых рассмотрены функции обработки строк в С-Ь-Ь). Лексема, возвращенная strtok, преобразуется в целое число с помощью atoi и символ 5 ищется в таблице символических имен. Если указанный символ не найден, то он помещается в таблицу. Поскольку мы находимся пока в самом начале программы и смотрим первую строку, то никаких символов в таблице еще нет. Поэтому символ 5 помещается в таблицу как тип L (номер строки) и ему присваивается номер первой ячейки массива ЯМП (00). Хотя эта строка является комментарием, в таблице все-таки выделено для нее место (на случай, если на нее будут ссылаться операторы goto и if/goto). Для оператора rem не генерируется никакая команда, поэтому счетчик команд не увеличивается.
Рис. 15.25. Инструкции ЯМП, сгенерированные после первого прохода компилятора Следующим разбивается на лексемы оператор 10 input X Номер строки 10 помещается в таблицу символических имен как тип L и ему присваивается первая ячейка массива ЯМП (00, поскольку первым оператором программы был оператор комментария rem и значение счетчика команд не увеличилось). Команда input показывает, что следующей лексемой является переменная (только переменная может присутствовать в операторе input). Поскольку input непосредственно соответствует коду операции ЯМП, то компилятор просто должен определить ячейку для х в массиве ЯМП. Символ X не найден в таблице символических имен. Поэтому он помещается в таблицу символических имен в виде кода ASCII для символа X как тип V и ему присваивается адрес 99 в массиве ЯМП (память для хранения данных распределяется в обратном
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |