Browse Source

* Parse operators better

git-svn-id: trunk@31226 -
michael 10 years ago
parent
commit
e4cd8565ae

+ 111 - 4
packages/fcl-passrc/src/pastree.pp

@@ -65,6 +65,8 @@ resourcestring
   SPasTreeOverloadedProcedure = 'overloaded procedure';
   SPasTreeProcedure = 'procedure';
   SPasTreeFunction = 'function';
+  SPasTreeOperator = 'operator';
+  SPasTreeClassOperator = 'class operator';
   SPasTreeClassProcedure = 'class procedure';
   SPasTreeClassFunction = 'class function';
   SPasTreeClassConstructor = 'class constructor';
@@ -765,14 +767,39 @@ type
   end;
 
   { TPasOperator }
-
-  TPasOperator = class(TPasProcedure)
-  public
+  TOperatorType = (otUnknown,otImplicit,otExplicit,otMul,otPlus, otMinus, otDivision,otLessThan, otEqual,
+                   otGreaterThan, otAssign,otNotEqual,otLessEqualThan,otGreaterEqualThan,otPower,
+                   otSymmetricalDifference, otInc, otDec, otMod, otNegative, otPositive, otBitWiseOr, otDiv,
+                   otLeftShift, otLogicalOr, otBitwiseAnd, otbitwiseXor,otLogicalAnd,otLogicalNot,otLogicalXor,
+                   otRightShift);
+  TOperatorTypes = set of TOperatorType;
+
+  TPasOperator = class(TPasFunction)
+  private
+    FOperatorType: TOperatorType;
+    FTokenBased: Boolean;
+  public
+    Class Function OperatorTypeToToken(T : TOperatorType) : String;
+    Class Function OperatorTypeToOperatorName(T: TOperatorType) : String;
+    Class Function TokenToOperatorType(S : String) : TOperatorType;
+    Class Function NameToOperatorType(S : String) : TOperatorType;
+    Procedure CorrectName;
     function ElementTypeName: string; override;
     function TypeName: string; override;
     function GetDeclaration (full : boolean) : string; override;
+    Property OperatorType : TOperatorType Read FOperatorType Write FOperatorType;
+    // True if the declaration was using a token instead of a
+    Property TokenBased : Boolean Read FTokenBased Write FTokenBased;
   end;
 
+Type
+  { TPasClassOperator }
+
+  TPasClassOperator = class(TPasOperator)
+    function TypeName: string; override;
+  end;
+
+
   { TPasConstructor }
 
   TPasConstructor = class(TPasProcedure)
@@ -1184,6 +1211,22 @@ const
         '@','^',
         '.');
 
+
+  UnaryOperators = [otImplicit,otExplicit,otAssign,otNegative,otPositive];
+
+  OperatorTokens : Array[TOperatorType] of string
+       =  ('','','','*','+','-','/','<','=',
+           '>',':=','<>','<=','>=','**',
+           '><','Inc','Dec','mod','-','+','Or','div',
+           'shl','or','and','xor','and','not','xor',
+           'shr');
+  OperatorNames : Array[TOperatorType] of string
+       =  ('','implicit','explicit','multiply','add','subtract','divide','lessthan','equal',
+           'greaterthan','assign','notequal','lessthanequal','greaterthanequal','power',
+           'symmetricaldifference','inc','dec','modulus','negative','positive','bitwiseor','intdivide',
+           'leftshift','logicalor','bitwiseand','bitwisexor','logicaland','logicalnot','logicalxor',
+           'rightshift');
+
   cPasMemberHint : array[TPasMemberHint] of string =
       ( 'deprecated', 'library', 'platform', 'experimental', 'unimplemented' );
   cCallingConventions : array[TCallingConvention] of string =
@@ -1199,6 +1242,13 @@ implementation
 
 uses SysUtils;
 
+{ TPasClassOperator }
+
+function TPasClassOperator.TypeName: string;
+begin
+  Result:='class operator';
+end;
+
 { TPasImplAsmStatement }
 
 constructor TPasImplAsmStatement.Create(const AName: string;
@@ -1412,7 +1462,63 @@ begin
 end;
 
 function TPasClassFunction.ElementTypeName: string; begin Result := SPasTreeClassFunction; end;
-function TPasOperator.ElementTypeName: string; begin Result := SPasTreeFunction end;
+
+class function TPasOperator.OperatorTypeToToken(T: TOperatorType): String;
+begin
+  Result:=OperatorTokens[T];
+end;
+
+class function TPasOperator.OperatorTypeToOperatorName(T: TOperatorType
+  ): String;
+begin
+  Result:=OperatorNames[T];
+end;
+
+class function TPasOperator.TokenToOperatorType(S: String): TOperatorType;
+begin
+  Result:=High(TOperatorType);
+  While (Result>otUnknown) and (CompareText(S,OperatorTokens[Result])<>0) do
+    Result:=Pred(Result);
+end;
+
+class function TPasOperator.NameToOperatorType(S: String): TOperatorType;
+begin
+  Result:=High(TOperatorType);
+  While (Result>otUnknown) and (CompareText(S,OperatorNames[Result])<>0) do
+    Result:=Pred(Result);
+end;
+
+procedure TPasOperator.CorrectName;
+
+Var
+  I : Integer;
+
+begin
+  I:=Pos('(',Name);
+  if I<>0 then
+    Name:=Copy(Name,1,I)
+  else
+    Name:=Name+'(';
+  if Assigned(ProcType) and Assigned(ProcType.Args) then
+  for i:=0 to ProcType.Args.Count-1 do
+    begin
+    if i>0 then
+      Name:=Name+',';
+    Name:=Name+TPasArgument(ProcType.Args[i]).ArgType.Name;
+    end;
+  if Assigned(TPasFunctionType(ProcType).ResultEl) and
+    Assigned(TPasFunctionType(ProcType).ResultEl.ResultType) then
+    Name:=Name+'):'+TPasFunctionType(ProcType).ResultEl.ResultType.Name;
+end;
+
+function TPasOperator.ElementTypeName: string;
+begin
+  if self is TPasClassOperator then
+    Result := SPasTreeClassOperator
+  else
+  Result := SPasTreeOperator
+end;
+
 function TPasConstructor.ElementTypeName: string; begin Result := SPasTreeConstructor end;
 function TPasDestructor.ElementTypeName: string; begin Result := SPasTreeDestructor end;
 function TPasProcedureImpl.ElementTypeName: string; begin Result := SPasTreeProcedureImpl end;
@@ -2968,6 +3074,7 @@ begin
         end;
     GetModifiers(S);
     Result:=IndentStrings(S,Length(S[0]));
+
   finally
     S.Free;
   end;

+ 77 - 48
packages/fcl-passrc/src/pparser.pp

@@ -38,6 +38,7 @@ resourcestring
   SParserExpectedCommaSemicolon = 'Expected "," or ";"';
   SParserExpectedAssignIn = 'Expected := or in';
   SParserExpectedCommaColon = 'Expected "," or ":"';
+  SErrUnknownOperatorType = 'Unknown operator type: %s';
   SParserOnlyOneArgumentCanHaveDefault = 'A default value can only be assigned to 1 parameter';
   SParserExpectedLBracketColon = 'Expected "(" or ":"';
   SParserExpectedLBracketSemicolon = 'Expected "(" or ";"';
@@ -119,7 +120,7 @@ type
     property Column: Integer read FColumn;
   end;
 
-  TProcType = (ptProcedure, ptFunction, ptOperator, ptConstructor, ptDestructor,
+  TProcType = (ptProcedure, ptFunction, ptOperator, ptClassOperator, ptConstructor, ptDestructor,
                ptClassProcedure, ptClassFunction, ptClassConstructor, ptClassDestructor);
 
 
@@ -175,6 +176,7 @@ type
     function CheckProcedureArgs(Parent: TPasElement; Args: TFPList; Mandatory: Boolean): boolean;
     function CheckVisibility(S: String; var AVisibility: TPasMemberVisibility): Boolean;
     procedure ParseExc(const Msg: String);
+    procedure ParseExc(const Fmt: String; Args : Array of const);
     function OpLevel(t: TToken): Integer;
     Function TokenToExprOp (AToken : TToken) : TExprOpCode;
     function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement): TPasElement;overload;
@@ -399,7 +401,7 @@ var
           if  (length(s)>2) then
             case S[3] of
               'c' : Scanner.Options:=Scanner.Options+[po_cassignments];
-              'd' : Parser.Options:=Parser.Options+[po_delphi];
+              'd','2' : Parser.Options:=Parser.Options+[po_delphi];
             end;
       end;
     end else
@@ -556,6 +558,11 @@ begin
     Scanner.CurFilename, Scanner.CurRow, Scanner.CurColumn);
 end;
 
