А. Григорьев - О чём не пишут в книгах по Delphi

Тут можно читать онлайн А. Григорьев - О чём не пишут в книгах по Delphi - бесплатно ознакомительный отрывок. Жанр: comp-programming, издательство БХВ-Петербург, год 2008. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    О чём не пишут в книгах по Delphi
  • Автор:
  • Жанр:
  • Издательство:
    БХВ-Петербург
  • Год:
    2008
  • Город:
    СПб
  • ISBN:
    978-5-9775-019003
  • Рейтинг:
    4.25/5. Голосов: 81
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

А. Григорьев - О чём не пишут в книгах по Delphi краткое содержание

О чём не пишут в книгах по Delphi - описание и краткое содержание, автор А. Григорьев, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

Рассмотрены малоосвещённые вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные механизмы их работы, особенности для протоколов TCP и UDP и др. Большое внимание уделено разбору ситуаций возникновения ошибок и получения неверных результатов в "простом и правильном" коде. Отдельно рассмотрены особенности работы с целыми, вещественными и строковыми типами данных, а также приведены примеры неверных результатов, связанных с ошибками компилятора, VCL и др. Для каждой из таких ситуаций предложены методы решения проблемы. Подробно рассмотрен синтаксический анализ в Delphi на примере арифметических выражений. Многочисленные примеры составлены с учётом различных версий: от Delphi 3 до Delphi 2007. Прилагаемый компакт-диск содержит примеры из книги.

Для программистов

О чём не пишут в книгах по Delphi - читать онлайн бесплатно ознакомительный отрывок

О чём не пишут в книгах по 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, которая принимает произвольное число аргументов и возвращает их среднее. Для этого правила, связанные с функциями, переопределим так:

::= '(' { } ')'

::= 'sin' | 'cos' | 'ln' | 'log' | 'mean'

Отдельного комментария требует символ , разделяющий аргументы в функции. В Delphi, как и во многих других языках программирования, таким разделителем служит запятая. Но наша грамматика определена так, что запятая, в принципе, может служить разделителем целой и дробной части числа. Как уже говорилось, в этом случае может возникнуть неоднозначность в выражениях типа f(1,5)— это вызов функции fто ли с одним аргументом 1.5, то ли с двумя аргументами 1 и 5. Чтобы избежать подобных неоднозначностей, в нашей грамматике разделителем аргументов будет символ, выбранный разделителем элементов списка (в русской локализации Windows это точка с запятой). Для корректной работы программы следите, чтобы на вашем компьютере разделители элементов списка, а также целой и дробной частей не оказались одинаковыми.

Особенность нашего нового синтаксиса в том, что он допускает любое число аргументов для любой функции, т.е., например, выражение sin(0, 1, 2, 4)синтаксически корректно (при условии, что разделителем элементов списка является запятая), хотя смысла это выражение не имеет. Можно было бы ввести отдельные синтаксические правила для функций с одним аргументом, с двумя аргументами и с произвольным числом аргументов, но такой подход встречается редко, т.к. обычно намного проще осуществить проверку на этапе семантического анализа (т.е. в нашем случае — при вычислении функции).

Для реализации новых синтаксических и семантических правил в код вносятся следующие изменения. Во-первых, появляются новые лексемы ltLog, ltMeanи ltListSeparator, а соответствующие методы лексического анализатора модифицируются так, чтобы распознавать их. Во-вторых, модифицируется функция Func— она сначала вычисляет все аргументы, переданные функции, а потом проверяет, является ли количество аргументов допустимым, и если да, вычисляет требуемую функцию.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


А. Григорьев читать все книги автора по порядку

А. Григорьев - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




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


Отзывы читателей о книге О чём не пишут в книгах по Delphi, автор: А. Григорьев. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x