Джек Креншоу - Давайте создадим компилятор!
Название: | Давайте создадим компилятор! | |
Автор: | Джек Креншоу | |
Жанр: | Самиздат, сетевая литература, Литература ХX века (эпоха Социальных революций), Системное программирование, Pascal, Delphi, Lazarus и т.п. | |
Изадано в серии: | неизвестно | |
Издательство: | неизвестно | |
Год издания: | - | |
ISBN: | неизвестно | |
Отзывы: | Комментировать | |
Рейтинг: | ||
Поделись книгой с друзьями! Помощь сайту: донат на оплату сервера |
Краткое содержание книги "Давайте создадим компилятор!"
Эта серия, написанная в период с 1988 по 1995 года и состоящая из шестнадцати частей, является нетехническим введением в конструирование компиляторов. Серия является руководством по теории и практике разработки синтаксических анализаторов и компиляторов языков программирования. До того как вы закончите чтение этой книги, вы раскроете каждый аспект конструирования компиляторов, разработаете новый язык программирования и создадите работающий компилятор.
Читаем онлайн "Давайте создадим компилятор!". [Страница - 120]
Один из уроков, которым я научился в жизни: Если у вас есть два выбора и вы не можете решить которому их них последовать, иногда самое лучшее – не делать ничего. Зачем добавлять дополнительные ограничители в процессор, чтобы осуществить чужие представления о хорошей практике программирования? Оставьте эти инструкции и позвольте программистам поспорить что такое хорошая практика программирования. Точно так же, почему мы должны добавлять дополнительный код в наш синтаксический анализатор для проверки и предупреждения условий, которые пользователь мог бы предпочесть использовать? Я предпочел бы оставить компилятор простым и позволить программным экспертам спорить, должна ли такая практика использоваться или нет.
Все это служит как объяснение моего решения как избежать смешанной арифметики: я не буду ее избегать. Для языка, предназначенного для системного программирования, чем меньше правил, тем лучше. Если вы не согласны, и хотите выполнять проверку на такие условия, мы сможем сделать это, когда у нас будет таблица идентификаторов.
БУЛЕВО «AND»
С это небольшой философией, мы можем приступить к оператору «and», который пойдет в процедуру Term. К настоящему времени вы возможно сможете сделать это без меня, но в любом случае вот код:В Scanner:
{–}
function IsMulop(c: char): boolean;
begin
IsMulop := c in ['*','/', '&'];
end;
{–}
в Parser:
{–}
procedure Term;
begin
Factor;
while IsMulop(Look) do
case Look of
'*': Multiply;
'/': Divide;
'&': _And;
end;
end;
{–}
{ Parse and Translate a Boolean And Operation }
procedure _And;
begin
Match('&');
Push;
Factor;
PopAnd;
end;
{–}
и в CodeGen:
{–}
{ And Primary with TOS }
procedure PopAnd;
begin
EmitLn('AND (SP)+,D0');
end;
{–}
Ваш синтаксический анализатор теперь должен быть способен обрабатывать почти любые виды логических выражений а также (если вы хотите) и смешанные выражения.
Почему не «все виды логических выражений»? Потому что пока мы не имели дела с логическим оператором «not» и с ним все становится сложнее. Логический оператор «not» кажется на первый взгляд идентичным в своем поведении унарному минусу, поэтому моей первой мыслью было позволить оператору исключающего или, '~', дублировать унарный «not». Это не работало. При моей первой попытке процедура SignedTerm просто съедала мой '~' потому что символ проходил проверку на addop но SignedTerm игнорировал все addop за исключением "-". Было бы достаточно просто добавить другую строку в SignedTerm, но это все равно не решит проблему, потому что, заметьте, Expression принимает терм со знаком только для первого аргумента.
Математически, выражение типа:
–a * -b
имеет небольшой или совсем никакого смысла и синтаксический анализатор должен отметить его как ошибку. Но то же самое выражение, использующее логическое «not», имеет точный смысл:
not a and not b
В случае с этими унарными операторами выбор заставить их работать таким же самым способом кажется исскуственным принуждением, жертвованием примлемым поведением на алтаре простоты реализуемости. Хотя я полностью за сохранение реализации настолько простой, насколько возможно, я не думаю, что мы должны делать это за счет приемлемости. Исправления подобные этому, приведут к потере основной детали, которая заключается в том, чтобы логическое «not» просто не является тем же самым что унарный минус. Рассмотрим исключающее «or», которое обычно записывается так:
a~b ::= (a and not b) or (not a and b)
Если мы разрешим «not» изменять весь терм, последний терм в круглых скобках интерпретировался бы как:
not(a and b)
что совсем не то же самое. Так что ясно, что о логическом «not» нужно думать как о связанном с показателем а не термом.
Идея перегрузки оператор '~' не имеет смысла и с математической точки зрения. Применение унарного минуса эквивалентно вычитанию из нуля:
–x <=> 0-x
Фактически, в одной из моих более простых версий Expression я реагировал на ведущий addop просто предзагружая нуль, затем обрабатывая оператор как если бы это был двоичный оператор. Но «not» это не эквивалент исключающему или с нулем... которое просто возвратит исходное число. Вместо этого, это --">Книги схожие с «Давайте создадим компилятор!» по жанру, серии, автору или названию:
Тина Валевич - Плоть и кровь (СИ) Жанр: Любовная фантастика Год издания: 2017 |