mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-13 11:49:30 +02:00
--- Recording mergeinfo for merge of r34169 into '.':
U . --- Merging r34198 into '.': U packages/fcl-passrc/tests/tctypeparser.pas U packages/fcl-passrc/src/pparser.pp U packages/fcl-passrc/src/pastree.pp --- Recording mergeinfo for merge of r34198 into '.': U . --- Merging r34201 into '.': G packages/fcl-passrc/src/pparser.pp --- Recording mergeinfo for merge of r34201 into '.': G . --- Merging r34205 into '.': G packages/fcl-passrc/src/pparser.pp --- Recording mergeinfo for merge of r34205 into '.': G . --- Merging r34214 into '.': G packages/fcl-passrc/src/pparser.pp --- Recording mergeinfo for merge of r34214 into '.': G . --- Merging r34225 into '.': U packages/fcl-passrc/tests/tcmoduleparser.pas U packages/fcl-passrc/tests/testpassrc.lpi U packages/fcl-passrc/tests/tcstatements.pas U packages/fcl-passrc/tests/tcpassrcutil.pas G packages/fcl-passrc/src/pastree.pp U packages/fcl-passrc/src/passrcutil.pp U packages/fcl-passrc/src/pscanner.pp G packages/fcl-passrc/src/pparser.pp --- Recording mergeinfo for merge of r34225 into '.': G . --- Merging r34237 into '.': G packages/fcl-passrc/src/pastree.pp G packages/fcl-passrc/src/pparser.pp --- Recording mergeinfo for merge of r34237 into '.': G . --- Merging r34241 into '.': G packages/fcl-passrc/src/pastree.pp G packages/fcl-passrc/src/pparser.pp --- Recording mergeinfo for merge of r34241 into '.': G . # revisions: 34169,34198,34201,34205,34214,34225,34237,34241 git-svn-id: branches/fixes_3_0@35972 -
This commit is contained in:
parent
3803b78124
commit
3170e650ca
@ -171,8 +171,6 @@ procedure TPasSrcAnalysis.GetClassMembers(AClass: TPasClassType; List: TStrings;
|
||||
Var
|
||||
I : Integer;
|
||||
E : TPasElement;
|
||||
V : TPasVariant;
|
||||
|
||||
begin
|
||||
For I:=0 to AClass.Members.Count-1 do
|
||||
begin
|
||||
|
@ -134,7 +134,7 @@ type
|
||||
procedure Accept(Visitor: TPassTreeVisitor); override;
|
||||
property RefCount: LongWord read FRefCount;
|
||||
property Name: string read FName write FName;
|
||||
property Parent: TPasElement read FParent;
|
||||
property Parent: TPasElement read FParent Write FParent;
|
||||
Property Hints : TPasMemberHints Read FHints Write FHints;
|
||||
Property CustomData : TObject Read FData Write FData;
|
||||
Property HintMessage : String Read FHintMessage Write FHintMessage;
|
||||
@ -158,7 +158,7 @@ type
|
||||
|
||||
TPasExpr = class(TPasElement)
|
||||
Kind : TPasExprKind;
|
||||
OpCode : TexprOpcode;
|
||||
OpCode : TExprOpCode;
|
||||
constructor Create(AParent : TPasElement; AKind: TPasExprKind; AOpCode: TexprOpcode); virtual; overload;
|
||||
end;
|
||||
|
||||
@ -428,6 +428,7 @@ type
|
||||
IndexRange : string;
|
||||
PackMode : TPackMode;
|
||||
ElType: TPasType;
|
||||
Function IsGenericArray : Boolean;
|
||||
Function IsPacked : Boolean;
|
||||
end;
|
||||
|
||||
@ -512,7 +513,7 @@ type
|
||||
Function IsAdvancedRecord : Boolean;
|
||||
end;
|
||||
|
||||
TPasGenericTemplateType = Class(TPasElement);
|
||||
TPasGenericTemplateType = Class(TPasType);
|
||||
TPasObjKind = (okObject, okClass, okInterface, okGeneric, okSpecialize,
|
||||
okClassHelper,okRecordHelper,okTypeHelper);
|
||||
|
||||
@ -613,9 +614,9 @@ type
|
||||
{ TPasUnresolvedUnitRef }
|
||||
|
||||
TPasUnresolvedUnitRef = Class(TPasUnresolvedSymbolRef)
|
||||
function ElementTypeName: string; override;
|
||||
Public
|
||||
public
|
||||
FileName : string;
|
||||
function ElementTypeName: string; override;
|
||||
end;
|
||||
|
||||
{ TPasStringType }
|
||||
@ -629,7 +630,6 @@ type
|
||||
{ TPasTypeRef }
|
||||
|
||||
TPasTypeRef = class(TPasUnresolvedTypeRef)
|
||||
public
|
||||
public
|
||||
RefType: TPasType;
|
||||
end;
|
||||
@ -656,6 +656,7 @@ type
|
||||
{ TPasExportSymbol }
|
||||
|
||||
TPasExportSymbol = class(TPasElement)
|
||||
public
|
||||
ExportName : TPasExpr;
|
||||
Exportindex : TPasExpr;
|
||||
Destructor Destroy; override;
|
||||
@ -666,7 +667,6 @@ type
|
||||
{ TPasConst }
|
||||
|
||||
TPasConst = class(TPasVariable)
|
||||
public
|
||||
public
|
||||
function ElementTypeName: string; override;
|
||||
end;
|
||||
@ -674,7 +674,7 @@ type
|
||||
{ TPasProperty }
|
||||
|
||||
TPasProperty = class(TPasVariable)
|
||||
Public
|
||||
public
|
||||
FResolvedType : TPasType;
|
||||
public
|
||||
constructor Create(const AName: string; AParent: TPasElement); override;
|
||||
@ -863,7 +863,6 @@ Type
|
||||
constructor Create(const AName: string; AParent: TPasElement); override;
|
||||
destructor Destroy; override;
|
||||
public
|
||||
|
||||
Labels: TFPList;
|
||||
Body: TPasImplBlock;
|
||||
end;
|
||||
@ -2561,6 +2560,11 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPasArrayType.IsGenericArray: Boolean;
|
||||
begin
|
||||
Result:=elType is TPasGenericTemplateType;
|
||||
end;
|
||||
|
||||
function TPasArrayType.IsPacked: Boolean;
|
||||
begin
|
||||
Result:=PackMode=pmPacked;
|
||||
@ -3527,7 +3531,7 @@ end;
|
||||
|
||||
{ TBinaryExpr }
|
||||
|
||||
function TBinaryExpr.GetDeclaration(Full : Boolean):AnsiString;
|
||||
function TBinaryExpr.GetDeclaration(full: Boolean): string;
|
||||
function OpLevel(op: TPasExpr): Integer;
|
||||
begin
|
||||
case op.OpCode of
|
||||
@ -3574,14 +3578,18 @@ constructor TBinaryExpr.Create(AParent : TPasElement; xleft,xright:TPasExpr; AOp
|
||||
begin
|
||||
inherited Create(AParent,pekBinary, AOpCode);
|
||||
left:=xleft;
|
||||
left.Parent:=Self;
|
||||
right:=xright;
|
||||
right.Parent:=Self;
|
||||
end;
|
||||
|
||||
constructor TBinaryExpr.CreateRange(AParent : TPasElement; xleft,xright:TPasExpr);
|
||||
begin
|
||||
inherited Create(AParent,pekRange, eopNone);
|
||||
left:=xleft;
|
||||
left.Parent:=Self;
|
||||
right:=xright;
|
||||
right.Parent:=Self;
|
||||
end;
|
||||
|
||||
destructor TBinaryExpr.Destroy;
|
||||
|
@ -68,6 +68,10 @@ const
|
||||
nParserArrayPropertiesCannotHaveDefaultValue = 2041;
|
||||
nParserDefaultPropertyMustBeArray = 2042;
|
||||
nParserUnknownProcedureType = 2043;
|
||||
nParserGenericArray1Element = 2044;
|
||||
nParserGenericClassOrArray = 2045;
|
||||
nParserDuplicateIdentifier = 2046;
|
||||
|
||||
|
||||
// resourcestring patterns of messages
|
||||
resourcestring
|
||||
@ -114,6 +118,9 @@ resourcestring
|
||||
SParserArrayPropertiesCannotHaveDefaultValue = 'Array properties cannot have default value';
|
||||
SParserDefaultPropertyMustBeArray = 'The default property must be an array property';
|
||||
SParserUnknownProcedureType = 'Unknown procedure type "%d"';
|
||||
SParserGenericArray1Element = 'Generic arrays can have only 1 template element';
|
||||
SParserGenericClassOrArray = 'Generic can only be used with classes or arrays';
|
||||
SParserDuplicateIdentifier = 'Duplicate identifier "%s"';
|
||||
|
||||
type
|
||||
TPasParserLogHandler = Procedure (Sender : TObject; Const Msg : String) of object;
|
||||
@ -237,8 +244,19 @@ type
|
||||
Function TokenToExprOp (AToken : TToken) : TExprOpCode;
|
||||
function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement): TPasElement;overload;
|
||||
function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement; AVisibility: TPasMemberVisibility): TPasElement;overload;
|
||||
function CreatePrimitiveExpr(AParent: TPasElement; AKind: TPasExprKind; const AValue: String): TPrimitiveExpr;
|
||||
function CreateBoolConstExpr(AParent: TPasElement; AKind: TPasExprKind; const ABoolValue : Boolean): TBoolConstExpr;
|
||||
function CreateBinaryExpr(AParent : TPasElement; xleft, xright: TPasExpr; AOpCode: TExprOpCode): TBinaryExpr;
|
||||
procedure AddToBinaryExprChain(var ChainFirst, ChainLast: TPasExpr;
|
||||
Element: TPasExpr; AOpCode: TExprOpCode);
|
||||
function CreateUnaryExpr(AParent : TPasElement; AOperand: TPasExpr; AOpCode: TExprOpCode): TUnaryExpr;
|
||||
function CreateArrayValues(AParent : TPasElement): TArrayValues;
|
||||
function CreateFunctionType(const AName, AResultName: String; AParent: TPasElement;
|
||||
UseParentAsResultParent: Boolean): TPasFunctionType;
|
||||
function CreateInheritedExpr(AParent : TPasElement): TInheritedExpr;
|
||||
function CreateSelfExpr(AParent : TPasElement): TSelfExpr;
|
||||
function CreateNilExpr(AParent : TPasElement): TNilExpr;
|
||||
function CreateRecordValues(AParent : TPasElement): TRecordValues;
|
||||
Function IsCurTokenHint(out AHint : TPasMemberHint) : Boolean; overload;
|
||||
Function IsCurTokenHint: Boolean; overload;
|
||||
Function TokenIsCallingConvention(S : String; out CC : TCallingConvention) : Boolean; virtual;
|
||||
@ -250,6 +268,8 @@ type
|
||||
function DoParseExpression(Aparent : TPaselement;InitExpr: TPasExpr=nil): TPasExpr;
|
||||
function DoParseConstValueExpression(AParent : TPasElement): TPasExpr;
|
||||
function CheckPackMode: TPackMode;
|
||||
function CheckUseUnit(ASection: TPasSection; AUnitName : string): TPasElement;
|
||||
procedure CheckImplicitUsedUnits(ASection: TPasSection);
|
||||
// Overload handling
|
||||
procedure AddProcOrFunction(Decs: TPasDeclarations; AProc: TPasProcedure);
|
||||
function CheckIfOverloaded(AParent: TPasElement; const AName: String): TPasElement;
|
||||
@ -300,6 +320,7 @@ type
|
||||
procedure ParseUnit(var Module: TPasModule);
|
||||
procedure ParseProgram(var Module: TPasModule; SkipHeader : Boolean = False);
|
||||
procedure ParseLibrary(var Module: TPasModule);
|
||||
procedure ParseOptionalUsesList(ASection: TPasSection);
|
||||
procedure ParseUsesList(ASection: TPasSection);
|
||||
procedure ParseInterface;
|
||||
procedure ParseImplementation;
|
||||
@ -594,6 +615,7 @@ end;
|
||||
|
||||
function TPasTreeContainer.FindModule(const AName: String): TPasModule;
|
||||
begin
|
||||
if AName='' then ;
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
@ -1019,7 +1041,7 @@ function TPasParser.ParseAliasType(Parent: TPasElement; const TypeName: String
|
||||
begin
|
||||
Result := TPasTypeAliasType(CreateElement(TPasTypeAliasType, TypeName, Parent));
|
||||
try
|
||||
Result.DestType := ParseType(nil,'');
|
||||
Result.DestType := ParseType(Result,'');
|
||||
except
|
||||
FreeAndNil(Result);
|
||||
raise;
|
||||
@ -1032,7 +1054,7 @@ function TPasParser.ParsePointerType(Parent: TPasElement; const TypeName: String
|
||||
begin
|
||||
Result := TPasPointerType(CreateElement(TPasPointerType, TypeName, Parent));
|
||||
Try
|
||||
TPasPointerType(Result).DestType := ParseType(nil);
|
||||
TPasPointerType(Result).DestType := ParseType(Result);
|
||||
except
|
||||
FreeAndNil(Result);
|
||||
Raise;
|
||||
@ -1201,7 +1223,7 @@ begin
|
||||
until CurToken = tkSquaredBraceClose;
|
||||
Result.IndexRange:=S;
|
||||
ExpectToken(tkOf);
|
||||
Result.ElType := ParseType(nil);
|
||||
Result.ElType := ParseType(Result);
|
||||
end;
|
||||
tkOf:
|
||||
begin
|
||||
@ -1210,7 +1232,7 @@ begin
|
||||
else
|
||||
begin
|
||||
UngetToken;
|
||||
Result.ElType := ParseType(nil);
|
||||
Result.ElType := ParseType(Result);
|
||||
end
|
||||
end
|
||||
else
|
||||
@ -1230,7 +1252,7 @@ begin
|
||||
Result:=TPasFileType(CreateElement(TPasFileType, TypeName, Parent));
|
||||
NextToken;
|
||||
If CurToken=tkOf then
|
||||
Result.ElType := ParseType(nil)
|
||||
Result.ElType := ParseType(Result)
|
||||
else
|
||||
ungettoken;
|
||||
end;
|
||||
@ -1260,8 +1282,9 @@ begin
|
||||
PClose:=tkBraceClose;
|
||||
end;
|
||||
|
||||
params:=TParamsExpr.Create(AParent,paramskind);
|
||||
params:=TParamsExpr(CreateElement(TParamsExpr,'',AParent));
|
||||
try
|
||||
params.Kind:=paramskind;
|
||||
NextToken;
|
||||
if not isEndOfExp then begin
|
||||
repeat
|
||||
@ -1326,55 +1349,55 @@ end;
|
||||
|
||||
function TPasParser.ParseExpIdent(AParent : TPasElement):TPasExpr;
|
||||
var
|
||||
x : TPasExpr;
|
||||
Last , Expr: TPasExpr;
|
||||
prm : TParamsExpr;
|
||||
u : TUnaryExpr;
|
||||
b : TBinaryExpr;
|
||||
optk : TToken;
|
||||
ok: Boolean;
|
||||
begin
|
||||
Result:=nil;
|
||||
case CurToken of
|
||||
tkString: x:=TPrimitiveExpr.Create(AParent,pekString, CurTokenString);
|
||||
tkChar: x:=TPrimitiveExpr.Create(AParent,pekString, CurTokenText);
|
||||
tkNumber: x:=TPrimitiveExpr.Create(AParent,pekNumber, CurTokenString);
|
||||
tkIdentifier: x:=TPrimitiveExpr.Create(AParent,pekIdent, CurTokenText);
|
||||
tkfalse, tktrue: x:=TBoolConstExpr.Create(Aparent,pekBoolConst, CurToken=tktrue);
|
||||
tknil: x:=TNilExpr.Create(Aparent);
|
||||
tkSquaredBraceOpen: x:=ParseParams(AParent,pekSet);
|
||||
tkString: Last:=CreatePrimitiveExpr(AParent,pekString,CurTokenString);
|
||||
tkChar: Last:=CreatePrimitiveExpr(AParent,pekString, CurTokenText);
|
||||
tkNumber: Last:=CreatePrimitiveExpr(AParent,pekNumber, CurTokenString);
|
||||
tkIdentifier: Last:=CreatePrimitiveExpr(AParent,pekIdent, CurTokenText);
|
||||
tkfalse, tktrue: Last:=CreateBoolConstExpr(Aparent,pekBoolConst, CurToken=tktrue);
|
||||
tknil: Last:=CreateNilExpr(AParent);
|
||||
tkSquaredBraceOpen: Last:=ParseParams(AParent,pekSet);
|
||||
tkinherited:
|
||||
begin
|
||||
//inherited; inherited function
|
||||
x:=TInheritedExpr.Create(AParent);
|
||||
Last:=CreateInheritedExpr(AParent);
|
||||
NextToken;
|
||||
if (CurToken=tkIdentifier) then
|
||||
begin
|
||||
b:=TBinaryExpr.Create(AParent,x, DoParseExpression(AParent), eopNone);
|
||||
b:=CreateBinaryExpr(AParent,Last, DoParseExpression(AParent), eopNone);
|
||||
if not Assigned(b.right) then
|
||||
begin
|
||||
B.Free;
|
||||
Exit; // error
|
||||
end;
|
||||
x:=b;
|
||||
Last:=b;
|
||||
UngetToken;
|
||||
end
|
||||
else
|
||||
UngetToken;
|
||||
end;
|
||||
tkself: begin
|
||||
//x:=TPrimitiveExpr.Create(AParent,pekString, CurTokenText); //function(self);
|
||||
x:=TSelfExpr.Create(AParent);
|
||||
//Last:=CreatePrimitiveExpr(AParent,pekString, CurTokenText); //function(self);
|
||||
Last:=CreateSelfExpr(AParent);
|
||||
NextToken;
|
||||
if CurToken = tkDot then
|
||||
begin // self.Write(EscapeText(AText));
|
||||
optk:=CurToken;
|
||||
NextToken;
|
||||
b:=TBinaryExpr.Create(AParent,x, ParseExpIdent(AParent), TokenToExprOp(optk));
|
||||
b:=CreateBinaryExpr(AParent,Last, ParseExpIdent(AParent), TokenToExprOp(optk));
|
||||
if not Assigned(b.right) then
|
||||
begin
|
||||
B.Free;
|
||||
Exit; // error
|
||||
end;
|
||||
x:=b;
|
||||
Last:=b;
|
||||
end;
|
||||
UngetToken;
|
||||
end;
|
||||
@ -1385,7 +1408,7 @@ begin
|
||||
UngetToken;
|
||||
ParseExcExpectedIdentifier;
|
||||
end;
|
||||
x:=TPrimitiveExpr.Create(AParent,pekString, '@'+CurTokenText);
|
||||
Last:=CreatePrimitiveExpr(AParent,pekString, '@'+CurTokenText);
|
||||
end;
|
||||
tkCaret: begin
|
||||
// ^A..^_ characters. See #16341
|
||||
@ -1394,23 +1417,27 @@ begin
|
||||
UngetToken;
|
||||
ParseExcExpectedIdentifier;
|
||||
end;
|
||||
x:=TPrimitiveExpr.Create(AParent,pekString, '^'+CurTokenText);
|
||||
Last:=CreatePrimitiveExpr(AParent,pekString, '^'+CurTokenText);
|
||||
end;
|
||||
else
|
||||
ParseExcExpectedIdentifier;
|
||||
end;
|
||||
|
||||
if x.Kind<>pekSet then NextToken;
|
||||
Result:=Last;
|
||||
|
||||
if Last.Kind<>pekSet then NextToken;
|
||||
|
||||
ok:=false;
|
||||
try
|
||||
if x.Kind=pekIdent then
|
||||
if Last.Kind=pekIdent then
|
||||
begin
|
||||
while CurToken in [tkDot] do
|
||||
begin
|
||||
NextToken;
|
||||
if CurToken=tkIdentifier then
|
||||
begin
|
||||
b:=TBinaryExpr.Create(AParent,x, TPrimitiveExpr.Create(AParent,pekIdent, CurTokenText), eopSubIdent);
|
||||
AddToBinaryExprChain(Result,Last,
|
||||
CreatePrimitiveExpr(AParent,pekIdent, CurTokenText), eopSubIdent);
|
||||
NextToken;
|
||||
end
|
||||
else
|
||||
@ -1418,7 +1445,6 @@ begin
|
||||
UngetToken;
|
||||
ParseExcExpectedIdentifier;
|
||||
end;
|
||||
x:=b;
|
||||
end;
|
||||
while CurToken in [tkBraceOpen, tkSquaredBraceOpen, tkCaret] do
|
||||
case CurToken of
|
||||
@ -1426,20 +1452,22 @@ begin
|
||||
begin
|
||||
prm:=ParseParams(AParent,pekFuncParams);
|
||||
if not Assigned(prm) then Exit;
|
||||
prm.Value:=x;
|
||||
x:=prm;
|
||||
prm.Value:=Last;
|
||||
Result:=prm;
|
||||
Last:=prm;
|
||||
end;
|
||||
tkSquaredBraceOpen:
|
||||
begin
|
||||
prm:=ParseParams(AParent,pekArrayParams);
|
||||
if not Assigned(prm) then Exit;
|
||||
prm.Value:=x;
|
||||
x:=prm;
|
||||
prm.Value:=Last;
|
||||
Result:=prm;
|
||||
Last:=prm;
|
||||
end;
|
||||
tkCaret:
|
||||
begin
|
||||
u:=TUnaryExpr.Create(AParent,x, TokenToExprOp(CurToken));
|
||||
x:=u;
|
||||
Result:=CreateUnaryExpr(AParent,Result,TokenToExprOp(CurToken));
|
||||
Last:=Result;
|
||||
NextToken;
|
||||
end;
|
||||
end;
|
||||
@ -1448,19 +1476,16 @@ begin
|
||||
begin
|
||||
optk:=CurToken;
|
||||
NextToken;
|
||||
b:=TBinaryExpr.Create(AParent,x, ParseExpIdent(AParent), TokenToExprOp(optk));
|
||||
if not Assigned(b.right) then
|
||||
begin
|
||||
b.free;
|
||||
Expr:=ParseExpIdent(AParent);
|
||||
if Expr=nil then
|
||||
Exit; // error
|
||||
end;
|
||||
x:=b;
|
||||
AddToBinaryExprChain(Result,Last,Expr,TokenToExprOp(optk));
|
||||
end;
|
||||
end;
|
||||
|
||||
Result:=x;
|
||||
ok:=true;
|
||||
finally
|
||||
if not Assigned(Result) then x.Free;
|
||||
if not ok then
|
||||
FreeAndNil(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -1537,9 +1562,12 @@ const
|
||||
xright:=PopExp;
|
||||
xleft:=PopExp;
|
||||
if t=tkDotDot then
|
||||
bin := TBinaryExpr.CreateRange(AParent,xleft, xright)
|
||||
begin
|
||||
bin:=CreateBinaryExpr(Aparent,xleft,xright,eopNone);
|
||||
bin.Kind:=pekRange;
|
||||
end
|
||||
else
|
||||
bin := TBinaryExpr.Create(AParent,xleft, xright, TokenToExprOp(t));
|
||||
bin:=CreateBinaryExpr(AParent,xleft,xright,TokenToExprOp(t));
|
||||
expstack.Add(bin);
|
||||
end;
|
||||
|
||||
@ -1590,7 +1618,7 @@ begin
|
||||
begin
|
||||
NextToken;
|
||||
// DumpCurToken('Here 2');
|
||||
x:=TBinaryExpr.Create(AParent,x, ParseExpIdent(AParent), TokenToExprOp(tkDot));
|
||||
x:=CreateBinaryExpr(AParent,x, ParseExpIdent(AParent), TokenToExprOp(tkDot));
|
||||
// DumpCurToken('Here 3');
|
||||
end;
|
||||
|
||||
@ -1609,11 +1637,11 @@ begin
|
||||
x:=popexp;
|
||||
if (tempop=tkMinus) and (X.Kind=pekRange) then
|
||||
begin
|
||||
TBinaryExpr(x).Left:=TUnaryExpr.Create(x, TBinaryExpr(X).left, eopSubtract);
|
||||
TBinaryExpr(x).Left:=CreateUnaryExpr(x, TBinaryExpr(X).left, eopSubtract);
|
||||
expstack.Add(x);
|
||||
end
|
||||
else
|
||||
expstack.Add( TUnaryExpr.Create(AParent, x, TokenToExprOp(tempop) ));
|
||||
expstack.Add(CreateUnaryExpr(AParent, x, TokenToExprOp(tempop) ));
|
||||
end;
|
||||
end
|
||||
else
|
||||
@ -1697,7 +1725,7 @@ begin
|
||||
case CurToken of
|
||||
tkComma: // array of values (a,b,c);
|
||||
begin
|
||||
a:=TArrayValues.Create(AParent);
|
||||
a:=CreateArrayValues(AParent);
|
||||
a.AddValues(x);
|
||||
repeat
|
||||
NextToken;
|
||||
@ -1711,7 +1739,7 @@ begin
|
||||
begin
|
||||
n:=GetExprIdent(x);
|
||||
x.Free;
|
||||
r:=TRecordValues.Create(AParent);
|
||||
r:=CreateRecordValues(AParent);
|
||||
NextToken;
|
||||
x:=DoParseConstValueExpression(AParent);
|
||||
r.AddField(n, x);
|
||||
@ -1757,7 +1785,7 @@ begin
|
||||
Result:=TPasOverloadedProc(OldMember)
|
||||
else
|
||||
begin
|
||||
Result:=TPasOverloadedProc.Create(AName, OldMember.Parent);
|
||||
Result:=TPasOverloadedProc(CreateElement(TPasOverloadedProc, AName, OldMember.Parent));
|
||||
Result.Visibility:=OldMember.Visibility;
|
||||
Result.Overloads.Add(OldMember);
|
||||
Result.SourceFilename:=OldMember.SourceFilename;
|
||||
@ -1915,6 +1943,7 @@ begin
|
||||
end;
|
||||
Section := TProgramSection(CreateElement(TProgramSection, '', CurModule));
|
||||
PP.ProgramSection := Section;
|
||||
ParseOptionalUsesList(Section);
|
||||
ParseDeclarations(Section);
|
||||
finally
|
||||
FCurModule:=nil;
|
||||
@ -1942,12 +1971,25 @@ begin
|
||||
ParseExcTokenError(';');
|
||||
Section := TLibrarySection(CreateElement(TLibrarySection, '', CurModule));
|
||||
PP.LibrarySection := Section;
|
||||
ParseOptionalUsesList(Section);
|
||||
ParseDeclarations(Section);
|
||||
finally
|
||||
FCurModule:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPasParser.ParseOptionalUsesList(ASection: TPasSection);
|
||||
// checks if next token is Uses keyword and read uses list
|
||||
begin
|
||||
NextToken;
|
||||
if CurToken=tkuses then
|
||||
ParseUsesList(ASection)
|
||||
else begin
|
||||
CheckImplicitUsedUnits(ASection);
|
||||
UngetToken;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Starts after the "interface" token
|
||||
procedure TPasParser.ParseInterface;
|
||||
var
|
||||
@ -1955,6 +1997,7 @@ var
|
||||
begin
|
||||
Section := TInterfaceSection(CreateElement(TInterfaceSection, '', CurModule));
|
||||
CurModule.InterfaceSection := Section;
|
||||
ParseOptionalUsesList(Section);
|
||||
ParseDeclarations(Section);
|
||||
end;
|
||||
|
||||
@ -1965,6 +2008,7 @@ var
|
||||
begin
|
||||
Section := TImplementationSection(CreateElement(TImplementationSection, '', CurModule));
|
||||
CurModule.ImplementationSection := Section;
|
||||
ParseOptionalUsesList(Section);
|
||||
ParseDeclarations(Section);
|
||||
end;
|
||||
|
||||
@ -2064,6 +2108,7 @@ var
|
||||
ResStrEl: TPasResString;
|
||||
TypeEl: TPasType;
|
||||
ClassEl: TPasClassType;
|
||||
ArrEl : TPasArrayType;
|
||||
List: TFPList;
|
||||
i,j: Integer;
|
||||
VarEl: TPasVariable;
|
||||
@ -2112,8 +2157,10 @@ begin
|
||||
break;
|
||||
end;
|
||||
tkUses:
|
||||
if Declarations is TPasSection then
|
||||
ParseUsesList(TPasSection(Declarations))
|
||||
if Declarations.ClassType=TInterfaceSection then
|
||||
ParseExcTokenError(TokenInfos[tkimplementation])
|
||||
else if Declarations is TPasSection then
|
||||
ParseExcTokenError(TokenInfos[tkend])
|
||||
else
|
||||
ParseExcSyntaxError;
|
||||
tkConst:
|
||||
@ -2255,21 +2302,44 @@ begin
|
||||
if CurBlock <> declType then
|
||||
ParseExcSyntaxError;
|
||||
TypeName := ExpectIdentifier;
|
||||
ClassEl := TPasClassType(Engine.CreateElement(TPasClassType,TypeName,Declarations, Scanner.CurFilename, Scanner.CurRow));
|
||||
ClassEl.ObjKind:=okGeneric;
|
||||
List:=TFPList.Create;
|
||||
try
|
||||
ReadGenericArguments(ClassEl.GenericTemplateTypes,ClassEl);
|
||||
Except
|
||||
ReadGenericArguments(List,Nil);
|
||||
ExpectToken(tkEqual);
|
||||
NextToken;
|
||||
Case CurToken of
|
||||
tkClass :
|
||||
begin
|
||||
ClassEl := TPasClassType(Engine.CreateElement(TPasClassType,TypeName,Declarations, Scanner.CurFilename, Scanner.CurRow));
|
||||
ClassEl.ObjKind:=okGeneric;
|
||||
For I:=0 to List.Count-1 do
|
||||
begin
|
||||
TPasElement(List[i]).Parent:=ClassEl;
|
||||
ClassEl.GenericTemplateTypes.Add(List[i]);
|
||||
end;
|
||||
NextToken;
|
||||
DoParseClassType(ClassEl);
|
||||
Declarations.Declarations.Add(ClassEl);
|
||||
Declarations.Classes.Add(ClassEl);
|
||||
CheckHint(classel,True);
|
||||
end;
|
||||
tkArray:
|
||||
begin
|
||||
if List.Count<>1 then
|
||||
ParseExc(nParserGenericArray1Element,sParserGenericArray1Element);
|
||||
ArrEl:=TPasArrayType(ParseArrayType(Declarations,TypeName,pmNone));
|
||||
CheckHint(ArrEl,True);
|
||||
ArrEl.ElType.Release;
|
||||
ArrEl.elType:=TPasGenericTemplateType(List[0]);
|
||||
Declarations.Declarations.Add(ArrEl);
|
||||
Declarations.Types.Add(ArrEl);
|
||||
end;
|
||||
else
|
||||
ParseExc(nParserGenericClassOrArray,SParserGenericClassOrArray);
|
||||
end;
|
||||
finally
|
||||
List.Free;
|
||||
Raise;
|
||||
end;
|
||||
ExpectToken(tkEqual);
|
||||
ExpectToken(tkClass);
|
||||
NextToken;
|
||||
DoParseClassType(ClassEl);
|
||||
Declarations.Declarations.Add(ClassEl);
|
||||
Declarations.Classes.Add(ClassEl);
|
||||
CheckHint(classel,True);
|
||||
end;
|
||||
tkbegin:
|
||||
begin
|
||||
@ -2298,34 +2368,57 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
// Starts after the "uses" token
|
||||
procedure TPasParser.ParseUsesList(ASection: TPasSection);
|
||||
function TPasParser.CheckUseUnit(ASection: TPasSection; AUnitName: string
|
||||
): TPasElement;
|
||||
|
||||
function CheckUnit(AUnitName : string):TPasElement;
|
||||
procedure CheckDuplicateInUsesList(AUnitName : string; UsesList: TFPList);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
result := Engine.FindModule(AUnitName); // should we resolve module here when "IN" filename is not known yet?
|
||||
if Assigned(result) then
|
||||
result.AddRef
|
||||
else
|
||||
Result := TPasType(CreateElement(TPasUnresolvedUnitRef, AUnitName,
|
||||
ASection));
|
||||
ASection.UsesList.Add(Result);
|
||||
if UsesList=nil then exit;
|
||||
for i:=0 to UsesList.Count-1 do
|
||||
if CompareText(AUnitName,TPasModule(UsesList[i]).Name)=0 then
|
||||
ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
|
||||
end;
|
||||
|
||||
begin
|
||||
if CompareText(AUnitName,CurModule.Name)=0 then
|
||||
ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
|
||||
CheckDuplicateInUsesList(AUnitName,ASection.UsesList);
|
||||
if ASection.ClassType=TImplementationSection then
|
||||
CheckDuplicateInUsesList(AUnitName,CurModule.InterfaceSection.UsesList);
|
||||
|
||||
result := Engine.FindModule(AUnitName); // should we resolve module here when "IN" filename is not known yet?
|
||||
if Assigned(result) then
|
||||
result.AddRef
|
||||
else
|
||||
Result := TPasUnresolvedUnitRef(CreateElement(TPasUnresolvedUnitRef,
|
||||
AUnitName, ASection));
|
||||
ASection.UsesList.Add(Result);
|
||||
end;
|
||||
|
||||
procedure TPasParser.CheckImplicitUsedUnits(ASection: TPasSection);
|
||||
var
|
||||
AUnitName: String;
|
||||
Element: TPasElement;
|
||||
i: Integer;
|
||||
begin
|
||||
If not (Asection.ClassType=TImplementationSection) Then // interface,program,library,package
|
||||
If not (ASection.ClassType=TImplementationSection) Then // interface,program,library,package
|
||||
begin
|
||||
// load implicit units, like 'System'
|
||||
for i:=0 to ImplicitUses.Count-1 do
|
||||
CheckUnit(ImplicitUses[i]);
|
||||
CheckUseUnit(ASection,ImplicitUses[i]);
|
||||
end;
|
||||
end;
|
||||
|
||||
// Starts after the "uses" token
|
||||
procedure TPasParser.ParseUsesList(ASection: TPasSection);
|
||||
var
|
||||
AUnitName: String;
|
||||
Element: TPasElement;
|
||||
begin
|
||||
CheckImplicitUsedUnits(ASection);
|
||||
|
||||
Repeat
|
||||
AUnitName := ExpectIdentifier;
|
||||
AUnitName := ExpectIdentifier;
|
||||
NextToken;
|
||||
while CurToken = tkDot do
|
||||
begin
|
||||
@ -2333,7 +2426,7 @@ begin
|
||||
AUnitName := AUnitName + '.' + CurTokenString;
|
||||
NextToken;
|
||||
end;
|
||||
Element := CheckUnit(AUnitName);
|
||||
Element := CheckUseUnit(ASection,AUnitName);
|
||||
if (CurToken=tkin) then
|
||||
begin
|
||||
ExpectToken(tkString);
|
||||
@ -2357,7 +2450,7 @@ begin
|
||||
try
|
||||
NextToken;
|
||||
if CurToken = tkColon then
|
||||
Result.VarType := ParseType(nil)
|
||||
Result.VarType := ParseType(Result)
|
||||
else
|
||||
UngetToken;
|
||||
ExpectToken(tkEqual);
|
||||
@ -2468,7 +2561,7 @@ begin
|
||||
Result := TPasClassType(Engine.CreateElement(TPasClassType, TypeName, Parent, Scanner.CurFilename, Scanner.CurRow));
|
||||
try
|
||||
Result.ObjKind := okSpecialize;
|
||||
Result.AncestorType := ParseType(nil);
|
||||
Result.AncestorType := ParseType(Result);
|
||||
Result.IsShortDefinition:=True;
|
||||
ReadGenericArguments(TPasClassType(Result).GenericTemplateTypes,Result);
|
||||
except
|
||||
@ -2619,10 +2712,7 @@ begin
|
||||
if CurToken=tkComma then
|
||||
ExpectIdentifier;
|
||||
Until (CurToken=tkColon);
|
||||
If Full then
|
||||
VarType := ParseComplexType(Nil)
|
||||
else
|
||||
VarType := ParseComplexType(Parent);
|
||||
VarType := ParseComplexType(Parent);
|
||||
Value:=Nil;
|
||||
H:=CheckHint(Nil,False);
|
||||
If Full then
|
||||
@ -2638,13 +2728,14 @@ begin
|
||||
// Writeln(VarNames[i], AVisibility);
|
||||
VarEl:=TPasVariable(CreateElement(TPasVariable,VarNames[i],Parent,AVisibility));
|
||||
VarEl.VarType := VarType;
|
||||
VarType.Parent := VarEl;
|
||||
// Procedure declaration eats the hints.
|
||||
if Assigned(VarType) and (VarType is TPasprocedureType) then
|
||||
VarEl.Hints:=VarType.Hints
|
||||
else
|
||||
VarEl.Hints:=H;
|
||||
Varel.Modifiers:=Mods;
|
||||
Varel.VarModifiers:=VarMods;
|
||||
VarEl.Modifiers:=Mods;
|
||||
VarEl.VarModifiers:=VarMods;
|
||||
if (i=0) then
|
||||
VarEl.Expr:=Value;
|
||||
VarEl.AbsoluteLocation:=Loc;
|
||||
@ -2737,7 +2828,7 @@ end;
|
||||
procedure TPasParser.ParseArgList(Parent: TPasElement; Args: TFPList; EndToken: TToken);
|
||||
var
|
||||
ArgNames: TStringList;
|
||||
IsUntyped: Boolean;
|
||||
IsUntyped, ok: Boolean;
|
||||
Name : String;
|
||||
Value : TPasExpr;
|
||||
i: Integer;
|
||||
@ -2795,6 +2886,7 @@ begin
|
||||
if not IsUntyped then
|
||||
begin
|
||||
ArgType := ParseType(nil);
|
||||
ok:=false;
|
||||
try
|
||||
NextToken;
|
||||
if CurToken = tkEqual then
|
||||
@ -2809,9 +2901,10 @@ begin
|
||||
// After this, we're on ), which must be unget.
|
||||
end;
|
||||
UngetToken;
|
||||
except
|
||||
FreeAndNil(ArgType);
|
||||
Raise;
|
||||
ok:=true;
|
||||
finally
|
||||
if not ok then
|
||||
FreeAndNil(ArgType);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -2820,8 +2913,12 @@ begin
|
||||
Arg := TPasArgument(CreateElement(TPasArgument, ArgNames[i], Parent));
|
||||
Arg.Access := Access;
|
||||
Arg.ArgType := ArgType;
|
||||
if (i > 0) and Assigned(ArgType) then
|
||||
ArgType.AddRef;
|
||||
if Assigned(ArgType) then
|
||||
begin
|
||||
ArgType.Parent := Arg;
|
||||
if (i > 0) then
|
||||
ArgType.AddRef;
|
||||
end;
|
||||
Arg.ValueExpr := Value;
|
||||
Value:=Nil; // Only the first gets a value. OK, since Var A,B : Integer = 1 is not allowed.
|
||||
Args.Add(Arg);
|
||||
@ -3712,7 +3809,7 @@ begin
|
||||
ParseExcSyntaxError;
|
||||
end;
|
||||
else
|
||||
left:=DoParseExpression(nil);
|
||||
left:=DoParseExpression(Parent);
|
||||
case CurToken of
|
||||
tkAssign,
|
||||
tkAssignPlus,
|
||||
@ -3723,8 +3820,10 @@ begin
|
||||
// assign statement
|
||||
Ak:=TokenToAssignKind(CurToken);
|
||||
NextToken;
|
||||
right:=DoParseExpression(nil); // this may solve TPasImplWhileDo.AddElement BUG
|
||||
right:=DoParseExpression(Parent); // this may solve TPasImplWhileDo.AddElement BUG
|
||||
el:=TPasImplAssign(CreateElement(TPasImplAssign,'',CurBlock));
|
||||
left.Parent:=el;
|
||||
right.Parent:=el;
|
||||
TPasImplAssign(el).left:=Left;
|
||||
TPasImplAssign(el).right:=Right;
|
||||
TPasImplAssign(el).Kind:=ak;
|
||||
@ -4253,7 +4352,7 @@ begin
|
||||
Atype.IsForward:=(CurToken=tkSemiColon);
|
||||
if (CurToken=tkBraceOpen) then
|
||||
begin
|
||||
AType.AncestorType := ParseType(nil);
|
||||
AType.AncestorType := ParseType(AType);
|
||||
while True do
|
||||
begin
|
||||
NextToken;
|
||||
@ -4261,7 +4360,7 @@ begin
|
||||
break;
|
||||
UngetToken;
|
||||
ExpectToken(tkComma);
|
||||
Element:=ParseType(Nil); // search interface.
|
||||
Element:=ParseType(AType); // search interface.
|
||||
if assigned(element) then
|
||||
AType.Interfaces.add(element);
|
||||
end;
|
||||
@ -4272,7 +4371,7 @@ begin
|
||||
begin
|
||||
if (CurToken<>tkFor) then
|
||||
ParseExcTokenError(TokenInfos[tkFor]);
|
||||
AType.HelperForType:=ParseType(Nil);
|
||||
AType.HelperForType:=ParseType(AType);
|
||||
NextToken;
|
||||
end;
|
||||
if (AType.IsShortDefinition or AType.IsForward) then
|
||||
@ -4350,6 +4449,96 @@ begin
|
||||
Scanner.CurFilename, Scanner.CurRow);
|
||||
end;
|
||||
|
||||
function TPasParser.CreatePrimitiveExpr(AParent: TPasElement;
|
||||
AKind: TPasExprKind; const AValue: String): TPrimitiveExpr;
|
||||
begin
|
||||
Result:=TPrimitiveExpr(CreateElement(TPrimitiveExpr,'',AParent));
|
||||
Result.Kind:=AKind;
|
||||
Result.Value:=AValue;
|
||||
end;
|
||||
|
||||
function TPasParser.CreateBoolConstExpr(AParent: TPasElement;
|
||||
AKind: TPasExprKind; const ABoolValue: Boolean): TBoolConstExpr;
|
||||
begin
|
||||
Result:=TBoolConstExpr(CreateElement(TBoolConstExpr,'',AParent));
|
||||
Result.Kind:=AKind;
|
||||
Result.Value:=ABoolValue;
|
||||
end;
|
||||
|
||||
function TPasParser.CreateBinaryExpr(AParent: TPasElement; xleft,
|
||||
xright: TPasExpr; AOpCode: TExprOpCode): TBinaryExpr;
|
||||
begin
|
||||
Result:=TBinaryExpr(CreateElement(TBinaryExpr,'',AParent));
|
||||
Result.OpCode:=AOpCode;
|
||||
Result.Kind:=pekBinary;
|
||||
if xleft<>nil then
|
||||
begin
|
||||
Result.left:=xleft;
|
||||
xleft.Parent:=Result;
|
||||
end;
|
||||
if xright<>nil then
|
||||
begin
|
||||
Result.right:=xright;
|
||||
xright.Parent:=Result;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPasParser.AddToBinaryExprChain(var ChainFirst, ChainLast: TPasExpr;
|
||||
Element: TPasExpr; AOpCode: TExprOpCode);
|
||||
|
||||
procedure RaiseInternal;
|
||||
begin
|
||||
raise Exception.Create('TBinaryExpr.AddToChain: internal error');
|
||||
end;
|
||||
|
||||
var
|
||||
Last: TBinaryExpr;
|
||||
begin
|
||||
if Element=nil then
|
||||
exit
|
||||
else if ChainFirst=nil then
|
||||
begin
|
||||
// empty chain => simply add element, no need to create TBinaryExpr
|
||||
if (ChainLast<>nil) then
|
||||
RaiseInternal;
|
||||
ChainFirst:=Element;
|
||||
ChainLast:=Element;
|
||||
end
|
||||
else if ChainLast is TBinaryExpr then
|
||||
begin
|
||||
// add a new TBinaryExpr at the end of the chain
|
||||
Last:=TBinaryExpr(ChainLast);
|
||||
if (Last.left=nil) or (Last.right=nil) then
|
||||
// chain not yet full => inconsistency
|
||||
RaiseInternal;
|
||||
Last.right:=CreateBinaryExpr(Last,Last.right,Element,AOpCode);
|
||||
ChainLast:=Last;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// one element => create a TBinaryExpr with two elements
|
||||
if ChainFirst<>ChainLast then
|
||||
RaiseInternal;
|
||||
ChainLast:=CreateBinaryExpr(ChainLast.Parent,ChainLast,Element,AOpCode);
|
||||
ChainFirst:=ChainLast;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPasParser.CreateUnaryExpr(AParent: TPasElement; AOperand: TPasExpr;
|
||||
AOpCode: TExprOpCode): TUnaryExpr;
|
||||
begin
|
||||
Result:=TUnaryExpr(CreateElement(TUnaryExpr,'',AParent));
|
||||
Result.Kind:=pekUnary;
|
||||
Result.Operand:=AOperand;
|
||||
Result.OpCode:=AOpCode;
|
||||
end;
|
||||
|
||||
function TPasParser.CreateArrayValues(AParent: TPasElement): TArrayValues;
|
||||
begin
|
||||
Result:=TArrayValues(CreateElement(TArrayValues,'',AParent));
|
||||
Result.Kind:=pekListOfExp;
|
||||
end;
|
||||
|
||||
function TPasParser.CreateFunctionType(const AName, AResultName: String;
|
||||
AParent: TPasElement; UseParentAsResultParent: Boolean): TPasFunctionType;
|
||||
begin
|
||||
@ -4358,8 +4547,28 @@ begin
|
||||
Scanner.CurFilename,Scanner.CurRow);
|
||||
end;
|
||||
|
||||
function TPasParser.CreateInheritedExpr(AParent: TPasElement): TInheritedExpr;
|
||||
begin
|
||||
Result:=TInheritedExpr(CreateElement(TInheritedExpr,'',AParent));
|
||||
Result.Kind:=pekInherited;
|
||||
end;
|
||||
|
||||
function TPasParser.CreateSelfExpr(AParent: TPasElement): TSelfExpr;
|
||||
begin
|
||||
Result:=TSelfExpr(CreateElement(TSelfExpr,'Self',AParent));
|
||||
Result.Kind:=pekSelf;
|
||||
end;
|
||||
|
||||
initialization
|
||||
function TPasParser.CreateNilExpr(AParent: TPasElement): TNilExpr;
|
||||
begin
|
||||
Result:=TNilExpr(CreateElement(TNilExpr,'nil',AParent));
|
||||
Result.Kind:=pekNil;
|
||||
end;
|
||||
|
||||
function TPasParser.CreateRecordValues(AParent: TPasElement): TRecordValues;
|
||||
begin
|
||||
Result:=TRecordValues(CreateElement(TRecordValues,'',AParent));
|
||||
Result.Kind:=pekListOfExp;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -251,7 +251,7 @@ type
|
||||
|
||||
TStringStreamLineReader = class(TStreamLineReader)
|
||||
Public
|
||||
constructor Create( const AFilename: string; Const ASource: String);
|
||||
constructor Create( const AFilename: string; Const ASource: String); reintroduce;
|
||||
end;
|
||||
|
||||
{ TMacroReader }
|
||||
|
@ -118,7 +118,8 @@ begin
|
||||
StartUnit('unit1');
|
||||
StartImplementation;
|
||||
ParseUnit;
|
||||
AssertEquals('No interface units',0,IntfSection.UsesList.Count);
|
||||
AssertEquals('Only system in interface units',1,IntfSection.UsesList.Count);
|
||||
CheckUnit(0,'System',IntfSection.UsesList);
|
||||
AssertEquals('No implementation units',0,ImplSection.UsesList.Count);
|
||||
end;
|
||||
|
||||
@ -155,7 +156,8 @@ begin
|
||||
ParseUnit;
|
||||
AssertEquals('One implementation units',1,ImplSection.UsesList.Count);
|
||||
CheckUnit(0,'a',ImplSection.UsesList);
|
||||
AssertEquals('No interface units',0,IntfSection.UsesList.Count);
|
||||
AssertEquals('Only system in interface units',1,IntfSection.UsesList.Count);
|
||||
CheckUnit(0,'System',IntfSection.UsesList);
|
||||
end;
|
||||
|
||||
procedure TTestModuleParser.TestUnitTwoImplUses;
|
||||
@ -164,10 +166,11 @@ begin
|
||||
StartImplementation;
|
||||
UsesClause(['a','b']);
|
||||
ParseUnit;
|
||||
AssertEquals('One interface unit',1,IntfSection.UsesList.Count);
|
||||
CheckUnit(0,'System',IntfSection.UsesList);
|
||||
AssertEquals('Two implementation units',2,ImplSection.UsesList.Count);
|
||||
CheckUnit(0,'a',ImplSection.UsesList);
|
||||
CheckUnit(1,'b',ImplSection.UsesList);
|
||||
AssertEquals('No interface units',0,IntfSection.UsesList.Count);
|
||||
end;
|
||||
|
||||
procedure TTestModuleParser.TestEmptyUnitInitialization;
|
||||
|
@ -5,7 +5,7 @@ unit tcpassrcutil;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, fpcunit, testutils,passrcutil, testregistry;
|
||||
Classes, SysUtils, fpcunit,passrcutil, testregistry;
|
||||
|
||||
type
|
||||
|
||||
@ -78,7 +78,7 @@ begin
|
||||
StartImplementation;
|
||||
EndSource;
|
||||
Analyser.GetInterfaceUnits(List);
|
||||
AssertList('0 interface units',[]);
|
||||
AssertList('1 interface unit',['System']);
|
||||
end;
|
||||
|
||||
procedure TPasSrcUtilTest.TestGetImplementationUses;
|
||||
|
@ -1,3 +1,7 @@
|
||||
{
|
||||
Examples:
|
||||
./testpassrc --suite=TTestStatementParser.TestCallQualified2
|
||||
}
|
||||
unit tcstatements;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
@ -382,10 +386,10 @@ begin
|
||||
S:=Statement as TPasImplSimple;
|
||||
AssertExpression('Doit call',S.Expr,pekBinary,TBinaryExpr);
|
||||
B:=S.Expr as TBinaryExpr;
|
||||
AssertExpression('Unit name',B.Left,pekIdent,'Unita');
|
||||
AssertExpression('Doit call',B.Right,pekBinary,TBinaryExpr);
|
||||
B:=B.Right as TBinaryExpr;
|
||||
AssertExpression('Unit name',B.Left,pekIdent,'ClassB');
|
||||
AssertExpression('Unit name part 1',B.Left,pekIdent,'Unita');
|
||||
AssertExpression('Second part of unit name',B.Right,pekBinary,TBinaryExpr);
|
||||
B:=B.Right as TBinaryExpr;
|
||||
AssertExpression('Unit name part 2',B.Left,pekIdent,'ClassB');
|
||||
AssertExpression('Doit call',B.Right,pekIdent,'Doit');
|
||||
end;
|
||||
|
||||
@ -979,9 +983,6 @@ procedure TTestStatementParser.TestCaseOtherwiseBlockEmpty;
|
||||
|
||||
Var
|
||||
C : TPasImplCaseOf;
|
||||
S : TPasImplCaseStatement;
|
||||
B : TPasImplbeginBlock;
|
||||
|
||||
begin
|
||||
DeclareVar('integer');
|
||||
TestStatement(['case a of','1 : begin end;','otherwise',' end;']);
|
||||
|
@ -114,6 +114,7 @@ type
|
||||
Procedure TestStaticArrayTypedIndex;
|
||||
Procedure TestDynamicArray;
|
||||
Procedure TestDynamicArrayComment;
|
||||
Procedure TestGenericArray;
|
||||
Procedure TestSimpleEnumerated;
|
||||
Procedure TestSimpleEnumeratedComment;
|
||||
Procedure TestSimpleEnumeratedComment2;
|
||||
@ -2837,6 +2838,20 @@ begin
|
||||
AssertComment;
|
||||
end;
|
||||
|
||||
procedure TTestTypeParser.TestGenericArray;
|
||||
begin
|
||||
Add('Type');
|
||||
Add('generic TArray<T> = array of T;');
|
||||
// Writeln(source.text);
|
||||
ParseDeclarations;
|
||||
AssertEquals('One type definition',1,Declarations.Types.Count);
|
||||
AssertEquals('First declaration is type definition.',TPasArrayType,TObject(Declarations.Types[0]).ClassType);
|
||||
AssertEquals('First declaration has correct name.','TArray',TPasType(Declarations.Types[0]).Name);
|
||||
FType:=TPasType(Declarations.Types[0]);
|
||||
AssertEquals('Array type','',TPasArrayType(TheType).IndexRange);
|
||||
AssertEquals('Generic Array type',True,TPasArrayType(TheType).IsGenericArray);
|
||||
end;
|
||||
|
||||
procedure TTestTypeParser.TestSimpleEnumerated;
|
||||
|
||||
begin
|
||||
|
@ -30,7 +30,7 @@
|
||||
<RunParams>
|
||||
<local>
|
||||
<FormatVersion Value="1"/>
|
||||
<CommandLineParams Value="--suite=TTestProcedureFunction.TestOperatorTokens"/>
|
||||
<CommandLineParams Value="--suite=TTestTypeParser.TestGenericArray"/>
|
||||
</local>
|
||||
</RunParams>
|
||||
<RequiredPackages Count="1">
|
||||
|
Loading…
Reference in New Issue
Block a user