Лекции по построению компилятора на Pascal
В нашем случае мы начали с чистого листа бумаги. Имеется опасность, конечно, что вы
попадетесь в ловушки, которые другие люди давно научились избегать. Но это также
позволило нам использовать различные подходы, которые, частично из-за проекта, частично
из-за чистой удачи, позволили нам добиться простоты.
Имеются области, которые, я думаю, в прошлом приводили к сложности:
Ограниченная оперативная память, вынуждающая выполнять множество проходов.
Я только что прочитал "Brinch Hansen on Pascal Compilers" (отличная книга, BTW). Он
разработал компилятор Pascal для PC, но он начал в 1981 г. с систем с 64К памяти и]
поэтому почти каждое решение проекта который он делал, было нацелено на то,
чтобы уместить компилятор в ОЗУ. Чтобы сделать это, его компилятор выполнял три
прохода, один из которых - лексический анализ. Не было никакого способа, с
помощью которого он мог бы, например, использовать распределенный сканер,
который я представил в последней главе, потому что структура программы не
позволяла этого. Ему также требовались не один а два промежуточных языка для
обеспечения связи между фазами.
Все ранние создатели компиляторов были вынуждены иметь дело с такой проблемой:
разбить компилятор на достаточные части так, чтобы они поместились в памяти.
Когда у вас есть множество проходов, вы должны добавить структуры данных для
поддержки информации которую каждый проход оставляет для следующего. Это
добавляет сложность и завершает управление проектом. В книге Ли "The Anatomy of
a] Compiler" упоминается компилятор Fortran, разработанный для IBM 1401. Он имел
не менее 63 отдельных проходов! Само собой разумеется, в компиляторе, подобном
этому, разделение на фазы доминировало бы над дизайном.
Даже в ситуации, когда ОЗУ достаточно, люди предпочитали использовать те же
самые методы, с которыми они хорошо знакомы. До тех пор, пока не появился Turbo
Pascal, мы не знали насколько может быть простым компилятор если бы вы начали с
других предположений.
Пакетная обработка.
В ранние дни пакетная обработка была единственным выбором... не существовало
никаких интерактивных вычислений. Даже сегодня компиляторы по существу
выполняются в пакетном режиме.
В компиляторах для майн-фреймов, так же как и во многих микро компиляторах,]
значительные усилия расходуются на восстановление после ошибок... это может
занять 30-40% компилятора и полностью управлять проектом. Идея состоит в том,
чтобы избежать остановки на первой ошибке, а скорее идти любой ценой, так чтобы
вы могли сказать программисту о как можно большем количестве ошибок во всей
программе насколько возможно.
Все это возвращает нас к дням ранних майн-фреймов, где время выполнения
измерялось в часах и днях и было важно выжать каждую последнюю унцию
информации из каждого выполнения.
В этой серии я был очень осторожен и избежал проблемы восстановления после
ошибок и вместо этого наш компилятор просто останавливается с сообщением на
первой ошибке. Я откровенно признаюсь, что это было в основном потому, что я
захотел использовать легкий путь и сохранить простоту. Но этот метод, заданный
изначально Borland в Turbo Pascal также имеет много полезного в любом случае.
Кроме сохранения простоты компилятора это также очень хорошо соответствует идее
интерактивной системы. Когда компиляция происходит быстро и, особенно, когда вы
имеете] редактор типа Borland который будет правильно указывать вам на точку
ошибки, тогда имеет смысл остановиться там и просто перезапустить компиляцию
после того, как ошибка исправлена.