"Джек Креншоу. Давайте создадим компилятор! " - читать интересную книгу автора

проигранная битва... возможно никогда не придет время, когда хороший
программист на ассемблере не смог бы превзойти компилятор. Прежде чем
закончится этот урок, я кратко упомяну некоторые способы, которые мы можем
применить для небольшой оптимизации, просто, чтобы показать вам, что мы на
самом деле сможем сделать некоторые улучшения без излишних проблем. Но
запомните, мы здесь для того, чтобы учиться, а не для того, чтобы узнать
насколько компактным мы можем сделать код. А сейчас и на протяжении всей
этой серии мы старательно будем игнорировать оптимизацию и сконцентрируемся
на получении работающего кода.
Но наш код не работает! В коде есть ошибка! Команда вычитания вычитает
D1 (первый аргумент) из D0 (второй аргумент). Но это неправильный способ,
так как мы получаем неправильный знак результата. Поэтому исправим процедуру
Subtract с помощью замены знака следующим образом:

{-}
{ Recognize and Translate a Subtract }
procedure Subtract;
begin
Match('-');
Term;
EmitLn('SUB D1,D0');
EmitLn('NEG D0');
end;
{-}

Теперь наш код даже еще менее эффективен, но по крайней мере выдает
правильный ответ! К сожалению, правила, которые определяют значение
математических выражений, требуют, чтобы условия в выражении следовали в
неудобном для нас порядке. Опять, это только один из фактов жизни, с
которыми вы учитесь жить. Все это возвратится снова, чтобы преследовать нас,
когда мы примемся за деление.
Итак, на данном этапе мы имеем синтаксический анализатор, который может
распознавать сумму или разность двух цифр. Ранее мы могли распознавать
только одиночные цифры. Но настоящие выражения могут иметь любую форму (или
бесконечность других). Вернитесь и запустите программу с единственным
входным символом "1".
Не работает? А почему должен работать? Мы только указали анализатору,
что единственным правильными видами выражений являются выражения с двумя
термами. Мы должны переписать процедуру Expression так, чтобы она была
намного более универсальной и с этого начать создание настоящего
синтаксического анализатора.

ОБЩАЯ ФОРМА ВЫРАЖЕНИЯ

В реальном мире выражение может состоять из одного или более термов,
разделенных "addops" ('+' или '-'). В БНФ это может быть записано как:
::= [ ]*
Мы можем применить это определение выражения, добавив простой цикл к
процедуре Expression: