Browse Source

* Expression parsing tests, nested types

git-svn-id: trunk@22144 -
michael 13 years ago
parent
commit
649bbae1c3

+ 1 - 0
.gitattributes

@@ -2328,6 +2328,7 @@ packages/fcl-passrc/src/pscanner.pp svneol=native#text/plain
 packages/fcl-passrc/src/readme.txt svneol=native#text/plain
 packages/fcl-passrc/src/readme.txt svneol=native#text/plain
 packages/fcl-passrc/tests/tcbaseparser.pas svneol=native#text/plain
 packages/fcl-passrc/tests/tcbaseparser.pas svneol=native#text/plain
 packages/fcl-passrc/tests/tcclasstype.pas svneol=native#text/plain
 packages/fcl-passrc/tests/tcclasstype.pas svneol=native#text/plain
+packages/fcl-passrc/tests/tcexprparser.pas svneol=native#text/plain
 packages/fcl-passrc/tests/tcmoduleparser.pas svneol=native#text/plain
 packages/fcl-passrc/tests/tcmoduleparser.pas svneol=native#text/plain
 packages/fcl-passrc/tests/tconstparser.pas svneol=native#text/plain
 packages/fcl-passrc/tests/tconstparser.pas svneol=native#text/plain
 packages/fcl-passrc/tests/tcscanner.pas svneol=native#text/plain
 packages/fcl-passrc/tests/tcscanner.pas svneol=native#text/plain

+ 9 - 6
packages/fcl-passrc/src/pastree.pp

@@ -192,6 +192,7 @@ type
   { TInheritedExpr }
   { TInheritedExpr }
 
 
   TInheritedExpr = class(TPasExpr)
   TInheritedExpr = class(TPasExpr)
+  Public
     constructor Create(AParent : TPasElement); overload;
     constructor Create(AParent : TPasElement); overload;
     function GetDeclaration(full : Boolean) : string; override;
     function GetDeclaration(full : Boolean) : string; override;
   end;
   end;
@@ -492,7 +493,7 @@ type
     Members: TFPList;     // array of TPasVariable elements
     Members: TFPList;     // array of TPasVariable elements
     VariantName: string;
     VariantName: string;
     VariantType: TPasType;
     VariantType: TPasType;
-    Variants: TFPList;  // array of TPasVariant elements, may be nil!
+    Variants: TFPList;	// array of TPasVariant elements, may be nil!
     Function IsPacked: Boolean;
     Function IsPacked: Boolean;
     Function IsBitPacked : Boolean;
     Function IsBitPacked : Boolean;
   end;
   end;
@@ -616,7 +617,7 @@ type
   end;
   end;
 
 
   { TPasVariable }
   { TPasVariable }
-  TVariableModifier = (vmCVar, vmExternal, vmPublic, vmExport);
+  TVariableModifier = (vmCVar, vmExternal, vmPublic, vmExport, vmClass);
   TVariableModifiers = set of TVariableModifier;
   TVariableModifiers = set of TVariableModifier;
 
 
   TPasVariable = class(TPasElement)
   TPasVariable = class(TPasElement)
@@ -692,7 +693,7 @@ type
 
 
   TProcedureModifier = (pmVirtual, pmDynamic, pmAbstract, pmOverride,
   TProcedureModifier = (pmVirtual, pmDynamic, pmAbstract, pmOverride,
                         pmExported, pmOverload, pmMessage, pmReintroduce,
                         pmExported, pmOverload, pmMessage, pmReintroduce,
-                        pmStatic,pmInline,pmAssembler,pmVarargs,
+                        pmStatic,pmInline,pmAssembler,pmVarargs, pmPublic,
                         pmCompilerProc,pmExternal,pmForward);
                         pmCompilerProc,pmExternal,pmForward);
   TProcedureModifiers = Set of TProcedureModifier;
   TProcedureModifiers = Set of TProcedureModifier;
   TProcedureMessageType = (pmtInteger,pmtString);
   TProcedureMessageType = (pmtInteger,pmtString);
@@ -1023,11 +1024,12 @@ type
   end;
   end;
 
 
   { TPasImplAssign }
   { TPasImplAssign }
-
+  TAssignKind = (akDefault,akAdd,akMinus,akMul,akDivision);
   TPasImplAssign = class (TPasImplStatement)
   TPasImplAssign = class (TPasImplStatement)
   public
   public
     left  : TPasExpr;
     left  : TPasExpr;
     right : TPasExpr;
     right : TPasExpr;
+    Kind : TAssignKind;
     Destructor Destroy; override;
     Destructor Destroy; override;
   end;
   end;
 
 
@@ -1136,6 +1138,7 @@ const
   cCallingConventions : array[TCallingConvention] of string =
   cCallingConventions : array[TCallingConvention] of string =
       ( '', 'Register','Pascal','CDecl','StdCall','OldFPCCall','SafeCall');
       ( '', 'Register','Pascal','CDecl','StdCall','OldFPCCall','SafeCall');
 
 
+
 implementation
 implementation
 
 
 uses SysUtils;
 uses SysUtils;
@@ -1203,7 +1206,6 @@ begin
     Result:=Result+' name '+ExportName.GetDeclaration(Full)
     Result:=Result+' name '+ExportName.GetDeclaration(Full)
   else if (ExportIndex<>Nil) then
   else if (ExportIndex<>Nil) then
     Result:=Result+' index '+ExportIndex.GetDeclaration(Full);
     Result:=Result+' index '+ExportIndex.GetDeclaration(Full);
-
 end;
 end;
 
 
 { TPasUnresolvedUnitRef }
 { TPasUnresolvedUnitRef }
@@ -3225,7 +3227,7 @@ end;
 
 
 { TInheritedExpr }
 { TInheritedExpr }
 
 
-Function TInheritedExpr.GetDeclaration(Full :Boolean):AnsiString;
+function TInheritedExpr.GetDeclaration(full: Boolean): string;
 begin
 begin
   Result:='Inherited';
   Result:='Inherited';
 end;
 end;
@@ -3291,6 +3293,7 @@ begin
   inherited Create(AParent,pekInherited, eopNone);
   inherited Create(AParent,pekInherited, eopNone);
 end;
 end;
 
 
+
 { TSelfExpr }
 { TSelfExpr }
 
 
 constructor TSelfExpr.Create(AParent : TPasElement);
 constructor TSelfExpr.Create(AParent : TPasElement);

+ 85 - 51
packages/fcl-passrc/src/pparser.pp

@@ -135,6 +135,7 @@ type
     function GetVariableModifiers(Out VarMods : TVariableModifiers; Out Libname,ExportName : string): string;
     function GetVariableModifiers(Out VarMods : TVariableModifiers; Out Libname,ExportName : string): string;
     function GetVariableValueAndLocation(Parent : TPasElement; Out Value : TPasExpr; Out Location: String): Boolean;
     function GetVariableValueAndLocation(Parent : TPasElement; Out Value : TPasExpr; Out Location: String): Boolean;
     procedure HandleProcedureModifier(Parent: TPasElement; pm : TProcedureModifier);
     procedure HandleProcedureModifier(Parent: TPasElement; pm : TProcedureModifier);
+    procedure ParseClassLocalTypes(AType: TPasClassType; AVisibility: TPasMemberVisibility);
     procedure ParseVarList(Parent: TPasElement; VarList: TFPList; AVisibility: TPasMemberVisibility; Full: Boolean);
     procedure ParseVarList(Parent: TPasElement; VarList: TFPList; AVisibility: TPasMemberVisibility; Full: Boolean);
   protected
   protected
     function LogEvent(E : TPParserLogEvent) : Boolean; inline;
     function LogEvent(E : TPParserLogEvent) : Boolean; inline;
@@ -144,7 +145,7 @@ type
     procedure ParseRecordFieldList(ARec: TPasRecordType; AEndToken: TToken);
     procedure ParseRecordFieldList(ARec: TPasRecordType; AEndToken: TToken);
     procedure ParseRecordVariantParts(ARec: TPasRecordType; AEndToken: TToken);
     procedure ParseRecordVariantParts(ARec: TPasRecordType; AEndToken: TToken);
     function GetProcedureClass(ProcType : TProcType): TPTreeElement;
     function GetProcedureClass(ProcType : TProcType): TPTreeElement;
-    procedure ParseClassFields(AType: TPasClassType; const AVisibility: TPasMemberVisibility);
+    procedure ParseClassFields(AType: TPasClassType; const AVisibility: TPasMemberVisibility; IsClassField : Boolean);
     procedure ParseClassMembers(AType: TPasClassType);
     procedure ParseClassMembers(AType: TPasClassType);
     procedure ProcessMethod(AType: TPasClassType; IsClass : Boolean; AVisibility : TPasMemberVisibility);
     procedure ProcessMethod(AType: TPasClassType; IsClass : Boolean; AVisibility : TPasMemberVisibility);
     procedure ReadGenericArguments(List : TFPList;Parent : TPasElement);
     procedure ReadGenericArguments(List : TFPList;Parent : TPasElement);
@@ -160,7 +161,7 @@ type
     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;
-    Function TokenIsProcedureModifier(S : String; Out Pm : TProcedureModifier) : Boolean; virtual;
+    Function TokenIsProcedureModifier(Parent : TPasElement; S : String; Out Pm : TProcedureModifier) : Boolean; virtual;
     Function CheckHint(Element : TPasElement; ExpectSemiColon : Boolean) : TPasMemberHints;
     Function CheckHint(Element : TPasElement; ExpectSemiColon : Boolean) : TPasMemberHints;
     function ParseParams(AParent : TPasElement;paramskind: TPasExprKind): TParamsExpr;
     function ParseParams(AParent : TPasElement;paramskind: TPasExprKind): TParamsExpr;
     function ParseExpIdent(AParent : TPasElement): TPasExpr;
     function ParseExpIdent(AParent : TPasElement): TPasExpr;
@@ -308,7 +309,7 @@ Const
   ModifierNames : Array[TProcedureModifier] of string
   ModifierNames : Array[TProcedureModifier] of string
                 = ('virtual', 'dynamic','abstract', 'override',
                 = ('virtual', 'dynamic','abstract', 'override',
                    'exported', 'overload', 'message', 'reintroduce',
                    'exported', 'overload', 'message', 'reintroduce',
-                   'static','inline','assembler','varargs',
+                   'static','inline','assembler','varargs', 'public',
                    'compilerproc','external','forward');
                    'compilerproc','external','forward');
 
 
 Var
 Var
@@ -368,19 +369,16 @@ var
       case s[2] of
       case s[2] of
         'd': // -d define
         'd': // -d define
           Scanner.AddDefine(UpperCase(Copy(s, 3, Length(s))));
           Scanner.AddDefine(UpperCase(Copy(s, 3, Length(s))));
-        'S': // -d define
-          case S[3] of
-            'c' :Scanner.Options:=Scanner.Options+[c_assignments];
-          end;
         'F': // -F
         'F': // -F
           if (length(s)>2) and (s[3] = 'i') then // -Fi include path
           if (length(s)>2) and (s[3] = 'i') then // -Fi include path
             FileResolver.AddIncludePath(Copy(s, 4, Length(s)));
             FileResolver.AddIncludePath(Copy(s, 4, Length(s)));
         'I': // -I include path
         'I': // -I include path
           FileResolver.AddIncludePath(Copy(s, 3, Length(s)));
           FileResolver.AddIncludePath(Copy(s, 3, Length(s)));
         'S': // -S mode
         'S': // -S mode
-          if  (length(s)>2) and (s[3]='d') then
-            begin // -Sd mode delphi
-              Parser.Options:=Parser.Options+[po_delphi];
+          if  (length(s)>2) then
+            case S[3] of
+              'c' : Scanner.Options:=Scanner.Options+[po_cassignments];
+              'd' : Parser.Options:=Parser.Options+[po_delphi];
             end;
             end;
       end;
       end;
     end else
     end else
@@ -658,9 +656,15 @@ begin
   Result:=IsCallingConvention(S,CC);
   Result:=IsCallingConvention(S,CC);
 end;
 end;
 
 
-function TPasParser.TokenIsProcedureModifier(S: String; out Pm: TProcedureModifier): Boolean;
+function TPasParser.TokenIsProcedureModifier(Parent : TPasElement; S: String; out Pm: TProcedureModifier): Boolean;
 begin
 begin
   Result:=IsModifier(S,PM);
   Result:=IsModifier(S,PM);
+  if result and (pm=pmPublic)then
+    begin
+    While (Parent<>Nil) and Not (Parent is TPasClassType) do
+     Parent:=Parent.Parent;
+    Result:=Not Assigned(Parent);
+    end;
 end;
 end;
 
 
 
 
@@ -1142,11 +1146,13 @@ begin
     tkfalse, tktrue:    x:=TBoolConstExpr.Create(Aparent,pekBoolConst, CurToken=tktrue);
     tkfalse, tktrue:    x:=TBoolConstExpr.Create(Aparent,pekBoolConst, CurToken=tktrue);
     tknil:              x:=TNilExpr.Create(Aparent);
     tknil:              x:=TNilExpr.Create(Aparent);
     tkSquaredBraceOpen: x:=ParseParams(AParent,pekSet);
     tkSquaredBraceOpen: x:=ParseParams(AParent,pekSet);
-    tkinherited: begin
+    tkinherited:
+      begin
       //inherited; inherited function
       //inherited; inherited function
       x:=TInheritedExpr.Create(AParent);
       x:=TInheritedExpr.Create(AParent);
       NextToken;
       NextToken;
-      if (length(CurTokenText)>0) and (CurTokenText[1] in ['A'..'_']) then begin
+      if (CurToken=tkIdentifier) then
+        begin
         b:=TBinaryExpr.Create(AParent,x, DoParseExpression(AParent), eopNone);
         b:=TBinaryExpr.Create(AParent,x, DoParseExpression(AParent), eopNone);
         if not Assigned(b.right) then
         if not Assigned(b.right) then
           begin
           begin
@@ -1155,9 +1161,10 @@ begin
           end;
           end;
         x:=b;
         x:=b;
         UngetToken;
         UngetToken;
-      end
-       else UngetToken;
-    end;
+        end
+      else
+        UngetToken;
+      end;
     tkself: begin
     tkself: begin
       //x:=TPrimitiveExpr.Create(AParent,pekString, CurTokenText); //function(self);
       //x:=TPrimitiveExpr.Create(AParent,pekString, CurTokenText); //function(self);
       x:=TSelfExpr.Create(AParent);
       x:=TSelfExpr.Create(AParent);
@@ -2231,7 +2238,7 @@ begin
   if Result then
   if Result then
     begin
     begin
     NextToken;
     NextToken;
-    Value := DoParseExpression(Parent);
+    Value := DoParseConstValueExpression(Parent);
 //    NextToken;
 //    NextToken;
     end;
     end;
   if (CurToken=tkAbsolute) then
   if (CurToken=tkAbsolute) then
@@ -2548,7 +2555,7 @@ Var
 begin
 begin
   if parent is TPasProcedure then
   if parent is TPasProcedure then
     TPasProcedure(Parent).AddModifier(pm);
     TPasProcedure(Parent).AddModifier(pm);
-  if pm=pmExternal then
+  if (pm=pmExternal) then
     begin
     begin
     NextToken;
     NextToken;
     if CurToken in [tkString,tkIdentifier] then
     if CurToken in [tkString,tkIdentifier] then
@@ -2570,6 +2577,23 @@ begin
     else
     else
       UngetToken;
       UngetToken;
     end
     end
+  else if (pm = pmPublic) then
+    begin
+    NextToken;
+    { Should be token Name,
+      if not we're in a class and the public section starts }
+    If (Uppercase(CurTokenString)<>'NAME') then
+      begin
+      UngetToken;
+      UngetToken;
+      exit;
+      end
+    else
+      begin
+      NextToken;  // Should be export name string.
+      ExpectToken(tkSemicolon);
+      end;
+    end
   else if pm=pmForward then
   else if pm=pmForward then
     begin
     begin
     if (Parent.Parent is TInterfaceSection) then
     if (Parent.Parent is TInterfaceSection) then
@@ -2643,7 +2667,6 @@ begin
         TPasFunctionType(Element).ResultEl.ResultType := ParseType(Parent)
         TPasFunctionType(Element).ResultEl.ResultType := ParseType(Parent)
       else
       else
         ParseType(nil);
         ParseType(nil);
-      Writeln('Function : ',TokenInfos[Curtoken],' ',CurtokenString);
       end;
       end;
     ptOperator:
     ptOperator:
       begin
       begin
@@ -2699,38 +2722,22 @@ begin
         Element.CallingConvention:=Cc;
         Element.CallingConvention:=Cc;
       ExpectToken(tkSemicolon);
       ExpectToken(tkSemicolon);
       end
       end
-    else if TokenIsProcedureModifier(CurTokenString,pm) then
+    else if TokenIsProcedureModifier(Parent,CurTokenString,pm) then
       HandleProcedureModifier(Parent,Pm)
       HandleProcedureModifier(Parent,Pm)
-    else if (CurToken = tkIdentifier) or (CurToken=tklibrary) then // library is a token and a directive.
+    else if (CurToken=tklibrary) then // library is a token and a directive.
       begin
       begin
       Tok:=UpperCase(CurTokenString);
       Tok:=UpperCase(CurTokenString);
-      if DoCheckHint then
-        begin
-        consumesemi;
-        end
-      else if (tok = 'PUBLIC') then
-        begin
-        NextToken;
-        { Should be token Name,
-          if not we're in a class and the public section starts }
-        If (Uppercase(CurTokenString)<>'NAME') then
-          begin
-          UngetToken;
-          UngetToken;
-          Break;
-          end
-        else
-          begin
-          NextToken;  // Should be export name string.
-          ExpectToken(tkSemicolon);
-          end;
-        end
+      NextToken;
+      If (tok<>'NAME') then
+        Element.Hints:=Element.Hints+[hLibrary]
       else
       else
         begin
         begin
-        UnGetToken;
-        Break;
-        end
+        NextToken;  // Should be export name string.
+        ExpectToken(tkSemicolon);
+        end;
       end
       end
+    else if DoCheckHint then
+      consumesemi
     else if (CurToken = tkSquaredBraceOpen) then
     else if (CurToken = tkSquaredBraceOpen) then
       begin
       begin
       repeat
       repeat
@@ -2742,11 +2749,12 @@ begin
     if Done then
     if Done then
       begin
       begin
       NextToken;
       NextToken;
-      Done:=Not (IsCurtokenHint or IsModifier(CurtokenString,Pm) or TokenisCallingConvention(CurTokenString,cc));
+      Done:=Not ((Curtoken=tkSquaredBraceOpen) or TokenIsProcedureModifier(Parent,CurtokenString,Pm) or IscurtokenHint() or TokenisCallingConvention(CurTokenString,cc));
+//      DumpCurToken('Done '+IntToStr(Ord(Done)));
       UngetToken;
       UngetToken;
       end;
       end;
+//    Writeln('Done: ',TokenInfos[Curtoken],' ',CurtokenString);
   Until Done;
   Until Done;
-// Writeln('End: ',TokenInfos[Curtoken],' ',CurtokenString);
   if DoCheckHint then  // deprecated,platform,experimental,library, unimplemented etc
   if DoCheckHint then  // deprecated,platform,experimental,library, unimplemented etc
     ConsumeSemi;
     ConsumeSemi;
   if (ProcType = ptOperator) and (Parent is TPasProcedure) then
   if (ProcType = ptOperator) and (Parent is TPasProcedure) then
@@ -3484,7 +3492,7 @@ end;
 
 
 procedure TPasParser.DumpCurToken(Const Msg : String);
 procedure TPasParser.DumpCurToken(Const Msg : String);
 begin
 begin
-  Writeln(Msg,' : ',TokenInfos[CurToken],' "',CurTokenString,'"');
+  Writeln(Msg,' : ',TokenInfos[CurToken],' "',CurTokenString,'"',Scanner.CurFilename,'(',Scanner.CurRow,',',SCanner.CurColumn,') : ',Scanner.CurLine);
   Flush(output)
   Flush(output)
 end;
 end;
 
 
@@ -3606,7 +3614,7 @@ begin
     AType.Members.Add(Proc);
     AType.Members.Add(Proc);
 end;
 end;
 
 
-procedure TPasParser.ParseClassFields(AType: TPasClassType; Const AVisibility : TPasMemberVisibility);
+procedure TPasParser.ParseClassFields(AType: TPasClassType; Const AVisibility : TPasMemberVisibility; IsClassField : Boolean);
 
 
 Var
 Var
   VarList: TFPList;
   VarList: TFPList;
@@ -3621,6 +3629,8 @@ begin
       begin
       begin
       Element := TPasElement(VarList[i]);
       Element := TPasElement(VarList[i]);
       Element.Visibility := AVisibility;
       Element.Visibility := AVisibility;
+      if IsClassField and (Element is TPasVariable) then
+        TPasVariable(Element).VarModifiers:=TPasVariable(Element).VarModifiers+[vmClass];
       AType.Members.Add(Element);
       AType.Members.Add(Element);
       end;
       end;
   finally
   finally
@@ -3628,6 +3638,25 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TPasParser.ParseClassLocalTypes(AType: TPasClassType; AVisibility : TPasMemberVisibility);
+
+Var
+  T : TPasType;
+  Done : Boolean;
+begin
+//  Writeln('Parsing local types');
+  Repeat
+    T:=ParseTypeDecl(AType);
+    T.Visibility:=AVisibility;
+    AType.Members.Add(t);
+//    Writeln(CurtokenString,' ',TokenInfos[Curtoken]);
+    NextToken;
+    Done:=Curtoken<>tkIdentifier;
+    if Done then
+      UngetToken;
+  Until Done;
+end;
+
 procedure TPasParser.ParseClassMembers(AType: TPasClassType);
 procedure TPasParser.ParseClassMembers(AType: TPasClassType);
 
 
 Var
 Var
@@ -3638,13 +3667,18 @@ begin
   while (CurToken<>tkEnd) do
   while (CurToken<>tkEnd) do
     begin
     begin
     case CurToken of
     case CurToken of
+      tkType:
+        begin
+        ExpectToken(tkIdentifier);
+        ParseClassLocalTypes(AType,CurVisibility);
+        end;
       tkVar,
       tkVar,
       tkIdentifier:
       tkIdentifier:
         begin
         begin
         if CurToken=tkVar then
         if CurToken=tkVar then
           ExpectToken(tkIdentifier);
           ExpectToken(tkIdentifier);
         if Not CheckVisibility(CurtokenString,CurVisibility) then
         if Not CheckVisibility(CurtokenString,CurVisibility) then
-          ParseClassFields(AType,CurVisibility);
+          ParseClassFields(AType,CurVisibility,false);
         end;
         end;
       tkProcedure,tkFunction,tkConstructor,tkDestructor:
       tkProcedure,tkFunction,tkConstructor,tkDestructor:
         ProcessMethod(AType,False,CurVisibility);
         ProcessMethod(AType,False,CurVisibility);
@@ -3656,7 +3690,7 @@ begin
          else if CurToken = tkVar then
          else if CurToken = tkVar then
            begin
            begin
            ExpectToken(tkIdentifier);
            ExpectToken(tkIdentifier);
-           ParseClassFields(AType,CurVisibility);
+           ParseClassFields(AType,CurVisibility,true);
            end
            end
          else if CurToken=tkProperty then
          else if CurToken=tkProperty then
            begin
            begin

+ 8 - 0
packages/fcl-passrc/tests/tcbaseparser.pas

@@ -60,6 +60,7 @@ Type
     Function AssertExpression(Const Msg: String; AExpr : TPasExpr; aKind : TPasExprKind; AValue : String) : TPrimitiveExpr;
     Function AssertExpression(Const Msg: String; AExpr : TPasExpr; aKind : TPasExprKind; AValue : String) : TPrimitiveExpr;
     Procedure AssertExportSymbol(Const Msg: String; AIndex : Integer; AName,AExportName : String; AExportIndex : Integer = -1);
     Procedure AssertExportSymbol(Const Msg: String; AIndex : Integer; AName,AExportName : String; AExportIndex : Integer = -1);
     Procedure AssertEquals(Const Msg : String; AExpected, AActual: TPasExprKind); overload;
     Procedure AssertEquals(Const Msg : String; AExpected, AActual: TPasExprKind); overload;
+    Procedure AssertEquals(Const Msg : String; AExpected, AActual: TexprOpcode); overload;
     Procedure AssertEquals(Const Msg : String; AExpected, AActual: TPasMemberHint); overload;
     Procedure AssertEquals(Const Msg : String; AExpected, AActual: TPasMemberHint); overload;
     Procedure AssertEquals(Const Msg : String; AExpected, AActual: TCallingConvention); overload;
     Procedure AssertEquals(Const Msg : String; AExpected, AActual: TCallingConvention); overload;
     Procedure AssertEquals(Const Msg : String; AExpected, AActual: TArgumentAccess); overload;
     Procedure AssertEquals(Const Msg : String; AExpected, AActual: TArgumentAccess); overload;
@@ -345,6 +346,13 @@ begin
                    GetEnumName(TypeInfo(TPasExprKind),Ord(AActual)));
                    GetEnumName(TypeInfo(TPasExprKind),Ord(AActual)));
 end;
 end;
 
 
+procedure TTestParser.AssertEquals(const Msg: String; AExpected,
+  AActual: TexprOpcode);
+begin
+  AssertEquals(Msg,GetEnumName(TypeInfo(TexprOpcode),Ord(AExpected)),
+                   GetEnumName(TypeInfo(TexprOpcode),Ord(AActual)));
+end;
+
 procedure TTestParser.AssertEquals(const Msg: String; AExpected,
 procedure TTestParser.AssertEquals(const Msg: String; AExpected,
   AActual: TPasMemberHint);
   AActual: TPasMemberHint);
 begin
 begin

+ 99 - 6
packages/fcl-passrc/tests/tcclasstype.pas

@@ -21,10 +21,11 @@ type
     FStarted: Boolean;
     FStarted: Boolean;
     function GetF1: TPasVariable;
     function GetF1: TPasVariable;
     function GetM(AIndex : Integer): TPasElement;
     function GetM(AIndex : Integer): TPasElement;
-    function GetM1: TPasProcedure;
+    function GetMM(AIndex : Integer): TPasProcedure;
     function GetMF1: TPasFunction;
     function GetMF1: TPasFunction;
     function GetP1: TPasProperty;
     function GetP1: TPasProperty;
     function GetP2: TPasProperty;
     function GetP2: TPasProperty;
+    function GetT(AIndex : Integer) : TPasType;
   protected
   protected
     Procedure StartClass (AParent : String = 'TObject'; InterfaceList : String = '');
     Procedure StartClass (AParent : String = 'TObject'; InterfaceList : String = '');
     Procedure StartVisibility(A : TPasMemberVisibility);
     Procedure StartVisibility(A : TPasMemberVisibility);
@@ -42,10 +43,14 @@ type
     Property Members[AIndex : Integer] : TPasElement Read GetM;
     Property Members[AIndex : Integer] : TPasElement Read GetM;
     Property Member1 : TPasElement Read FMember1;
     Property Member1 : TPasElement Read FMember1;
     Property Field1 : TPasVariable Read GetF1;
     Property Field1 : TPasVariable Read GetF1;
-    Property Method1 : TPasProcedure Read GetM1;
+    Property Method1 : TPasProcedure Index 0 Read GetMM;
+    Property Method2 : TPasProcedure Index 1 Read GetMM;
+    Property Method3 : TPasProcedure index 2 Read GetMM;
     Property FunctionMethod1 : TPasFunction Read GetMF1;
     Property FunctionMethod1 : TPasFunction Read GetMF1;
     Property Property1 : TPasProperty Read GetP1;
     Property Property1 : TPasProperty Read GetP1;
     Property Property2 : TPasProperty Read GetP2;
     Property Property2 : TPasProperty Read GetP2;
+    Property Type1 : TPasType Index 0 Read GetT;
+    Property Type2 : TPasType Index 1 Read GetT;
   published
   published
     procedure TestEmpty;
     procedure TestEmpty;
     procedure TestEmptyDeprecated;
     procedure TestEmptyDeprecated;
