ОК, переименуйте старую версию BoolExpression в BoolTerm, затем наберите код, представленный выше. Откомпилируйте и протестируйте эту версию. К этому моменту выходной код начинает выглядеть довольно хорошим. Конечно, нет большого смысла от булевой алгебры над постоянными значениями, но скоро мы расширим булевы типы, с которыми мы работаем.

Возможно вы уже предположили, какой будет следующий шаг: булевская версия Term.

Переименуйте текущую процедуру BoolTerm в NotFactor, и введите следующую новую версию BoolTerm. Заметьте, что она намного более простая, чем числовая версия, так как здесь нет эквивалента деления.

{–}

{ Parse and Translate a Boolean Term }

procedure BoolTerm;

begin

NotFactor;

while Look = '&' do begin

EmitLn('MOVE D0,-(SP)');

Match('&');

NotFactor;

EmitLn('AND (SP)+,D0');

end;

end;

{–}

Теперь мы почти дома. Мы транслируем сложные булевые выражения, хотя только и для постоянных значений. Следующий шаг – учесть NOT. Напишите следующую процедуру:

{–}

{ Parse and Translate a Boolean Factor with NOT }

procedure NotFactor;

begin

if Look = '!' then begin

Match('!');

BoolFactor;

EmitLn('EOR #-1,D0');

end

else

BoolFactor;

end;

{–}

И переименуйте предыдущую процедуру в BoolFactor. Теперь испытайте компилятор. К этому времени синтаксический анализатор должен обрабатывать любое булевое выражение, которое вы позаботитесь ему подкинуть. Работает? Отлавливает ли он неправильно сформированные выражения?

Если вы следили за тем, что мы делали в синтаксическом анализаторе для математических выражений вы знаете что далее мы расширили определение показателя для включения переменных и круглых скобок. Мы не должны делать это для булевого показателя, потому что об этих маленьких вещах позаботится наш следующий шаг. Необходима только одна дополнительная строка в BoolFactor, чтобы позаботиться об отношениях:

{–}

{ Parse and Translate a Boolean Factor }

procedure BoolFactor;

begin

if IsBoolean(Look) then

if GetBoolean then

EmitLn('MOVE #-1,D0')

else

EmitLn('CLR D0')

else Relation;

end;

{–}

Вы могли бы задаться вопросом, когда я собираюсь предоставить булевские переменные и булевские выражения в скобках. Отвечаю: никогда. Помните, ранее мы убрали их из грамматики. Прямо сейчас я собираюсь кодировать грамматику, которую мы уже согласовали. Сам компилятор не может видеть разницы между булевыми переменными или выражениями и арифметическими переменными или выражениями... все это будет обрабатываться в Relation в любом случае.

Конечно, понадобится некоторый код для Relation. Однако, я не чувствую себя комфортно, добавляя еще код, не проверив сперва тот, который мы уже имеем. Так что давайте сейчас просто напишем фиктивную версию Relation, которая ничего не делает за исключением того, что съедает текущий символ и выводит небольшое сообщение:

{–}

{ Parse and Translate a Relation }

procedure Relation;

begin

WriteLn('');

GetChar;

end;

{–}

ОК, наберите этот код и испытайте его. Все старые дела все еще должны работать... у вас должна быть возможность генерировать код для AND, OR и NOT. Кроме того, если вы наберете любой алфавитный символ, вы должны получить небольшой заменитель , где должен быть булев показатель. Вы получили это? Отлично, тогда давайте перейдем к полной версии Relation.

Чтобы получить ее, тем не менее, сначала мы должны положить небольшое основание. Вспомните, что отношение имеет форму:

 ::= | [


Перейти на страницу:
Изменить размер шрифта: