// Помещение лексемы в список. Параметры метода задают
// одноименные поля типа 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);
if (Р > Length(S)) or not IsDigit(S[P]) then Dec(P)
else repeat
Inc(P);
until (P > Length(S)) or not IsDigit(S(P));
end;
// Выделяем экспоненту