@@ -54,10 +59,13 @@ type
     Procedure TestOneInterface;
     Procedure TestOneInterface;
     Procedure TestTwoInterfaces;
     Procedure TestTwoInterfaces;
     Procedure TestOneField;
     Procedure TestOneField;
+    Procedure TestOneVarField;
+    Procedure TestOneClassField;
     Procedure TestOneFieldVisibility;
     Procedure TestOneFieldVisibility;
     Procedure TestOneFieldDeprecated;
     Procedure TestOneFieldDeprecated;
     Procedure TestTwoFields;
     Procedure TestTwoFields;
     Procedure TestTwoFieldsB;
     Procedure TestTwoFieldsB;
+    Procedure TestTwoVarFieldsB;
     Procedure TestTwoFieldsVisibility;
     Procedure TestTwoFieldsVisibility;
     procedure TestHintFieldDeprecated;
     procedure TestHintFieldDeprecated;
     procedure TestHintFieldPlatform;
     procedure TestHintFieldPlatform;
@@ -100,6 +108,8 @@ type
     Procedure TestPropertyImplementsFullyQualifiedName;
     Procedure TestPropertyImplementsFullyQualifiedName;
     Procedure TestPropertyReadFromRecordField;
     Procedure TestPropertyReadFromRecordField;
     procedure TestPropertyReadWriteFromRecordField;
     procedure TestPropertyReadWriteFromRecordField;
+    Procedure TestLocalSimpleType;
+    Procedure TestLocalSimpleTypes;
   end;
   end;
 
 
 implementation
 implementation
@@ -117,11 +127,11 @@ begin
   Result:=TPasElement(TheClass.Members[AIndex])
   Result:=TPasElement(TheClass.Members[AIndex])
 end;
 end;
 
 
-function TTestClassType.GetM1: TPasProcedure;
+function TTestClassType.GetMM(AIndex : integer): TPasProcedure;
 begin
 begin
-  AssertNotNull('Have 1 member',Member1);
-  AssertEquals('Member 1 is method',TPasProcedure,Member1.ClassType);
-  Result:=TPasProcedure(Member1);
+  AssertNotNull('Have member '+IntToStr(AIndex),Members[AIndex]);
+  AssertEquals('Member is method '+IntToStr(AIndex),TPasProcedure,Members[Aindex].ClassType);
+  Result:=TPasProcedure(Members[Aindex]);
 end;
 end;
 
 
 function TTestClassType.GetMF1: TPasFunction;
 function TTestClassType.GetMF1: TPasFunction;
@@ -145,6 +155,14 @@ begin
   Result:=TPasProperty(Members[1]);
   Result:=TPasProperty(Members[1]);
 end;
 end;
 
 
+function TTestClassType.GetT(Aindex :integer): TPasType;
+begin
+  AssertNotNull('Have member '+IntToStr(AIndex),Members[AIndex]);
+  if not (Members[AIndex] is TPasType) then
+    Fail('Member '+IntToStr(AIndex)+' is not a type');
+  Result:=TPasType(Members[AIndex]);
+end;
+
 function TTestClassType.GetF1: TPasVariable;
 function TTestClassType.GetF1: TPasVariable;
 begin
 begin
   AssertNotNull('Have 1 member',Member1);
   AssertNotNull('Have 1 member',Member1);
@@ -325,6 +343,30 @@ begin
   AssertVisibility;
   AssertVisibility;
 end;
 end;
 
 
+procedure TTestClassType.TestOneVarField;
+begin
+  StartVisibility(visPublished);
+  FDecl.Add('var');
+  AddMember('a : integer');
+  ParseClass;
+  AssertNotNull('Have 1 field',Field1);
+  AssertMemberName('a');
+  AssertVisibility(visPublished);
+end;
+
+procedure TTestClassType.TestOneClassField;
+begin
+  StartVisibility(visPublished);
+  FDecl.Add('class var');
+  AddMember('a : integer');
+  ParseClass;
+  AssertNotNull('Have 1 field',Field1);
+  AssertMemberName('a');
+  AssertVisibility(visPublished);
+  if not (vmClass in Field1.VarModifiers) then
+     Fail('Field is not a class field');
+end;
+
 procedure TTestClassType.TestOneFieldVisibility;
 procedure TTestClassType.TestOneFieldVisibility;
 begin
 begin
   StartVisibility(visPublished);
   StartVisibility(visPublished);
@@ -374,6 +416,22 @@ begin
   AssertVisibility(visDefault,Members[1]);
   AssertVisibility(visDefault,Members[1]);
 end;
 end;
 
 
+procedure TTestClassType.TestTwoVarFieldsB;
+begin
+  StartVisibility(visPublic);
+  FDecl.Add('var');
+  AddMember('a,b : integer');
+  ParseClass;
+  AssertEquals('2 members',2,TheClass.members.Count);
+  AssertNotNull('Have field',Field1);
+  AssertMemberName('a');
+  AssertVisibility(vispublic);
+  AssertNotNull('Have field',Members[1]);
+  AssertMemberName('b',Members[1]);
+  AssertMemberType(TPasVariable,Members[1]);
+  AssertVisibility(visPublic,Members[1]);
+end;
+
 procedure TTestClassType.TestTwoFieldsVisibility;
 procedure TTestClassType.TestTwoFieldsVisibility;
 begin
 begin
   StartVisibility(visPublic);
   StartVisibility(visPublic);
@@ -985,6 +1043,41 @@ begin
   Assertequals('Default value','',Property1.DefaultValue);
   Assertequals('Default value','',Property1.DefaultValue);
 end;
 end;
 
 
+procedure TTestClassType.TestLocalSimpleType;
+begin
+  StartVisibility(visPublic);
+  FDecl.add('Type');
+  AddMember('TDirection = (left,right)');
+  AddMember('Procedure Something');
+  ParseClass;
+  AssertEquals('Local Enumeration type',TPasEnumType, Type1.ClassType);
+  AssertEquals('Visibility is correct',VisPublic, Type1.Visibility);
+  AssertEquals('Type name','TDirection', Type1.Name);
+  AssertSame('Type parent is class',TheClass, Type1.Parent);
+  AssertNotNull('Member 2 is procedure',Method2);
+  AssertEquals('method name','Something', Method2.Name);
+end;
+
+procedure TTestClassType.TestLocalSimpleTypes;
+begin
+  StartVisibility(visPublic);
+  FDecl.add('Type');
+  AddMember('TDirection = (left,right)');
+  AddMember('TVerticalDirection = (up,down)');
+  AddMember('Procedure Something');
+  ParseClass;
+  AssertEquals('Local Enumeration type',TPasEnumType, Type1.ClassType);
+  AssertEquals('Visibility is correct',VisPublic, Type1.Visibility);
+  AssertEquals('Type name','TDirection', Type1.Name);
+  AssertSame('Type parent is class',TheClass, Type1.Parent);
+  AssertEquals('Local Enumeration type',TPasEnumType, Type2.ClassType);
+  AssertEquals('Visibility is correct',VisPublic, Type2.Visibility);
+  AssertEquals('Type name','TVerticalDirection', Type2.Name);
+  AssertSame('Type parent is class',TheClass, Type2.Parent);
+  AssertNotNull('Member 2 is procedure',Method3);
+  AssertEquals('method name','Something', Method3.Name);
+end;
+
 initialization
 initialization
 
 
   RegisterTest(TTestClassType);
   RegisterTest(TTestClassType);

+ 901 - 0
packages/fcl-passrc/tests/tcexprparser.pas

@@ -0,0 +1,901 @@
+unit tcexprparser;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpcunit, testutils, testregistry, tcbaseparser, pastree;
+
+type
+
+  { TTestExpressions }
+
+  TTestExpressions= class(TTestParser)
+  private
+    FLeft: TPAsExpr;
+    FRight: TPAsExpr;
+    FTheExpr: TPasExpr;
+    FVariables : TStringList;
+    procedure AssertLeftPrecedence(AInnerLeft: Integer; AInnerOp: TExprOpCode;
+      AInnerRight: Integer; AOuterOp: TexprOpCode; AOuterRight: Integer);
+    procedure AssertRightPrecedence(AOuterLeft: Integer; AOuterOp: TExprOpCode;
+      AInnerLeft: Integer; AInnerOp: TexprOpCode; AInnerRight: Integer);
+    procedure DeclareVar(const AVarType: String; const AVarName: String = 'a');
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+    Procedure SetExpression(Const AExpression : String);
+    Procedure ParseExpression;
+    Procedure ParseExpression(Const AExpression : String);
+    Function AssertBinaryExpr(Const Msg : String; Op : TExprOpCode; Out ALeft,ARight : TPasExpr) : TBinaryExpr;
+    Function AssertBinaryExpr(Const Msg : String; AExpr : TPasExpr; Op : TExprOpCode; Out ALeft,ARight : TPasExpr) : TBinaryExpr;
+    Function AssertUnaryExpr(Const Msg : String; Op : TExprOpCode; Out AOperand : TPasExpr) : TUnaryExpr;
+    Function AssertUnaryExpr(Const Msg : String; AExpr: TPasExpr; Op : TExprOpCode; Out AOperand : TPasExpr) : TUnaryExpr;
+    Property TheExpr : TPasExpr read FTheExpr;
+    Property Theleft : TPAsExpr Read FLeft;
+    Property TheRight : TPAsExpr Read FRight;
+  published
+    {
+      TPasExprKind = (pekRange,
+       pekListOfExp, );
+    }
+    procedure TestPrimitiveInteger;
+    procedure TestPrimitiveIntegerHex;
+    procedure TestPrimitiveIntegerOctal;
+    procedure TestPrimitiveIntegerBinary;
+    procedure TestPrimitiveDouble;
+    procedure TestPrimitiveString;
+    procedure TestPrimitiveIdent;
+    procedure TestPrimitiveBooleanFalse;
+    procedure TestPrimitiveBooleanTrue;
+    procedure TestPrimitiveNil;
+    procedure TestPrimitiveSet;
+    procedure TestPrimitiveChar;
+    procedure TestPrimitiveControlChar;
+    procedure TestPrimitiveSetEmpty;
+    procedure TestPrimitiveSelf;
+    Procedure TestInherited;
+    Procedure TestInheritedFunction;
+    Procedure TestUnaryMinus;
+    Procedure TestUnaryMinusWhiteSpace;
+    Procedure TestUnaryAddress;
+    Procedure TestUnaryNot;
+    Procedure TestUnaryDeref;
+    Procedure TestBinaryAdd;
+    Procedure TestBinarySubtract;
+    Procedure TestBinaryMultiply;
+    Procedure TestBinaryDivision;
+    Procedure TestBinaryPower;
+    Procedure TestBinaryMod;
+    Procedure TestBinaryDiv;
+    procedure TestBinaryShl;
+    procedure TestBinaryShr;
+    Procedure TestBinarySymmetricalDifference;
+    Procedure TestBinaryAnd;
+    Procedure TestBinaryOr;
+    Procedure TestBinaryXOr;
+    Procedure TestBinaryIn;
+    Procedure TestBinaryIs;
+    Procedure TestBinaryAs;
+    Procedure TestBinaryEquals;
+    Procedure TestBinaryDiffers;
+    Procedure TestBinaryLessThan;
+    Procedure TestBinaryLessThanEqual;
+    Procedure TestBinaryLargerThan;
+    Procedure TestBinaryLargerThanEqual;
+    procedure TestBinaryFullIdent;
+    Procedure TestArrayElement;
+    Procedure TestArrayElement2Dims;
+    Procedure TestFunctionCall;
+    Procedure TestFunctionCall2args;
+    Procedure TestFunctionCallNoArgs;
+    Procedure TestRange;
+    Procedure TestBracketsTotal;
+    Procedure TestBracketsLeft;
+    Procedure TestBracketsRight;
+    Procedure TestPrecedenceLeftToRight;
+    Procedure TestPrecedenceLeftToRightMinus;
+    Procedure TestPrecedenceLeftToRightMultiply;
+    Procedure TestPrecedenceLeftToRightDivision;
+    Procedure TestPrecedenceLeftToRightPlusMinus;
+    Procedure TestPrecedenceLeftToRightMinusPlus;
+    Procedure TestPrecedenceLeftToRightMultiplyDivision;
+    Procedure TestPrecedenceLeftToRightDivisionMultiply;
+    Procedure TestPrecedencePlusMultiply;
+    Procedure TestPrecedencePlusDivide;
+    Procedure TestPrecedenceMinusMultiply;
+    Procedure TestPrecedenceMinusDivide;
+    Procedure TestPrecedencePlusOr;
+    Procedure TestPrecedenceAndOr;
+    Procedure TestPrecedenceAndNot;
+    Procedure TestPrecedencePlusAnd;
+    Procedure TestPrecedenceMinusOr;
+    Procedure TestPrecedenceMinusAnd;
+    Procedure TestPrecedenceMultiplyOr;
+    Procedure TestPrecedenceMultiplyAnd;
+    Procedure TestPrecedencePlusDiv;
+    Procedure TestPrecedencePlusMod;
+    Procedure TestPrecedenceMultiplyDiv;
+    Procedure TestPrecedenceDivMultiply;
+  end;
+
+implementation
+
+procedure TTestExpressions.DeclareVar(const AVarType: String;
+const AVarName: String = 'a');
+begin
+  FVariables.Add(AVarName+' : '+AVarType+';');
+end;
+
+procedure TTestExpressions.TestPrimitiveInteger;
+begin
+  ParseExpression('1');
+  AssertExpression('Simple integer',theExpr,pekNumber,'1');
+end;
+
+procedure TTestExpressions.TestPrimitiveIntegerHex;
+begin
+  ParseExpression('$FF');
+  AssertExpression('Simple integer',theExpr,pekNumber,'$FF');
+end;
+
+procedure TTestExpressions.TestPrimitiveIntegerOctal;
+begin
+  ParseExpression('&777');
+  AssertExpression('Simple integer',theExpr,pekNumber,'&777');
+end;
+
+procedure TTestExpressions.TestPrimitiveIntegerBinary;
+begin
+  ParseExpression('%10101010');
+  AssertExpression('Simple integer',theExpr,pekNumber,'%10101010');
+end;
+
+procedure TTestExpressions.TestPrimitiveDouble;
+begin
+  ParseExpression('1.2');
+  AssertExpression('Simple double',theExpr,pekNumber,'1.2');
+end;
+
+procedure TTestExpressions.TestPrimitiveString;
+begin
+  DeclareVar('string');
+  ParseExpression('''123''');
+  AssertExpression('Simple string',theExpr,pekString,'''123''');
+end;
+
+procedure TTestExpressions.TestPrimitiveIdent;
+begin
+  DeclareVar('integer','a');
+  DeclareVar('integer','b');
+  ParseExpression('b');
+  AssertExpression('Simple identifier',theExpr,pekIdent,'b');
+end;
+
+procedure TTestExpressions.TestBinaryFullIdent;
+begin
+  DeclareVar('integer','a');
+  DeclareVar('record x,y : integer; end','b');
+  ParseExpression('b.x');
+  AssertBinaryExpr('sub identifier',eopSubIdent,Fleft,FRight);
+  AssertExpression('Simple identifier',Theleft,pekIdent,'b');
+  AssertExpression('Simple identifier',Theright,pekIdent,'x');
+end;
+
+procedure TTestExpressions.TestArrayElement;
+
+Var
+  P : TParamsExpr;
+
+begin
+  DeclareVar('integer','a');
+  DeclareVar('array[1..2] of integer','b');
+  ParseExpression('b[1]');
+  P:=TParamsExpr(AssertExpression('Simple identifier',theExpr,pekArrayParams,TParamsExpr));
+  AssertExpression('Name of array',P.Value,pekIdent,'b');
+  AssertEquals('One dimension',1,Length(p.params));
+  AssertExpression('Simple identifier',p.params[0],pekNumber,'1');
+end;
+
+procedure TTestExpressions.TestArrayElement2Dims;
+Var
+  P : TParamsExpr;
+
+begin
+  DeclareVar('integer','a');
+  DeclareVar('array[1..2,1..2] of integer','b');
+  ParseExpression('b[1,2]');
+  P:=TParamsExpr(AssertExpression('Simple identifier',theExpr,pekArrayParams,TParamsExpr));
+  AssertExpression('Name of array',P.Value,pekIdent,'b');
+  AssertEquals('Two dimensions',2,Length(p.params));
+  AssertExpression('Simple identifier',p.params[0],pekNumber,'1');
+  AssertExpression('Simple identifier',p.params[1],pekNumber,'2');
+end;
+
+procedure TTestExpressions.TestFunctionCall;
+Var
+  P : TParamsExpr;
+
+begin
+  DeclareVar('integer','a');
+  ParseExpression('Random(10)');
+  P:=TParamsExpr(AssertExpression('Simple identifier',theExpr,pekFuncParams,TParamsExpr));
+  AssertExpression('Name of function',P.Value,pekIdent,'Random');
+  AssertEquals('1 argument',1,Length(p.params));
+  AssertExpression('Simple identifier',p.params[0],pekNumber,'10');
+end;
+
+procedure TTestExpressions.TestFunctionCall2args;
+Var
+  P : TParamsExpr;
+
+begin
+  DeclareVar('integer','a');
+  ParseExpression('Random(10,12)');
+  P:=TParamsExpr(AssertExpression('Simple identifier',theExpr,pekFuncParams,TParamsExpr));
+  AssertExpression('Name of function',P.Value,pekIdent,'Random');
+  AssertEquals('2 argument',2,Length(p.params));
+  AssertExpression('Simple identifier 1',p.params[0],pekNumber,'10');
+  AssertExpression('Simple identifier 2',p.params[1],pekNumber,'12');
+end;
+
+procedure TTestExpressions.TestFunctionCallNoArgs;
+
+Var
+  P : TParamsExpr;
+
+begin
+  DeclareVar('integer','a');
+  ParseExpression('Random()');
+  P:=TParamsExpr(AssertExpression('Simple identifier',theExpr,pekFuncParams,TParamsExpr));
+  AssertExpression('Name of function',P.Value,pekIdent,'Random');
+  AssertEquals('0 arguments',0,Length(p.params));
+end;
+
+procedure TTestExpressions.TestRange;
+
+Var
+  B : TBinaryExpr;
+
+begin
+  DeclareVar('boolean','a');
+  DeclareVar('byte','b');
+  ParseExpression('b in 0..10');
+  AssertBinaryExpr('Simple binary In',eopIn,FLeft,FRight);
+  AssertExpression('Left is b',TheLeft,pekIdent,'b');
+  B:=TBinaryExpr(AssertExpression('Right is range',TheRight,pekRange,TBinaryExpr));
+  AssertExpression('Left is 0',B.Left,pekNumber,'0');
+  AssertExpression('Right is 10',B.Right,pekNumber,'10');
+end;
+
+procedure TTestExpressions.TestBracketsTotal;
+begin
+  DeclareVar('integer','a');
+  ParseExpression('(3+4)');
+  AssertBinaryExpr('simple binary add',eopAdd,FLeft,FRight);
+  AssertExpression('Inner Left is 3',TheLeft,pekNumber,'3');
+  AssertExpression('Inner Right is 4',TheRight,pekNumber,'4');
+end;
+
+procedure TTestExpressions.TestBracketsLeft;
+begin
+  DeclareVar('integer','a');
+  ParseExpression('2*(3+4)');
+  AssertRightPrecedence(2,eopMultiply,3,eopAdd,4);
+end;
+
+procedure TTestExpressions.TestBracketsRight;
+begin
+  DeclareVar('integer','a');
+  ParseExpression('(2*3)+4');
+  AssertLeftPrecedence(2,eopMultiply,3,eopAdd,4);
+end;
+
+procedure TTestExpressions.TestPrecedenceLeftToRight;
+begin
+  ParseExpression('1+2+3');
+  AssertLeftPrecedence(1,eopAdd,2,eopAdd,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceLeftToRightMinus;
+begin
+  ParseExpression('1-2-3');
+  AssertLeftPrecedence(1,eopSubtract,2,eopSubtract,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceLeftToRightMultiply;
+begin
+  ParseExpression('1*2*3');
+  AssertLeftPrecedence(1,eopMultiply,2,eopMultiply,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceLeftToRightDivision;
+begin
+  ParseExpression('1/2/3');
+  AssertLeftPrecedence(1,eopDivide,2,eopDivide,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceLeftToRightPlusMinus;
+begin
+  ParseExpression('1+2-3');
+  AssertLeftPrecedence(1,eopAdd,2,eopSubtract,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceLeftToRightMinusPlus;
+begin
+  ParseExpression('1-2+3');
+  AssertLeftPrecedence(1,eopSubtract,2,eopAdd,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceLeftToRightMultiplyDivision;
+begin
+  ParseExpression('1*2/3');
+  AssertLeftPrecedence(1,eopMultiply,2,eopDivide,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceLeftToRightDivisionMultiply;
+begin
+  ParseExpression('1/2*3');
+  AssertLeftPrecedence(1,eopDivide,2,eopMultiply,3);
+end;
+
+procedure TTestExpressions.TestPrecedencePlusMultiply;
+begin
+  ParseExpression('1+2*3');
+  AssertRightPrecedence(1,eopAdd,2,eopMultiply,3);
+end;
+
+procedure TTestExpressions.TestPrecedencePlusDivide;
+begin
+  ParseExpression('1+2/3');
+  AssertRightPrecedence(1,eopAdd,2,eopDivide,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceMinusMultiply;
+begin
+  ParseExpression('1-2*3');
+  AssertRightPrecedence(1,eopsubtract,2,eopMultiply,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceMinusDivide;
+begin
+  ParseExpression('1-2/3');
+  AssertRightPrecedence(1,eopsubtract,2,eopDivide,3);
+end;
+
+procedure TTestExpressions.TestPrecedencePlusOr;
+begin
+  ParseExpression('1 or 2 + 3');
+  AssertLeftPrecedence(1,eopor,2,eopAdd,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceAndOr;
+begin
+  ParseExpression('1 or 2 and 3');
+  AssertRightPrecedence(1,eopor,2,eopAnd,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceAndNot;
+begin
+  ParseExpression('Not 1 and 3');
+  AssertBinaryExpr('Simple binary and',eopAnd,FLeft,FRight);
+  AssertExpression('Outer right is 3',TheRight,pekNumber,'3');
+  AssertUnaryExpr('Left is Unary not ',TheLeft,eopNot,FRight);
+  AssertExpression('Inner Right is 1',TheRight,pekNumber,'1');
+end;
+
+procedure TTestExpressions.TestPrecedencePlusAnd;
+begin
+  ParseExpression('1 + 2 and 3');
+  AssertRightPrecedence(1,eopAdd,2,eopAnd,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceMinusOr;
+begin
+  ParseExpression('1 or 2 - 3');
+  AssertLeftPrecedence(1,eopOr,2,eopSubtract,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceMinusAnd;
+begin
+  ParseExpression('1 - 2 and 3');
+  AssertRightPrecedence(1,eopSubtract,2,eopand,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceMultiplyOr;
+begin
+  ParseExpression('1 or 2 * 3');
+  AssertRightPrecedence(1,eopOr,2,eopMultiply,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceMultiplyAnd;
+begin
+  ParseExpression('1 * 2 and 3');
+  AssertLeftPrecedence(1,eopMultiply,2,eopAnd,3);
+end;
+
+procedure TTestExpressions.TestPrecedencePlusDiv;
+begin
+  ParseExpression('1+2 div 3');
+  AssertRightPrecedence(1,eopAdd,2,eopDiv,3);
+end;
+
+procedure TTestExpressions.TestPrecedencePlusMod;
+begin
+  ParseExpression('1+2 mod 3');
+  AssertRightPrecedence(1,eopAdd,2,eopMod,3);
+end;
+
+procedure TTestExpressions.AssertLeftPrecedence(AInnerLeft : Integer; AInnerOp : TExprOpCode; AInnerRight : Integer; AOuterOp : TexprOpCode; AOuterRight: Integer);
+
+begin
+  AssertBinaryExpr('Outer expression',AOuterOp,FLeft,FRight);
+  AssertExpression('Outer right constant',TheRight,pekNumber,intToStr(AOuterRight));
+  AssertBinaryExpr('Inner (left) expression',TheLeft,AInnerOp,FLeft,FRight);
+  AssertExpression('Inner Left constant',TheLeft,pekNumber,IntToStr(AInnerLeft));
+  AssertExpression('Inner Right constant',TheRight,pekNumber,IntToStr(AInnerRight));
+end;
+
+
+procedure TTestExpressions.AssertRightPrecedence(AOuterLeft : Integer; AOuterOp : TExprOpCode; AInnerLeft : Integer; AInnerOp : TexprOpCode; AInnerRight: Integer);
+
+begin
+  AssertBinaryExpr('Outer expression',AOuterOp,FLeft,FRight);
+  AssertExpression('Outer left constant',TheLeft,pekNumber,intToStr(AOuterLeft));
+  AssertBinaryExpr('Inner (right) expression',TheRight,AInnerOp,FLeft,FRight);
+  AssertExpression('Inner Left constant',TheLeft,pekNumber,IntToStr(AInnerLeft));
+  AssertExpression('Inner Right constant',TheRight,pekNumber,IntToStr(AInnerRight));
+end;
+
+procedure TTestExpressions.TestPrecedenceMultiplyDiv;
+begin
+  ParseExpression('1 * 2 div 3');
+  AssertLeftPrecedence(1,eopMultiply,2,eopDiv,3);
+end;
+
+procedure TTestExpressions.TestPrecedenceDivMultiply;
+begin
+  ParseExpression('1 div 2 * 3');
+  AssertLeftPrecedence(1,eopDiv,2,eopMultiply,3);
+end;
+
+
+procedure TTestExpressions.TestUnaryMinus;
+begin
+  DeclareVar('integer','a');
+  DeclareVar('integer','b');
+  ParseExpression('-b');
+  AssertUnaryExpr('Simple minus unary',eopSubtract,FLeft);
+  AssertExpression('Simple identifier',theLeft,pekIdent,'b');
+end;
+
+procedure TTestExpressions.TestUnaryMinusWhiteSpace;
+begin
+  DeclareVar('integer','a');
+  DeclareVar('integer','b');
+  ParseExpression('- b');
+  AssertUnaryExpr('Simple minus unary',eopSubtract,FLeft);
+  AssertExpression('Simple identifier',theLeft,pekIdent,'b');
+end;
+
+procedure TTestExpressions.TestUnaryAddress;
+begin
+  DeclareVar('integer','a');
+  DeclareVar('integer','b');
+  ParseExpression('@b');
+  AssertUnaryExpr('Simple address unary',eopAddress,FLeft);
+  AssertExpression('Simple identifier',theLeft,pekIdent,'b');
+end;
+
+procedure TTestExpressions.TestUnaryNot;
+begin
+  DeclareVar('boolean','a');
+  DeclareVar('boolean','b');
+  ParseExpression('not b');
+  AssertUnaryExpr('Simple address unary',eopNot,FLeft);
+  AssertExpression('Simple identifier',theLeft,pekIdent,'b');
+end;
+
+procedure TTestExpressions.TestUnaryDeref;
+begin
+  DeclareVar('integer','a');
+  DeclareVar('pinteger','b');
+  ParseExpression('b^');
+  AssertUnaryExpr('Simple address unary',eopDeref,FLeft);
+  AssertExpression('Simple identifier',theLeft,pekIdent,'b');
+end;
+
+procedure TTestExpressions.TestBinaryAdd;
+begin
+  ParseExpression('1+2');
+  AssertBinaryExpr('Simple binary add',eopAdd,FLeft,FRight);
+  AssertExpression('Left is 1',TheLeft,pekNumber,'1');
+  AssertExpression('Right is 2',TheRight,pekNumber,'2');
+end;
+
+procedure TTestExpressions.TestBinarySubtract;
+begin
+  ParseExpression('1-2');
+  AssertBinaryExpr('Simple binary subtract',eopSubtract,FLeft,FRight);
+  AssertExpression('Left is 1',TheLeft,pekNumber,'1');
+  AssertExpression('Right is 2',TheRight,pekNumber,'2');
+end;
+
+procedure TTestExpressions.TestBinaryMultiply;
+begin
+  ParseExpression('1*2');
+  AssertBinaryExpr('Simple binary multiply',eopMultiply,FLeft,FRight);
+  AssertExpression('Left is 1',TheLeft,pekNumber,'1');
+  AssertExpression('Right is 2',TheRight,pekNumber,'2');
+end;
+
+procedure TTestExpressions.TestBinaryDivision;
+begin
+  DeclareVar('double');
+  ParseExpression('1/2');
+  AssertBinaryExpr('Simple binary division',eopDivide,FLeft,FRight);
+  AssertExpression('Left is 1',TheLeft,pekNumber,'1');
+  AssertExpression('Right is 2',TheRight,pekNumber,'2');
+end;
+
+procedure TTestExpressions.TestBinaryPower;
+begin
+  DeclareVar('double');
+  ParseExpression('1**2');
+  AssertBinaryExpr('Simple binary power',eopPower,FLeft,FRight);
+  AssertExpression('Left is 1',TheLeft,pekNumber,'1');
+  AssertExpression('Right is 2',TheRight,pekNumber,'2');
+end;
+
+procedure TTestExpressions.TestBinaryMod;
+begin
+  ParseExpression('1 mod 2');
+  AssertBinaryExpr('Simple binary mod',eopMod,FLeft,FRight);
+  AssertExpression('Left is 1',TheLeft,pekNumber,'1');
+  AssertExpression('Right is 2',TheRight,pekNumber,'2');
+end;
+
+procedure TTestExpressions.TestBinaryDiv;
+begin
+  ParseExpression('1 div 2');
+  AssertBinaryExpr('Simple binary div',eopDiv,FLeft,FRight);
+  AssertExpression('Left is 1',TheLeft,pekNumber,'1');
+  AssertExpression('Right is 2',TheRight,pekNumber,'2');
+end;
+
+procedure TTestExpressions.TestBinaryShl;
+begin
+  ParseExpression('1 shl 2');
+  AssertBinaryExpr('Simple binary shl',eopShl,FLeft,FRight);
+  AssertExpression('Left is 1',TheLeft,pekNumber,'1');
+  AssertExpression('Right is 2',TheRight,pekNumber,'2');
+end;
+
+procedure TTestExpressions.TestBinaryShr;
+begin
+  ParseExpression('1 shr 2');
+  AssertBinaryExpr('Simple binary shr',eopShr,FLeft,FRight);
+  AssertExpression('Left is 1',TheLeft,pekNumber,'1');
+  AssertExpression('Right is 2',TheRight,pekNumber,'2');
+end;
+
+procedure TTestExpressions.TestBinarySymmetricalDifference;
+begin
+  DeclareVar('Set of Byte','a');
+  DeclareVar('Set of Byte','b');
+  DeclareVar('Set of Byte','c');
+  ParseExpression('b >< c');
+  AssertBinaryExpr('Simple binary smmetrical difference',eopSymmetricalDifference,FLeft,FRight);
+  AssertExpression('Left is b',TheLeft,pekident,'b');
+  AssertExpression('Right is c',TheRight,pekIdent,'c');
+end;
+
+procedure TTestExpressions.TestBinaryAnd;
+begin
+  DeclareVar('boolean','a');
+  DeclareVar('boolean','b');
+  DeclareVar('boolean','b');
+  ParseExpression('b and c');
+  AssertBinaryExpr('Simple binary and',eopAnd,FLeft,FRight);
+  AssertExpression('Left is b',TheLeft,pekIdent,'b');
+  AssertExpression('Right is c',TheRight,pekIdent,'c');
+end;
+
+procedure TTestExpressions.TestBinaryOr;
+begin
+  DeclareVar('boolean','a');
+  DeclareVar('boolean','b');
+  DeclareVar('boolean','b');
+  ParseExpression('b or c');
+  AssertBinaryExpr('Simple binary or',eopOr,FLeft,FRight);
+  AssertExpression('Left is b',TheLeft,pekIdent,'b');
+  AssertExpression('Right is c',TheRight,pekIdent,'c');
+end;
+
+procedure TTestExpressions.TestBinaryXOr;
+begin
+  DeclareVar('boolean','a');
+  DeclareVar('boolean','b');
+  DeclareVar('boolean','b');
+  ParseExpression('b xor c');
+  AssertBinaryExpr('Simple binary xor',eopxOr,FLeft,FRight);
+  AssertExpression('Left is b',TheLeft,pekIdent,'b');
+  AssertExpression('Right is c',TheRight,pekIdent,'c');
+end;
+
+procedure TTestExpressions.TestBinaryIn;
+begin
+  DeclareVar('boolean','a');
+  ParseExpression('1 in [1,2,3]');
+  AssertBinaryExpr('Simple binary In',eopIn,FLeft,FRight);
+  AssertExpression('Left is 1',TheLeft,pekNumber,'1');
+  AssertExpression('Right is array set',TheRight,pekSet,TParamsExpr);
+end;
+
+procedure TTestExpressions.TestBinaryIs;
+begin
+  DeclareVar('boolean','a');
+  DeclareVar('TObject','b');
+  ParseExpression('b is TObject');
+  AssertBinaryExpr('Simple binary Is',eopIs,FLeft,FRight);
+  AssertExpression('Left is 1',TheLeft,pekident,'b');
+  AssertExpression('Right is TObject',TheRight,pekIdent,'TObject');
+end;
+
+procedure TTestExpressions.TestBinaryAs;
+begin
+  DeclareVar('TObject','a');
+  DeclareVar('TObject','b');
+  ParseExpression('b as TObject');
+  AssertBinaryExpr('Simple binary As',eopAs,FLeft,FRight);
+  AssertExpression('Left is 1',TheLeft,pekident,'b');
+  AssertExpression('Right is TObject',TheRight,pekIdent,'TObject');
+end;
+
+procedure TTestExpressions.TestBinaryEquals;
+begin
+  DeclareVar('boolean','a');
+  DeclareVar('integer','b');
+  DeclareVar('integer','c');
+  ParseExpression('b=c');
+  AssertBinaryExpr('Simple binary equals',eopEqual,FLeft,FRight);
+  AssertExpression('Left is b',TheLeft,pekident,'b');
+  AssertExpression('Right is c',TheRight,pekIdent,'c');
+end;
+
+procedure TTestExpressions.TestBinaryDiffers;
+begin
+  DeclareVar('boolean','a');
+  DeclareVar('integer','b');
+  DeclareVar('integer','c');
+  ParseExpression('b<>c');
+  AssertBinaryExpr('Simple binary differs',eopNotEqual,FLeft,FRight);
+  AssertExpression('Left is b',TheLeft,pekident,'b');
+  AssertExpression('Right is c',TheRight,pekIdent,'c');
+end;
+
+procedure TTestExpressions.TestBinaryLessThan;
+begin
+  DeclareVar('boolean','a');
+  DeclareVar('integer','b');
+  DeclareVar('integer','c');
+  ParseExpression('b<c');
+  AssertBinaryExpr('Simple binary less than',eopLessThan,FLeft,FRight);
+  AssertExpression('Left is b',TheLeft,pekident,'b');
+  AssertExpression('Right is c',TheRight,pekIdent,'c');
+end;
+
+procedure TTestExpressions.TestBinaryLessThanEqual;
+begin
+  DeclareVar('boolean','a');
+  DeclareVar('integer','b');
+  DeclareVar('integer','c');
+  ParseExpression('b<=c');
+  AssertBinaryExpr('Simple binary less than or equal',eopLessThanEqual,FLeft,FRight);
+  AssertExpression('Left is b',TheLeft,pekident,'b');
+  AssertExpression('Right is c',TheRight,pekIdent,'c');
+end;
+
+procedure TTestExpressions.TestBinaryLargerThan;
+begin
+  DeclareVar('boolean','a');
+  DeclareVar('integer','b');
+  DeclareVar('integer','c');
+  ParseExpression('b>c');
+  AssertBinaryExpr('Simple binary larger than ',eopGreaterThan,FLeft,FRight);
+  AssertExpression('Left is b',TheLeft,pekident,'b');
+  AssertExpression('Right is c',TheRight,pekIdent,'c');
+end;
+
+procedure TTestExpressions.TestBinaryLargerThanEqual;
+begin
+  DeclareVar('boolean','a');
+  DeclareVar('integer','b');
+  DeclareVar('integer','c');
+  ParseExpression('b>=c');
+  AssertBinaryExpr('Simple binary larger than or equal',eopGreaterThanEqual,FLeft,FRight);
+  AssertExpression('Left is b',TheLeft,pekident,'b');
+  AssertExpression('Right is c',TheRight,pekIdent,'c');
+end;
+
+procedure TTestExpressions.TestPrimitiveBooleanFalse;
+begin
+  DeclareVar('boolean','a');
+  ParseExpression('False');
+  AssertExpression('Simple boolean',theExpr,pekBoolConst,TBoolConstExpr);
+  AssertEquals('Boolean false',False,TBoolConstExpr(TheExpr).Value);
+end;
+
+procedure TTestExpressions.TestPrimitiveBooleanTrue;
+begin
+  DeclareVar('boolean','a');
+  ParseExpression('True');
+  AssertExpression('Simple boolean',theExpr,pekBoolConst,TBoolConstExpr);
+  AssertEquals('Boolean true',True,TBoolConstExpr(TheExpr).Value);
+end;
+
+procedure TTestExpressions.TestPrimitiveNil;
+begin
+  DeclareVar('pointer','a');
+  ParseExpression('Nil');
+  AssertExpression('Nil expr',theExpr,pekNil,TNilExpr);
+end;
+
+procedure TTestExpressions.TestPrimitiveSet;
+
+Var
+  P : TParamsExpr;
+begin
+  DeclareVar('set of byte','a');
+  ParseExpression('[1,2,3]');
+  P:=TParamsExpr(AssertExpression('Set expr',theExpr,pekSet,TParamsExpr));
+  AssertEquals('Element count',3,Length(P.Params));
+  AssertExpression('Element 1 in set',P.Params[0],pekNumber,'1');
+  AssertExpression('Element 2 in set',P.Params[1],pekNumber,'2');
+  AssertExpression('Element 3 in set',P.Params[2],pekNumber,'3');
+end;
+
+procedure TTestExpressions.TestPrimitiveChar;
+begin
+  DeclareVar('char');
+  ParseExpression('#32');
+  AssertExpression('Simple string',theExpr,pekString,'#32');
+end;
+
+procedure TTestExpressions.TestPrimitiveControlChar;
+begin
+  DeclareVar('char');
+  ParseExpression('^M');
+  AssertExpression('Simple string',theExpr,pekString,'^M');
+end;
+
+procedure TTestExpressions.TestPrimitiveSetEmpty;
+
+Var
+  P : TParamsExpr;
+begin
+  DeclareVar('set of byte','a');
+  ParseExpression('[]');
+  P:=TParamsExpr(AssertExpression('Set expr',theExpr,pekSet,TParamsExpr));
+  AssertEquals('Element count',0,Length(P.Params));
+end;
+
+procedure TTestExpressions.TestPrimitiveSelf;
+Var
+  S : TSelfExpr;
+begin
+  DeclareVar('pointer','a');
+  ParseExpression('Self');
+  S:=TSelfExpr(AssertExpression('Inherited expr',theExpr,pekSelf,TSelfExpr));
+end;
+
+procedure TTestExpressions.TestInherited;
+
+Var
+  I: TInheritedExpr;
+begin
+  DeclareVar('pointer','a');
+  ParseExpression('inherited');
+  I:=TInheritedExpr(AssertExpression('Inherited expr',theExpr,pekInherited,TInheritedExpr));
+end;
+
+procedure TTestExpressions.TestInheritedFunction;
+
+Var
+  I: TInheritedExpr;
+begin
+  DeclareVar('pointer','a');
+  ParseExpression('inherited myfunction');
+  AssertBinaryExpr('Inherited expr',eopNone,Fleft,FRight);
+  AssertExpression('Inherited expr',theleft,pekInherited,TInheritedExpr);
+  AssertExpression('Inherited expr',theright,pekIdent,'myfunction');
+end;
+
+procedure TTestExpressions.SetUp;
+begin
+  Inherited;
+  FVariables:=TStringList.Create;
+end;
+
+procedure TTestExpressions.TearDown;
+
+begin
+  FreeAndNil(FVariables);
+  Inherited;
+end;
+
+procedure TTestExpressions.SetExpression(const AExpression: String);
+
+Var
+  I : Integer;
+
+begin
+  StartProgram('afile');
+  if FVariables.Count=0 then
+    DeclareVar('integer');
+  Add('Var');
+  For I:=0 to FVariables.Count-1 do
+    Add('  '+Fvariables[I]);
+  Add('begin');
+  Add('  a:='+AExpression+';');
+end;
+
+procedure TTestExpressions.ParseExpression;
+begin
+  ParseModule;
+  AssertEquals('Have program',TPasProgram,Module.ClassType);
+  AssertNotNull('Have program section',PasProgram.ProgramSection);
+  AssertNotNull('Have initialization section',PasProgram.InitializationSection);
+  AssertEquals('Have initialization statement',1,PasProgram.InitializationSection.Elements.Count);
+  AssertNotNull('Have initialization statement',PasProgram.InitializationSection.Elements[0]);
+  AssertEquals('Assignment statement',TPasImplAssign,TObject(PasProgram.InitializationSection.Elements[0]).ClassType);
+  FTheExpr:=TPasImplAssign(PasProgram.InitializationSection.Elements[0]).right;
+  AssertNotNull('Have assignment expression',FTheExpr);
+end;
+
+procedure TTestExpressions.ParseExpression(const AExpression: String);
+begin
+  SetExpression(AExpression);
+  ParseExpression;
+end;
+
+function TTestExpressions.AssertBinaryExpr(const Msg: String; Op: TExprOpCode;
+  out ALeft, ARight: TPasExpr): TBinaryExpr;
+begin
+  Result:=AssertBinaryExpr(Msg,TheExpr,Op,ALeft,ARight);
+end;
+
+function TTestExpressions.AssertBinaryExpr(const Msg: String; AExpr: TPasExpr;
+  Op: TExprOpCode; out ALeft, ARight: TPasExpr): TBinaryExpr;
+begin
+  AssertExpression(Msg+' is binary',AExpr,pekBinary,TBinaryExpr);
+  Result:=AExpr as TBinaryExpr;
+  AssertEquals(Msg+' opcode OK',Op,Result.OpCode);
+  ALeft:=Result.Left;
+  ARight:=Result.Right;
+  AssertNotNull('Have left',ALeft);
+  AssertNotNull('Have right',ARight);
+end;
+
+function TTestExpressions.AssertUnaryExpr(const Msg: String; Op: TExprOpCode;
+  out AOperand : TPasExpr): TUnaryExpr;
+begin
+  Result:=AssertUnaryExpr(Msg,TheExpr,OP,AOperand);
+end;
+
+function TTestExpressions.AssertUnaryExpr(const Msg: String; AExpr: TPasExpr;
+  Op: TExprOpCode; out AOperand: TPasExpr): TUnaryExpr;
+begin
+  AssertExpression(Msg+' is unary',AExpr,pekUnary,TUnaryExpr);
+  Result:=AExpr as TUnaryExpr;
+  AssertEquals(Msg+' opcode OK',Op,Result.OpCode);
+  AOperand:=Result.Operand;
+  AssertNotNull('Have left',AOperand);
+end;
+
+initialization
+
+  RegisterTest(TTestExpressions);
+end.
+

+ 1 - 1
packages/fcl-passrc/tests/tcscanner.pas

@@ -663,7 +663,7 @@ end;
 
 
 procedure TTestScanner.TestAssignDivision;
 procedure TTestScanner.TestAssignDivision;
 begin
 begin
-  TestTokens([tkDivision,tkEqual],'*=');
+  TestTokens([tkDivision,tkEqual],'/=');
   FScanner.Options:=[po_cassignments];
   FScanner.Options:=[po_cassignments];
   TestToken(tkAssignDivision,'/=');
   TestToken(tkAssignDivision,'/=');
 end;
 end;

+ 1 - 1
packages/fcl-passrc/tests/tcstatements.pas

@@ -144,7 +144,7 @@ begin
   ParseModule;
   ParseModule;
   AssertEquals('Have program',TPasProgram,Module.ClassType);
   AssertEquals('Have program',TPasProgram,Module.ClassType);
   AssertNotNull('Have program section',PasProgram.ProgramSection);
   AssertNotNull('Have program section',PasProgram.ProgramSection);
-  AssertNotNull('Have program section',PasProgram.InitializationSection);
+  AssertNotNull('Have initialization section',PasProgram.InitializationSection);
   if (PasProgram.InitializationSection.Elements.Count>0) then
   if (PasProgram.InitializationSection.Elements.Count>0) then
     if TObject(PasProgram.InitializationSection.Elements[0]) is TPasImplBlock then
     if TObject(PasProgram.InitializationSection.Elements[0]) is TPasImplBlock then
       FStatement:=TPasImplBlock(PasProgram.InitializationSection.Elements[0]);
       FStatement:=TPasImplBlock(PasProgram.InitializationSection.Elements[0]);

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

@@ -37,7 +37,7 @@
         <PackageName Value="FCL"/>
         <PackageName Value="FCL"/>
       </Item2>
       </Item2>
     </RequiredPackages>
     </RequiredPackages>
-    <Units Count="9">
+    <Units Count="10">
       <Unit0>
       <Unit0>
         <Filename Value="testpassrc.lpr"/>
         <Filename Value="testpassrc.lpr"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
@@ -83,6 +83,11 @@
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <UnitName Value="tcclasstype"/>
         <UnitName Value="tcclasstype"/>
       </Unit8>
       </Unit8>
+      <Unit9>
+        <Filename Value="tcexprparser.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="tcexprparser"/>
+      </Unit9>
     </Units>
     </Units>
   </ProjectOptions>
   </ProjectOptions>
   <CompilerOptions>
   <CompilerOptions>

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

@@ -5,7 +5,7 @@ program testpassrc;
 uses
 uses
   Classes, consoletestrunner, tcscanner, 
   Classes, consoletestrunner, tcscanner, 
 tctypeparser, tcstatements, tcbaseparser,
 tctypeparser, tcstatements, tcbaseparser,
-  tcmoduleparser, tconstparser, tcvarparser, tcclasstype;
+  tcmoduleparser, tconstparser, tcvarparser, tcclasstype, tcexprparser;
 
 
 type
 type