конечно выглядит несерьезно.
Нам нужен завершающий символ. Я выступаю за завершающую точку в Pascal ('.'). Небольшое осложнение состоит в том, что Turbo Pascal завершает каждую нормальную строку двумя символами: возврат каретки (CR) и перевод строки (LF). В конце каждой строки мы должны «съедать» эти символы перед обработкой следующей. Естественным способом было бы сделать это в процедуре Match за исключением того, что сообщение об ошибке Match выводит ожидаемые символы, что для CR и LF не будет выглядеть так хорошо. Для этого нам нужна специальная процедура, которую мы, без сомнения, будем использовать много раз. Вот она:
{–}
{ Recognize and Skip Over a Newline }
procedure NewLine;
begin
if Look = CR then begin
GetChar;
if Look = LF then
GetChar;
end;
end;
{–}
Вставьте эту процедуру в любом удобном месте… я поместил ее сразу после Match. Теперь перепишите основную программу, чтобы она выглядела следующим образом:
{–}
{ Main Program }
begin
Init;
repeat
Assignment;
NewLine;
until Look = '.';
end.
{–}
Обратите внимание, что проверка на CR теперь исчезла и что также нет проверки на ошибку непосредственно внутри NewLine. Это нормально… все оставшиеся фиктивные символы будут отловлены в начале следующей операции присваивания.
Хорошо, сейчас мы имеем функционирующий интерпретатор. Однако, это не дает нам много хорошего, так как у нас нет никакого способа для ввода или вывода данных. Уверен что нам помогут несколько подпрограмм ввода/вывода!
Тогда давайте завершим этот урок добавив подпрограммы ввода/вывода. Так как мы придерживаемся односимвольных токенов, я буду использовать знак '?' для замены операции чтения, знак '!' для операции записи и символ, немедленно следующий после них, который будет использоваться как односимвольный «список параметров». Вот эти подпрограммы:
{–}
{ Input Routine }
procedure Input;
begin
Match('?');
Read(Table[GetName]);
end;
{–}
{ Output Routine }
procedure Output;
begin
Match('!');
WriteLn(Table[GetName]);
end;
{–}
Я полагаю они не очень причудливы… например нет никакого символа приглашения при вводе… но они делают свою работу.
Соответствующие изменения в основной программе показаны ниже. Обратите внимание, что мы используем обычный прием – оператор выбора по текущему предсказывающему символу, чтобы решить что делать.
{–}
{ Main Program }
begin
Init;
repeat
case Look of
'?': Input;
'!': Output;
else Assignment;
end;
NewLine;
until Look = '.';
end.
{–}
Теперь вы закончили создание настоящего, работающего интерпретатора. Он довольно скудный, но работает совсем как «большой мальчик». Он включает три вида операторов (и может различить их!), 26 переменных и операторы ввода/вывода. Единственное, в чем он действительно испытывает недостаток – это операторы управления, подпрограммы и некоторые виды функций для редактирования программы. Функции редактирования программ я собираюсь пропустить. В конце концов, мы здесь не для того, чтобы создать готовый продукт, а чтобы учиться. Управляющие операторы мы раскроем в следующей главе, а подпрограммы вскоре после нее. Я стремлюсь продолжать дальше, поэтому мы оставим интерпретатор в его текущем состоянии.
Я надеюсь, к настоящему времени вы убедились, что ограничение имен одним символом и обработка пробелов это вещи о которых легко позаботиться, как мы сделали это на последнем уроке. На этот раз, если вам захотелось поиграть с этими расширениями, будьте моим гостем… они «оставлены как упражнение для студента». Увидимся в следующий раз.
Управляющие конструкции