View Issue Details

IDProjectCategoryView StatusLast Update
0030615FPCPackagespublic2017-01-29 12:36
ReporterAndrey Zubarev Assigned ToMichael Van Canneyt  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Fixed in Version3.1.1 
Summary0030615: fcl-passrc errors
DescriptionFunction declarations and generics specializations cause errors in delphi mode. Also error with str procedure.
In this example, the fcl-passrc finds 3 errors. But they are not there:
8<----cut here----

unit passrcerrors;
{$mode delphi}
interface
uses
  Classes, SysUtils, fgl;
type TMyList=TFPGList<integer>;//<--------Identifier expected at token ";"

function TestDelphiModeFuncs(d:double):string;
implementation
function TestDelphiModeFuncs;//<--------Expected ":" at token ";"
begin
   str(d:3:3,result);//<--------Expected ";" at token ":"
end;
end.

8<----cut here----
TagsNo tags attached.
Fixed in Revision34691
FPCOldBugId
FPCTarget
Attached Files

Activities

Andrey Zubarev

2016-09-20 09:00

reporter  

passrc1.patch (3,419 bytes)   
Index: packages/fcl-passrc/src/pparser.pp
===================================================================
--- packages/fcl-passrc/src/pparser.pp	(revision 34540)
+++ packages/fcl-passrc/src/pparser.pp	(working copy)
@@ -1224,7 +1224,28 @@
       tkClass: Result := ParseClassDecl(Parent, TypeName, okClass, PM);
       tkType: Result:=ParseAliasType(Parent,NamePos,TypeName);
       // Always allowed
-      tkIdentifier: Result:=ParseSimpleType(Parent,NamePos,TypeName,Full);
+      tkIdentifier:
+        begin
+        if po_delphi in Scanner.Options then
+          begin
+          NextToken;
+          if (Curtoken=tkLessThan) then
+            begin
+            UnGetToken;
+            UnGetToken;
+            Scanner.Options:=Scanner.Options-[po_delphi];
+            Result:=ParseSpecializeType(Parent,TypeName);
+            Scanner.Options:=Scanner.Options+[po_delphi];
+            end
+          else
+            begin
+            UnGetToken;
+            Result:=ParseSimpleType(Parent,NamePos,TypeName,Full);
+            end;
+          end
+        else
+          Result:=ParseSimpleType(Parent,NamePos,TypeName,Full);
+        end;
       tkCaret: Result:=ParsePointerType(Parent,NamePos,TypeName);
       tkFile: Result:=ParseFileType(Parent,NamePos,TypeName);
       tkArray: Result:=ParseArrayType(Parent,NamePos,TypeName,pm);
@@ -3234,7 +3255,7 @@
   Tok : String;
   CC : TCallingConvention;
   PM : TProcedureModifier;
-  Done: Boolean;
+  Done, NeedFunctionResult : Boolean;
   ResultEl: TPasResultElement;
 
 begin
@@ -3244,9 +3265,22 @@
   case ProcType of
     ptFunction,ptClassFunction:
       begin
-      ExpectToken(tkColon);
-      ResultEl:=TPasFunctionType(Element).ResultEl;
-      ResultEl.ResultType := ParseType(ResultEl,Scanner.CurSourcePos);
+      NeedFunctionResult:=not(po_delphi in Scanner.Options);
+      if not NeedFunctionResult then
+        begin
+        NextToken;
+        if (CurToken=tkColon) then
+          NeedFunctionResult:=true;
+          UnGetToken;
+        end;
+      if NeedFunctionResult then
+        begin
+        ExpectToken(tkColon);
+        ResultEl:=TPasFunctionType(Element).ResultEl;
+        ResultEl.ResultType := ParseType(ResultEl,Scanner.CurSourcePos);
+        end
+      else
+        ResultEl.Name := 'Result';
       end;
     ptOperator,ptClassOperator:
       begin
Index: packages/fcl-passrc/src/pscanner.pp
===================================================================
--- packages/fcl-passrc/src/pscanner.pp	(revision 34540)
+++ packages/fcl-passrc/src/pscanner.pp	(working copy)
@@ -1420,7 +1420,7 @@
   TokenStart, CurPos: PChar;
   i: TToken;
   OldLength, SectionLength, NestingLevel, Index: Integer;
-  Directive, Param : string;
+  Directive, Param, UCParam : string;
 begin
   if TokenStr = nil then
     if not FetchLine then
@@ -1807,6 +1807,14 @@
                   exit;
                   end
                 end
+              else if (Directive = 'MODE')then
+                begin
+                  UCParam:=UpperCase(Param);
+                  if UCParam='DELPHI' then
+                    Options:=Options+[po_delphi]
+                  else if UCParam='OBJFPC' then
+                    Options:=Options-[po_delphi]
+                end
               else if (Directive = 'DEFINE') then
                 HandleDefine(Param)
               else if (Directive = 'UNDEF') then
passrc1.patch (3,419 bytes)   

Andrey Zubarev

2016-09-20 09:04

reporter   ~0094731

Please review the passrc1.patch It solves the problem generics and functions in delphi mode. Perhaps incorrectly.
Also I noticed that fcl-passrc unsuported generics inheritance

Andrey Zubarev

2016-09-20 11:44

reporter   ~0094734

Last edited: 2016-09-20 11:45

View 2 revisions

fcl-passrc allow generics only for arrays and classes. Other types throw 'Generic can only be used with classes or arrays'
What about objects and records? fpc allow generics for it

Andrey Zubarev

2016-09-20 21:28

reporter   ~0094740

Applied passrc2.patch (contain passrc1.patch, passrc1 need delete) he solves all described here problems, and a bit more - expr like (ppdouble)^^

Andrey Zubarev

2016-09-20 21:29

reporter  

passrc2.patch (10,616 bytes)   
Index: packages/fcl-passrc/src/pastree.pp
===================================================================
--- packages/fcl-passrc/src/pastree.pp	(revision 34540)
+++ packages/fcl-passrc/src/pastree.pp	(working copy)
@@ -1211,6 +1211,11 @@
       const Arg: Pointer); override;
   end;
 
+  { TPasImplStr }
+
+  TPasImplStr = class (TPasImplBlock)
+  end;
+
   { TPasImplSimple }
 
   TPasImplSimple = class (TPasImplStatement)
Index: packages/fcl-passrc/src/pparser.pp
===================================================================
--- packages/fcl-passrc/src/pparser.pp	(revision 34540)
+++ packages/fcl-passrc/src/pparser.pp	(working copy)
@@ -1224,7 +1224,28 @@
       tkClass: Result := ParseClassDecl(Parent, TypeName, okClass, PM);
       tkType: Result:=ParseAliasType(Parent,NamePos,TypeName);
       // Always allowed
-      tkIdentifier: Result:=ParseSimpleType(Parent,NamePos,TypeName,Full);
+      tkIdentifier:
+        begin
+        if po_delphi in Scanner.Options then
+          begin
+          NextToken;
+          if (Curtoken=tkLessThan) then
+            begin
+            UnGetToken;
+            UnGetToken;
+            Scanner.Options:=Scanner.Options-[po_delphi];
+            Result:=ParseSpecializeType(Parent,TypeName);
+            Scanner.Options:=Scanner.Options+[po_delphi];
+            end
+          else
+            begin
+            UnGetToken;
+            Result:=ParseSimpleType(Parent,NamePos,TypeName,Full);
+            end;
+          end
+        else
+          Result:=ParseSimpleType(Parent,NamePos,TypeName,Full);
+        end;
       tkCaret: Result:=ParsePointerType(Parent,NamePos,TypeName);
       tkFile: Result:=ParseFileType(Parent,NamePos,TypeName);
       tkArray: Result:=ParseArrayType(Parent,NamePos,TypeName,pm);
@@ -1702,6 +1723,14 @@
             Exit;
             end;
           NextToken;
+
+          // for the expression like  (ppdouble)^^;
+          while (x<>Nil) and (CurToken=tkCaret) do
+            begin
+            NextToken;
+            x:=CreateUnaryExpr(AParent,x, TokenToExprOp(tkCaret));
+            end;
+
           //     DumpCurToken('Here 1');
                // for the expression like  (TObject(m)).Free;
                if (x<>Nil) and (CurToken=tkDot) then
@@ -1710,8 +1739,7 @@
           //       DumpCurToken('Here 2');
                  x:=CreateBinaryExpr(AParent,x, ParseExpIdent(AParent), TokenToExprOp(tkDot));
           //       DumpCurToken('Here 3');
-                 end;
-
+                 end
           end
         else
           begin
@@ -2222,14 +2250,28 @@
   TypeName: String;
   PT : TProcType;
   NamePos: TPasSourcePos;
-
+  TempToken: TToken;
+  DelphiGeneric:boolean;
 begin
   CurBlock := declNone;
   while True do
   begin
     NextToken;
+    TempToken:=CurToken;
+    DelphiGeneric:=false;
+    if po_delphi in Scanner.Options then
+      if CurToken=tkIdentifier then
+      begin
+        NextToken;
+        if CurToken=tkLessThan then
+          begin
+          TempToken:=tkgeneric;
+          DelphiGeneric:=true;
+          end;
+        UngetToken;
+      end;
   //  writeln('TPasParser.ParseSection Token=',CurTokenString,' ',CurToken, ' ',scanner.CurFilename);
-    case CurToken of
+    case {CurToken}TempToken of
       tkend:
         begin
         If (CurModule is TPasProgram) and (CurModule.InitializationSection=Nil) then
@@ -2401,7 +2443,10 @@
         begin
           if CurBlock <> declType then
             ParseExcSyntaxError;
-          TypeName := ExpectIdentifier;
+          if DelphiGeneric then
+            TypeName:=CurTokenString
+          else
+            TypeName := ExpectIdentifier;
           NamePos:=Scanner.CurSourcePos;
           List:=TFPList.Create;
           try
@@ -2409,7 +2454,7 @@
             ExpectToken(tkEqual);
             NextToken;
             Case CurToken of
-              tkClass :
+              tkobject,tkpacked:
                  begin
                  ClassEl := TPasClassType(CreateElement(TPasClassType,
                    TypeName, Declarations, NamePos));
@@ -2419,6 +2464,8 @@
                    TPasElement(List[i]).Parent:=ClassEl;
                    ClassEl.GenericTemplateTypes.Add(List[i]);
                    end;
+                 if CurToken=tkpacked then
+                   NextToken;
                  NextToken;
                  DoParseClassType(ClassEl);
                  Declarations.Declarations.Add(ClassEl);
@@ -2425,6 +2472,22 @@
                  Declarations.Classes.Add(ClassEl);
                  CheckHint(classel,True);
                  end;
+              tkClass:
+                 begin
+                 ClassEl := TPasClassType(CreateElement(TPasClassType,
+                   TypeName, Declarations, NamePos));
+                 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
@@ -3234,7 +3297,7 @@
   Tok : String;
   CC : TCallingConvention;
   PM : TProcedureModifier;
-  Done: Boolean;
+  Done, NeedFunctionResult : Boolean;
   ResultEl: TPasResultElement;
 
 begin
@@ -3244,9 +3307,22 @@
   case ProcType of
     ptFunction,ptClassFunction:
       begin
-      ExpectToken(tkColon);
-      ResultEl:=TPasFunctionType(Element).ResultEl;
-      ResultEl.ResultType := ParseType(ResultEl,Scanner.CurSourcePos);
+      NeedFunctionResult:=not(po_delphi in Scanner.Options);
+      if not NeedFunctionResult then
+        begin
+        NextToken;
+        if (CurToken=tkColon) then
+          NeedFunctionResult:=true;
+          UnGetToken;
+        end;
+      if NeedFunctionResult then
+        begin
+        ExpectToken(tkColon);
+        ResultEl:=TPasFunctionType(Element).ResultEl;
+        ResultEl.ResultType := ParseType(ResultEl,Scanner.CurSourcePos);
+        end
+      else
+        ResultEl.Name := 'Result';
       end;
     ptOperator,ptClassOperator:
       begin
@@ -3630,7 +3706,9 @@
   El : TPasImplElement;
   ak : TAssignKind;
   lt : TLoopType;
-  ok: Boolean;
+  ok, matched : Boolean;
+  ident : string;
+  PE : TPasExpr;
 
 begin
   NewImplElement:=nil;
@@ -4007,6 +4085,56 @@
           ParseExcSyntaxError;
       end;
     else
+      matched:=false;
+      if (CurToken=tkIdentifier)and(UpperCase(CurTokenString)='STR')then
+      begin
+       NextToken;
+       if CurToken=tkBraceOpen then
+       matched:=true;
+       UngetToken;
+      end;
+      if matched then
+      begin
+      El:=TPasImplElement(CreateElement(TPasImplStr,'',CurBlock));
+      expecttoken(tkBraceOpen);
+      NextToken;
+      PE:=ParseExpIdent(El);
+      if CurToken=tkColon then
+        begin
+          NextToken;
+          PE:=DoParseExpression(El,Nil);
+          if not ((PE is TPrimitiveExpr) and (TPrimitiveExpr(PE).Kind=pekNumber)) then
+            begin
+            PE.Release;
+            ParseExc(nParserExpectTokenError,format(SParserExpectTokenError,['number']));
+            end;
+          if CurToken=tkColon then
+          begin
+            NextToken;
+            PE:=DoParseExpression(El,Nil);
+            if not ((PE is TPrimitiveExpr) and (TPrimitiveExpr(PE).Kind=pekNumber)) then
+              begin
+              PE.Release;
+              ParseExc(nParserExpectTokenError,format(SParserExpectTokenError,['number']));
+              end;
+          end
+          else
+            begin
+            UngetToken;
+            expecttoken(tkComma);
+            end
+        end
+        else
+          begin
+          UngetToken;
+          expecttoken(tkComma);
+          end;
+      ident:=ExpectIdentifier;
+      expecttoken(tkBraceClose);
+      NewImplElement:=El;
+      end
+      else
+      begin
       left:=DoParseExpression(Parent);
       case CurToken of
         tkAssign,
@@ -4019,6 +4147,8 @@
           Ak:=TokenToAssignKind(CurToken);
           NextToken;
           right:=DoParseExpression(Parent); // this may solve TPasImplWhileDo.AddElement BUG
+          if right=nil then
+                           right:=right;
           El:=TPasImplAssign(CreateElement(TPasImplAssign,'',CurBlock));
           left.Parent:=El;
           right.Parent:=El;
@@ -4051,6 +4181,7 @@
 
       if not (CmdElem is TPasImplLabelMark) then
         if NewImplElement=nil then NewImplElement:=CmdElem;
+      end;
     end;
   end;
 end;
@@ -4091,6 +4222,8 @@
 function TPasParser.ParseProcedureOrFunctionDecl(Parent: TPasElement; ProcType: TProcType;AVisibility : TPasMemberVisibility = VisDefault): TPasProcedure;
 
   function ExpectProcName: string;
+  var
+    List:TFPList;
   begin
     Result:=ExpectIdentifier;
     //writeln('ExpectProcName ',Parent.Classname);
@@ -4097,6 +4230,15 @@
     if Parent is TImplementationSection then
     begin
       NextToken;
+      if CurToken=tkLessThan then
+      begin
+        UngetToken;
+        List:=TFPList.Create;
+        ReadGenericArguments(List,Nil);
+        Result:=Result+'<>';
+        List.Free;
+        NextToken;
+      end;
       if CurToken=tkDot then
       begin
         Result:=Result+'.'+ExpectIdentifier;
Index: packages/fcl-passrc/src/pscanner.pp
===================================================================
--- packages/fcl-passrc/src/pscanner.pp	(revision 34540)
+++ packages/fcl-passrc/src/pscanner.pp	(working copy)
@@ -1420,7 +1420,7 @@
   TokenStart, CurPos: PChar;
   i: TToken;
   OldLength, SectionLength, NestingLevel, Index: Integer;
-  Directive, Param : string;
+  Directive, Param, UCParam : string;
 begin
   if TokenStr = nil then
     if not FetchLine then
@@ -1807,6 +1807,14 @@
                   exit;
                   end
                 end
+              else if (Directive = 'MODE')then
+                begin
+                  UCParam:=UpperCase(Param);
+                  if UCParam='DELPHI' then
+                    Options:=Options+[po_delphi]
+                  else if UCParam='OBJFPC' then
+                    Options:=Options-[po_delphi]
+                end
               else if (Directive = 'DEFINE') then
                 HandleDefine(Param)
               else if (Directive = 'UNDEF') then
passrc2.patch (10,616 bytes)   

Andrey Zubarev

2016-09-30 08:26

reporter   ~0094879

Please review a patch

Andrey Zubarev

2016-10-06 12:28

reporter   ~0094984

passrc2.path are conflicted after r34631.
I fix it in passrc3.path, passrc2.path and passrc1.path need to delete
Please review

Andrey Zubarev

2016-10-06 12:28

reporter  

passrc3.patch (10,651 bytes)   
Index: packages/fcl-passrc/src/pastree.pp
===================================================================
--- packages/fcl-passrc/src/pastree.pp	(revision 34633)
+++ packages/fcl-passrc/src/pastree.pp	(working copy)
@@ -1224,6 +1224,11 @@
       const Arg: Pointer); override;
   end;
 
+  { TPasImplStr }
+
+  TPasImplStr = class (TPasImplBlock)
+  end;
+
   { TPasImplSimple }
 
   TPasImplSimple = class (TPasImplStatement)
Index: packages/fcl-passrc/src/pparser.pp
===================================================================
--- packages/fcl-passrc/src/pparser.pp	(revision 34633)
+++ packages/fcl-passrc/src/pparser.pp	(working copy)
@@ -1248,7 +1248,28 @@
       tkClass: Result := ParseClassDecl(Parent, NamePos, TypeName, okClass, PM);
       tkType: Result:=ParseAliasType(Parent,NamePos,TypeName);
       // Always allowed
-      tkIdentifier: Result:=ParseSimpleType(Parent,NamePos,TypeName,Full);
+      tkIdentifier:
+        begin
+        if po_delphi in Scanner.Options then
+          begin
+          NextToken;
+          if (Curtoken=tkLessThan) then
+            begin
+            UnGetToken;
+            UnGetToken;
+            Scanner.Options:=Scanner.Options-[po_delphi];
+            Result:=ParseSpecializeType(Parent,TypeName);
+            Scanner.Options:=Scanner.Options+[po_delphi];
+            end
+          else
+            begin
+            UnGetToken;
+            Result:=ParseSimpleType(Parent,NamePos,TypeName,Full);
+            end;
+          end
+        else
+          Result:=ParseSimpleType(Parent,NamePos,TypeName,Full);
+        end;
       tkCaret: Result:=ParsePointerType(Parent,NamePos,TypeName);
       tkFile: Result:=ParseFileType(Parent,NamePos,TypeName);
       tkArray: Result:=ParseArrayType(Parent,NamePos,TypeName,pm);
@@ -1731,6 +1752,14 @@
             Exit;
             end;
           NextToken;
+
+          // for the expression like  (ppdouble)^^;
+          while (x<>Nil) and (CurToken=tkCaret) do
+            begin
+            NextToken;
+            x:=CreateUnaryExpr(AParent,x, TokenToExprOp(tkCaret));
+            end;
+
           //     DumpCurToken('Here 1');
                // for the expression like  (TObject(m)).Free;
                if (x<>Nil) and (CurToken=tkDot) then
@@ -1739,8 +1768,7 @@
           //       DumpCurToken('Here 2');
                  x:=CreateBinaryExpr(AParent,x, ParseExpIdent(AParent), TokenToExprOp(tkDot));
           //       DumpCurToken('Here 3');
-                 end;
-
+                 end
           end
         else
           begin
@@ -2259,14 +2287,28 @@
   PT : TProcType;
   NamePos: TPasSourcePos;
   ok: Boolean;
-
+  TempToken: TToken;
+  DelphiGeneric:boolean;
 begin
   CurBlock := declNone;
   while True do
   begin
     NextToken;
+    TempToken:=CurToken;
+    DelphiGeneric:=false;
+    if po_delphi in Scanner.Options then
+      if CurToken=tkIdentifier then
+      begin
+        NextToken;
+        if CurToken=tkLessThan then
+          begin
+          TempToken:=tkgeneric;
+          DelphiGeneric:=true;
+          end;
+        UngetToken;
+      end;
   //  writeln('TPasParser.ParseSection Token=',CurTokenString,' ',CurToken, ' ',scanner.CurFilename);
-    case CurToken of
+    case {CurToken}TempToken of
       tkend:
         begin
         If (CurModule is TPasProgram) and (CurModule.InitializationSection=Nil) then
@@ -2444,7 +2486,10 @@
         begin
           if CurBlock <> declType then
             ParseExcSyntaxError;
-          TypeName := ExpectIdentifier;
+          if DelphiGeneric then
+            TypeName:=CurTokenString
+          else
+            TypeName := ExpectIdentifier;
           NamePos:=Scanner.CurSourcePos;
           List:=TFPList.Create;
           try
@@ -2452,7 +2497,7 @@
             ExpectToken(tkEqual);
             NextToken;
             Case CurToken of
-              tkClass :
+              tkobject,tkpacked:
                  begin
                  ClassEl := TPasClassType(CreateElement(TPasClassType,
                    TypeName, Declarations, NamePos));
@@ -2462,6 +2507,8 @@
                    TPasElement(List[i]).Parent:=ClassEl;
                    ClassEl.GenericTemplateTypes.Add(List[i]);
                    end;
+                 if CurToken=tkpacked then
+                   NextToken;
                  NextToken;
                  DoParseClassType(ClassEl);
                  Declarations.Declarations.Add(ClassEl);
@@ -2468,6 +2515,22 @@
                  Declarations.Classes.Add(ClassEl);
                  CheckHint(classel,True);
                  end;
+              tkClass:
+                 begin
+                 ClassEl := TPasClassType(CreateElement(TPasClassType,
+                   TypeName, Declarations, NamePos));
+                 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
@@ -3291,7 +3354,7 @@
   Tok : String;
   CC : TCallingConvention;
   PM : TProcedureModifier;
-  Done: Boolean;
+  Done, NeedFunctionResult : Boolean;
   ResultEl: TPasResultElement;
 
 begin
@@ -3301,9 +3364,22 @@
   case ProcType of
     ptFunction,ptClassFunction:
       begin
-      ExpectToken(tkColon);
-      ResultEl:=TPasFunctionType(Element).ResultEl;
-      ResultEl.ResultType := ParseType(ResultEl,Scanner.CurSourcePos);
+      NeedFunctionResult:=not(po_delphi in Scanner.Options);
+      if not NeedFunctionResult then
+        begin
+        NextToken;
+        if (CurToken=tkColon) then
+          NeedFunctionResult:=true;
+          UnGetToken;
+        end;
+      if NeedFunctionResult then
+        begin
+        ExpectToken(tkColon);
+        ResultEl:=TPasFunctionType(Element).ResultEl;
+        ResultEl.ResultType := ParseType(ResultEl,Scanner.CurSourcePos);
+        end
+      else
+        ResultEl.Name := 'Result';
       end;
     ptOperator,ptClassOperator:
       begin
@@ -3702,7 +3778,9 @@
   El : TPasImplElement;
   ak : TAssignKind;
   lt : TLoopType;
-  ok: Boolean;
+  ok, matched : Boolean;
+  ident : string;
+  PE : TPasExpr;
   SrcPos: TPasSourcePos;
   Name: String;
   TypeEl: TPasType;
@@ -4089,6 +4167,56 @@
           ParseExcSyntaxError;
       end;
     else
+      matched:=false;
+      if (CurToken=tkIdentifier)and(UpperCase(CurTokenString)='STR')then
+      begin
+       NextToken;
+       if CurToken=tkBraceOpen then
+       matched:=true;
+       UngetToken;
+      end;
+      if matched then
+      begin
+      El:=TPasImplElement(CreateElement(TPasImplStr,'',CurBlock));
+      expecttoken(tkBraceOpen);
+      NextToken;
+      PE:=ParseExpIdent(El);
+      if CurToken=tkColon then
+        begin
+          NextToken;
+          PE:=DoParseExpression(El,Nil);
+          if not ((PE is TPrimitiveExpr) and (TPrimitiveExpr(PE).Kind=pekNumber)) then
+            begin
+            PE.Release;
+            ParseExc(nParserExpectTokenError,format(SParserExpectTokenError,['number']));
+            end;
+          if CurToken=tkColon then
+          begin
+            NextToken;
+            PE:=DoParseExpression(El,Nil);
+            if not ((PE is TPrimitiveExpr) and (TPrimitiveExpr(PE).Kind=pekNumber)) then
+              begin
+              PE.Release;
+              ParseExc(nParserExpectTokenError,format(SParserExpectTokenError,['number']));
+              end;
+          end
+          else
+            begin
+            UngetToken;
+            expecttoken(tkComma);
+            end
+        end
+        else
+          begin
+          UngetToken;
+          expecttoken(tkComma);
+          end;
+      ident:=ExpectIdentifier;
+      expecttoken(tkBraceClose);
+      NewImplElement:=El;
+      end
+      else
+      begin
       left:=DoParseExpression(Parent);
       case CurToken of
         tkAssign,
@@ -4101,6 +4229,8 @@
           Ak:=TokenToAssignKind(CurToken);
           NextToken;
           right:=DoParseExpression(Parent); // this may solve TPasImplWhileDo.AddElement BUG
+          if right=nil then
+                           right:=right;
           El:=TPasImplAssign(CreateElement(TPasImplAssign,'',CurBlock));
           left.Parent:=El;
           right.Parent:=El;
@@ -4133,6 +4263,7 @@
 
       if not (CmdElem is TPasImplLabelMark) then
         if NewImplElement=nil then NewImplElement:=CmdElem;
+      end;
     end;
   end;
 end;
@@ -4173,6 +4304,8 @@
 function TPasParser.ParseProcedureOrFunctionDecl(Parent: TPasElement; ProcType: TProcType;AVisibility : TPasMemberVisibility = VisDefault): TPasProcedure;
 
   function ExpectProcName: string;
+  var
+    List:TFPList;
   begin
     Result:=ExpectIdentifier;
     //writeln('ExpectProcName ',Parent.Classname);
@@ -4179,6 +4312,15 @@
     if Parent is TImplementationSection then
     begin
       NextToken;
+      if CurToken=tkLessThan then
+      begin
+        UngetToken;
+        List:=TFPList.Create;
+        ReadGenericArguments(List,Nil);
+        Result:=Result+'<>';
+        List.Free;
+        NextToken;
+      end;
       if CurToken=tkDot then
       begin
         Result:=Result+'.'+ExpectIdentifier;
Index: packages/fcl-passrc/src/pscanner.pp
===================================================================
--- packages/fcl-passrc/src/pscanner.pp	(revision 34633)
+++ packages/fcl-passrc/src/pscanner.pp	(working copy)
@@ -1423,7 +1423,7 @@
   TokenStart, CurPos: PChar;
   i: TToken;
   OldLength, SectionLength, NestingLevel, Index: Integer;
