unit uSymbol;
interface
uses
SysUtils,uSymbolType,uError;
type
TSymbolAnalyzer = class
private
FScript: string;
FChar: char;
FCharPos: integer;
FSymbol: TSymbol;
FError: TError;
public
constructor Create(const AScript: string; const AError: TError = nil);
//---
procedure GetSymbol;
//---
property Symbol: TSymbol read FSymbol;
end;
implementation
uses uErrorInfo;
constructor TSymbolAnalyzer.Create(const AScript: string; const AError: TError
= nil);
begin
FScript := LowerCase(AScript);
FChar := ' ';
FCharPos := 0;
//---
FError := AError;
end;
procedure TSymbolAnalyzer.GetSymbol;
//---
procedure _ReportError(const AMsg: string);
begin
if Assigned(FError) then
FError.ReportError(AMsg);
end;
//---获取字符
procedure _GetChar;
begin
if FCharPos > length(FScript) then
_ReportError(CNT_Error1)
else
begin
inc(FCharPos);
FChar := FScript[FCharPos];
end;
end;
//---去掉空白字符
procedure _SkipBlanks;
begin
while FChar in [' ',#9,#10,#13] do
_GetChar;
end;
//---是否是关键字(二分法查找)
function _IsKeyword: TSymbolType;
var
AMin,AMax,AMid: integer;
begin
AMin := Low(CNT_KeywordMap);
AMax := high(CNT_KeywordMap);
repeat
AMid := (AMin + AMax) div 2;
//---
if FSymbol.Ident <= CNT_KeywordMap[AMid].Name then
AMax := AMid - 1;
if FSymbol.Ident >= CNT_KeywordMap[AMid].Name then
AMin := AMid + 1;
until AMin > AMax;
//---
if AMin - 1 > AMax then
Result := TSymbolType(CNT_KeywordMap[AMid].Value)
else
Result := symIdent;
end;
//---
procedure _GetIdent;
var
k: integer;
begin
with FSymbol do
begin
FillChar(Ident[1],Length(Ident), ' ');
//---
k := 0;
repeat
if k < CNT_Ident_MaxLen then
begin
k := k + 1;
Ident[k] := FChar;
end;
//---
_GetChar;
until not (FChar in ['a'..'z', '0'..'9']);
end;
//---
FSymbol.Kind := _IsKeyword;
end;
//---
procedure _GetNumber;
var
ANumLen: integer;
begin
with FSymbol do
begin
Num := 0;
ANumLen := 0;
//---
repeat
Num := 10 * Num + (ord(FChar) - ord('0'));
ANumLen := ANumLen + 1;
//---
_GetChar;
until not (FChar in ['0'..'9']);
//---
if ANumLen > CNT_Number_MaxLen then
_ReportError(CNT_Error2);
end;
//---
FSymbol.Kind := symNumber;
end;
//---获取赋值符号':='
procedure _GetBecomes;
begin
_GetChar;
if FChar = '=' then
begin
FSymbol.Kind := symBecomes;
_GetChar;
end
else
FSymbol.Kind := symNull;
end;
//---
procedure _GetLessOrEuqal;
begin
_GetChar;
if FChar = '=' then
begin
FSymbol.Kind := symLeq;
_GetChar;
end
else
FSymbol.Kind := symLss;
end;
//---
procedure _GetGreatOrEuqal;
begin
_GetChar;
if FChar = '=' then
begin
FSymbol.Kind := symGeq;
_GetChar;
end
else
FSymbol.Kind := symGtr;
end;
//---
procedure _GetEof;
begin
FSymbol.Kind := symEof;
end;
//---
procedure _GetSign;
begin
FSymbol.Kind := SignMap[FChar];
_GetChar;
//---
if FSymbol.Kind = symNull then
_ReportError(CNT_Error3);
end;
begin
_SkipBlanks;
//---
case FChar of
'a'..'z': _GetIdent;
'0'..'9': _GetNumber;
':': _GetBecomes;
'<': _GetLessOrEuqal;
'>': _GetGreatOrEuqal;
#0: _GetEof;
else
_GetSign;
end;
end;
end.