Browse Source

* Patch from Mattias Gaertner
- a.b.c is now stored as (a.b).c, which makes restructuring easier.
- fixed closing a type section before a procedure is parsed.

git-svn-id: trunk@35641 -

michael 8 years ago
parent
commit
d9a21a8071
2 changed files with 30 additions and 58 deletions
  1. 26 54
      packages/fcl-passrc/src/pparser.pp
  2. 4 4
      packages/fcl-passrc/tests/tcstatements.pas

+ 26 - 54
packages/fcl-passrc/src/pparser.pp

@@ -282,9 +282,9 @@ type
     function CreatePrimitiveExpr(AParent: TPasElement; AKind: TPasExprKind; const AValue: String): TPrimitiveExpr;
     function CreatePrimitiveExpr(AParent: TPasElement; AKind: TPasExprKind; const AValue: String): TPrimitiveExpr;
     function CreateBoolConstExpr(AParent: TPasElement; AKind: TPasExprKind; const ABoolValue : Boolean): TBoolConstExpr;
     function CreateBoolConstExpr(AParent: TPasElement; AKind: TPasExprKind; const ABoolValue : Boolean): TBoolConstExpr;
     function CreateBinaryExpr(AParent : TPasElement; xleft, xright: TPasExpr; AOpCode: TExprOpCode): TBinaryExpr;
     function CreateBinaryExpr(AParent : TPasElement; xleft, xright: TPasExpr; AOpCode: TExprOpCode): TBinaryExpr;
-    procedure AddToBinaryExprChain(var ChainFirst, ChainLast: TPasExpr;
+    procedure AddToBinaryExprChain(var ChainFirst: TPasExpr;
       Element: TPasExpr; AOpCode: TExprOpCode);
       Element: TPasExpr; AOpCode: TExprOpCode);
-    procedure AddParamsToBinaryExprChain(var ChainFirst, ChainLast: TPasExpr;
+    procedure AddParamsToBinaryExprChain(var ChainFirst: TPasExpr;
       Params: TParamsExpr);
       Params: TParamsExpr);
     {$IFDEF VerbosePasParser}
     {$IFDEF VerbosePasParser}
     procedure WriteBinaryExprChain(Prefix: string; First, Last: TPasExpr);
     procedure WriteBinaryExprChain(Prefix: string; First, Last: TPasExpr);
@@ -1682,7 +1682,7 @@ begin
         if CurToken in [tkIdentifier,tktrue,tkfalse] then // true and false are also identifiers
         if CurToken in [tkIdentifier,tktrue,tkfalse] then // true and false are also identifiers
           begin
           begin
           expr:=CreatePrimitiveExpr(AParent,pekIdent,CurTokenString);
           expr:=CreatePrimitiveExpr(AParent,pekIdent,CurTokenString);
-          AddToBinaryExprChain(Result,Last,expr,eopSubIdent);
+          AddToBinaryExprChain(Result,expr,eopSubIdent);
           func:=expr;
           func:=expr;
           NextToken;
           NextToken;
           end
           end
@@ -1701,12 +1701,11 @@ begin
             else
             else
               prm:=ParseParams(AParent,pekArrayParams);
               prm:=ParseParams(AParent,pekArrayParams);
             if not Assigned(prm) then Exit;
             if not Assigned(prm) then Exit;
-            AddParamsToBinaryExprChain(Result,Last,prm);
+            AddParamsToBinaryExprChain(Result,prm);
             end;
             end;
           tkCaret:
           tkCaret:
             begin
             begin
             Result:=CreateUnaryExpr(AParent,Result,TokenToExprOp(CurToken));
             Result:=CreateUnaryExpr(AParent,Result,TokenToExprOp(CurToken));
-            Last:=Result;
             NextToken;
             NextToken;
             end;
             end;
           else
           else
@@ -1722,7 +1721,7 @@ begin
         if Expr=nil then
         if Expr=nil then
           ParseExcExpectedIdentifier;
           ParseExcExpectedIdentifier;
         if optk=tkDot then
         if optk=tkDot then
-          AddToBinaryExprChain(Result,Last,Expr,TokenToExprOp(optk))
+          AddToBinaryExprChain(Result,Expr,TokenToExprOp(optk))
         else
         else
           begin
           begin
           // a as b
           // a as b
@@ -2498,20 +2497,20 @@ begin
         SetBlock(declProperty);
         SetBlock(declProperty);
       tkProcedure, tkFunction, tkConstructor, tkDestructor,tkOperator:
       tkProcedure, tkFunction, tkConstructor, tkDestructor,tkOperator:
         begin
         begin
+        SetBlock(declNone);
         SaveComments;
         SaveComments;
         pt:=GetProcTypeFromToken(CurToken);
         pt:=GetProcTypeFromToken(CurToken);
         AddProcOrFunction(Declarations, ParseProcedureOrFunctionDecl(Declarations, pt));
         AddProcOrFunction(Declarations, ParseProcedureOrFunctionDecl(Declarations, pt));
-        SetBlock(declNone);
         end;
         end;
       tkClass:
       tkClass:
         begin
         begin
+          SetBlock(declNone);
           SaveComments;
           SaveComments;
           NextToken;
           NextToken;
           If CurToken in [tkprocedure,tkFunction,tkConstructor, tkDestructor] then
           If CurToken in [tkprocedure,tkFunction,tkConstructor, tkDestructor] then
             begin
             begin
             pt:=GetProcTypeFromToken(CurToken,True);
             pt:=GetProcTypeFromToken(CurToken,True);
             AddProcOrFunction(Declarations,ParseProcedureOrFunctionDecl(Declarations, pt));
             AddProcOrFunction(Declarations,ParseProcedureOrFunctionDecl(Declarations, pt));
-            SetBlock(declNone);
             end
             end
           else
           else
             ExpectToken(tkprocedure);
             ExpectToken(tkprocedure);
@@ -3132,17 +3131,20 @@ begin
       ParseExc(nParserOnlyOneVariableCanBeInitialized,SParserOnlyOneVariableCanBeInitialized);
       ParseExc(nParserOnlyOneVariableCanBeInitialized,SParserOnlyOneVariableCanBeInitialized);
     TPasVariable(VarList[OldListCount]).Expr:=Value;
     TPasVariable(VarList[OldListCount]).Expr:=Value;
     Value:=nil;
     Value:=nil;
+
+    // Note: external members are allowed for non external classes too
     ExternalClass:=(msExternalClass in CurrentModeSwitches)
     ExternalClass:=(msExternalClass in CurrentModeSwitches)
-                    and (Parent is TPasClassType) ;
+                    and (Parent is TPasClassType);
+
     H:=H+CheckHint(Nil,False);
     H:=H+CheckHint(Nil,False);
     if Full or Externalclass then
     if Full or Externalclass then
       begin
       begin
       NextToken;
       NextToken;
       If Curtoken<>tkSemicolon then
       If Curtoken<>tkSemicolon then
         UnGetToken;
         UnGetToken;
-      Mods:=GetVariableModifiers(Parent,VarMods,aLibName,aExpName,ExternalClass)  ;
+      Mods:=GetVariableModifiers(Parent,VarMods,aLibName,aExpName,ExternalClass);
       if (mods='') and (CurToken<>tkSemicolon) then
       if (mods='') and (CurToken<>tkSemicolon) then
-         NextToken;
+        NextToken;
       end
       end
     else
     else
       begin
       begin
@@ -3767,14 +3769,12 @@ function TPasParser.ParseProperty(Parent: TPasElement; const AName: String;
 
 
   function GetAccessorName(aParent: TPasElement; out Expr: TPasExpr): String;
   function GetAccessorName(aParent: TPasElement; out Expr: TPasExpr): String;
   var
   var
-    Last: TPasExpr;
     Params: TParamsExpr;
     Params: TParamsExpr;
     Param: TPasExpr;
     Param: TPasExpr;
   begin
   begin
     ExpectIdentifier;
     ExpectIdentifier;
     Result := CurTokenString;
     Result := CurTokenString;
     Expr := CreatePrimitiveExpr(aParent,pekIdent,CurTokenString);
     Expr := CreatePrimitiveExpr(aParent,pekIdent,CurTokenString);
-    Last := Expr;
 
 
     // read .subident.subident...
     // read .subident.subident...
     repeat
     repeat
@@ -3782,7 +3782,7 @@ function TPasParser.ParseProperty(Parent: TPasElement; const AName: String;
       if CurToken <> tkDot then break;
       if CurToken <> tkDot then break;
       ExpectIdentifier;
       ExpectIdentifier;
       Result := Result + '.' + CurTokenString;
       Result := Result + '.' + CurTokenString;
-      AddToBinaryExprChain(Expr,Last,CreatePrimitiveExpr(aParent,pekIdent,CurTokenString),eopSubIdent);
+      AddToBinaryExprChain(Expr,CreatePrimitiveExpr(aParent,pekIdent,CurTokenString),eopSubIdent);
     until false;
     until false;
 
 
     // read optional array index
     // read optional array index
@@ -3793,7 +3793,7 @@ function TPasParser.ParseProperty(Parent: TPasElement; const AName: String;
       Result := Result + '[';
       Result := Result + '[';
       Params:=TParamsExpr(CreateElement(TParamsExpr,'',aParent));
       Params:=TParamsExpr(CreateElement(TParamsExpr,'',aParent));
       Params.Kind:=pekArrayParams;
       Params.Kind:=pekArrayParams;
-      AddParamsToBinaryExprChain(Expr,Last,Params);
+      AddParamsToBinaryExprChain(Expr,Params);
       NextToken;
       NextToken;
       case CurToken of
       case CurToken of
         tkChar:             Param:=CreatePrimitiveExpr(aParent,pekString, CurTokenText);
         tkChar:             Param:=CreatePrimitiveExpr(aParent,pekString, CurTokenText);
@@ -3817,7 +3817,7 @@ function TPasParser.ParseProperty(Parent: TPasElement; const AName: String;
         end;
         end;
       ExpectIdentifier;
       ExpectIdentifier;
       Result := Result + '.' + CurTokenString;
       Result := Result + '.' + CurTokenString;
-      AddToBinaryExprChain(Expr,Last,CreatePrimitiveExpr(aParent,pekIdent,CurTokenString),eopSubIdent);
+      AddToBinaryExprChain(Expr,CreatePrimitiveExpr(aParent,pekIdent,CurTokenString),eopSubIdent);
     until false;
     until false;
   end;
   end;
 
 
@@ -4189,7 +4189,6 @@ begin
         Try
         Try
           ExpectIdentifier;
           ExpectIdentifier;
           Left:=CreatePrimitiveExpr(El,pekIdent,CurTokenString);
           Left:=CreatePrimitiveExpr(El,pekIdent,CurTokenString);
-          Right:=Left;
           TPasImplForLoop(El).VariableName:=Left;
           TPasImplForLoop(El).VariableName:=Left;
           repeat
           repeat
             NextToken;
             NextToken;
@@ -4207,7 +4206,7 @@ begin
               tkDot:
               tkDot:
                 begin
                 begin
                 ExpectIdentifier;
                 ExpectIdentifier;
-                AddToBinaryExprChain(Left,Right,
+                AddToBinaryExprChain(Left,
                   CreatePrimitiveExpr(El,pekIdent,CurTokenString), eopSubIdent);
                   CreatePrimitiveExpr(El,pekIdent,CurTokenString), eopSubIdent);
                 TPasImplForLoop(El).VariableName:=Left;
                 TPasImplForLoop(El).VariableName:=Left;
                 end;
                 end;
@@ -5276,60 +5275,36 @@ begin
     end;
     end;
 end;
 end;
 
 
-procedure TPasParser.AddToBinaryExprChain(var ChainFirst, ChainLast: TPasExpr;
+procedure TPasParser.AddToBinaryExprChain(var ChainFirst: TPasExpr;
   Element: TPasExpr; AOpCode: TExprOpCode);
   Element: TPasExpr; AOpCode: TExprOpCode);
-
-  procedure RaiseInternal;
-  begin
-    raise Exception.Create('TBinaryExpr.AddToChain: internal error');
-  end;
-
-var
-  Last: TBinaryExpr;
 begin
 begin
   if Element=nil then
   if Element=nil then
     exit
     exit
   else if ChainFirst=nil then
   else if ChainFirst=nil then
     begin
     begin
     // empty chain => simply add element, no need to create TBinaryExpr
     // empty chain => simply add element, no need to create TBinaryExpr
-    if (ChainLast<>nil) then
-      RaiseInternal;
     ChainFirst:=Element;
     ChainFirst:=Element;
-    ChainLast:=Element;
-    end
-  else if ChainLast is TBinaryExpr then
-    begin
-    // add a new TBinaryExpr at the end of the chain
-    Last:=TBinaryExpr(ChainLast);
-    if (Last.left=nil) or (Last.right=nil) then
-      // chain not yet full => inconsistency
-      RaiseInternal;
-    Last.right:=CreateBinaryExpr(Last,Last.right,Element,AOpCode);
-    ChainLast:=Last.right;
     end
     end
   else
   else
     begin
     begin
-    // one element => create a TBinaryExpr with two elements
-    if ChainFirst<>ChainLast then
-      RaiseInternal;
-    ChainLast:=CreateBinaryExpr(ChainLast.Parent,ChainLast,Element,AOpCode);
-    ChainFirst:=ChainLast;
+    // create new binary, old becomes left, Element right
+    ChainFirst:=CreateBinaryExpr(ChainFirst.Parent,ChainFirst,Element,AOpCode);
     end;
     end;
 end;
 end;
 
 
-procedure TPasParser.AddParamsToBinaryExprChain(var ChainFirst,
-  ChainLast: TPasExpr; Params: TParamsExpr);
-// append Params to chain, using the last element as Params.Value
+procedure TPasParser.AddParamsToBinaryExprChain(var ChainFirst: TPasExpr;
+  Params: TParamsExpr);
+// append Params to chain, using the last(right) element as Params.Value
 var
 var
   Bin: TBinaryExpr;
   Bin: TBinaryExpr;
 begin
 begin
   if Params.Value<>nil then
   if Params.Value<>nil then
     ParseExcSyntaxError;
     ParseExcSyntaxError;
-  if ChainLast=nil then
+  if ChainFirst=nil then
     ParseExcSyntaxError;
     ParseExcSyntaxError;
-  if ChainLast is TBinaryExpr then
+  if ChainFirst is TBinaryExpr then
     begin
     begin
-    Bin:=TBinaryExpr(ChainLast);
+    Bin:=TBinaryExpr(ChainFirst);
     if Bin.left=nil then
     if Bin.left=nil then
       ParseExcSyntaxError;
       ParseExcSyntaxError;
     if Bin.right=nil then
     if Bin.right=nil then
@@ -5341,13 +5316,10 @@ begin
     end
     end
   else
   else
     begin
     begin
-    if ChainFirst<>ChainLast then
-      ParseExcSyntaxError;
     Params.Value:=ChainFirst;
     Params.Value:=ChainFirst;
     Params.Parent:=ChainFirst.Parent;
     Params.Parent:=ChainFirst.Parent;
     ChainFirst.Parent:=Params;
     ChainFirst.Parent:=Params;
     ChainFirst:=Params;
     ChainFirst:=Params;
-    ChainLast:=Params;
     end;
     end;
 end;
 end;
 
 

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

@@ -402,11 +402,11 @@ begin
   S:=Statement as TPasImplSimple;
   S:=Statement as TPasImplSimple;
   AssertExpression('Doit call',S.Expr,pekBinary,TBinaryExpr);
   AssertExpression('Doit call',S.Expr,pekBinary,TBinaryExpr);
   B:=S.Expr as TBinaryExpr;
   B:=S.Expr as TBinaryExpr;
-  AssertExpression('Unit name part 1',B.Left,pekIdent,'Unita');
-  AssertExpression('Second part of unit name',B.Right,pekBinary,TBinaryExpr);
-  B:=B.Right as TBinaryExpr;
-  AssertExpression('Unit name part 2',B.Left,pekIdent,'ClassB');
   AssertExpression('Doit call',B.Right,pekIdent,'Doit');
   AssertExpression('Doit call',B.Right,pekIdent,'Doit');
+  AssertExpression('First two parts of unit name',B.left,pekBinary,TBinaryExpr);
+  B:=B.left as TBinaryExpr;
+  AssertExpression('Unit name part 1',B.Left,pekIdent,'Unita');
+  AssertExpression('Unit name part 2',B.right,pekIdent,'ClassB');
 end;
 end;
 
 
 procedure TTestStatementParser.TestCallNoArgs;
 procedure TTestStatementParser.TestCallNoArgs;