Лекции по построению компилятора на Pascal
Так что я думаю, что предпочитаю Паскалевский подход встраивания подпрограмм
ввода/вывода, даже если мы не нуждаемся в этом.
Как обычно, для этого нам нужны еще несколько подпрограмм генерации кода. Они,
оказывается, самые простые из всех, потому что все, что мы делаем это вызываем
библиотечные процедуры для выполнения работы.
{---------------------------------------------------------------}
{ Read Variable to Primary Register }
procedure ReadVar;
begin
## EmitLn('BSR READ');
## Store(Value);
end;
{---------------------------------------------------------------}
{ Write Variable from Primary Register }
procedure WriteVar;
begin
## EmitLn('BSR WRITE');
end;
{--------------------------------------------------------------}
Идея состоит в том, что READ загружает значение из входного потока в D0, а WRITE
выводит его оттуда.
Эти две процедуры представляют собой нашу первую встречу с потребностью в
библиотечных процедурах... компонентах Run Time Library (RTL). Конечно кто-то (а именно
мы) должен написать эти подпрограммы, но они не являются непосредственно частью
компилятора. Я даже не буду беспокоиться о том, чтобы показать здесь эти подпрограммы,
так как они очевидно очень ОС-зависимы. Я просто скажу, что для SK*DOS они особенно
просты... почти тривиальны. Одна из причин, по которым я не буду показывать их здесь в
том, что вы можете добавлять новые виды возможностей, например приглашение в READ
или возможность пользователю повторить ошибочный ввод.
Но это действительно отдельный от компилятора проект, так что теперь я буду
подразумевать что библиотека, называемая TINYLIB.LIB, существует.
Так как нам теперь нужно загружать ее, мы должны добавить ее загрузку в процедуру
Header:
{--------------------------------------------------------------}
{ Write Header Info }
procedure Header;
begin
## WriteLn('WARMST', TAB, 'EQU $A01E');
## EmitLn('LIB TINYLIB');
end;
{--------------------------------------------------------------}
Она возьмет на себя эту часть работы. Теперь нам также необходимо распознавать команды
ввода и вывода. Мы можем сделать это добавив еще два ключевых слова в наш список:
{--------------------------------------------------------------}
{ Definition of Keywords and Token Types }
const NKW =## 11;
##### NKW1 = 12;
const KWlist: array[1..NKW] of Symbol =
############# ('IF', 'ELSE', 'ENDIF', 'WHILE', 'ENDWHILE',
############## 'READ',### 'WRITE',### 'VAR',### 'BEGIN',## 'END',
'PROGRAM');
const KWcode: string[NKW1] = 'xileweRWvbep';
{--------------------------------------------------------------}
(Обратите внимание, что здесь я использую кода в верхнем регистре чтобы избежать
конфликта с 'w' из WHILE.)