Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Pascal_Unkn.doc
Скачиваний:
8
Добавлен:
03.11.2018
Размер:
1.63 Mб
Скачать

Операторы

Мы могли бы сейчас остановиться и иметь в своем распоряжении довольно полезный сканер. В тех фрагментах KISS, которые мы построили, единственными токенами, состоящими из нескольких символов, являются идентификаторы и числа. Все операторы были одно-символьными. Единственное исключение, которое я могу придумать - это операторы отношений "<=", ">="  и  "<>", но они могут быть обработаны как особые случаи.

Однако другие языки имеют много символьные операторы такие как ":=" в Паскале или "++" и ">>" в C. Хотя пока нам и не нужны много символьные операторы, было бы хорошо знать как получить их в случае необходимости.

Само собой разумеется, что мы можем обрабатывать операторы точно таким же способом, что и другие токены. Давайте начнем с подпрограммы распознавания:

{--------------------------------------------------------------}

{ Recognize Any Operator }

function IsOp(c: char): boolean; begin    IsOp := c in ['+', '-', '*', '/', '<', '>', ':', '=']; end;

{--------------------------------------------------------------}

Важно заметить, что мы не должны включать в этот список каждый возможный оператор. К примеру круглые скобки не включены, так же как и завершающая точка. Текущая версия Scan и так хорошо поддерживает одно-символьные операторы. Список выше включает только те символы, которые могут появиться в много символьных операторах. (Для конкретных языков список конечно всегда может быть отредактирован).

Теперь давайте изменим Scan следующим образом:

{--------------------------------------------------------------}

{ Lexical Scanner }

Function Scan: string; begin    while Look = CR do       Fin;    if IsAlpha(Look) then       Scan := GetName    else if IsDigit(Look) then       Scan := GetNum    else if IsOp(Look) then       Scan := GetOp    else begin       Scan := Look;       GetChar;    end;    SkipWhite; end;

{--------------------------------------------------------------}

Теперь испытайте программу. Вы убедитесь, что любые фрагменты кода, которые вы  захотите бросить в нее будут аккуратно разложены на индивидуальные токены.

Списки, запятые и командные строки.

Прежде чем возвратиться к основной цели нашего обучения, я хотел бы немного выступить.

Сколько раз вы работали с программой или операционной системой, которая имела жесткие правила того, как вы должны разделять элементы в списке? (Попробую, последний раз вы использовали MS DOS!). Некоторые программы требуют пробелов как разделителей, некоторые требуют запятые. Хуже всего, что некоторые требуют и того и другого в разных местах. Большинство довольно неумолимы к нарушениям их правил.

Я думаю, это непростительно. Слишком просто написать синтаксически анализатор, который поддерживает и пробелы и запятые гибким способом. Рассмотрите следующую процедуру:

{--------------------------------------------------------------}

{ Skip Over a Comma }

procedure SkipComma; begin    SkipWhite;    if Look = ',' then begin       GetChar;       SkipWhite;    end; end;

{--------------------------------------------------------------}

Эта процедура из восьми строк пропустит разделитель, состоящий из любого числа (включая ноль) пробелов, с нулем или одной запятой, вложенной в строку.

Временно измените вызов SkipWhite в Scan на вызов SkipComma и попробуйте ввести какие-нибудь списки. Хорошо работает, да? Разве вы не хотите, чтобы больше создателей программ знало о SkipComma?

К слову сказать, я обнаружил, что добавление эквивалента SkipComma в мою программу на ассемблере для Z80 заняло всего шесть дополнительных байт кода. Даже на 64K машинах это не слишком большая цена за дружелюбие к пользователю.

Я думаю вы  можете видеть к чему я клоню. Даже если вы в своей жизни не написали ни одной строчки кода для компилятора, в каждой программе существуют места, где вы можете использовать понятие синтаксического анализа. Любая программа, которая обрабатывает командные строки, нуждается в нем. Фактически, если вы подумаете немного об этом, вы придете к заключению, что всякий раз, когда вы пишете программу, обрабатывающую ввод пользователя, вы определяете язык. Люди общаются с помощью языков и неявный синтаксис в вашей программе определяет этот язык. Настоящий вопрос: вы собираетесь определять его преднамеренно и явно, или просто позволите существовать независимо от того, как программа завершает синтаксический анализ?

Я утверждаю, что у вас будет лучший, более дружественный интерфейс если вы потратите время на то, чтобы определить синтаксис явно. Запишите синтаксические уравнения или нарисуйте "railroad-track"  диаграммы и закодируйте синтаксический анализатор используя методы, которые я показал вам здесь. Вы получите более хорошую программу и ее будет проще писать, в придачу.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]