Лекции по построению компилятора на Pascal
грамматики. Прямо сейчас я собираюсь кодировать грамматику, которую мы уже
согласовали. Сам компилятор не может видеть разницы между булевыми переменными или
выражениями и арифметическими переменными или выражениями... все это будет
обрабатываться в Relation в любом случае.
Конечно, понадобится некоторый код для Relation. Однако, я не чувствую себя комфортно,
добавляя еще код, не проверив с начала тот, который мы уже имеем. Так что давайте сейчас
просто напишем фиктивную версию Relation, которая ничего не делает за исключением того,
что съедает текущий символ и выводит небольшое сообщение:
{---------------------------------------------------------------}
{ Parse and Translate a Relation }
procedure Relation;
begin
## WriteLn('<Relation>');
## GetChar;
end;
{--------------------------------------------------------------}
ОК, наберите этот код и испытайте его. Все старые дела все еще должны работать... у вас
должна быть возможность генерировать код для AND, OR и NOT. Кроме того, если вы
наберете любой алфавитный символ, вы должны получить небольшой заменитель
<Relation>, где должен быть булев показатель. Вы получили это? Отлично, тогда давайте
перейдем к полной версии Relation.
Чтобы получить ее, тем не менее, сначала мы должны положить небольшое основание.
Вспомните, что отношение имеет форму:
#### <relation>#### ::= | <expression> [<relop> <expression]
Так как у нас появился новый вид операторов, нам также понадобится новая логическая
функция для ее распознавания. Эта функция показана ниже. Из-за ограничения в один
символ, я придерживаюсь четырех операторов, которые могут быть закодированы такими
символами ("не равно" закодировано как "#").
{--------------------------------------------------------------}
{ Recognize a Relop }
function IsRelop(c: char): Boolean;
begin
## IsRelop := c in ['=', '#', '<', '>'];
end;
{--------------------------------------------------------------}
Теперь вспомните, что мы используем нуль или -1 в регистре D0 для представления
логического значения и также то, что операторы цикла ожидают, что будет установлен
соответствующий флаг. При реализации всего этого для 68000 все становится немного
сложным.
Так как операторы цикла выполняются только по флажкам, было бы хорошо (а также
довольно эффективно) просто установить эти флажки и совсем ничего не загружать в D0.
Это было бы прекрасно для циклов и ветвлений, но запомните, что отношения могут быть
использованы везде, где могут быть использованы булевы показатели. Мы можем сохранять
его результат в булевой переменной. Так как мы не можем знать пока как будет
использоваться результат, мы должны учесть оба случая.
Сравнение числовых данных достаточно просто... 68000 имеет команду для этого... но она
устанавливает флажки а не значение. Более того, всегда будут устанавливаться те же самые
флажки (ноль если равно, и т.д.), в то время, как нам необходим по-разному установленный]
флажок нуля для каждого различного оператора отношения.
Решение заключается в инструкции Scc процессора 68000, которая устанавливает значение
байта в 0000 или FFFF (забавно как это работает!) в зависимости от результата
определенного условия. Если мы сделаем байтом результата регистр D0, мы получим
необходимое логическое значение.