MyBooks.club
Все категории

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

На сайте mybooks.club вы можете бесплатно читать книги онлайн без регистрации, включая А. Григорьев - О чём не пишут в книгах по Delphi. Жанр: Программирование издательство -,. Доступна полная версия книги с кратким содержанием для предварительного ознакомления, аннотацией (предисловием), рецензиями от других читателей и их экспертным мнением.
Кроме того, на сайте mybooks.club вы найдете множество новинок, которые стоит прочитать.

Название:
О чём не пишут в книгах по Delphi
Издательство:
-
ISBN:
-
Год:
-
Дата добавления:
17 сентябрь 2019
Количество просмотров:
245
Читать онлайн
А. Григорьев - О чём не пишут в книгах по Delphi

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

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

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

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

В зависимости от типа лексем разделители между ними могут быть обязательными или необязательными. Например, в выражении "2+3" разделители между лексемами "2", "+" и "5" не нужны, потому что они могут быть отделены друг от друга и без этого. А в выражении 6 div 3 разделитель между "div" и "3" необходим, потому что в противном случае эти лексемы будут восприняты как идентификатор div3. А вот разделитель между "6" и "div" не обязателен, т.к. 6div не является допустимым идентификатором, и анализатор сможет отделить эти лексемы друг от друга и без разделителя. Вообще, если подстрока, получающаяся в результате слияния двух лексем, может быть целиком интерпретирована как какая-либо другая лексема, разделитель между ними необходим, в противном случае — необязателен. Разделитель внутри отдельной лексемы не допускается (т.е. подстрока "a 1" будет интерпретироваться как последовательность лексем "а" и "1", а не как лексема "а1").

Чтобы продемонстрировать возможности лексического анализатора, добавим поддержку комментариев. Комментарий — это последовательность символов, начинающаяся с "{" и заканчивающаяся "}", которая может содержать внутри себя любые символы, кроме "}". Комментарий считается разделителем, он допустим в любом месте, где возможно появление других разделителей, т.е. в начале и в конце строки и между лексемами.

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

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

Листинг 4.11. Тип TLexeme для хранения информации об одной лексеме

TLexemeType = (

 ltEqual, ltLess, ltGreater, ltLessOrEqual,

 ltGreaterOrEqual, ltNotEqual, ltPlus, ltMinus,

 ltOr, ltXor, ltAsterisk, ltSlash, ltDiv, ltMod,

 ltAnd, ltNot, ltCap,

ltLeftBracket, ltRightBracket,

 ltSin, ltCos, ltLn,

 ltIdentifier, ltNumber, ltEnd);


TLexeme = record

 LexemeType: TLexemeType;

 Pos: Integer;

 Lexeme: string;

end;

LexemeType — поле, содержащее информацию о том, что это за лексема. Тип TLexemeType — это специально определенный перечислимый тип, каждое из значений которого соответствует одному из возможных типов лексемы. Поле Pos хранит номер позиции в строке, начиная с которой идет данная лексема. Это поле нужно только для того, чтобы синтаксический анализатор мог точно указать место ошибки, если встретит недопустимую лексему.

Поле Lexeme хранит саму подстроку, распознанную как лексема. Оно используется, только если тип лексемы равен ltIdentifier или ltNumber. Для остальных типов лексем достаточно информации из поля LexemeType.

Лексический анализатор реализован в виде класса TLexicalAnalyzer. В конструкторе класса выполняется разбор строки и формирование списка лексем. Через этот же класс синтаксический анализатор получает доступ к лексемам: свойство Lexeme возвращает текущую лексему, метод Next позволяет перейти к следующей. Так как наша грамматика предусматривает разбор слева направо, таких примитивных возможностей навигации синтаксическому анализатору вполне хватает. Код анализатора показан в листинге 4.12.

Листинг 4.12. Код лексического анализатора

type

 TLexicalAnalyzer = class

 private

  FLexemeList: TList;

  // Номер текущей лексемы в списке

  FIndex: Integer;

  function GetLexeme: PLexeme;

  // Пропуск всего, что является разделителем лексем

  procedure SkipWhiteSpace(const S: string; var P: Integer);

  // Выделение лексемы, начинающейся с позиции P

  procedure ExtractLexeme(const S: string; var P: Integer);

  // Помещение лексемы в список

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

  // Выделение лексемы-числа

  procedure Number(const S: string; var P: Integer);

  // Выделение слова и отнесение его к идентификаторам

  // или зарезервированным словам

  procedure Word(const S: string; var P: Integer);

 public

  constructor Create(const Expr: string);

  destructor Destroy; override;

  // Переход к следующей лексеме

  procedure Next;

  // Указатель на текущую лексему

  property Lexeme: PLexeme read GetLexeme;

 end;


constructor TLexicalAnalyzer.Create(const Expr: string);

var

 P: Integer;