+procedure TPasParser.ParseExc(const Fmt: String; Args: array of const);
+begin
+  ParseExc(Format(Fmt,Args));
+end;
+
 constructor TPasParser.Create(AScanner: TPascalScanner;
   AFileResolver: TBaseFileResolver; AEngine: TPasTreeContainer);
 begin
@@ -1943,7 +1950,10 @@ begin
       else
         Result:=ptDestructor;
     tkOperator:
-      Result:=ptOperator;
+      if IsClass then
+        Result:=ptClassOperator
+      else
+        Result:=ptOperator;
   else
     ParseExc(SParserNotAProcToken);
   end;
@@ -2867,24 +2877,21 @@ procedure TPasParser.ParseProcedureOrFunctionHeader(Parent: TPasElement;
 
 Var
   Tok : String;
-  i: Integer;
-  Proc: TPasProcedure;
   CC : TCallingConvention;
   PM : TProcedureModifier;
   Done: Boolean;
 
 begin
-  CheckProcedureArgs(Parent,Element.Args,ProcType=ptOperator);
+  // Element must be non-nil. Removed all checks for not-nil.
+  // If it is nil, the following fails anyway.
+  CheckProcedureArgs(Parent,Element.Args,ProcType in [ptOperator,ptClassOperator]);
   case ProcType of
     ptFunction,ptClassFunction:
       begin
       ExpectToken(tkColon);
-      if Assigned(Element) then        // !!!
-        TPasFunctionType(Element).ResultEl.ResultType := ParseType(Parent)
-      else
-        ParseType(nil);
+      TPasFunctionType(Element).ResultEl.ResultType := ParseType(Parent)
       end;
-    ptOperator:
+    ptOperator,ptClassOperator:
       begin
       NextToken;
       if (CurToken=tkIdentifier) then
@@ -2897,10 +2904,7 @@ begin
           TPasFunctionType(Element).ResultEl.Name := 'Result'
         else
           ParseExc(SParserExpectedColonID);
-        if Assigned(Element) then        // !!!
-          TPasFunctionType(Element).ResultEl.ResultType := ParseType(Parent)
-        else
-          ParseType(nil);
+        TPasFunctionType(Element).ResultEl.ResultType := ParseType(Parent)
       end;
   end;
   if OfObjectPossible then
@@ -2934,16 +2938,20 @@ begin
     NextToken;
     If TokenisCallingConvention(CurTokenString,cc) then
       begin
-      if Assigned(Element) then        // !!!
-        Element.CallingConvention:=Cc;
+      Element.CallingConvention:=Cc;
       if cc = ccSysCall then
       begin
         // remove LibBase
         NextToken;
-        // remove legacy or basesysv on MorphOS syscalls
-        if CurTokenIsIdentifier('legacy') or CurTokenIsIdentifier('BaseSysV') then
-          NextToken;
-        NextToken; // remove offset
+        if CurToken=tkSemiColon then
+          UngetToken
+        else
+          // remove legacy or basesysv on MorphOS syscalls
+          begin
+          if CurTokenIsIdentifier('legacy') or CurTokenIsIdentifier('BaseSysV') then
+            NextToken;
+          NextToken; // remove offset
+          end;
       end;
       ExpectToken(tkSemicolon);
       end
@@ -2982,21 +2990,8 @@ begin
   Until Done;
   if DoCheckHint then  // deprecated,platform,experimental,library, unimplemented etc
     ConsumeSemi;
-  if (ProcType = ptOperator) and (Parent is TPasProcedure) then
-  begin
-    Proc:=TPasProcedure(Parent);
-    Proc.Name := Proc.Name + '(';
-    for i := 0 to Proc.ProcType.Args.Count - 1 do
-    begin
-      if i > 0 then
-        Proc.Name := Proc.Name + ', ';
-      Proc.Name := Proc.Name +
-        TPasArgument(Proc.ProcType.Args[i]).ArgType.Name;
-    end;
-    Proc.Name := Proc.Name + '): ' +
-      TPasFunctionType(Proc.ProcType).ResultEl.ResultType.Name;
-  end;
-
+  if (ProcType in [ptOperator,ptClassOperator]) and (Parent is TPasOperator) then
+    TPasOperator(Parent).CorrectName;
   if (Parent is TPasProcedure)
   and (not TPasProcedure(Parent).IsForward)
   and (not TPasProcedure(Parent).IsExternal)
@@ -3659,12 +3654,13 @@ begin
     ptFunction       : Result:=TPasFunction;
     ptClassFunction  : Result:=TPasClassFunction;
     ptClassProcedure : Result:=TPasClassProcedure;
-    ptClassConstructor  : Result:=TPasClassConstructor;
-    ptClassDestructor   : Result:=TPasClassDestructor;
+    ptClassConstructor : Result:=TPasClassConstructor;
+    ptClassDestructor  : Result:=TPasClassDestructor;
     ptProcedure      : Result:=TPasProcedure;
     ptConstructor    : Result:=TPasConstructor;
     ptDestructor     : Result:=TPasDestructor;
     ptOperator       : Result:=TPasOperator;
+    ptClassOperator  : Result:=TPasClassOperator;
   else
     ParseExc('Unknown procedure Type '+intToStr(Ord(ProcType)));
   end;
@@ -3690,28 +3686,60 @@ function TPasParser.ParseProcedureOrFunctionDecl(Parent: TPasElement; ProcType:
 var
   Name: String;
   PC : TPTreeElement;
+  Ot : TOperatorType;
+  IsTokenBased : Boolean;
 
 begin
-  If (ProcType<>ptOperator) then
+  If (Not (ProcType in [ptOperator,ptClassOperator])) then
     Name:=ExpectProcName
   else
     begin
     NextToken;
-    Name := 'operator ' + TokenInfos[CurToken];
+    IsTokenBased:=Curtoken<>tkIdentifier;
+    if IsTokenBased then
+      OT:=TPasOperator.TokenToOperatorType(CurTokenText)
+    else
+      OT:=TPasOperator.NameToOperatorType(CurTokenString);
+    if (ot=otUnknown) then
+      ParseExc(SErrUnknownOperatorType,[CurTokenString]);
+    Name:=OperatorNames[Ot];
     end;
   PC:=GetProcedureClass(ProcType);
   Parent:=CheckIfOverLoaded(Parent,Name);
   Result:=TPasProcedure(CreateElement(PC,Name,Parent,AVisibility));
   try
-    if ProcType in [ptFunction, ptClassFunction] then
-      Result.ProcType := CreateFunctionType('', 'Result', Result, True)
-    else if ProcType=ptOperator then
-      Result.ProcType := CreateFunctionType('', '__INVALID__', Result,True)
+    if Not (ProcType in [ptFunction, ptClassFunction, ptOperator, ptClassOperator]) then
+      Result.ProcType := TPasProcedureType(CreateElement(TPasProcedureType, '', Result))
     else
-      Result.ProcType := TPasProcedureType(CreateElement(TPasProcedureType, '', Result));
+      begin
+      Result.ProcType := CreateFunctionType('', 'Result', Result, True);
+      if (ProcType in [ptOperator, ptClassOperator]) then
+        begin
+        TPasOperator(Result).TokenBased:=IsTokenBased;
+        TPasOperator(Result).OperatorType:=OT;
+        TPasOperator(Result).CorrectName;
+        end;
+      end;
     ParseProcedureOrFunctionHeader(Result, Result.ProcType, ProcType, False);
     Result.Hints:=Result.ProcType.Hints;
-    Result.HintMessage:=Result.ProcType.HintMessage
+    Result.HintMessage:=Result.ProcType.HintMessage;
+    // + is detected as 'positive', but is in fact Add if there are 2 arguments.
+    if (ProcType in [ptOperator, ptClassOperator]) then
+      With TPasOperator(Result) do
+        begin
+        if (OperatorType in [otPositive, otNegative]) then
+          begin
+          if (ProcType.Args.Count>1) then
+            begin
+            Case OperatorType of
+              otPositive : OperatorType:=otPlus;
+              otNegative : OperatorType:=otMinus;
+            end;
+            Name:=OperatorNames[OperatorType];
+            TPasOperator(Result).CorrectName;
+            end;
+          end;
+        end;
   except
     FreeAndNil(Result);
     Raise;
@@ -3802,6 +3830,7 @@ begin
         Prop.isClass:=isClass;
         Arec.Members.Add(Prop);
         end;
+      tkOperator,
       tkProcedure,
       tkFunction :
         begin
@@ -3848,10 +3877,10 @@ begin
     else
       ParseExc(SParserTypeSyntaxError);
     end;
-    if CurToken<>AEndToken then
-      NextToken;
     If CurToken<>tkClass then
       isClass:=False;
+    if CurToken<>AEndToken then
+      NextToken;
     end;
 end;
 

+ 34 - 2
packages/fcl-passrc/tests/tcbaseparser.pas

@@ -43,6 +43,8 @@ Type
     FUseImplementation: Boolean;
     function GetPL: TPasLibrary;
     function GetPP: TPasProgram;
+    procedure CleanupParser;
+    procedure SetupParser;
   protected
     procedure SetUp; override;
     procedure TearDown; override;
@@ -56,6 +58,7 @@ Type
     Procedure StartParsing;
     Procedure ParseDeclarations;
     Procedure ParseModule;
+    procedure ResetParser;
     Procedure CheckHint(AHint : TPasMemberHint);
     Function AssertExpression(Const Msg: String; AExpr : TPasExpr; aKind : TPasExprKind; AClass : TClass) : TPasExpr;
     Function AssertExpression(Const Msg: String; AExpr : TPasExpr; aKind : TPasExprKind; AValue : String) : TPrimitiveExpr;
@@ -74,6 +77,7 @@ Type
     Procedure AssertEquals(Const Msg : String; AExpected, AActual: TProcedureModifiers); overload;
     Procedure AssertEquals(Const Msg : String; AExpected, AActual: TAssignKind); overload;
     Procedure AssertEquals(Const Msg : String; AExpected, AActual: TProcedureMessageType); overload;
+    Procedure AssertEquals(Const Msg : String; AExpected, AActual: TOperatorType); overload;
     Procedure HaveHint(AHint : TPasMemberHint; AHints : TPasMemberHints);
     Property Resolver : TStreamResolver Read FResolver;
     Property Scanner : TPascalScanner Read FScanner;
@@ -148,7 +152,8 @@ begin
   Result:=Module as TPasLibrary;
 end;
 
-procedure TTestParser.SetUp;
+procedure TTestParser.SetupParser;
+
 begin
   FResolver:=TStreamResolver.Create;
   FResolver.OwnsStreams:=True;
@@ -163,7 +168,8 @@ begin
   FIsUnit:=False;
 end;
 
-procedure TTestParser.TearDown;
+procedure TTestParser.CleanupParser;
+
 begin
   if Not Assigned(FModule) then
     FreeAndNil(FDeclarations)
@@ -181,6 +187,25 @@ begin
   FreeAndNil(FResolver);
 end;
 
+procedure TTestParser.ResetParser;
+
+begin
+  CleanupParser;
+  SetupParser;
+end;
+
+procedure TTestParser.SetUp;
+begin
+  Inherited;
+  SetupParser;
+end;
+
+procedure TTestParser.TearDown;
+begin
+  CleanupParser;
+  Inherited;
+end;
+
 procedure TTestParser.StartUnit(AUnitName: String);
 begin
   FIsUnit:=True;
@@ -492,6 +517,13 @@ begin
                    GetEnumName(TypeInfo(TProcedureMessageType),Ord(AActual)));
 end;
 
+procedure TTestParser.AssertEquals(const Msg: String; AExpected,
+  AActual: TOperatorType);
+begin
+  AssertEquals(Msg,GetEnumName(TypeInfo(TOperatorType),Ord(AExpected)),
+                   GetEnumName(TypeInfo(TOperatorType),Ord(AExpected)));
+end;
+
 procedure TTestParser.HaveHint(AHint: TPasMemberHint; AHints: TPasMemberHints);
 begin
   If not (AHint in AHints) then

+ 151 - 87
packages/fcl-passrc/tests/tcprocfunc.pas

@@ -17,6 +17,7 @@ type
     FFunc: TPasFunction;
     FHint: String;
     FProc: TPasProcedure;
+    FOperator:TPasOperator;
     procedure AddDeclaration(const ASource: string; const AHint: String='');
     procedure AssertArg(ProcType: TPasProcedureType; AIndex: Integer;
       AName: String; AAccess: TArgumentAccess; const TypeName: String;
@@ -33,6 +34,7 @@ type
     function ParseProcedure(const ASource: string; const AHint: String=''): TPasProcedure;
     Procedure ParseFunction;
     function ParseFunction(const ASource : String; AResult: string = ''; const AHint: String=''; CC : TCallingConvention = ccDefault): TPasProcedure;
+    Procedure ParseOperator;
   protected
     procedure SetUp; override;
     procedure TearDown; override;
@@ -156,6 +158,8 @@ type
     Procedure TestFunctionCdeclExternalLibNameName;
     Procedure TestProcedureCdeclExternalName;
     Procedure TestFunctionCdeclExternalName;
+    Procedure TestOperatorTokens;
+    procedure TestOperatorNames;
   end;
 
 implementation
@@ -199,7 +203,7 @@ begin
     AssertComment;
 end;
 
-Procedure TTestProcedureFunction.ParseProcedure;
+procedure TTestProcedureFunction.ParseProcedure;
 
 begin
   //  Writeln(source.text);
@@ -230,7 +234,19 @@ begin
   AssertEquals('Correct function result type name',AResult,FuncType.ResultEl.ResultType.Name);
 end;
 
-Procedure TTestProcedureFunction.ParseFunction;
+procedure TTestProcedureFunction.ParseOperator;
+begin
+  //  Writeln(source.text);
+  ParseDeclarations;
+  AssertEquals('One operator definition',1,Declarations.Functions.Count);
+  AssertEquals('First declaration is function declaration.',TPasOperator,TObject(Declarations.Functions[0]).ClassType);
+  FOperator:=TPasOperator(Declarations.Functions[0]);
+  Definition:=FOperator;
+  if (Hint<>'') then
+    CheckHint(TPasMemberHint(Getenumvalue(typeinfo(TPasMemberHint),'h'+Hint)));
+end;
+
+procedure TTestProcedureFunction.ParseFunction;
 begin
   //  Writeln(source.text);
   ParseDeclarations;
@@ -367,13 +383,13 @@ begin
   TestEmptyProcedure;
 end;
 
-Procedure TTestProcedureFunction.TestEmptyFunction;
+procedure TTestProcedureFunction.TestEmptyFunction;
 begin
   ParseFunction('');
   AssertFunc([],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestEmptyFunctionComment;
+procedure TTestProcedureFunction.TestEmptyFunctionComment;
 begin
   AddComment:=True;
   TestEmptyProcedure;
@@ -385,7 +401,7 @@ begin
   AssertProc([],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestEmptyFunctionDeprecated;
+procedure TTestProcedureFunction.TestEmptyFunctionDeprecated;
 begin
   ParseFunction('','deprecated');
   AssertFunc([],ccDefault,0);
@@ -397,7 +413,7 @@ begin
   AssertProc([],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestEmptyFunctionPlatform;
+procedure TTestProcedureFunction.TestEmptyFunctionPlatform;
 begin
   ParseFunction('','platform');
   AssertFunc([],ccDefault,0);
@@ -409,7 +425,7 @@ begin
   AssertProc([],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestEmptyFunctionExperimental;
+procedure TTestProcedureFunction.TestEmptyFunctionExperimental;
 begin
   ParseFunction('','experimental');
   AssertFunc([],ccDefault,0);
@@ -421,7 +437,7 @@ begin
   AssertProc([],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestEmptyFunctionUnimplemented;
+procedure TTestProcedureFunction.TestEmptyFunctionUnimplemented;
 begin
   ParseFunction('','unimplemented');
   AssertFunc([],ccDefault,0);
@@ -437,7 +453,7 @@ begin
   AssertArg(ProcType,0,'B',argDefault,'Integer','');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionOneArg;
+procedure TTestProcedureFunction.TestFunctionOneArg;
 begin
   ParseFunction('(B : Integer)');
   AssertFunc([],ccDefault,1);
@@ -451,7 +467,7 @@ begin
   AssertArg(ProcType,0,'B',argVar,'Integer','');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionOneVarArg;
+procedure TTestProcedureFunction.TestFunctionOneVarArg;
 begin
   ParseFunction('(Var B : Integer)');
   AssertFunc([],ccDefault,1);
@@ -465,7 +481,7 @@ begin
   AssertArg(ProcType,0,'B',argConst,'Integer','');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionOneConstArg;
+procedure TTestProcedureFunction.TestFunctionOneConstArg;
 begin
   ParseFunction('(Const B : Integer)');
   AssertFunc([],ccDefault,1);
@@ -479,7 +495,7 @@ begin
   AssertArg(ProcType,0,'B',argOut,'Integer','');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionOneOutArg;
+procedure TTestProcedureFunction.TestFunctionOneOutArg;
 begin
   ParseFunction('(Out B : Integer)');
   AssertFunc([],ccDefault,1);
@@ -493,7 +509,7 @@ begin
   AssertArg(ProcType,0,'B',argConstRef,'Integer','');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionOneConstRefArg;
+procedure TTestProcedureFunction.TestFunctionOneConstRefArg;
 begin
   ParseFunction('(ConstRef B : Integer)');
   AssertFunc([],ccDefault,1);
@@ -508,7 +524,7 @@ begin
   AssertArg(ProcType,1,'C',argDefault,'Integer','');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionTwoArgs;
+procedure TTestProcedureFunction.TestFunctionTwoArgs;
 begin
   ParseFunction('(B,C : Integer)');
   AssertFunc([],ccDefault,2);
@@ -524,7 +540,7 @@ begin
   AssertArg(ProcType,1,'C',argDefault,'Integer','');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionTwoArgsSeparate;
+procedure TTestProcedureFunction.TestFunctionTwoArgsSeparate;
 begin
   ParseFunction('(B : Integer;C : Integer)');
   AssertFunc([],ccDefault,2);
@@ -539,7 +555,7 @@ begin
   AssertArg(ProcType,0,'B',argDefault,'Integer','1');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionOneArgDefault;
+procedure TTestProcedureFunction.TestFunctionOneArgDefault;
 begin
   ParseFunction('(B : Integer = 1)');
   AssertFunc([],ccDefault,1);
@@ -553,7 +569,7 @@ begin
   AssertArg(ProcType,0,'B',argDefault,'MySet','[1, 2]');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionOneArgDefaultSet;
+procedure TTestProcedureFunction.TestFunctionOneArgDefaultSet;
 begin
   ParseFunction('(B : MySet = [1,2])');
   AssertFunc([],ccDefault,1);
@@ -567,7 +583,7 @@ begin
   AssertArg(ProcType,0,'B',argDefault,'Integer','1 + 2');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionOneArgDefaultExpr;
+procedure TTestProcedureFunction.TestFunctionOneArgDefaultExpr;
 begin
   ParseFunction('(B : Integer = 1 + 2)');
   AssertFunc([],ccDefault,1);
@@ -582,7 +598,7 @@ begin
   AssertArg(ProcType,1,'C',argDefault,'Integer','2');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionTwoArgsDefault;
+procedure TTestProcedureFunction.TestFunctionTwoArgsDefault;
 begin
   ParseFunction('(B : Integer = 1; C : Integer = 2)');
   AssertFunc([],ccDefault,2);
@@ -597,7 +613,7 @@ begin
   AssertArg(ProcType,0,'B',argVar,'','');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionOneUntypedVarArg;
+procedure TTestProcedureFunction.TestFunctionOneUntypedVarArg;
 begin
   ParseFunction('(Var B)');
   AssertFunc([],ccDefault,1);
@@ -612,7 +628,7 @@ begin
   AssertArg(ProcType,1,'C',argVar,'','');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionTwoUntypedVarArgs;
+procedure TTestProcedureFunction.TestFunctionTwoUntypedVarArgs;
 begin
   ParseFunction('(Var B; Var C)');
   AssertFunc([],ccDefault,2);
@@ -627,7 +643,7 @@ begin
   AssertArg(ProcType,0,'B',argConst,'','');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionOneUntypedConstArg;
+procedure TTestProcedureFunction.TestFunctionOneUntypedConstArg;
 begin
   ParseFunction('(Const B)');
   AssertFunc([],ccDefault,1);
@@ -642,7 +658,7 @@ begin
   AssertArg(ProcType,1,'C',argConst,'','');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionTwoUntypedConstArgs;
+procedure TTestProcedureFunction.TestFunctionTwoUntypedConstArgs;
 begin
   ParseFunction('(Const B; Const C)');
   AssertFunc([],ccDefault,2);
@@ -657,7 +673,7 @@ begin
   AssertArrayArg(ProcType,0,'B',argDefault,'Integer');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionOpenArrayArg;
+procedure TTestProcedureFunction.TestFunctionOpenArrayArg;
 begin
   ParseFunction('(B : Array of Integer)');
   AssertFunc([],ccDefault,1);
@@ -672,7 +688,7 @@ begin
   AssertArrayArg(ProcType,1,'C',argDefault,'Integer');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionTwoOpenArrayArgs;
+procedure TTestProcedureFunction.TestFunctionTwoOpenArrayArgs;
 begin
   ParseFunction('(B : Array of Integer;C : Array of Integer)');
   AssertFunc([],ccDefault,2);
@@ -687,7 +703,7 @@ begin
   AssertArrayArg(ProcType,0,'B',argConst,'Integer');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionConstOpenArrayArg;
+procedure TTestProcedureFunction.TestFunctionConstOpenArrayArg;
 begin
   ParseFunction('(Const B : Array of Integer)');
   AssertFunc([],ccDefault,1);
@@ -701,7 +717,7 @@ begin
   AssertArrayArg(ProcType,0,'B',argVar,'Integer');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionVarOpenArrayArg;
+procedure TTestProcedureFunction.TestFunctionVarOpenArrayArg;
 begin
   ParseFunction('(Var B : Array of Integer)');
   AssertFunc([],ccDefault,1);
@@ -715,7 +731,7 @@ begin
   AssertArrayArg(ProcType,0,'B',argDefault,'');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionArrayOfConstArg;
+procedure TTestProcedureFunction.TestFunctionArrayOfConstArg;
 begin
   ParseFunction('(B : Array of Const)');
   AssertFunc([],ccDefault,1);
@@ -729,100 +745,100 @@ begin
   AssertArrayArg(ProcType,0,'B',argConst,'');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionConstArrayOfConstArg;
+procedure TTestProcedureFunction.TestFunctionConstArrayOfConstArg;
 begin
   ParseFunction('(Const B : Array of Const)');
   AssertFunc([],ccDefault,1);
   AssertArrayArg(FuncType,0,'B',argConst,'');
 end;
 
-Procedure TTestProcedureFunction.TestProcedureCdecl;
+procedure TTestProcedureFunction.TestProcedureCdecl;
 begin
   ParseProcedure('; cdecl');
   AssertProc([],ccCdecl,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionCdecl;
+procedure TTestProcedureFunction.TestFunctionCdecl;
 begin
   ParseFunction('','','',ccCdecl);
   AssertFunc([],ccCdecl,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureCdeclDeprecated;
+procedure TTestProcedureFunction.TestProcedureCdeclDeprecated;
 begin
   ParseProcedure('; cdecl;','deprecated');
   AssertProc([],ccCdecl,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionCdeclDeprecated;
+procedure TTestProcedureFunction.TestFunctionCdeclDeprecated;
 begin
   ParseFunction('','','deprecated',ccCdecl);
   AssertFunc([],ccCdecl,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureSafeCall;
+procedure TTestProcedureFunction.TestProcedureSafeCall;
 begin
   ParseProcedure('; safecall;','');
   AssertProc([],ccSafeCall,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionSafeCall;
+procedure TTestProcedureFunction.TestFunctionSafeCall;
 begin
   ParseFunction('','','',ccSafecall);
   AssertFunc([],ccSafecall,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedurePascal;
+procedure TTestProcedureFunction.TestProcedurePascal;
 begin
   ParseProcedure('; pascal;','');
   AssertProc([],ccPascal,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionPascal;
+procedure TTestProcedureFunction.TestFunctionPascal;
 begin
   ParseFunction('','','',ccPascal);
   AssertFunc([],ccPascal,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureStdCall;
+procedure TTestProcedureFunction.TestProcedureStdCall;
 begin
   ParseProcedure('; stdcall;','');
   AssertProc([],ccstdcall,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionStdCall;
+procedure TTestProcedureFunction.TestFunctionStdCall;
 begin
   ParseFunction('','','',ccStdCall);
   AssertFunc([],ccStdCall,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureOldFPCCall;
+procedure TTestProcedureFunction.TestProcedureOldFPCCall;
 begin
   ParseProcedure('; oldfpccall;','');
   AssertProc([],ccoldfpccall,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionOldFPCCall;
+procedure TTestProcedureFunction.TestFunctionOldFPCCall;
 begin
   ParseFunction('','','',ccOldFPCCall);
   AssertFunc([],ccOldFPCCall,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedurePublic;
+procedure TTestProcedureFunction.TestProcedurePublic;
 begin
   ParseProcedure('; public name ''myfunc'';','');
   AssertProc([pmPublic],ccDefault,0);
   AssertExpression('Public name',Proc.PublicName,pekString,'''myfunc''');
 end;
 
-Procedure TTestProcedureFunction.TestProcedurePublicIdent;
+procedure TTestProcedureFunction.TestProcedurePublicIdent;
 begin
   ParseProcedure('; public name exportname;','');
   AssertProc([pmPublic],ccDefault,0);
   AssertExpression('Public name',Proc.PublicName,pekIdent,'exportname');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionPublic;
+procedure TTestProcedureFunction.TestFunctionPublic;
 begin
   AddDeclaration('function A : Integer; public name exportname');
   ParseFunction;
@@ -830,14 +846,14 @@ begin
   AssertExpression('Public name',Func.PublicName,pekIdent,'exportname');
 end;
 
-Procedure TTestProcedureFunction.TestProcedureCdeclPublic;
+procedure TTestProcedureFunction.TestProcedureCdeclPublic;
 begin
   ParseProcedure('; cdecl; public name exportname;','');
   AssertProc([pmPublic],ccCDecl,0);
   AssertExpression('Public name',Proc.PublicName,pekIdent,'exportname');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionCdeclPublic;
+procedure TTestProcedureFunction.TestFunctionCdeclPublic;
 begin
   AddDeclaration('function A : Integer; cdecl; public name exportname');
   ParseFunction;
@@ -845,58 +861,58 @@ begin
   AssertExpression('Public name',Func.PublicName,pekIdent,'exportname');
 end;
 
-Procedure TTestProcedureFunction.TestProcedureOverload;
+procedure TTestProcedureFunction.TestProcedureOverload;
 begin
   ParseProcedure('; overload;','');
   AssertProc([pmOverload],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionOverload;
+procedure TTestProcedureFunction.TestFunctionOverload;
 begin
   AddDeclaration('function A : Integer; overload');
   ParseFunction;
   AssertFunc([pmOverload],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureVarargs;
+procedure TTestProcedureFunction.TestProcedureVarargs;
 begin
   ParseProcedure('; varargs;','');
   AssertProc([pmVarArgs],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionVarArgs;
+procedure TTestProcedureFunction.TestFunctionVarArgs;
 begin
   AddDeclaration('function A : Integer; varargs');
   ParseFunction;
   AssertFunc([pmVarArgs],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureCDeclVarargs;
+procedure TTestProcedureFunction.TestProcedureCDeclVarargs;
 begin
   ParseProcedure(';cdecl; varargs;','');
   AssertProc([pmVarArgs],ccCDecl,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionCDeclVarArgs;
+procedure TTestProcedureFunction.TestFunctionCDeclVarArgs;
 begin
   AddDeclaration('function A : Integer; cdecl; varargs');
   ParseFunction;
   AssertFunc([pmVarArgs],ccCdecl,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureForwardInterface;
+procedure TTestProcedureFunction.TestProcedureForwardInterface;
 begin
   AddDeclaration('procedure A; forward;');
   AssertException(EParserError,@ParseProcedure);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionForwardInterface;
+procedure TTestProcedureFunction.TestFunctionForwardInterface;
 begin
   AddDeclaration('function A : integer; forward;');
   AssertException(EParserError,@ParseFunction);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureForward;
+procedure TTestProcedureFunction.TestProcedureForward;
 begin
   UseImplementation:=True;
   AddDeclaration('procedure A; forward;');
@@ -904,7 +920,7 @@ begin
   AssertProc([pmforward],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionForward;
+procedure TTestProcedureFunction.TestFunctionForward;
 begin
   UseImplementation:=True;
   AddDeclaration('function A : integer; forward;');
@@ -912,7 +928,7 @@ begin
   AssertFunc([pmforward],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureCdeclForward;
+procedure TTestProcedureFunction.TestProcedureCdeclForward;
 begin
   UseImplementation:=True;
   AddDeclaration('procedure A; cdecl; forward;');
@@ -920,7 +936,7 @@ begin
   AssertProc([pmforward],ccCDecl,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionCDeclForward;
+procedure TTestProcedureFunction.TestFunctionCDeclForward;
 begin
   UseImplementation:=True;
   AddDeclaration('function A : integer; cdecl; forward;');
@@ -928,92 +944,92 @@ begin
   AssertFunc([pmforward],ccCDecl,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureCompilerProc;
+procedure TTestProcedureFunction.TestProcedureCompilerProc;
 begin
   ParseProcedure(';compilerproc;','');
   AssertProc([pmCompilerProc],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionCompilerProc;
+procedure TTestProcedureFunction.TestFunctionCompilerProc;
 begin
   AddDeclaration('function A : Integer; compilerproc');
   ParseFunction;
   AssertFunc([pmCompilerProc],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureCDeclCompilerProc;
+procedure TTestProcedureFunction.TestProcedureCDeclCompilerProc;
 begin
   ParseProcedure(';cdecl;compilerproc;','');
   AssertProc([pmCompilerProc],ccCDecl,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionCDeclCompilerProc;
+procedure TTestProcedureFunction.TestFunctionCDeclCompilerProc;
 begin
   AddDeclaration('function A : Integer; cdecl; compilerproc');
   ParseFunction;
   AssertFunc([pmCompilerProc],ccCDecl,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureAssembler;
+procedure TTestProcedureFunction.TestProcedureAssembler;
 begin
   ParseProcedure(';assembler;','');
   AssertProc([pmAssembler],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionAssembler;
+procedure TTestProcedureFunction.TestFunctionAssembler;
 begin
   AddDeclaration('function A : Integer; assembler');
   ParseFunction;
   AssertFunc([pmAssembler],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureCDeclAssembler;
+procedure TTestProcedureFunction.TestProcedureCDeclAssembler;
 begin
   ParseProcedure(';cdecl;assembler;','');
   AssertProc([pmAssembler],ccCDecl,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionCDeclAssembler;
+procedure TTestProcedureFunction.TestFunctionCDeclAssembler;
 begin
   AddDeclaration('function A : Integer; cdecl; assembler');
   ParseFunction;
   AssertFunc([pmAssembler],ccCDecl,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureExport;
+procedure TTestProcedureFunction.TestProcedureExport;
 begin
   ParseProcedure(';export;','');
   AssertProc([pmExport],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionExport;
+procedure TTestProcedureFunction.TestFunctionExport;
 begin
   AddDeclaration('function A : Integer; export');
   ParseFunction;
   AssertFunc([pmExport],ccDefault,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureCDeclExport;
+procedure TTestProcedureFunction.TestProcedureCDeclExport;
 begin
   ParseProcedure('cdecl;export;','');
   AssertProc([pmExport],ccCDecl,0);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionCDeclExport;
+procedure TTestProcedureFunction.TestFunctionCDeclExport;
 begin
   AddDeclaration('function A : Integer; cdecl; export');
   ParseFunction;
   AssertFunc([pmExport],ccCDecl,0);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureExternal;
+procedure TTestProcedureFunction.TestProcedureExternal;
 begin
   ParseProcedure(';external','');
   AssertProc([pmExternal],ccDefault,0);
   AssertNull('No Library name expression',Proc.LibraryExpr);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionExternal;
+procedure TTestProcedureFunction.TestFunctionExternal;
 begin
   AddDeclaration('function A : Integer; external');
   ParseFunction;
@@ -1021,14 +1037,14 @@ begin
   AssertNull('No Library name expression',Func.LibraryExpr);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureExternalLibName;
+procedure TTestProcedureFunction.TestProcedureExternalLibName;
 begin
   ParseProcedure(';external ''libname''','');
   AssertProc([pmExternal],ccDefault,0);
   AssertExpression('Library name expression',Proc.LibraryExpr,pekString,'''libname''');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionExternalLibName;
+procedure TTestProcedureFunction.TestFunctionExternalLibName;
 begin
   AddDeclaration('function A : Integer; external ''libname''');
   ParseFunction;
@@ -1036,7 +1052,7 @@ begin
   AssertExpression('Library name expression',Func.LibraryExpr,pekString,'''libname''');
 end;
 
-Procedure TTestProcedureFunction.TestProcedureExternalLibNameName;
+procedure TTestProcedureFunction.TestProcedureExternalLibNameName;
 begin
   ParseProcedure(';external ''libname'' name ''symbolname''','');
   AssertProc([pmExternal],ccDefault,0);
@@ -1044,7 +1060,7 @@ begin
   AssertExpression('Library symbol expression',Proc.LibrarySymbolName,pekString,'''symbolname''');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionExternalLibNameName;
+procedure TTestProcedureFunction.TestFunctionExternalLibNameName;
 begin
   AddDeclaration('function A : Integer; external ''libname'' name ''symbolname''');
   ParseFunction;
@@ -1053,7 +1069,7 @@ begin
   AssertExpression('Library symbol expression',Func.LibrarySymbolName,pekString,'''symbolname''');
 end;
 
-Procedure TTestProcedureFunction.TestProcedureExternalName;
+procedure TTestProcedureFunction.TestProcedureExternalName;
 begin
   ParseProcedure(';external name ''symbolname''','');
   AssertProc([pmExternal],ccDefault,0);
@@ -1061,7 +1077,7 @@ begin
   AssertExpression('Library symbol expression',Proc.LibrarySymbolName,pekString,'''symbolname''');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionExternalName;
+procedure TTestProcedureFunction.TestFunctionExternalName;
 begin
   AddDeclaration('function A : Integer; external name ''symbolname''');
   ParseFunction;
@@ -1070,14 +1086,14 @@ begin
   AssertExpression('Library symbol expression',Func.LibrarySymbolName,pekString,'''symbolname''');
 end;
 
-Procedure TTestProcedureFunction.TestProcedureCdeclExternal;
+procedure TTestProcedureFunction.TestProcedureCdeclExternal;
 begin
   ParseProcedure('; cdecl; external','');
   AssertProc([pmExternal],ccCdecl,0);
   AssertNull('No Library name expression',Proc.LibraryExpr);
 end;
 
-Procedure TTestProcedureFunction.TestFunctionCdeclExternal;
+procedure TTestProcedureFunction.TestFunctionCdeclExternal;
 begin
   AddDeclaration('function A : Integer; cdecl; external');
   ParseFunction;
@@ -1085,14 +1101,14 @@ begin
   AssertNull('No Library name expression',Func.LibraryExpr);
 end;
 
-Procedure TTestProcedureFunction.TestProcedureCdeclExternalLibName;
+procedure TTestProcedureFunction.TestProcedureCdeclExternalLibName;
 begin
   ParseProcedure('; cdecl; external ''libname''','');
   AssertProc([pmExternal],ccCdecl,0);
   AssertExpression('Library name expression',Proc.LibraryExpr,pekString,'''libname''');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionCdeclExternalLibName;
+procedure TTestProcedureFunction.TestFunctionCdeclExternalLibName;
 begin
   AddDeclaration('function A : Integer; cdecl; external ''libname''');
   ParseFunction;
@@ -1100,7 +1116,7 @@ begin
   AssertExpression('Library name expression',Func.LibraryExpr,pekString,'''libname''');
 end;
 
-Procedure TTestProcedureFunction.TestProcedureCdeclExternalLibNameName;
+procedure TTestProcedureFunction.TestProcedureCdeclExternalLibNameName;
 begin
   ParseProcedure('; cdecl; external ''libname'' name ''symbolname''','');
   AssertProc([pmExternal],ccCdecl,0);
@@ -1108,7 +1124,7 @@ begin
   AssertExpression('Library symbol expression',Proc.LibrarySymbolName,pekString,'''symbolname''');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionCdeclExternalLibNameName;
+procedure TTestProcedureFunction.TestFunctionCdeclExternalLibNameName;
 begin
   AddDeclaration('function A : Integer; cdecl; external ''libname'' name ''symbolname''');
   ParseFunction;
@@ -1117,7 +1133,7 @@ begin
   AssertExpression('Library symbol expression',Func.LibrarySymbolName,pekString,'''symbolname''');
 end;
 
-Procedure TTestProcedureFunction.TestProcedureCdeclExternalName;
+procedure TTestProcedureFunction.TestProcedureCdeclExternalName;
 begin
   ParseProcedure('; cdecl; external name ''symbolname''','');
   AssertProc([pmExternal],ccCdecl,0);
@@ -1125,7 +1141,7 @@ begin
   AssertExpression('Library symbol expression',Proc.LibrarySymbolName,pekString,'''symbolname''');
 end;
 
-Procedure TTestProcedureFunction.TestFunctionCdeclExternalName;
+procedure TTestProcedureFunction.TestFunctionCdeclExternalName;
 begin
   AddDeclaration('function A : Integer; cdecl; external name ''symbolname''');
   ParseFunction;
@@ -1134,6 +1150,54 @@ begin
   AssertExpression('Library symbol expression',Func.LibrarySymbolName,pekString,'''symbolname''');
 end;
 
+procedure TTestProcedureFunction.TestOperatorTokens;
+
+Var
+  t : TOperatorType;
+
+begin
+  For t:=otMul to High(TOperatorType) do
+    // No way to distinguish between logical/bitwise or/and/Xor
+    if not (t in [otBitwiseOr,otBitwiseAnd,otBitwiseXor]) then
+      begin
+      ResetParser;
+      if t in UnaryOperators then
+        AddDeclaration(Format('operator %s (a: Integer) : te',[OperatorTokens[t]]))
+      else
+        AddDeclaration(Format('operator %s (a: Integer; b: integer) : te',[OperatorTokens[t]]));
+      ParseOperator;
+      AssertEquals('Token based',Not (T in [otInc,otDec]),FOperator.TokenBased);
+      AssertEquals('Correct operator type',T,FOperator.OperatorType);
+      if t in UnaryOperators then
+        AssertEquals('Correct operator name',format('%s(Integer):te',[OperatorNames[t]]),FOperator.Name)
+      else
+        AssertEquals('Correct operator name',format('%s(Integer,Integer):te',[OperatorNames[t]]),FOperator.Name);
+      end;
+end;
+
+procedure TTestProcedureFunction.TestOperatorNames;
+
+Var
+  t : TOperatorType;
+
+begin
+  For t:=Succ(otUnknown) to High(TOperatorType) do
+      begin
+      ResetParser;
+      if t in UnaryOperators then
+        AddDeclaration(Format('operator %s (a: Integer) : te',[OperatorNames[t]]))
+      else
+        AddDeclaration(Format('operator %s (a: Integer; b: integer) : te',[OperatorNames[t]]));
+      ParseOperator;
+      AssertEquals('Token based',False,FOperator.TokenBased);
+      AssertEquals('Correct operator type',T,FOperator.OperatorType);
+      if t in UnaryOperators then
+        AssertEquals('Correct operator name',format('%s(Integer):te',[OperatorNames[t]]),FOperator.Name)
+      else
+        AssertEquals('Correct operator name',format('%s(Integer,Integer):te',[OperatorNames[t]]),FOperator.Name);
+      end;
+end;
+
 procedure TTestProcedureFunction.SetUp;
 begin
    Inherited;
@@ -1144,7 +1208,7 @@ begin
    Inherited;
 end;
 
-Procedure TTestProcedureFunction.AssertComment;
+procedure TTestProcedureFunction.AssertComment;
 begin
   AssertEquals('Correct comment',' A comment'+sLineBreak,FProc.DocComment);
 end;

+ 52 - 7
packages/fcl-passrc/tests/tctypeparser.pas

@@ -169,7 +169,8 @@ type
     procedure AssertVariantSelector(AName, AType: string);
     procedure AssertField1(Hints: TPasMemberHints);
     procedure AssertField2(Hints: TPasMemberHints);
-    procedure AssertMethod2(Hints: TPasMemberHints);
+    procedure AssertMethod2(Hints: TPasMemberHints; isClass : Boolean = False);
+    procedure AssertOperatorMethod2(Hints: TPasMemberHints; isClass : Boolean = False);
     procedure AssertVariant1(Hints: TPasMemberHints);
     procedure AssertVariant1(Hints: TPasMemberHints; VariantLabels : Array of string);
     procedure AssertVariant2(Hints: TPasMemberHints);
@@ -245,6 +246,7 @@ type
     Procedure TestFieldAnd2Methods;
     Procedure TestFieldAndProperty;
     Procedure TestFieldAndClassMethod;
+    Procedure TestFieldAndClassOperator;
     Procedure TestNested;
     Procedure TestNestedDeprecated;
     Procedure TestNestedPlatform;
@@ -731,15 +733,20 @@ end;
 Function TTestProcedureTypeParser.ParseType(ASource: String;
   CC: TCallingConvention; ATypeClass: TClass; Const AHint: String
   ): TPasProcedureType;
+
+Var
+  CCS : String;
+
 begin
   if CC=ccdefault then
     Result:=TPasProcedureType(ParseType(ASource,ATypeClass,AHint))
   else
     begin
+    CCS:=cCallingConventions[CC];
     if (AHint<>'') then
-      Result:=TPasProcedureType(ParseType(ASource+';' +cCallingConventions[CC]+';',ATypeClass,AHint))
+      Result:=TPasProcedureType(ParseType(ASource+';' +CCS+';',ATypeClass,AHint))
     else
-      Result:=TPasProcedureType(ParseType(ASource+';' +cCallingConventions[CC],ATypeClass,AHint));
+      Result:=TPasProcedureType(ParseType(ASource+';' +CCS,ATypeClass,AHint));
     end;
   FProc:=Result;
   AssertEquals('Correct calling convention for procedural type',cc,Result.CallingConvention);
@@ -1468,18 +1475,37 @@ begin
   AssertTrue('Field 2 hints match',Field2.Hints=Hints)
 end;
 
-procedure TTestRecordTypeParser.AssertMethod2(Hints: TPasMemberHints);
+procedure TTestRecordTypeParser.AssertMethod2(Hints: TPasMemberHints; isClass : Boolean = False);
 
 Var
   P : TPasProcedure;
 
 begin
-  AssertEquals('Member 2 type',TPasProcedure,TObject(TheRecord.Members[1]).ClassType);
+  if IsClass then
+    AssertEquals('Member 2 type',TPasClassProcedure,TObject(TheRecord.Members[1]).ClassType)
+  else
+    AssertEquals('Member 2 type',TPasProcedure,TObject(TheRecord.Members[1]).ClassType);
   P:=TPasProcedure(TheRecord.Members[1]);
   AssertEquals('Method name','dosomething2',P.Name);
   AssertTrue('Method hints match',P.Hints=Hints)
 end;
 
+procedure TTestRecordTypeParser.AssertOperatorMethod2(Hints: TPasMemberHints;
+  isClass: Boolean);
+Var
+  P : TPasOperator;
+
+begin
+  if IsClass then
+    AssertEquals('Member 2 type',TPasClassOperator,TObject(TheRecord.Members[1]).ClassType)
+  else
+    AssertEquals('Member 2 type',TPasOperator,TObject(TheRecord.Members[1]).ClassType);
+  P:=TPasOperator(TheRecord.Members[1]);
+  AssertEquals('Method name','assign(ta,Cardinal):Boolean',P.Name);
+
+  AssertTrue('Method hints match',P.Hints=Hints)
+end;
+
 procedure TTestRecordTypeParser.AssertOneIntegerField(Hints : TPasMemberHints);
 
 begin
@@ -1883,11 +1909,30 @@ Var
   P : TPasFunction;
 
 begin
+  Parser.Options:=[po_delphi];
   TestFields(['x : integer;','class procedure dosomething2;','function dosomething3 : Integer;'],'',False);
   AssertEquals('Member count',3,TheRecord.Members.Count);
   AssertField1([]);
-  AssertMethod2([]);
-  AssertEquals('Class procedure',TPasProcedure,TObject(TheRecord.Members[1]).ClassType);
+  AssertMethod2([],True);
+  AssertEquals('Class procedure',TPasClassProcedure,TObject(TheRecord.Members[1]).ClassType);
+  AssertEquals('Member 3 type',TPasFunction,TObject(TheRecord.Members[2]).ClassType);
+  P:=TPasFunction(TheRecord.Members[2]);
+  AssertEquals('Method 2 name','dosomething3',P.Name);
+  AssertTrue('Method 2 hints match',[]=P.Hints);
+  // Standard type
+  AssertEquals('Method 2 result type','Integer', P.FuncType.ResultEl.ResultType.Name);
+end;
+
+procedure TTestRecordTypeParser.TestFieldAndClassOperator;
+
+Var
+  P : TPasFunction;
+
+begin
+  TestFields(['x : integer;','class operator assign(a : ta; b : Cardinal) : boolean;','function dosomething3 : Integer;'],'',False);
+  AssertEquals('Member count',3,TheRecord.Members.Count);
+  AssertField1([]);
+  AssertOperatorMethod2([],True);
   AssertEquals('Member 3 type',TPasFunction,TObject(TheRecord.Members[2]).ClassType);
   P:=TPasFunction(TheRecord.Members[2]);
   AssertEquals('Method 2 name','dosomething3',P.Name);

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

@@ -30,7 +30,7 @@
     <RunParams>
       <local>
         <FormatVersion Value="1"/>
-        <CommandLineParams Value="--suite=TTestStatementParser.TestAsm"/>
+        <CommandLineParams Value="--suite=TTestProcedureFunction.TestOperatorTokens"/>
       </local>
     </RunParams>
     <RequiredPackages Count="1">
@@ -46,22 +46,18 @@
       <Unit1>
         <Filename Value="tcscanner.pas"/>
         <IsPartOfProject Value="True"/>
-        <UnitName Value="tcscanner"/>
       </Unit1>
       <Unit2>
         <Filename Value="tctypeparser.pas"/>
         <IsPartOfProject Value="True"/>
-        <UnitName Value="tctypeparser"/>
       </Unit2>
       <Unit3>
         <Filename Value="tcstatements.pas"/>
         <IsPartOfProject Value="True"/>
-        <UnitName Value="tcstatements"/>
       </Unit3>
       <Unit4>
         <Filename Value="tcbaseparser.pas"/>
         <IsPartOfProject Value="True"/>
-        <UnitName Value="tcbaseparser"/>
       </Unit4>
       <Unit5>
         <Filename Value="tcmoduleparser.pas"/>
@@ -74,7 +70,6 @@
       <Unit7>
         <Filename Value="tcvarparser.pas"/>
         <IsPartOfProject Value="True"/>
-        <UnitName Value="tcvarparser"/>
       </Unit7>
       <Unit8>
         <Filename Value="tcclasstype.pas"/>
@@ -83,7 +78,6 @@
       <Unit9>
         <Filename Value="tcexprparser.pas"/>
         <IsPartOfProject Value="True"/>
-        <UnitName Value="tcexprparser"/>
       </Unit9>
       <Unit10>
         <Filename Value="tcprocfunc.pas"/>