<expression> ::= <signed_term> (<addop> <term>)*

<assignment> ::= <variable> '=' <expression>

БУЛЕВА АЛГЕБРА

Следующий шаг, как мы изучили несколько раз до этого, это добавление булевой алгебры. В прошлом этот шаг по крайней мере удваивал количество кода, который мы должны были написать. Когда я прошел эти шаги в своем уме, я обнаружил, что отклоняюсь все больше и больше от того, что мы делали в предыдущих главах. Чтобы освежить вашу память, я отметил, что Паскаль обрабатывает булевы операторы в значительной степени идентично способу, которым он обрабатывает арифметические операторы. Булево «and» имеет тот же самый уровень приоритета, что и умножение, а «or» то же что сложение. Си, с другой стороны, устанавливает их на различных уровнях приоритета, которые занимают 17 уровней. В нашей более ранней работе я выбрал что-то среднее, с семью уровнями. В результате, мы закончили на чем-то называющемся булевыми выражениями, соответствующим в большинстве деталей арифметическим выражениям, но на другом уровне приоритета. Все это, как оказалось, возникло потому, что мне не хотелось помещать скобки вокруг булевых выражений в утверждениях типа:

IF (c >= 'A') and (c <= 'Z') then ...

При взгляде назад, это кажется довольно мелкой причиной для добавления многих уровней сложности в синтаксический анализатор. Возможно более существенно то, что я не уверен что был даже способен избежать скобок.

Чтобы оттолкнуться, давайте начнем заново, применяя более Паскаль-подобный подход и просто обрабатывая булевы операторы на том же самом уровне приоритетов что и арифметические. Мы увидим, куда это нас приведет. Если это окажется тупиком, мы всегда сможем возвратиться к предыдущему подходу.

Сперва, мы добавим в Expression операторы «уровня сложения». Это легко сделать; во первых, измените функцию IsAddop в модуле Scanner чтобы включить два дополнительных оператора: '|' для «или» и '~' для «исключающее или»:

{–}

function IsAddop(c: char): boolean;

begin

IsAddop := c in ['+','-', '|', '~'];

end;

{–}

Затем, мы должны включить анализ операторов в процедуру Expression:

{–}

procedure Expression;

begin

SignedTerm;

while IsAddop(Look) do

case Look of

'+': Add;

'-': Subtract;

'|': _Or;

'~': _Xor;

end;

end;

{–}

(Символы подчеркивания необходимы, конечно, потому что «or» and «xor» являются зарезервированными словами Turbo Pascal).

Затем процедуры _Or and _Xor:

{–}

{ Parse and Translate a Subtraction Operation }

procedure _Or;

begin

Match('|');

Push;

Term;

PopOr;

end;

{–}

{ Parse and Translate a Subtraction Operation }

procedure _Xor;

begin

Match('~');

Push;

Term;

PopXor;

end;

{–}

И, наконец, новые процедуры генерации кода:

{–}

{ Or TOS with Primary }

procedure PopOr;

begin

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

end;

{–}

{ Exclusive-Or TOS with Primary }

procedure PopXor;

begin

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

end;

{–}

Теперь давайте протестируем транслятор (вы возможно захотите изменить вызов в Main обратно на вызов Expression просто чтобы избежать необходимости набирать каждый раз «x=» для присваивания).

Пока все хорошо. Синтаксический анализатор четко обрабатывает выражения вида:

x|y~z

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

(a+b)*(c~d)

Мы говорили об этом немного в прошлом. Вообще, правила какие операции допустимы а какие нет не могут быть применены самим синтаксическим анализатором, потому что они не являются частью

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату