Browse Source

--- 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 -

marco 8 years ago
parent
commit
3170e650ca

+ 0 - 2
packages/fcl-passrc/src/passrcutil.pp

@@ -171,8 +171,6 @@ procedure TPasSrcAnalysis.GetClassMembers(AClass: TPasClassType; List: TStrings;
 Var
 Var
   I : Integer;
   I : Integer;
   E : TPasElement;
   E : TPasElement;
-  V : TPasVariant;
-
 begin
 begin
   For I:=0 to AClass.Members.Count-1 do
   For I:=0 to AClass.Members.Count-1 do
     begin
     begin

+ 18 - 10
packages/fcl-passrc/src/pastree.pp

@@ -134,7 +134,7 @@ type
     procedure Accept(Visitor: TPassTreeVisitor); override;
     procedure Accept(Visitor: TPassTreeVisitor); override;
     property RefCount: LongWord read FRefCount;
     property RefCount: LongWord read FRefCount;
     property Name: string read FName write FName;
     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 Hints : TPasMemberHints Read FHints Write FHints;
     Property CustomData : TObject Read FData Write FData;
     Property CustomData : TObject Read FData Write FData;
     Property HintMessage : String Read FHintMessage Write FHintMessage;
     Property HintMessage : String Read FHintMessage Write FHintMessage;
@@ -158,7 +158,7 @@ type
 
 
   TPasExpr = class(TPasElement)
   TPasExpr = class(TPasElement)
     Kind      : TPasExprKind;
     Kind      : TPasExprKind;
-    OpCode    : TexprOpcode;
+    OpCode    : TExprOpCode;
     constructor Create(AParent : TPasElement; AKind: TPasExprKind; AOpCode: TexprOpcode); virtual; overload;
     constructor Create(AParent : TPasElement; AKind: TPasExprKind; AOpCode: TexprOpcode); virtual; overload;
   end;
   end;
 
 
@@ -428,6 +428,7 @@ type
     IndexRange : string;
     IndexRange : string;
     PackMode : TPackMode;
     PackMode : TPackMode;
     ElType: TPasType;
     ElType: TPasType;
+    Function IsGenericArray : Boolean;
     Function IsPacked : Boolean;
     Function IsPacked : Boolean;
   end;
   end;
 
 
@@ -512,7 +513,7 @@ type
     Function IsAdvancedRecord : Boolean;
     Function IsAdvancedRecord : Boolean;
   end;
   end;
 
 
-  TPasGenericTemplateType = Class(TPasElement);
+  TPasGenericTemplateType = Class(TPasType);
   TPasObjKind = (okObject, okClass, okInterface, okGeneric, okSpecialize,
   TPasObjKind = (okObject, okClass, okInterface, okGeneric, okSpecialize,
                  okClassHelper,okRecordHelper,okTypeHelper);
                  okClassHelper,okRecordHelper,okTypeHelper);
 
 
@@ -613,9 +614,9 @@ type
   { TPasUnresolvedUnitRef }
   { TPasUnresolvedUnitRef }
 
 
   TPasUnresolvedUnitRef = Class(TPasUnresolvedSymbolRef)
   TPasUnresolvedUnitRef = Class(TPasUnresolvedSymbolRef)
-    function ElementTypeName: string; override;
-  Public
+  public
     FileName : string;
     FileName : string;
+    function ElementTypeName: string; override;
   end;
   end;
 
 
   { TPasStringType }
   { TPasStringType }
@@ -629,7 +630,6 @@ type
   { TPasTypeRef }
   { TPasTypeRef }
 
 
   TPasTypeRef = class(TPasUnresolvedTypeRef)
   TPasTypeRef = class(TPasUnresolvedTypeRef)
-  public
   public
   public
     RefType: TPasType;
     RefType: TPasType;
   end;
   end;
@@ -656,6 +656,7 @@ type
   { TPasExportSymbol }
   { TPasExportSymbol }
 
 
   TPasExportSymbol = class(TPasElement)
   TPasExportSymbol = class(TPasElement)
+  public
     ExportName : TPasExpr;
     ExportName : TPasExpr;
     Exportindex : TPasExpr;
     Exportindex : TPasExpr;
     Destructor Destroy; override;
     Destructor Destroy; override;
@@ -666,7 +667,6 @@ type
   { TPasConst }
   { TPasConst }
 
 
   TPasConst = class(TPasVariable)
   TPasConst = class(TPasVariable)
-  public
   public
   public
     function ElementTypeName: string; override;
     function ElementTypeName: string; override;
   end;
   end;
@@ -674,7 +674,7 @@ type
   { TPasProperty }
   { TPasProperty }
 
 
   TPasProperty = class(TPasVariable)
   TPasProperty = class(TPasVariable)
-  Public
+  public
     FResolvedType : TPasType;
     FResolvedType : TPasType;
   public
   public
     constructor Create(const AName: string; AParent: TPasElement); override;
     constructor Create(const AName: string; AParent: TPasElement); override;
@@ -863,7 +863,6 @@ Type
     constructor Create(const AName: string; AParent: TPasElement); override;
     constructor Create(const AName: string; AParent: TPasElement); override;
     destructor Destroy; override;
     destructor Destroy; override;
   public
   public
-
     Labels: TFPList;
     Labels: TFPList;
     Body: TPasImplBlock;
     Body: TPasImplBlock;
   end;
   end;
@@ -2561,6 +2560,11 @@ begin
     end;
     end;
 end;
 end;
 
 
+function TPasArrayType.IsGenericArray: Boolean;
+begin
+  Result:=elType is TPasGenericTemplateType;
+end;
+
 function TPasArrayType.IsPacked: Boolean;
 function TPasArrayType.IsPacked: Boolean;
 begin
 begin
   Result:=PackMode=pmPacked;
   Result:=PackMode=pmPacked;
@@ -3527,7 +3531,7 @@ end;
 
 
 { TBinaryExpr }
 { TBinaryExpr }
 
 
-function TBinaryExpr.GetDeclaration(Full : Boolean):AnsiString;
+function TBinaryExpr.GetDeclaration(full: Boolean): string;
   function OpLevel(op: TPasExpr): Integer;
   function OpLevel(op: TPasExpr): Integer;
   begin
   begin
     case op.OpCode of
     case op.OpCode of
@@ -3574,14 +3578,18 @@ constructor TBinaryExpr.Create(AParent : TPasElement; xleft,xright:TPasExpr; AOp
 begin
 begin
   inherited Create(AParent,pekBinary, AOpCode);
   inherited Create(AParent,pekBinary, AOpCode);
   left:=xleft;
   left:=xleft;
+  left.Parent:=Self;
   right:=xright;
   right:=xright;
+  right.Parent:=Self;
 end;
 end;
 
 
 constructor TBinaryExpr.CreateRange(AParent : TPasElement; xleft,xright:TPasExpr);
 constructor TBinaryExpr.CreateRange(AParent : TPasElement; xleft,xright:TPasExpr);
 begin
 begin
   inherited Create(AParent,pekRange, eopNone);
   inherited Create(AParent,pekRange, eopNone);
   left:=xleft;
   left:=xleft;
+  left.Parent:=Self;
   right:=xright;
   right:=xright;
+  right.Parent:=Self;
 end;
 end;
 
 
 destructor TBinaryExpr.Destroy;
 destructor TBinaryExpr.Destroy;

+ 310 - 101
packages/fcl-passrc/src/pparser.pp

@@ -68,6 +68,10 @@ const
   nParserArrayPropertiesCannotHaveDefaultValue = 2041;
   nParserArrayPropertiesCannotHaveDefaultValue = 2041;
   nParserDefaultPropertyMustBeArray = 2042;
   nParserDefaultPropertyMustBeArray = 2042;
   nParserUnknownProcedureType = 2043;
   nParserUnknownProcedureType = 2043;
+  nParserGenericArray1Element = 2044;
+  nParserGenericClassOrArray = 2045;
+  nParserDuplicateIdentifier = 2046;
+
 
 
 // resourcestring patterns of messages
 // resourcestring patterns of messages
 resourcestring
 resourcestring
@@ -114,6 +118,9 @@ resourcestring
   SParserArrayPropertiesCannotHaveDefaultValue = 'Array properties cannot have default value';
   SParserArrayPropertiesCannotHaveDefaultValue = 'Array properties cannot have default value';
   SParserDefaultPropertyMustBeArray = 'The default property must be an array property';
   SParserDefaultPropertyMustBeArray = 'The default property must be an array property';
   SParserUnknownProcedureType = 'Unknown procedure type "%d"';
   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
 type
   TPasParserLogHandler = Procedure (Sender : TObject; Const Msg : String) of object;
   TPasParserLogHandler = Procedure (Sender : TObject; Const Msg : String) of object;
@@ -237,8 +244,19 @@ type
     Function TokenToExprOp (AToken : TToken) : TExprOpCode;
     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): TPasElement;overload;
     function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement; AVisibility: TPasMemberVisibility): 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;
     function CreateFunctionType(const AName, AResultName: String; AParent: TPasElement;
              UseParentAsResultParent: Boolean): TPasFunctionType;
              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(out AHint : TPasMemberHint) : Boolean; overload;
     Function IsCurTokenHint: Boolean; overload;
     Function IsCurTokenHint: Boolean; overload;
     Function TokenIsCallingConvention(S : String; out CC : TCallingConvention) : Boolean; virtual;
     Function TokenIsCallingConvention(S : String; out CC : TCallingConvention) : Boolean; virtual;
@@ -250,6 +268,8 @@ type
     function DoParseExpression(Aparent : TPaselement;InitExpr: TPasExpr=nil): TPasExpr;
     function DoParseExpression(Aparent : TPaselement;InitExpr: TPasExpr=nil): TPasExpr;
     function DoParseConstValueExpression(AParent : TPasElement): TPasExpr;
     function DoParseConstValueExpression(AParent : TPasElement): TPasExpr;
     function CheckPackMode: TPackMode;
     function CheckPackMode: TPackMode;
+    function CheckUseUnit(ASection: TPasSection; AUnitName : string): TPasElement;
+    procedure CheckImplicitUsedUnits(ASection: TPasSection);
     // Overload handling
     // Overload handling
     procedure AddProcOrFunction(Decs: TPasDeclarations; AProc: TPasProcedure);
     procedure AddProcOrFunction(Decs: TPasDeclarations; AProc: TPasProcedure);
     function  CheckIfOverloaded(AParent: TPasElement; const AName: String): TPasElement;
     function  CheckIfOverloaded(AParent: TPasElement; const AName: String): TPasElement;
@@ -300,6 +320,7 @@ type
     procedure ParseUnit(var Module: TPasModule);
     procedure ParseUnit(var Module: TPasModule);
     procedure ParseProgram(var Module: TPasModule; SkipHeader : Boolean = False);
     procedure ParseProgram(var Module: TPasModule; SkipHeader : Boolean = False);
     procedure ParseLibrary(var Module: TPasModule);
     procedure ParseLibrary(var Module: TPasModule);
+    procedure ParseOptionalUsesList(ASection: TPasSection);
     procedure ParseUsesList(ASection: TPasSection);
     procedure ParseUsesList(ASection: TPasSection);
     procedure ParseInterface;
     procedure ParseInterface;
     procedure ParseImplementation;
     procedure ParseImplementation;
@@ -594,6 +615,7 @@ end;
 
 
 function TPasTreeContainer.FindModule(const AName: String): TPasModule;
 function TPasTreeContainer.FindModule(const AName: String): TPasModule;
 begin
 begin
+  if AName='' then ;
   Result := nil;
   Result := nil;
 end;
 end;
 
 
@@ -1019,7 +1041,7 @@ function TPasParser.ParseAliasType(Parent: TPasElement; const TypeName: String
 begin
 begin
   Result := TPasTypeAliasType(CreateElement(TPasTypeAliasType, TypeName, Parent));
   Result := TPasTypeAliasType(CreateElement(TPasTypeAliasType, TypeName, Parent));
   try
   try
-    Result.DestType := ParseType(nil,'');
+    Result.DestType := ParseType(Result,'');
   except
   except
     FreeAndNil(Result);
     FreeAndNil(Result);
     raise;
     raise;
@@ -1032,7 +1054,7 @@ function TPasParser.ParsePointerType(Parent: TPasElement; const TypeName: String
 begin
 begin
   Result := TPasPointerType(CreateElement(TPasPointerType, TypeName, Parent));
   Result := TPasPointerType(CreateElement(TPasPointerType, TypeName, Parent));
   Try
   Try
-    TPasPointerType(Result).DestType := ParseType(nil);
+    TPasPointerType(Result).DestType := ParseType(Result);
   except
   except
     FreeAndNil(Result);
     FreeAndNil(Result);
     Raise;
     Raise;
@@ -1201,7 +1223,7 @@ begin
           until CurToken = tkSquaredBraceClose;
           until CurToken = tkSquaredBraceClose;
           Result.IndexRange:=S;
           Result.IndexRange:=S;
           ExpectToken(tkOf);
           ExpectToken(tkOf);
-          Result.ElType := ParseType(nil);
+          Result.ElType := ParseType(Result);
         end;
         end;
       tkOf:
       tkOf:
         begin
         begin
@@ -1210,7 +1232,7 @@ begin
           else
           else
           begin
           begin
             UngetToken;
             UngetToken;
-              Result.ElType := ParseType(nil);
+              Result.ElType := ParseType(Result);
           end
           end
         end
         end
       else
       else
@@ -1230,7 +1252,7 @@ begin
   Result:=TPasFileType(CreateElement(TPasFileType, TypeName, Parent));
   Result:=TPasFileType(CreateElement(TPasFileType, TypeName, Parent));
   NextToken;
   NextToken;
   If CurToken=tkOf then
   If CurToken=tkOf then
-    Result.ElType := ParseType(nil)
+    Result.ElType := ParseType(Result)
   else 
   else 
    ungettoken;
    ungettoken;
 end;
 end;
@@ -1260,8 +1282,9 @@ begin
     PClose:=tkBraceClose;
     PClose:=tkBraceClose;
   end;
   end;
 
 
-  params:=TParamsExpr.Create(AParent,paramskind);
+  params:=TParamsExpr(CreateElement(TParamsExpr,'',AParent));
   try
   try
+    params.Kind:=paramskind;
     NextToken;
     NextToken;
     if not isEndOfExp then begin
     if not isEndOfExp then begin
       repeat
       repeat
@@ -1326,55 +1349,55 @@ end;
  
  
 function TPasParser.ParseExpIdent(AParent : TPasElement):TPasExpr;
 function TPasParser.ParseExpIdent(AParent : TPasElement):TPasExpr;
 var
 var
-  x       : TPasExpr;
+  Last    , Expr: TPasExpr;
   prm     : TParamsExpr;
   prm     : TParamsExpr;
-  u       : TUnaryExpr;
   b       : TBinaryExpr;
   b       : TBinaryExpr;
   optk    : TToken;
   optk    : TToken;
+  ok: Boolean;
 begin
 begin
   Result:=nil;
   Result:=nil;
   case CurToken of
   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:
     tkinherited:
       begin
       begin
       //inherited; inherited function
       //inherited; inherited function
-      x:=TInheritedExpr.Create(AParent);
+      Last:=CreateInheritedExpr(AParent);
       NextToken;
       NextToken;
       if (CurToken=tkIdentifier) then
       if (CurToken=tkIdentifier) then
         begin
         begin
-        b:=TBinaryExpr.Create(AParent,x, DoParseExpression(AParent), eopNone);
+        b:=CreateBinaryExpr(AParent,Last, DoParseExpression(AParent), eopNone);
         if not Assigned(b.right) then
         if not Assigned(b.right) then
           begin
           begin
           B.Free;
           B.Free;
           Exit; // error
           Exit; // error
           end;
           end;
-        x:=b;
+        Last:=b;
         UngetToken;
         UngetToken;
         end
         end
       else
       else
         UngetToken;
         UngetToken;
       end;
       end;
     tkself: begin
     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;
       NextToken;
       if CurToken = tkDot then
       if CurToken = tkDot then
         begin // self.Write(EscapeText(AText));
         begin // self.Write(EscapeText(AText));
         optk:=CurToken;
         optk:=CurToken;
         NextToken;
         NextToken;
-        b:=TBinaryExpr.Create(AParent,x, ParseExpIdent(AParent), TokenToExprOp(optk));
+        b:=CreateBinaryExpr(AParent,Last, ParseExpIdent(AParent), TokenToExprOp(optk));
         if not Assigned(b.right) then
         if not Assigned(b.right) then
           begin
           begin
           B.Free;
           B.Free;
           Exit; // error
           Exit; // error
           end;
           end;
-         x:=b;
+         Last:=b;
         end;
         end;
       UngetToken;
       UngetToken;
     end;
     end;
@@ -1385,7 +1408,7 @@ begin
         UngetToken;
         UngetToken;
         ParseExcExpectedIdentifier;
         ParseExcExpectedIdentifier;
       end;
       end;
-      x:=TPrimitiveExpr.Create(AParent,pekString, '@'+CurTokenText);
+      Last:=CreatePrimitiveExpr(AParent,pekString, '@'+CurTokenText);
     end;
     end;
     tkCaret: begin
     tkCaret: begin
       // ^A..^_ characters. See #16341
       // ^A..^_ characters. See #16341
@@ -1394,23 +1417,27 @@ begin
         UngetToken;
         UngetToken;
         ParseExcExpectedIdentifier;
         ParseExcExpectedIdentifier;
       end;
       end;
-      x:=TPrimitiveExpr.Create(AParent,pekString, '^'+CurTokenText);
+      Last:=CreatePrimitiveExpr(AParent,pekString, '^'+CurTokenText);
     end;
     end;
   else
   else
     ParseExcExpectedIdentifier;
     ParseExcExpectedIdentifier;
   end;
   end;
 
 
-  if x.Kind<>pekSet then NextToken;
+  Result:=Last;
+
+  if Last.Kind<>pekSet then NextToken;
 
 
+  ok:=false;
   try
   try
-    if x.Kind=pekIdent then
+    if Last.Kind=pekIdent then
       begin
       begin
       while CurToken in [tkDot] do
       while CurToken in [tkDot] do
         begin
         begin
         NextToken;
         NextToken;
         if CurToken=tkIdentifier then
         if CurToken=tkIdentifier then
           begin
           begin
-          b:=TBinaryExpr.Create(AParent,x, TPrimitiveExpr.Create(AParent,pekIdent, CurTokenText), eopSubIdent);
+          AddToBinaryExprChain(Result,Last,
+            CreatePrimitiveExpr(AParent,pekIdent, CurTokenText), eopSubIdent);
           NextToken;
           NextToken;
           end
           end
         else
         else
@@ -1418,7 +1445,6 @@ begin
           UngetToken;
           UngetToken;
           ParseExcExpectedIdentifier;
           ParseExcExpectedIdentifier;
           end;
           end;
-        x:=b;
         end;
         end;
       while CurToken in [tkBraceOpen, tkSquaredBraceOpen, tkCaret] do
       while CurToken in [tkBraceOpen, tkSquaredBraceOpen, tkCaret] do
         case CurToken of
         case CurToken of
@@ -1426,20 +1452,22 @@ begin
             begin
             begin
             prm:=ParseParams(AParent,pekFuncParams);
             prm:=ParseParams(AParent,pekFuncParams);
             if not Assigned(prm) then Exit;
             if not Assigned(prm) then Exit;
-            prm.Value:=x;
-            x:=prm;
+            prm.Value:=Last;
+            Result:=prm;
+            Last:=prm;
             end;
             end;
           tkSquaredBraceOpen:
           tkSquaredBraceOpen:
             begin
             begin
             prm:=ParseParams(AParent,pekArrayParams);
             prm:=ParseParams(AParent,pekArrayParams);
             if not Assigned(prm) then Exit;
             if not Assigned(prm) then Exit;
-            prm.Value:=x;
-            x:=prm;
+            prm.Value:=Last;
+            Result:=prm;
+            Last:=prm;
             end;
             end;
           tkCaret:
           tkCaret:
             begin
             begin
-            u:=TUnaryExpr.Create(AParent,x, TokenToExprOp(CurToken));
-            x:=u;
+            Result:=CreateUnaryExpr(AParent,Result,TokenToExprOp(CurToken));
+            Last:=Result;
             NextToken;
             NextToken;
             end;
             end;
         end;
         end;
@@ -1448,19 +1476,16 @@ begin
         begin
         begin
         optk:=CurToken;
         optk:=CurToken;
         NextToken;
         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
           Exit; // error
-          end;
-        x:=b;
+        AddToBinaryExprChain(Result,Last,Expr,TokenToExprOp(optk));
       end;
       end;
     end;
     end;
-
-    Result:=x;
+    ok:=true;
   finally
   finally
-    if not Assigned(Result) then x.Free;
+    if not ok then
+      FreeAndNil(Result);
   end;
   end;
 end;
 end;
 
 
@@ -1537,9 +1562,12 @@ const
     xright:=PopExp;
     xright:=PopExp;
     xleft:=PopExp;
     xleft:=PopExp;
     if t=tkDotDot then
     if t=tkDotDot then
-      bin := TBinaryExpr.CreateRange(AParent,xleft, xright)
+      begin
+      bin:=CreateBinaryExpr(Aparent,xleft,xright,eopNone);
+      bin.Kind:=pekRange;
+      end
     else
     else
-      bin := TBinaryExpr.Create(AParent,xleft, xright, TokenToExprOp(t));
+      bin:=CreateBinaryExpr(AParent,xleft,xright,TokenToExprOp(t));
     expstack.Add(bin);
     expstack.Add(bin);
   end;
   end;
 
 
@@ -1590,7 +1618,7 @@ begin
                  begin
                  begin
                  NextToken;
                  NextToken;
           //       DumpCurToken('Here 2');
           //       DumpCurToken('Here 2');
-                 x:=TBinaryExpr.Create(AParent,x, ParseExpIdent(AParent), TokenToExprOp(tkDot));
+                 x:=CreateBinaryExpr(AParent,x, ParseExpIdent(AParent), TokenToExprOp(tkDot));
           //       DumpCurToken('Here 3');
           //       DumpCurToken('Here 3');
                  end;
                  end;
 
 
@@ -1609,11 +1637,11 @@ begin
           x:=popexp;
           x:=popexp;
           if (tempop=tkMinus) and (X.Kind=pekRange) then
           if (tempop=tkMinus) and (X.Kind=pekRange) then
             begin
             begin
-            TBinaryExpr(x).Left:=TUnaryExpr.Create(x, TBinaryExpr(X).left, eopSubtract);
+            TBinaryExpr(x).Left:=CreateUnaryExpr(x, TBinaryExpr(X).left, eopSubtract);
             expstack.Add(x);
             expstack.Add(x);
             end
             end
           else
           else
-            expstack.Add( TUnaryExpr.Create(AParent, x, TokenToExprOp(tempop) ));
+            expstack.Add(CreateUnaryExpr(AParent, x, TokenToExprOp(tempop) ));
           end;
           end;
         end
         end
       else
       else
@@ -1697,7 +1725,7 @@ begin
     case CurToken of
     case CurToken of
       tkComma: // array of values (a,b,c);
       tkComma: // array of values (a,b,c);
         begin
         begin
-          a:=TArrayValues.Create(AParent);
+          a:=CreateArrayValues(AParent);
           a.AddValues(x);
           a.AddValues(x);
           repeat
           repeat
             NextToken;
             NextToken;
@@ -1711,7 +1739,7 @@ begin
         begin
         begin
           n:=GetExprIdent(x);
           n:=GetExprIdent(x);
           x.Free;
           x.Free;
-          r:=TRecordValues.Create(AParent);
+          r:=CreateRecordValues(AParent);
           NextToken;
           NextToken;
           x:=DoParseConstValueExpression(AParent);
           x:=DoParseConstValueExpression(AParent);
           r.AddField(n, x);
           r.AddField(n, x);
@@ -1757,7 +1785,7 @@ begin
         Result:=TPasOverloadedProc(OldMember)
         Result:=TPasOverloadedProc(OldMember)
       else
       else
         begin
         begin
-        Result:=TPasOverloadedProc.Create(AName, OldMember.Parent);
+        Result:=TPasOverloadedProc(CreateElement(TPasOverloadedProc, AName, OldMember.Parent));
         Result.Visibility:=OldMember.Visibility;
         Result.Visibility:=OldMember.Visibility;
         Result.Overloads.Add(OldMember);
         Result.Overloads.Add(OldMember);
         Result.SourceFilename:=OldMember.SourceFilename;
         Result.SourceFilename:=OldMember.SourceFilename;
@@ -1915,6 +1943,7 @@ begin
       end;
       end;
     Section := TProgramSection(CreateElement(TProgramSection, '', CurModule));
     Section := TProgramSection(CreateElement(TProgramSection, '', CurModule));
     PP.ProgramSection := Section;
     PP.ProgramSection := Section;
+    ParseOptionalUsesList(Section);
     ParseDeclarations(Section);
     ParseDeclarations(Section);
   finally
   finally
     FCurModule:=nil;
     FCurModule:=nil;
@@ -1942,12 +1971,25 @@ begin
         ParseExcTokenError(';');
         ParseExcTokenError(';');
     Section := TLibrarySection(CreateElement(TLibrarySection, '', CurModule));
     Section := TLibrarySection(CreateElement(TLibrarySection, '', CurModule));
     PP.LibrarySection := Section;
     PP.LibrarySection := Section;
+    ParseOptionalUsesList(Section);
     ParseDeclarations(Section);
     ParseDeclarations(Section);
   finally
   finally
     FCurModule:=nil;
     FCurModule:=nil;
   end;
   end;
 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
 // Starts after the "interface" token
 procedure TPasParser.ParseInterface;
 procedure TPasParser.ParseInterface;
 var
 var
@@ -1955,6 +1997,7 @@ var
 begin
 begin
   Section := TInterfaceSection(CreateElement(TInterfaceSection, '', CurModule));
   Section := TInterfaceSection(CreateElement(TInterfaceSection, '', CurModule));
   CurModule.InterfaceSection := Section;
   CurModule.InterfaceSection := Section;
+  ParseOptionalUsesList(Section);
   ParseDeclarations(Section);
   ParseDeclarations(Section);
 end;
 end;
 
 
@@ -1965,6 +2008,7 @@ var
 begin
 begin
   Section := TImplementationSection(CreateElement(TImplementationSection, '', CurModule));
   Section := TImplementationSection(CreateElement(TImplementationSection, '', CurModule));
   CurModule.ImplementationSection := Section;
   CurModule.ImplementationSection := Section;
+  ParseOptionalUsesList(Section);
   ParseDeclarations(Section);
   ParseDeclarations(Section);
 end;
 end;
 
 
@@ -2064,6 +2108,7 @@ var
   ResStrEl: TPasResString;
   ResStrEl: TPasResString;
   TypeEl: TPasType;
   TypeEl: TPasType;
   ClassEl: TPasClassType;
   ClassEl: TPasClassType;
+  ArrEl : TPasArrayType;
   List: TFPList;
   List: TFPList;
   i,j: Integer;
   i,j: Integer;
   VarEl: TPasVariable;
   VarEl: TPasVariable;
@@ -2112,8 +2157,10 @@ begin
           break;
           break;
           end;
           end;
       tkUses:
       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
         else
           ParseExcSyntaxError;
           ParseExcSyntaxError;
       tkConst:
       tkConst:
@@ -2255,21 +2302,44 @@ begin
           if CurBlock <> declType then
           if CurBlock <> declType then
             ParseExcSyntaxError;
             ParseExcSyntaxError;
           TypeName := ExpectIdentifier;
           TypeName := ExpectIdentifier;
-          ClassEl := TPasClassType(Engine.CreateElement(TPasClassType,TypeName,Declarations, Scanner.CurFilename, Scanner.CurRow));
-          ClassEl.ObjKind:=okGeneric;
+          List:=TFPList.Create;
           try
           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;
             List.Free;
-            Raise;
           end;
           end;
-          ExpectToken(tkEqual);
-          ExpectToken(tkClass);
-          NextToken;
-          DoParseClassType(ClassEl);
-          Declarations.Declarations.Add(ClassEl);
-          Declarations.Classes.Add(ClassEl);
-          CheckHint(classel,True);
         end;
         end;
       tkbegin:
       tkbegin:
         begin
         begin
@@ -2298,34 +2368,57 @@ begin
   end;
   end;
 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
   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;
   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
 var
-  AUnitName: String;
-  Element: TPasElement;
   i: Integer;
   i: Integer;
 begin
 begin
-  If not (Asection.ClassType=TImplementationSection) Then // interface,program,library,package
+  If not (ASection.ClassType=TImplementationSection) Then // interface,program,library,package
     begin
     begin
     // load implicit units, like 'System'
     // load implicit units, like 'System'
     for i:=0 to ImplicitUses.Count-1 do
     for i:=0 to ImplicitUses.Count-1 do
-      CheckUnit(ImplicitUses[i]);
+      CheckUseUnit(ASection,ImplicitUses[i]);
     end;
     end;
+end;
+
+// Starts after the "uses" token
+procedure TPasParser.ParseUsesList(ASection: TPasSection);
+var
+  AUnitName: String;
+  Element: TPasElement;
+begin
+  CheckImplicitUsedUnits(ASection);
 
 
   Repeat
   Repeat
-    AUnitName := ExpectIdentifier; 
+    AUnitName := ExpectIdentifier;
     NextToken;
     NextToken;
     while CurToken = tkDot do
     while CurToken = tkDot do
     begin
     begin
@@ -2333,7 +2426,7 @@ begin
       AUnitName := AUnitName + '.' + CurTokenString;
       AUnitName := AUnitName + '.' + CurTokenString;
       NextToken;
       NextToken;
     end;
     end;
-    Element := CheckUnit(AUnitName);
+    Element := CheckUseUnit(ASection,AUnitName);
     if (CurToken=tkin) then
     if (CurToken=tkin) then
       begin
       begin
       ExpectToken(tkString);
       ExpectToken(tkString);
@@ -2357,7 +2450,7 @@ begin
   try
   try
     NextToken;
     NextToken;
     if CurToken = tkColon then
     if CurToken = tkColon then
-      Result.VarType := ParseType(nil)
+      Result.VarType := ParseType(Result)
     else
     else
       UngetToken;
       UngetToken;
     ExpectToken(tkEqual);
     ExpectToken(tkEqual);
@@ -2468,7 +2561,7 @@ begin
   Result := TPasClassType(Engine.CreateElement(TPasClassType, TypeName, Parent, Scanner.CurFilename, Scanner.CurRow));
   Result := TPasClassType(Engine.CreateElement(TPasClassType, TypeName, Parent, Scanner.CurFilename, Scanner.CurRow));
   try
   try
     Result.ObjKind := okSpecialize;
     Result.ObjKind := okSpecialize;
-    Result.AncestorType := ParseType(nil);
+    Result.AncestorType := ParseType(Result);
     Result.IsShortDefinition:=True;
     Result.IsShortDefinition:=True;
     ReadGenericArguments(TPasClassType(Result).GenericTemplateTypes,Result);
     ReadGenericArguments(TPasClassType(Result).GenericTemplateTypes,Result);
   except
   except
@@ -2619,10 +2712,7 @@ begin
       if CurToken=tkComma then
       if CurToken=tkComma then
         ExpectIdentifier;
         ExpectIdentifier;
     Until (CurToken=tkColon);
     Until (CurToken=tkColon);
-    If Full then
-      VarType := ParseComplexType(Nil)
-    else
-      VarType := ParseComplexType(Parent);
+    VarType := ParseComplexType(Parent);
     Value:=Nil;
     Value:=Nil;
     H:=CheckHint(Nil,False);
     H:=CheckHint(Nil,False);
     If Full then
     If Full then
@@ -2638,13 +2728,14 @@ begin
       // Writeln(VarNames[i], AVisibility);
       // Writeln(VarNames[i], AVisibility);
       VarEl:=TPasVariable(CreateElement(TPasVariable,VarNames[i],Parent,AVisibility));
       VarEl:=TPasVariable(CreateElement(TPasVariable,VarNames[i],Parent,AVisibility));
       VarEl.VarType := VarType;
       VarEl.VarType := VarType;
+      VarType.Parent := VarEl;
       // Procedure declaration eats the hints.
       // Procedure declaration eats the hints.
       if Assigned(VarType) and (VarType is TPasprocedureType) then
       if Assigned(VarType) and (VarType is TPasprocedureType) then
         VarEl.Hints:=VarType.Hints
         VarEl.Hints:=VarType.Hints
       else
       else
         VarEl.Hints:=H;
         VarEl.Hints:=H;
-      Varel.Modifiers:=Mods;
-      Varel.VarModifiers:=VarMods;
+      VarEl.Modifiers:=Mods;
+      VarEl.VarModifiers:=VarMods;
       if (i=0) then
       if (i=0) then
         VarEl.Expr:=Value;
         VarEl.Expr:=Value;
       VarEl.AbsoluteLocation:=Loc;
       VarEl.AbsoluteLocation:=Loc;
@@ -2737,7 +2828,7 @@ end;
 procedure TPasParser.ParseArgList(Parent: TPasElement; Args: TFPList; EndToken: TToken);
 procedure TPasParser.ParseArgList(Parent: TPasElement; Args: TFPList; EndToken: TToken);
 var
 var
   ArgNames: TStringList;
   ArgNames: TStringList;
-  IsUntyped: Boolean;
+  IsUntyped, ok: Boolean;
   Name : String;
   Name : String;
   Value : TPasExpr;
   Value : TPasExpr;
   i: Integer;
   i: Integer;
@@ -2795,6 +2886,7 @@ begin
       if not IsUntyped then
       if not IsUntyped then
         begin
         begin
         ArgType := ParseType(nil);
         ArgType := ParseType(nil);
+        ok:=false;
         try
         try
           NextToken;
           NextToken;
           if CurToken = tkEqual then
           if CurToken = tkEqual then
@@ -2809,9 +2901,10 @@ begin
             // After this, we're on ), which must be unget.
             // After this, we're on ), which must be unget.
             end;
             end;
           UngetToken;
           UngetToken;
-        except
-          FreeAndNil(ArgType);
-          Raise;
+          ok:=true;
+        finally
+          if not ok then
+            FreeAndNil(ArgType);
         end;
         end;
         end;
         end;
 
 
@@ -2820,8 +2913,12 @@ begin
         Arg := TPasArgument(CreateElement(TPasArgument, ArgNames[i], Parent));
         Arg := TPasArgument(CreateElement(TPasArgument, ArgNames[i], Parent));
         Arg.Access := Access;
         Arg.Access := Access;
         Arg.ArgType := ArgType;
         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;
         Arg.ValueExpr := Value;
         Value:=Nil; // Only the first gets a value. OK, since Var A,B : Integer = 1 is not allowed.
         Value:=Nil; // Only the first gets a value. OK, since Var A,B : Integer = 1 is not allowed.
         Args.Add(Arg);
         Args.Add(Arg);
@@ -3712,7 +3809,7 @@ begin
           ParseExcSyntaxError;
           ParseExcSyntaxError;
       end;
       end;
     else
     else
-      left:=DoParseExpression(nil);
+      left:=DoParseExpression(Parent);
       case CurToken of
       case CurToken of
         tkAssign,
         tkAssign,
         tkAssignPlus,
         tkAssignPlus,
@@ -3723,8 +3820,10 @@ begin
           // assign statement
           // assign statement
           Ak:=TokenToAssignKind(CurToken);
           Ak:=TokenToAssignKind(CurToken);
           NextToken;
           NextToken;
-          right:=DoParseExpression(nil); // this may solve TPasImplWhileDo.AddElement BUG
+          right:=DoParseExpression(Parent); // this may solve TPasImplWhileDo.AddElement BUG
           el:=TPasImplAssign(CreateElement(TPasImplAssign,'',CurBlock));
           el:=TPasImplAssign(CreateElement(TPasImplAssign,'',CurBlock));
+          left.Parent:=el;
+          right.Parent:=el;
           TPasImplAssign(el).left:=Left;
           TPasImplAssign(el).left:=Left;
           TPasImplAssign(el).right:=Right;
           TPasImplAssign(el).right:=Right;
           TPasImplAssign(el).Kind:=ak;
           TPasImplAssign(el).Kind:=ak;
@@ -4253,7 +4352,7 @@ begin
   Atype.IsForward:=(CurToken=tkSemiColon);
   Atype.IsForward:=(CurToken=tkSemiColon);
   if (CurToken=tkBraceOpen) then
   if (CurToken=tkBraceOpen) then
     begin
     begin
-    AType.AncestorType := ParseType(nil);
+    AType.AncestorType := ParseType(AType);
     while True do
     while True do
       begin
       begin
       NextToken;
       NextToken;
@@ -4261,7 +4360,7 @@ begin
         break;
         break;
       UngetToken;
       UngetToken;
       ExpectToken(tkComma);
       ExpectToken(tkComma);
-      Element:=ParseType(Nil); // search interface.
+      Element:=ParseType(AType); // search interface.
       if assigned(element) then
       if assigned(element) then
         AType.Interfaces.add(element);
         AType.Interfaces.add(element);
       end;
       end;
@@ -4272,7 +4371,7 @@ begin
     begin
     begin
     if (CurToken<>tkFor) then
     if (CurToken<>tkFor) then
       ParseExcTokenError(TokenInfos[tkFor]);
       ParseExcTokenError(TokenInfos[tkFor]);
-    AType.HelperForType:=ParseType(Nil);
+    AType.HelperForType:=ParseType(AType);
     NextToken;
     NextToken;
     end;
     end;
   if (AType.IsShortDefinition or AType.IsForward) then
   if (AType.IsShortDefinition or AType.IsForward) then
@@ -4350,6 +4449,96 @@ begin
     Scanner.CurFilename, Scanner.CurRow);
     Scanner.CurFilename, Scanner.CurRow);
 end;
 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;
 function TPasParser.CreateFunctionType(const AName, AResultName: String;
   AParent: TPasElement; UseParentAsResultParent: Boolean): TPasFunctionType;
   AParent: TPasElement; UseParentAsResultParent: Boolean): TPasFunctionType;
 begin
 begin
@@ -4358,8 +4547,28 @@ begin
                                     Scanner.CurFilename,Scanner.CurRow);
                                     Scanner.CurFilename,Scanner.CurRow);
 end;
 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.
 end.

+ 1 - 1
packages/fcl-passrc/src/pscanner.pp

@@ -251,7 +251,7 @@ type
 
 
   TStringStreamLineReader = class(TStreamLineReader)
   TStringStreamLineReader = class(TStreamLineReader)
   Public
   Public
-    constructor Create( const AFilename: string; Const ASource: String);
+    constructor Create( const AFilename: string; Const ASource: String); reintroduce;
   end;
   end;
 
 
   { TMacroReader }
   { TMacroReader }

+ 6 - 3
packages/fcl-passrc/tests/tcmoduleparser.pas

@@ -118,7 +118,8 @@ begin
   StartUnit('unit1');
   StartUnit('unit1');
   StartImplementation;
   StartImplementation;
   ParseUnit;
   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);
   AssertEquals('No implementation units',0,ImplSection.UsesList.Count);
 end;
 end;
 
 
@@ -155,7 +156,8 @@ begin
   ParseUnit;
   ParseUnit;
   AssertEquals('One implementation units',1,ImplSection.UsesList.Count);
   AssertEquals('One implementation units',1,ImplSection.UsesList.Count);
   CheckUnit(0,'a',ImplSection.UsesList);
   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;
 end;
 
 
 procedure TTestModuleParser.TestUnitTwoImplUses;
 procedure TTestModuleParser.TestUnitTwoImplUses;
@@ -164,10 +166,11 @@ begin
   StartImplementation;
   StartImplementation;
   UsesClause(['a','b']);
   UsesClause(['a','b']);
   ParseUnit;
   ParseUnit;
+  AssertEquals('One interface unit',1,IntfSection.UsesList.Count);
+  CheckUnit(0,'System',IntfSection.UsesList);
   AssertEquals('Two implementation units',2,ImplSection.UsesList.Count);
   AssertEquals('Two implementation units',2,ImplSection.UsesList.Count);
   CheckUnit(0,'a',ImplSection.UsesList);
   CheckUnit(0,'a',ImplSection.UsesList);
   CheckUnit(1,'b',ImplSection.UsesList);
   CheckUnit(1,'b',ImplSection.UsesList);
-  AssertEquals('No interface units',0,IntfSection.UsesList.Count);
 end;
 end;
 
 
 procedure TTestModuleParser.TestEmptyUnitInitialization;
 procedure TTestModuleParser.TestEmptyUnitInitialization;

+ 2 - 2
packages/fcl-passrc/tests/tcpassrcutil.pas

@@ -5,7 +5,7 @@ unit tcpassrcutil;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, fpcunit, testutils,passrcutil, testregistry;
+  Classes, SysUtils, fpcunit,passrcutil, testregistry;
 
 
 type
 type
 
 
@@ -78,7 +78,7 @@ begin
   StartImplementation;
   StartImplementation;
   EndSource;
   EndSource;
   Analyser.GetInterfaceUnits(List);
   Analyser.GetInterfaceUnits(List);
-  AssertList('0 interface units',[]);
+  AssertList('1 interface unit',['System']);
 end;
 end;
 
 
 procedure TPasSrcUtilTest.TestGetImplementationUses;
 procedure TPasSrcUtilTest.TestGetImplementationUses;

+ 8 - 7
packages/fcl-passrc/tests/tcstatements.pas

@@ -1,3 +1,7 @@
+{
+  Examples:
+    ./testpassrc --suite=TTestStatementParser.TestCallQualified2
+}
 unit tcstatements;
 unit tcstatements;
 
 
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}
@@ -382,10 +386,10 @@ begin
   S:=Statement as TPasImplSimple;
   S:=Statement as TPasImplSimple;
   AssertExpression('Doit call',S.Expr,pekBinary,TBinaryExpr);
   AssertExpression('Doit call',S.Expr,pekBinary,TBinaryExpr);
   B:=S.Expr as 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');
   AssertExpression('Doit call',B.Right,pekIdent,'Doit');
 end;
 end;
 
 
@@ -979,9 +983,6 @@ procedure TTestStatementParser.TestCaseOtherwiseBlockEmpty;
 
 
 Var
 Var
   C : TPasImplCaseOf;
   C : TPasImplCaseOf;
-  S : TPasImplCaseStatement;
-  B : TPasImplbeginBlock;
-
 begin
 begin
   DeclareVar('integer');
   DeclareVar('integer');
   TestStatement(['case a of','1 : begin end;','otherwise',' end;']);
   TestStatement(['case a of','1 : begin end;','otherwise',' end;']);

+ 15 - 0
packages/fcl-passrc/tests/tctypeparser.pas

@@ -114,6 +114,7 @@ type
     Procedure TestStaticArrayTypedIndex;
     Procedure TestStaticArrayTypedIndex;
     Procedure TestDynamicArray;
     Procedure TestDynamicArray;
     Procedure TestDynamicArrayComment;
     Procedure TestDynamicArrayComment;
+    Procedure TestGenericArray;
     Procedure TestSimpleEnumerated;
     Procedure TestSimpleEnumerated;
     Procedure TestSimpleEnumeratedComment;
     Procedure TestSimpleEnumeratedComment;
     Procedure TestSimpleEnumeratedComment2;
     Procedure TestSimpleEnumeratedComment2;
@@ -2837,6 +2838,20 @@ begin
   AssertComment;
   AssertComment;
 end;
 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;
 procedure TTestTypeParser.TestSimpleEnumerated;
 
 
 begin
 begin

+ 1 - 1
packages/fcl-passrc/tests/testpassrc.lpi

@@ -30,7 +30,7 @@
     <RunParams>
     <RunParams>
       <local>
       <local>
         <FormatVersion Value="1"/>
         <FormatVersion Value="1"/>
-        <CommandLineParams Value="--suite=TTestProcedureFunction.TestOperatorTokens"/>
+        <CommandLineParams Value="--suite=TTestTypeParser.TestGenericArray"/>
       </local>
       </local>
     </RunParams>
     </RunParams>
     <RequiredPackages Count="1">
     <RequiredPackages Count="1">