-  Directive, Param : string;
+  Directive, Param, UCParam : string;
 begin
   if TokenStr = nil then
     if not FetchLine then
@@ -1810,6 +1810,14 @@
                   exit;
                   end
                 end
+              else if (Directive = 'MODE')then
+                begin
+                  UCParam:=UpperCase(Param);
+                  if UCParam='DELPHI' then
+                    Options:=Options+[po_delphi]
+                  else if UCParam='OBJFPC' then
+                    Options:=Options-[po_delphi]
+                end
               else if (Directive = 'DEFINE') then
                 HandleDefine(Param)
               else if (Directive = 'UNDEF') then
passrc3.patch (10,651 bytes)   

Michael Van Canneyt

2016-10-09 11:55

administrator   ~0095037

Fixed these issues, but differently from your patch.
(I was working on these issues anyway, based on other bugreports).

I added testcases as well.

Many thanks for the patch.

Andrey Zubarev

2016-10-10 07:57

reporter   ~0095093

Thanks!

Andrey Zubarev

2017-01-29 06:30

reporter   ~0097770

Now problems in delphi mode?

program Project1;
{$MODE DELPHI}
uses
  Classes, SysUtils, fgl;
type
    TMyObject=object(TMyOldOdject<T1,T2>)
    end;
begin
end.

not parsed((

Michael Van Canneyt

2017-01-29 11:39

administrator   ~0097773

Generics are not yet supported.

Michael Van Canneyt

2017-01-29 11:42

administrator   ~0097774

I have closed the original bug which was the problem. str() and specialization of generic in type section.
For new bugs with generics please file a different bugreport.

Andrey Zubarev

2017-01-29 12:36

reporter   ~0097776

I'm sorry, I thought that this error did not exist

Issue History

Date Modified Username Field Change
2016-09-19 08:15 Andrey Zubarev New Issue
2016-09-20 09:00 Andrey Zubarev File Added: passrc1.patch
2016-09-20 09:04 Andrey Zubarev Note Added: 0094731
2016-09-20 11:44 Andrey Zubarev Note Added: 0094734
2016-09-20 11:45 Andrey Zubarev Note Edited: 0094734 View Revisions
2016-09-20 21:28 Andrey Zubarev Note Added: 0094740
2016-09-20 21:29 Andrey Zubarev File Added: passrc2.patch
2016-09-30 08:26 Andrey Zubarev Note Added: 0094879
2016-10-06 12:28 Andrey Zubarev Note Added: 0094984
2016-10-06 12:28 Andrey Zubarev File Added: passrc3.patch
2016-10-08 16:30 Michael Van Canneyt Assigned To => Michael Van Canneyt
2016-10-08 16:30 Michael Van Canneyt Status new => assigned
2016-10-09 11:55 Michael Van Canneyt Fixed in Revision => 34691
2016-10-09 11:55 Michael Van Canneyt Note Added: 0095037
2016-10-09 11:55 Michael Van Canneyt Status assigned => resolved
2016-10-09 11:55 Michael Van Canneyt Fixed in Version => 3.1.1
2016-10-09 11:55 Michael Van Canneyt Resolution open => fixed
2016-10-10 07:57 Andrey Zubarev Note Added: 0095093
2016-10-10 07:57 Andrey Zubarev Status resolved => closed
2017-01-29 06:30 Andrey Zubarev Note Added: 0097770
2017-01-29 06:30 Andrey Zubarev Status closed => feedback
2017-01-29 06:30 Andrey Zubarev Resolution fixed => reopened
2017-01-29 11:39 Michael Van Canneyt Note Added: 0097773
2017-01-29 11:42 Michael Van Canneyt Note Added: 0097774
2017-01-29 11:42 Michael Van Canneyt Status feedback => resolved
2017-01-29 11:42 Michael Van Canneyt Resolution reopened => fixed
2017-01-29 12:36 Andrey Zubarev Note Added: 0097776
2017-01-29 12:36 Andrey Zubarev Status resolved => closed