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

ЖАНРЫ

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

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

Шрифт:
Листинг 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;

Поделиться с друзьями: