Чтение онлайн

на главную

Жанры

О чём не пишут в книгах по Delphi

Григорьев Антон Борисович

Шрифт:

4.9. Однопроходный калькулятор и функции с несколькими переменными

В предыдущем примере выражение сначала от начала до конца просматривается лексическим анализатором и переводится в иную форму (список лексем). Затем этот список обрабатывается синтаксическим анализатором. Таким образом, калькулятор получается двухпроходным, хотя из синтаксиса и семантики выражения необходимость нескольких проходов не вытекает. Попробуем переделать его так, чтобы он стал однопроходным.

Примечание

В некоторых языках многопроходность — обязательное требование к реализации компилятора.

Например, в языке C++ реализацию функций класса можно вставлять в само описание класса. При этом внутри этих функций можно обращаться к тем полям и функциям класса, которые объявлены ниже. Таким образом, откомпилировать подобный код может только компилятор как минимум с двумя проходами, чтобы на первом проходе можно было найти все поля класса, а на втором — откомпилировать функции класса.

В предыдущей реализации калькулятора синтаксический анализатор работал с лексическим через процедуру

Next
и свойство
Lexeme
: процедура
Next
передвигала текущую позицию в списке лексем, а свойство
Lexeme
давало доступ к текущей лексеме. Легко видеть, что при таком алгоритме лексическому анализатору нет необходимости хранить полный список лексем, достаточно помнить текущую, а при вызове
Next
анализировать очередную часть строки, выделяя из нее следующую лексему и делая ее текущей. Таким образом, синтаксический и лексический анализаторы будут работать по очереди, обрабатывая каждый по одной лексеме.

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

Next
теперь выполняет выделение очередной лексемы, которую помещает в специально созданное для этого поле, а свойство
Lexeme
возвращает указатель на это поле, а не на элемент списка. Остальные функции лексического анализатора изменились только в том отношении, что теперь выражение и указатель на позицию в строке получают не через параметры, а напрямую обращаются к соответствующим полям.

Пример однопроходного калькулятора с лексическим анализатором находится на компакт-диске в папке

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

Листинг 4.14. Однопроходный вариант класса
TLexicalAnalyzer

type

 TLexicalAnalyzer = class

 private

// Выражение для вычисления

FExpr: string;

// Текущая позиция

FP: Integer;

// Текущая лексема

FCurrLexeme: TLexeme;

function GetLexeme: PLexeme;

procedure SkipWhiteSpace;

procedure ExtractLexeme;

procedure PutLexeme(LexemeType: TLexemeType; Pos: Integer; const Lexeme: string);

procedure Number;

procedure Word;

 public

constructor Create(const Expr: string);

procedure Next;

property Lexeme: PLexeme read GetLexeme;

 end;

constructor TLexicalAnalyzer.Create(const Expr: string);

begin

 inherited Create;

 FP := 1;

 FExpr := Expr;

 Next;

end;

//
Получение указателя на текущую лексему

function TLexicalAnalyzer.GetLexeme: PLexeme;

begin

 Result := @FCurrLexeme;

end;

// Получение следующей лексемы

procedure TLexicalAnalyzer.Next;

begin

 if FP <= Length(FExpr) then

 begin

SkipWhiteSpace;

ExtractLexeme;

 end

 else PutLexeme(ltEnd, FP, '');

end;

// Замещение текущей лексемы новой лексемой

procedure TLexicalAnalyzer.PutLexeme(LexemeType: TLexemeType; Pos: Integer; const Lexeme: string);

begin

 FCurrLexeme.LexemeType := LexemeType;

 FCurrLexeme.Pos := Pos;

 FCurrLexeme.Lexeme := Lexeme;

end;

Теперь класс

TLexicalAnalyzer
хранит не список лексем, а только одну текущую лексему, а функция
PutLexeme
не добавляет лексему в список, а изменяет значение текущей лексемы. Функция
Next
вместо простого изменения индекса выделяет очередную лексему, т.е. выполняет одну итерацию цикла лексического анализа. Функции
SkipWhiteSpace
,
ExtractLexeme
и т.п. избавились от параметров, через которые передавалось выражение и позиция, потому что теперь выражение и позиция хранятся в полях класса.

Синтаксический анализатор при этом остается без изменений, т.к. интерфейс лексического анализатора не изменился.

Чтобы не реализовывать дважды одну и ту же грамматику, введем в наш синтаксис еще одну возможность — поддержку функций с несколькими аргументами. Конкретно — функцию с двумя аргументами

Log(а, x)
, возвращающей логарифм
x
по основанию
a
, а также функцию Mean, которая принимает произвольное число аргументов и возвращает их среднее. Для этого правила, связанные с функциями, переопределим так:

Поделиться:
Популярные книги

Камень. Книга пятая

Минин Станислав
5. Камень
Фантастика:
боевая фантастика
6.43
рейтинг книги
Камень. Книга пятая

Черный маг императора

Герда Александр
1. Черный маг императора
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Черный маг императора

Кодекс Крови. Книга VI

Борзых М.
6. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга VI

Отверженный. Дилогия

Опсокополос Алексис
Отверженный
Фантастика:
фэнтези
7.51
рейтинг книги
Отверженный. Дилогия

Неудержимый. Книга XIII

Боярский Андрей
13. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга XIII

Черный Маг Императора 6

Герда Александр
6. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
7.00
рейтинг книги
Черный Маг Императора 6

Начальник милиции. Книга 3

Дамиров Рафаэль
3. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции. Книга 3

На границе империй. Том 9. Часть 2

INDIGO
15. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 2

Лорд Системы 13

Токсик Саша
13. Лорд Системы
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Лорд Системы 13

На границе империй. Том 9. Часть 4

INDIGO
17. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 4

Вторая невеста Драконьего Лорда. Дилогия

Огненная Любовь
Вторая невеста Драконьего Лорда
Любовные романы:
любовно-фантастические романы
5.60
рейтинг книги
Вторая невеста Драконьего Лорда. Дилогия

Неудержимый. Книга X

Боярский Андрей
10. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга X

Гарем вне закона 18+

Тесленок Кирилл Геннадьевич
1. Гарем вне закона
Фантастика:
фэнтези
юмористическая фантастика
6.73
рейтинг книги
Гарем вне закона 18+

В зоне особого внимания

Иванов Дмитрий
12. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
В зоне особого внимания