Лекции по построению компилятора на Pascal
или функция абсолютного значения (определенно сложный код!):
### x*(1+2*(x<0))
Пожалуйста, заметьте, что я не защищаю программирование подобным образом как стиль
жизни. Я почти обязательно написал бы эти функции в более читаемой форме, используя IF,
только для того, чтобы защитить от запутывания того, кто будет сопровождать программу в
будущем. Все же возникает моральный вопрос: Имеем ли мы право осуществлять наши идеи
о хорошей практике кодирования на программисте, написав язык так, чтобы он не смог
сделать что-нибудь не так? Это то, что сделал Никлаус Вирт во многих местах Паскаля и
Паскаль критиковался за это - как не такой "прощающий" как Си.
Интересная параллель представлена в примере дизайна Motorola 68000. Хотя Motorola
громко хвастается об ортогональности их набора инструкций, факт то, что он является
далеко не ортогональным. К примеру, вы можете считать переменную по ее адресу:
### MOVE X,D0 (где X это имя переменной)
но вы не можете записать ее таким же образом. Для записи вы должны загрузить в регистр
адреса адрес X. То же самое остается истиной и для PC-относительной адресации.
### MOVE X(PC),DO (допустимо)
### MOVE D0,X(PC) (недопустимо)
Когда вы начинаете спрашивать, как возникло такое не ортогональное поведение, вы
находите, что кто-то в Motorola имел некоторые теории о том, как должно писаться
программное обеспечение. В частности, в этом случае они решили, что
самомодифицирующийся код, который вы можете реализовать, используя PC-относительные
записи - Плохая Вещь. Следовательно, они разработали процессор, запрещающий это. К
сожалению, по ходу дела они также запретили все записи в форме, показанной выше, даже
полезные. Заметьте, что это было не что-то, сделанное по умолчанию. Должна была быть
сделана дополнительная дизайнерская работа, добавлены дополнительные ограничения для
уничтожения естественной ортогональности набора инструкций.
Один из уроков, которым я научился в жизни: Если у вас есть два выбора и вы не можете
решить которому их них последовать, иногда самое лучшее - не делать ничего. Зачем
добавлять дополнительные ограничители в процессор, чтобы осуществить чужие
представления о хорошей практике программирования? Оставьте эти инструкции и
позвольте программистам поспорить что такое хорошая практика программирования. Точно
так же, почему мы должны добавлять дополнительный код в наш синтаксический анализатор
для проверки и предупреждения условий, которые пользователь мог бы предпочесть
использовать? Я предпочел бы оставить компилятор простым и позволить программным
экспертам спорить, должна ли такая практика использоваться или нет.
Все это служит как объяснение моего решения как избежать смешанной арифметики: я не
буду ее избегать. Для языка, предназначенного для системного программирования, чем
меньше правил, тем лучше. Если вы не согласны, и хотите выполнять проверку на такие
условия, мы сможем сделать это, когда у нас будет таблица идентификаторов.
### БУЛЕВО "AND"
С это небольшой философией, мы можем приступить к оператору "and", который пойдет в
процедуру Term. К настоящему времени вы возможно сможете сделать это без меня, но в
любом случае вот код:
В Scanner:
{--------------------------------------------------------------}
function IsMulop(c: char): boolean;
begin
#IsMulop := c in ['*','/', '&'];
end;
{--------------------------------------------------------------}
в Parser: