fcl-passrc: scanner: accelerated Macros

git-svn-id: trunk@36127 -
This commit is contained in:
Mattias Gaertner 2017-05-05 22:21:18 +00:00
parent 76734070c4
commit fef47e05e0
3 changed files with 164 additions and 101 deletions

View File

@ -21,7 +21,7 @@ unit PScanner;
interface interface
uses SysUtils, Classes; uses SysUtils, Classes, contnrs;
// message numbers // message numbers
const const
@ -244,18 +244,6 @@ type
); );
TModeSwitches = Set of TModeSwitch; TModeSwitches = Set of TModeSwitch;
{ TMacroDef }
TMacroDef = Class(TObject)
Private
FName: String;
FValue: String;
Public
Constructor Create(Const AName,AValue : String);
Property Name : String Read FName;
Property Value : String Read FValue Write FValue;
end;
{ TLineReader } { TLineReader }
TLineReader = class TLineReader = class
@ -399,6 +387,32 @@ type
Row, Column: Cardinal; Row, Column: Cardinal;
end; end;
PPasNameValue = ^TPasNameValue;
TPasNameValue = Record
Name: String;
Value: String;
end;
{ TPasNameValues }
TPasNameValues = class
private
FChangeStamp: integer;
FList: TFPHashList; // list of PPasNameValue
procedure OnClearItem(Item, Dummy: pointer);
public
constructor Create;
destructor Destroy; override;
procedure Clear;
function Define(const Name: String; const Value: String = ''): PPasNameValue;
function UnDefine(const Name: String): boolean;
function Find(const Name: String): PPasNameValue;
function IsDefined(const Name: String): boolean; inline;
property ChangeStamp: integer read FChangeStamp;
procedure Modified; inline;
property List: TFPHashList read FList;
end;
type type
{ TPascalScanner } { TPascalScanner }
@ -423,7 +437,7 @@ type
FCurToken: TToken; FCurToken: TToken;
FCurTokenString: string; FCurTokenString: string;
FCurLine: string; FCurLine: string;
FMacros, FMacros: TPasNameValues;
FDefines: TStrings; FDefines: TStrings;
FOptions: TPOptions; FOptions: TPOptions;
FLogEvents: TPScannerLogEvents; FLogEvents: TPScannerLogEvents;
@ -466,7 +480,7 @@ type
function HandleInclude(const Param: String): TToken;virtual; function HandleInclude(const Param: String): TToken;virtual;
procedure HandleMode(const Param: String);virtual; procedure HandleMode(const Param: String);virtual;
procedure HandleModeSwitch(const Param: String);virtual; procedure HandleModeSwitch(const Param: String);virtual;
function HandleMacro(AIndex: integer): TToken;virtual; function HandleMacro(aMacro: PPasNameValue): TToken;virtual;
procedure PushStackItem; virtual; procedure PushStackItem; virtual;
function DoFetchTextToken: TToken; function DoFetchTextToken: TToken;
function DoFetchToken: TToken; function DoFetchToken: TToken;
@ -480,9 +494,11 @@ type
procedure OpenFile(const AFilename: string); procedure OpenFile(const AFilename: string);
function FetchToken: TToken; function FetchToken: TToken;
function ReadNonPascalTillEndToken(StopAtLineEnd: boolean): TToken; function ReadNonPascalTillEndToken(StopAtLineEnd: boolean): TToken;
Procedure AddDefine(S : String); Procedure AddDefine(aName: String);
Procedure RemoveDefine(S : String); Procedure RemoveDefine(const aName: String);
Procedure SetCompilerMode(S : String); Procedure UnDefine(const aName: String); // remove form Defines and Macros
function IsDefined(const aName: String): boolean; // check Defines and Macros
Procedure SetCompilerMode(const S: String);
function CurSourcePos: TPasSourcePos; function CurSourcePos: TPasSourcePos;
Function SetForceCaret(AValue : Boolean) : Boolean; Function SetForceCaret(AValue : Boolean) : Boolean;
@ -500,7 +516,7 @@ type
Property PreviousToken : TToken Read FPreviousToken; Property PreviousToken : TToken Read FPreviousToken;
property Defines: TStrings read FDefines; property Defines: TStrings read FDefines;
property Macros: TStrings read FMacros; property Macros: TPasNameValues read FMacros;
Property Options : TPOptions Read FOptions Write SetOptions; Property Options : TPOptions Read FOptions Write SetOptions;
Property LogEvents : TPScannerLogEvents Read FLogEvents Write FLogEvents; Property LogEvents : TPScannerLogEvents Read FLogEvents Write FLogEvents;
Property OnLog : TPScannerLogHandler Read FOnLog Write FOnLog; Property OnLog : TPScannerLogHandler Read FOnLog Write FOnLog;
@ -882,12 +898,90 @@ begin
Result:=(TheFilename<>'') and (TheFilename[1]='/'); Result:=(TheFilename<>'') and (TheFilename[1]='/');
end; end;
{ TMacroDef } { TPasNameValues }
constructor TMacroDef.Create(const AName, AValue: String); // inline
function TPasNameValues.IsDefined(const Name: String): boolean;
begin begin
FName:=AName; Result:=Find(Name)<>nil;
FValue:=AValue; end;
// inline
procedure TPasNameValues.Modified;
begin
if FChangeStamp=High(FChangeStamp) then
FChangeStamp:=Low(FChangeStamp)+1
else
inc(FChangeStamp);
end;
procedure TPasNameValues.OnClearItem(Item, Dummy: pointer);
var
NameValue: PPasNameValue absolute Item;
begin
if Dummy=nil then ;
Dispose(NameValue);
end;
constructor TPasNameValues.Create;
begin
FList:=TFPHashList.Create;
end;
destructor TPasNameValues.Destroy;
begin
Clear;
FreeAndNil(FList);
inherited Destroy;
end;
procedure TPasNameValues.Clear;
begin
if FList.Count=0 then exit;
FList.ForEachCall(@OnClearItem,nil);
FList.Clear;
Modified;
end;
function TPasNameValues.Define(const Name: String; const Value: String
): PPasNameValue;
var
Item: PPasNameValue;
begin
Item:=Find(Name);
if Item<>nil then
begin
if Item^.Value=Value then exit(Item);
Item^.Value:=Value;
end
else
begin
New(Item);
Item^.Name:=Name;
Item^.Value:=Value;
FList.Add(uppercase(Name),Item);
end;
Modified;
Result:=Item;
end;
function TPasNameValues.UnDefine(const Name: String): boolean;
var
Item: PPasNameValue;
Index: Integer;
begin
Index:=FList.FindIndexOf(uppercase(Name));
if Index<0 then exit(false);
Item:=PPasNameValue(FList.List^[Index].Data);
FList.Delete(Index);
Dispose(Item);
Modified;
Result:=true;
end;
function TPasNameValues.Find(const Name: String): PPasNameValue;
begin
Result:=PPasNameValue(FList.Find(uppercase(Name)));
end; end;
{ TStreamResolver } { TStreamResolver }
@ -1246,7 +1340,7 @@ begin
FFileResolver := AFileResolver; FFileResolver := AFileResolver;
FIncludeStack := TFPList.Create; FIncludeStack := TFPList.Create;
FDefines := CS; FDefines := CS;
FMacros:=CS; FMacros:=TPasNameValues.Create;
FCurrentModeSwitches:=FPCModeSwitches; FCurrentModeSwitches:=FPCModeSwitches;
FAllowedModeSwitches:=msAllFPCModeSwitches; FAllowedModeSwitches:=msAllFPCModeSwitches;
end; end;
@ -1275,13 +1369,7 @@ begin
end; end;
procedure TPascalScanner.ClearMacros; procedure TPascalScanner.ClearMacros;
Var
I : Integer;
begin begin
For I:=0 to FMacros.Count-1 do
FMacros.Objects[i].Free;
FMacros.Clear; FMacros.Clear;
end; end;
@ -1555,16 +1643,14 @@ begin
DoLog(mtInfo,nLogOpeningFile,SLogOpeningFile,[FCurFileName],True); DoLog(mtInfo,nLogOpeningFile,SLogOpeningFile,[FCurFileName],True);
end; end;
function TPascalScanner.HandleMacro(AIndex : integer) : TToken; function TPascalScanner.HandleMacro(aMacro: PPasNameValue): TToken;
Var Var
M : TMacroDef;
ML : TMacroReader; ML : TMacroReader;
begin begin
PushStackItem; PushStackItem;
M:=FMacros.Objects[AIndex] as TMacroDef; ML:=TMacroReader.Create(FCurFileName,aMacro^.Value);
ML:=TMacroReader.Create(FCurFileName,M.Value);
ML.CurRow:=FCurRow; ML.CurRow:=FCurRow;
ML.CurCol:=CurColumn; ML.CurCol:=CurColumn;
FCurSourceFile:=ML; FCurSourceFile:=ML;
@ -1576,7 +1662,7 @@ procedure TPascalScanner.HandleDefine(Param: String);
Var Var
Index : Integer; Index : Integer;
MN,MV : String; MName,MValue : String;
begin begin
Param := UpperCase(Param); Param := UpperCase(Param);
@ -1585,14 +1671,10 @@ begin
AddDefine(Param) AddDefine(Param)
else else
begin begin
MV:=Trim(Param); MValue:=Trim(Param);
MN:=Trim(Copy(MV,1,Index-1)); MName:=Trim(Copy(MValue,1,Index-1));
Delete(MV,1,Index+1); Delete(MValue,1,Index+1);
Index:=FMacros.IndexOf(MN); FMacros.Define(MName,MValue);
If (Index=-1) then
FMacros.AddObject(MN,TMacroDef.Create(MN,MV))
else
TMacroDef(FMacros.Objects[index]).Value:=MV;
end; end;
end; end;
@ -1602,24 +1684,8 @@ begin
end; end;
procedure TPascalScanner.HandleUnDefine(Param: String); procedure TPascalScanner.HandleUnDefine(Param: String);
Var
Index : integer;
begin begin
Param := UpperCase(Param); UnDefine(Param);
Index:=FDefines.IndexOf(Param);
If (Index>=0) then
RemoveDefine(Param)
else
begin
Index := FMacros.IndexOf(Param);
If (Index>=0) then
begin
FMacros.Objects[Index].FRee;
FMacros.Delete(Index);
end;
end;
end; end;
function TPascalScanner.HandleInclude(const Param: String): TToken; function TPascalScanner.HandleInclude(const Param: String): TToken;
@ -1724,27 +1790,19 @@ end;
procedure TPascalScanner.HandleIFDEF(const AParam: String); procedure TPascalScanner.HandleIFDEF(const AParam: String);
Var
ADefine : String;
Index : Integer;
begin begin
PushSkipMode; PushSkipMode;
if PPIsSkipping then if PPIsSkipping then
PPSkipMode := ppSkipAll PPSkipMode := ppSkipAll
else else
begin begin
ADefine := UpperCase(AParam); if IsDefined(UpperCase(AParam)) then
Index := Defines.IndexOf(ADefine); PPSkipMode := ppSkipElseBranch
if Index < 0 then else
Index := Macros.IndexOf(ADefine);
if Index < 0 then
begin begin
PPSkipMode := ppSkipIfBranch; PPSkipMode := ppSkipIfBranch;
PPIsSkipping := true; PPIsSkipping := true;
end end;
else
PPSkipMode := ppSkipElseBranch;
If LogEvent(sleConditionals) then If LogEvent(sleConditionals) then
if PPSkipMode=ppSkipElseBranch then if PPSkipMode=ppSkipElseBranch then
DoLog(mtInfo,nLogIFDefAccepted,sLogIFDefAccepted,[AParam]) DoLog(mtInfo,nLogIFDefAccepted,sLogIFDefAccepted,[AParam])
@ -1755,28 +1813,19 @@ end;
procedure TPascalScanner.HandleIFNDEF(const AParam: String); procedure TPascalScanner.HandleIFNDEF(const AParam: String);
Var
ADefine : String;
Index : Integer;
begin begin
PushSkipMode; PushSkipMode;
if PPIsSkipping then if PPIsSkipping then
PPSkipMode := ppSkipAll PPSkipMode := ppSkipAll
else else
begin begin
ADefine := UpperCase(AParam); if IsDefined(UpperCase(AParam)) then
Index := Defines.IndexOf(ADefine); PPSkipMode := ppSkipElseBranch
// Not sure about this else
if Index < 0 then
Index := Macros.IndexOf(ADefine);
if Index >= 0 then
begin begin
PPSkipMode := ppSkipIfBranch; PPSkipMode := ppSkipIfBranch;
PPIsSkipping := true; PPIsSkipping := true;
end end;
else
PPSkipMode := ppSkipElseBranch;
If LogEvent(sleConditionals) then If LogEvent(sleConditionals) then
if PPSkipMode=ppSkipElseBranch then if PPSkipMode=ppSkipElseBranch then
DoLog(mtInfo,nLogIFNDefAccepted,sLogIFNDefAccepted,[AParam]) DoLog(mtInfo,nLogIFNDefAccepted,sLogIFNDefAccepted,[AParam])
@ -1901,7 +1950,8 @@ function TPascalScanner.DoFetchToken: TToken;
var var
TokenStart: PChar; TokenStart: PChar;
i: TToken; i: TToken;
OldLength, SectionLength, NestingLevel, Index: Integer; OldLength, SectionLength, NestingLevel: Integer;
MacroValue: PPasNameValue;
begin begin
result:=tkLineEnding; result:=tkLineEnding;
if TokenStr = nil then if TokenStr = nil then
@ -2314,11 +2364,11 @@ begin
FCurToken := Result; FCurToken := Result;
exit; exit;
end; end;
Index:=FMacros.IndexOf(CurtokenString); MacroValue:=FMacros.Find(CurTokenString);
if (Index=-1) then if (MacroValue=nil) then
Result := tkIdentifier Result := tkIdentifier
else else
Result:=HandleMacro(index); Result:=HandleMacro(MacroValue);
end; end;
else else
if PPIsSkipping then if PPIsSkipping then
@ -2423,25 +2473,37 @@ begin
CreateMsgArgs(FLastMsgArgs,Args); CreateMsgArgs(FLastMsgArgs,Args);
end; end;
procedure TPascalScanner.AddDefine(S: String); procedure TPascalScanner.AddDefine(aName: String);
begin begin
If FDefines.IndexOf(S)=-1 then aName:=UpperCase(aName);
FDefines.Add(S); If FDefines.IndexOf(aName)=-1 then
FDefines.Add(aName);
end; end;
procedure TPascalScanner.RemoveDefine(S: String); procedure TPascalScanner.RemoveDefine(const aName: String);
Var Var
I : Integer; Index : Integer;
begin begin
I:=FDefines.IndexOf(S); Index:=FDefines.IndexOf(UpperCase(aName));
if (I<>-1) then If (Index>=0) then
FDefines.Delete(I); FDefines.Delete(Index);
end; end;
procedure TPascalScanner.SetCompilerMode(S: String); procedure TPascalScanner.UnDefine(const aName: String);
begin
RemoveDefine(aName);
Macros.UnDefine(aName);
end;
function TPascalScanner.IsDefined(const aName: String): boolean;
begin
Result:=(FDefines.IndexOf(aName)>=0) or Macros.IsDefined(aName);
end;
procedure TPascalScanner.SetCompilerMode(const S: String);
begin begin
HandleMode(S); HandleMode(S);
end; end;

View File

@ -460,6 +460,7 @@ type
Procedure TestPropertyReadAccessorFuncWrongResult; Procedure TestPropertyReadAccessorFuncWrongResult;
Procedure TestPropertyReadAccessorFuncWrongArgCount; Procedure TestPropertyReadAccessorFuncWrongArgCount;
Procedure TestPropertyReadAccessorFunc; Procedure TestPropertyReadAccessorFunc;
// ToDo: read accessor allow ancestor of field
Procedure TestPropertyWriteAccessorVarWrongType; Procedure TestPropertyWriteAccessorVarWrongType;
Procedure TestPropertyWriteAccessorFuncNotProc; Procedure TestPropertyWriteAccessorFuncNotProc;
Procedure TestPropertyWriteAccessorProcWrongArgCount; Procedure TestPropertyWriteAccessorProcWrongArgCount;

View File

@ -44,7 +44,7 @@ type
private private
FDoSpecial: Boolean; FDoSpecial: Boolean;
protected protected
function HandleMacro(AIndex: integer): TToken;override; function HandleMacro(aMacro: PPasNameValue): TToken; override;
Public Public
Property DoSpecial : Boolean Read FDoSpecial Write FDoSpecial; Property DoSpecial : Boolean Read FDoSpecial Write FDoSpecial;
end; end;
@ -231,7 +231,7 @@ implementation
{ TTestingPascalScanner } { TTestingPascalScanner }
function TTestingPascalScanner.HandleMacro(AIndex: integer): TToken; function TTestingPascalScanner.HandleMacro(aMacro: PPasNameValue): TToken;
begin begin
if DoSpecial then if DoSpecial then
begin begin
@ -239,7 +239,7 @@ begin
SetCurTokenstring('somethingweird'); SetCurTokenstring('somethingweird');
end end
else else
Result:=inherited HandleMacro(AIndex); Result:=inherited HandleMacro(aMacro);
end; end;
{ TTestTokenFinder } { TTestTokenFinder }