begin

 inherited Create;

 // Создаем список лексем

 FLexemeList := TList.Create;

 // И сразу же заполняем его

 Р := 1;

 while Р <= Length(Expr) do

 begin

  SkipWhiteSpace(Expr, P);

  ExtractLexeme(Expr, P);

 end;

 // Помещаем в конец списка специальную лексему

 PutLexeme(ltEnd, Р, '');

 FIndex := 0;

end;


destructor TLexicalAnalyzer.Destroy;

var

 I: Integer;

begin

 for I := 0 to FLexemeList.Count - 1 do

  Dispose(PLexeme(FLexemeList[I]));

 FLexemeList.Free;

 inherited Destroy;

end;


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

function TLexicalAnalyzer.GetLexeme: PLexeme;

begin

 Result := FLexemeList[FIndex];

end;


// Переход к следующей лексеме

procedure TLexicalAnalyzer.Next;

begin

 if FIndex < FLexemeList.Count - 1 then Inc(FIndex);

end;


// Помещение лексемы в список. Параметры метода задают

// одноименные поля типа TLexeme.

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

var

 NewLexeme: PLexeme;

begin

 New(NewLexeme);

 NewLexeme^.LexemeType := LexemeType;

 NewLexeme^.Pos := Pos;

 NewLexeme^.Lexeme := Lexeme;

 FLexemeList.Add(NewLexeme);

end;


// пропускает пробелы, символы табуляции, комментарии и переводы строки,

// которые могут находиться в начале и в конце строки и между лексемами

procedure TLexicalAnalyzer.SkipWhiteSpace(const S: string; var P: Integer);

begin

 while (P <= Length(S)) and (S[P] in [' ', #9, #13, #10, '{']) do

  if S[P] = '{' then

  begin

   Inc(P);

   while (P <-=Length(S)) and (S[P) <> '}') do Inc(P);

   if P > Length(S) then

    raise ESyntaxError.Create('Незавершенный комментарий');

   Inc(P);

  end

  else Inc(P);

end;


// Функция выделяет одну лексему и помещает ее в список

procedure TLexicalAnalyzer.ExtractLexeme(const S: string; var P: Integer);

begin

 if P > Length(S) then Exit;

 case S[P] of

 '(': begin

  PutLexeme(ltLeftBracket, P, '');

  Inc(P);

 end;

 ')': begin

  PutLexeme(ltRightBracket, P, '');

  Inc(P);

 end;

 '*': begin

  PutLexeme(ltAsterisk, P, '');

  Inc(P);

 end;

 '+': begin

  PutLexeme(ltPlus, P, '');

  Inc(P);

 end;

 '-': begin

  PutLexeme(ltMinus, P, '');

  Inc(P);

 end;

 '/': begin

  PutLexeme(ltSlash, P, '');

  Inc(P);

 end;

 '0'..'9': Number(S, P);

 '<':if (P < Length(S)) and (S[P + 1] = '=') then

 begin

  PutLexeme(ltLessOrEqual, P, '');

  Inc(P, 2);

 end

 else

  if (P < Length(S)) and (S[P + 1] = '>') then

  begin

   PutLexeme(ltNotEqual, P, '');

   Inc(P, 2);

  end

  else

  begin

   PutLexeme(ltLess, P, '');

   Inc(P);

  end;

 '=': begin

  PutLexeme(ltEqual, P, '');

  Inc(P);

 end;

 '>': if (P < Length(S)) and (S[P + 1] = '=') then

 begin

  PutLexeme(ltGreaterOrEqual, P, '');

  Inc(P, 2);

 end

 else

 begin

  PutLexeme(ltGreater, P, '');

  Inc(P);

 end;

 'A'..'Z, 'a'..'z', '_': Word(S, P);

 '^': begin

  PutLexeme(ltCap, P, '');

  Inc(P);

 end;

 else

  raise ESyntaxError.Create('Некорректный символ в позиции ' +

   IntToStr(Р));

 end;

end;


// Выделение лексемы-числа

procedure TLexicalAnalyzer.Number(const S: string; var P: Integer);

var

 InitPos, RollbackPos: Integer;

 function IsDigit(Ch: Char): Boolean;

 begin

  Result := Ch in ['0'..'9'];

 end;

begin

 InitPos := P;

 // Выделяем целую часть числа

 repeat

  Inc(P);

 until (P < Length(S)) or not IsDigit(S[P]);

 // Проверяем наличие дробной части и выделяем её

 if (Р <= Length(S)) and (S[P] = DecimalSeparator) then

 begin

  Inc(P);


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

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


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

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

Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*
Все материалы на сайте размещаются его пользователями.
Администратор сайта не несёт ответственности за действия пользователей сайта..
Вы можете направить вашу жалобу на почту librarybook.ru@gmail.com или заполнить форму обратной связи.