Browse Source

fcl-passrc: parser: use operator position for TBinaryExpr

git-svn-id: trunk@37245 -
Mattias Gaertner 8 years ago
parent
commit
b2796c13b6

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

@@ -299,7 +299,8 @@ type
     function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement; AVisibility: TPasMemberVisibility; const ASrcPos: TPasSourcePos): TPasElement;overload;
     function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement; AVisibility: TPasMemberVisibility; const ASrcPos: TPasSourcePos): TPasElement;overload;
     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; overload;
+    function CreateBinaryExpr(AParent : TPasElement; xleft, xright: TPasExpr; AOpCode: TExprOpCode; const ASrcPos: TPasSourcePos): TBinaryExpr; overload;
     procedure AddToBinaryExprChain(var ChainFirst: TPasExpr;
     procedure AddToBinaryExprChain(var ChainFirst: TPasExpr;
       Element: TPasExpr; AOpCode: TExprOpCode);
       Element: TPasExpr; AOpCode: TExprOpCode);
     procedure AddParamsToBinaryExprChain(var ChainFirst: TPasExpr;
     procedure AddParamsToBinaryExprChain(var ChainFirst: TPasExpr;
@@ -307,7 +308,8 @@ type
     {$IFDEF VerbosePasParser}
     {$IFDEF VerbosePasParser}
     procedure WriteBinaryExprChain(Prefix: string; First, Last: TPasExpr);
     procedure WriteBinaryExprChain(Prefix: string; First, Last: TPasExpr);
     {$ENDIF}
     {$ENDIF}
-    function CreateUnaryExpr(AParent : TPasElement; AOperand: TPasExpr; AOpCode: TExprOpCode): TUnaryExpr;
+    function CreateUnaryExpr(AParent : TPasElement; AOperand: TPasExpr; AOpCode: TExprOpCode): TUnaryExpr; overload;
+    function CreateUnaryExpr(AParent : TPasElement; AOperand: TPasExpr; AOpCode: TExprOpCode; const ASrcPos: TPasSourcePos): TUnaryExpr; overload;
     function CreateArrayValues(AParent : TPasElement): TArrayValues;
     function CreateArrayValues(AParent : TPasElement): TArrayValues;
     function CreateFunctionType(const AName, AResultName: String; AParent: TPasElement;
     function CreateFunctionType(const AName, AResultName: String; AParent: TPasElement;
              UseParentAsResultParent: Boolean; const NamePos: TPasSourcePos): TPasFunctionType;
              UseParentAsResultParent: Boolean; const NamePos: TPasSourcePos): TPasFunctionType;
@@ -2190,14 +2192,20 @@ begin
 end;
 end;
 
 
 function TPasParser.DoParseExpression(AParent : TPaselement;InitExpr: TPasExpr; AllowEqual : Boolean = True): TPasExpr;
 function TPasParser.DoParseExpression(AParent : TPaselement;InitExpr: TPasExpr; AllowEqual : Boolean = True): TPasExpr;
+type
+  TOpStackItem = record
+    Token: TToken;
+    SrcPos: TPasSourcePos;
+  end;
+
 var
 var
-  expstack  : TFPList;
-  opstack   : array of TToken;
-  opstackTop: integer;
-  pcount    : Integer;
+  ExpStack  : TFPList;
+  OpStack   : array of TOpStackItem;
+  OpStackTop: integer;
+  PrefixCnt : Integer;
   x         : TPasExpr;
   x         : TPasExpr;
   i         : Integer;
   i         : Integer;
-  tempop    : TToken;
+  TempOp    : TToken;
   NotBinary : Boolean;
   NotBinary : Boolean;
 
 
 const
 const
@@ -2210,31 +2218,38 @@ const
 
 
   function PopExp: TPasExpr; inline;
   function PopExp: TPasExpr; inline;
   begin
   begin
-    if expstack.Count>0 then begin
-      Result:=TPasExpr(expstack[expstack.Count-1]);
-      expstack.Delete(expstack.Count-1);
+    if ExpStack.Count>0 then begin
+      Result:=TPasExpr(ExpStack[ExpStack.Count-1]);
+      ExpStack.Delete(ExpStack.Count-1);
     end else
     end else
       Result:=nil;
       Result:=nil;
   end;
   end;
 
 
-  procedure PushOper(token: TToken); inline;
+  procedure PushOper(Token: TToken);
   begin
   begin
-    inc(opstackTop);
-    if opstackTop=length(opstack) then
-      SetLength(opstack,length(opstack)*2+4);
-    opstack[opstackTop]:=token;
+    inc(OpStackTop);
+    if OpStackTop=length(OpStack) then
+      SetLength(OpStack,length(OpStack)*2+4);
+    OpStack[OpStackTop].Token:=Token;
+    OpStack[OpStackTop].SrcPos:=CurTokenPos;
   end;
   end;
 
 
   function PeekOper: TToken; inline;
   function PeekOper: TToken; inline;
   begin
   begin
-    if opstackTop>=0 then Result:=opstack[opstackTop]
+    if OpStackTop>=0 then Result:=OpStack[OpStackTop].Token
     else Result:=tkEOF;
     else Result:=tkEOF;
   end;
   end;
 
 
-  function PopOper: TToken; inline;
+  function PopOper(out SrcPos: TPasSourcePos): TToken;
   begin
   begin
     Result:=PeekOper;
     Result:=PeekOper;
-    if Result<>tkEOF then dec(opstackTop);
+    if Result=tkEOF then
+      SrcPos:=DefPasSourcePos
+    else
+      begin
+      SrcPos:=OpStack[OpStackTop].SrcPos;
+      dec(OpStackTop);
+      end;
   end;
   end;
 
 
   procedure PopAndPushOperator;
   procedure PopAndPushOperator;
@@ -2243,22 +2258,24 @@ const
     xright  : TPasExpr;
     xright  : TPasExpr;
     xleft   : TPasExpr;
     xleft   : TPasExpr;
     bin     : TBinaryExpr;
     bin     : TBinaryExpr;
+    SrcPos: TPasSourcePos;
   begin
   begin
-    t:=PopOper;
+    t:=PopOper(SrcPos);
     xright:=PopExp;
     xright:=PopExp;
     xleft:=PopExp;
     xleft:=PopExp;
     if t=tkDotDot then
     if t=tkDotDot then
       begin
       begin
-      bin:=CreateBinaryExpr(AParent,xleft,xright,eopNone);
+      bin:=CreateBinaryExpr(AParent,xleft,xright,eopNone,SrcPos);
       bin.Kind:=pekRange;
       bin.Kind:=pekRange;
       end
       end
     else
     else
-      bin:=CreateBinaryExpr(AParent,xleft,xright,TokenToExprOp(t));
-    expstack.Add(bin);
+      bin:=CreateBinaryExpr(AParent,xleft,xright,TokenToExprOp(t),SrcPos);
+    ExpStack.Add(bin);
   end;
   end;
 
 
 Var
 Var
   AllowedBinaryOps : Set of TToken;
   AllowedBinaryOps : Set of TToken;
+  SrcPos: TPasSourcePos;
 
 
 begin
 begin
   AllowedBinaryOps:=BinaryOP;
   AllowedBinaryOps:=BinaryOP;
@@ -2266,13 +2283,13 @@ begin
     Exclude(AllowedBinaryOps,tkEqual);
     Exclude(AllowedBinaryOps,tkEqual);
   //DumpCurToken('Entry',iaIndent);
   //DumpCurToken('Entry',iaIndent);
   Result:=nil;
   Result:=nil;
-  expstack := TFPList.Create;
-  SetLength(opstack,4);
-  opstackTop:=-1;
+  ExpStack := TFPList.Create;
+  SetLength(OpStack,4);
+  OpStackTop:=-1;
   try
   try
     repeat
     repeat
       NotBinary:=True;
       NotBinary:=True;
-      pcount:=0;
+      PrefixCnt:=0;
       if not Assigned(InitExpr) then
       if not Assigned(InitExpr) then
         begin
         begin
         // the first part of the expression has been parsed externally.
         // the first part of the expression has been parsed externally.
@@ -2291,7 +2308,7 @@ begin
         while CurToken in PrefixSym do
         while CurToken in PrefixSym do
           begin
           begin
           PushOper(CurToken);
           PushOper(CurToken);
-          inc(pcount);
+          inc(PrefixCnt);
           NextToken;
           NextToken;
           end;
           end;
 
 
@@ -2311,6 +2328,7 @@ begin
             x:=CreateUnaryExpr(AParent,x, TokenToExprOp(tkCaret));
             x:=CreateUnaryExpr(AParent,x, TokenToExprOp(tkCaret));
             NextToken;
             NextToken;
             end;
             end;
+          // ToDo: move dot below []
           // for expressions like (TObject(m)).Free;
           // for expressions like (TObject(m)).Free;
           if (x<>Nil) and (CurToken=tkDot) then
           if (x<>Nil) and (CurToken=tkDot) then
             begin
             begin
@@ -2329,34 +2347,35 @@ begin
           end;
           end;
         if not Assigned(x) then
         if not Assigned(x) then
           ParseExcSyntaxError;
           ParseExcSyntaxError;
-        expstack.Add(x);
+        ExpStack.Add(x);
 
 
-        for i:=1 to pcount do
+        for i:=1 to PrefixCnt do
           begin
           begin
-          tempop:=PopOper;
-          x:=popexp;
-          if (tempop=tkMinus) and (x.Kind=pekRange) then
+          TempOp:=PopOper(SrcPos);
+          x:=PopExp;
+          if (TempOp=tkMinus) and (x.Kind=pekRange) then
             begin
             begin
-            TBinaryExpr(x).Left:=CreateUnaryExpr(x, TBinaryExpr(x).left, eopSubtract);
-            expstack.Add(x);
+            TBinaryExpr(x).Left:=CreateUnaryExpr(x, TBinaryExpr(x).left,
+                                                 eopSubtract, SrcPos);
+            ExpStack.Add(x);
             end
             end
           else
           else
-            expstack.Add(CreateUnaryExpr(AParent, x, TokenToExprOp(tempop) ));
+            ExpStack.Add(CreateUnaryExpr(AParent, x, TokenToExprOp(TempOp), SrcPos));
           end;
           end;
         end
         end
       else
       else
         begin
         begin
-        expstack.Add(InitExpr);
+        ExpStack.Add(InitExpr);
         InitExpr:=nil;
         InitExpr:=nil;
         end;
         end;
       if (CurToken in AllowedBinaryOPs) then
       if (CurToken in AllowedBinaryOPs) then
         begin
         begin
         // Adjusting order of the operations
         // Adjusting order of the operations
         NotBinary:=False;
         NotBinary:=False;
-        tempop:=PeekOper;
-        while (opstackTop>=0) and (OpLevel(tempop)>=OpLevel(CurToken)) do begin
+        TempOp:=PeekOper;
+        while (OpStackTop>=0) and (OpLevel(TempOp)>=OpLevel(CurToken)) do begin
           PopAndPushOperator;
           PopAndPushOperator;
-          tempop:=PeekOper;
+          TempOp:=PeekOper;
         end;
         end;
         PushOper(CurToken);
         PushOper(CurToken);
         NextToken;
         NextToken;
@@ -2366,14 +2385,14 @@ begin
 
 
     if not NotBinary then ParseExcExpectedIdentifier;
     if not NotBinary then ParseExcExpectedIdentifier;
 
 
-    while opstackTop>=0 do PopAndPushOperator;
+    while OpStackTop>=0 do PopAndPushOperator;
 
 
-    // only 1 expression should be on the stack, at the end of the correct expression
-    if expstack.Count<>1 then
+    // only 1 expression should be on the OpStack, at the end of the correct expression
+    if ExpStack.Count<>1 then
       ParseExcSyntaxError;
       ParseExcSyntaxError;
-    if expstack.Count=1 then
+    if ExpStack.Count=1 then
       begin
       begin
-      Result:=TPasExpr(expstack[0]);
+      Result:=TPasExpr(ExpStack[0]);
       Result.Parent:=AParent;
       Result.Parent:=AParent;
       end;
       end;
 
 
@@ -2384,11 +2403,11 @@ begin
       DumpCurtoken('Exiting (Result: "'+Result.GetDeclaration(true)+'") ',iaUndent);}
       DumpCurtoken('Exiting (Result: "'+Result.GetDeclaration(true)+'") ',iaUndent);}
     if not Assigned(Result) then begin
     if not Assigned(Result) then begin
       // expression error!
       // expression error!
-      for i:=0 to expstack.Count-1 do
-        TPasExpr(expstack[i]).Release;
+      for i:=0 to ExpStack.Count-1 do
+        TPasExpr(ExpStack[i]).Release;
     end;
     end;
-    SetLength(opstack,0);
-    expstack.Free;
+    SetLength(OpStack,0);
+    ExpStack.Free;
   end;
   end;
 end;
 end;
 
 
@@ -6037,7 +6056,10 @@ function TPasParser.CreateElement(AClass: TPTreeElement; const AName: String;
   AParent: TPasElement; AVisibility: TPasMemberVisibility;
   AParent: TPasElement; AVisibility: TPasMemberVisibility;
   const ASrcPos: TPasSourcePos): TPasElement;
   const ASrcPos: TPasSourcePos): TPasElement;
 begin
 begin
-  Result := Engine.CreateElement(AClass, AName, AParent, AVisibility, ASrcPos);
+  if (ASrcPos.Row=0) and (ASrcPos.FileName='') then
+    Result := Engine.CreateElement(AClass, AName, AParent, AVisibility, CurSourcePos)
+  else
+    Result := Engine.CreateElement(AClass, AName, AParent, AVisibility, ASrcPos);
 end;
 end;
 
 
 function TPasParser.CreatePrimitiveExpr(AParent: TPasElement;
 function TPasParser.CreatePrimitiveExpr(AParent: TPasElement;
@@ -6059,7 +6081,14 @@ end;
 function TPasParser.CreateBinaryExpr(AParent: TPasElement; xleft,
 function TPasParser.CreateBinaryExpr(AParent: TPasElement; xleft,
   xright: TPasExpr; AOpCode: TExprOpCode): TBinaryExpr;
   xright: TPasExpr; AOpCode: TExprOpCode): TBinaryExpr;
 begin
 begin
-  Result:=TBinaryExpr(CreateElement(TBinaryExpr,'',AParent));
+  Result:=CreateBinaryExpr(AParent,xleft,xright,AOpCode,CurSourcePos);
+end;
+
+function TPasParser.CreateBinaryExpr(AParent: TPasElement; xleft,
+  xright: TPasExpr; AOpCode: TExprOpCode; const ASrcPos: TPasSourcePos
+  ): TBinaryExpr;
+begin
+  Result:=TBinaryExpr(CreateElement(TBinaryExpr,'',AParent,ASrcPos));
   Result.OpCode:=AOpCode;
   Result.OpCode:=AOpCode;
   Result.Kind:=pekBinary;
   Result.Kind:=pekBinary;
   if xleft<>nil then
   if xleft<>nil then
@@ -6187,7 +6216,13 @@ end;
 function TPasParser.CreateUnaryExpr(AParent: TPasElement; AOperand: TPasExpr;
 function TPasParser.CreateUnaryExpr(AParent: TPasElement; AOperand: TPasExpr;
   AOpCode: TExprOpCode): TUnaryExpr;
   AOpCode: TExprOpCode): TUnaryExpr;
 begin
 begin
-  Result:=TUnaryExpr(CreateElement(TUnaryExpr,'',AParent,CurTokenPos));
+  Result:=CreateUnaryExpr(AParent,AOperand,AOpCode,CurTokenPos);
+end;
+
+function TPasParser.CreateUnaryExpr(AParent: TPasElement; AOperand: TPasExpr;
+  AOpCode: TExprOpCode; const ASrcPos: TPasSourcePos): TUnaryExpr;
+begin
+  Result:=TUnaryExpr(CreateElement(TUnaryExpr,'',AParent,ASrcPos));
   Result.Kind:=pekUnary;
   Result.Kind:=pekUnary;
   Result.Operand:=AOperand;
   Result.Operand:=AOperand;
   Result.Operand.Parent:=Result;
   Result.Operand.Parent:=Result;

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

@@ -493,6 +493,8 @@ type
     FileName: String;
     FileName: String;
     Row, Column: Cardinal;
     Row, Column: Cardinal;
   end;
   end;
+const
+  DefPasSourcePos: TPasSourcePos = (Filename:''; Row:0; Column:0);
 
 
 type
 type
   { TPascalScanner }
   { TPascalScanner }

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

@@ -6954,7 +6954,7 @@ begin
   Add('    Some: longint;');
   Add('    Some: longint;');
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
-  CheckResolverException('Duplicate identifier "Some" at afile.pp(5,9)',nDuplicateIdentifier);
+  CheckResolverException('Duplicate identifier "Some" at afile.pp(5,5)',nDuplicateIdentifier);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_ReintroducePrivateVar;
 procedure TTestResolver.TestClass_ReintroducePrivateVar;

+ 2 - 2
packages/pastojs/src/fppas2js.pp

@@ -1119,8 +1119,8 @@ type
         ForLoop: TPasImplForLoop;
         ForLoop: TPasImplForLoop;
         LoopVar: TPasElement;
         LoopVar: TPasElement;
         FoundLoop: boolean;
         FoundLoop: boolean;
-        LoopVarWrite: boolean; // true if first acces of LoopVar after loop is a write
-        LoopVarRead: boolean; // true if first acces of LoopVar after loop is a read
+        LoopVarWrite: boolean; // true if first access of LoopVar after loop is a write
+        LoopVarRead: boolean; // true if first access of LoopVar after loop is a read
       end;
       end;
       PForLoopFindData = ^TForLoopFindData;
       PForLoopFindData = ^TForLoopFindData;
     procedure ForLoop_OnProcBodyElement(El: TPasElement; arg: pointer);
     procedure ForLoop_OnProcBodyElement(El: TPasElement; arg: pointer);

+ 1 - 1
packages/pastojs/tests/tcmodules.pas

@@ -9289,7 +9289,7 @@ begin
   Add('    Id: longint;');
   Add('    Id: longint;');
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
-  SetExpectedPasResolverError('Duplicate identifier "Id" at test1.pp(6,7)',nDuplicateIdentifier);
+  SetExpectedPasResolverError('Duplicate identifier "Id" at test1.pp(6,5)',nDuplicateIdentifier);
   ConvertProgram;
   ConvertProgram;
 end;
 end;
 
 

+ 20 - 3
packages/pastojs/tests/tcsrcmap.pas

@@ -56,6 +56,7 @@ type
     procedure TestEmptyProgram;
     procedure TestEmptyProgram;
     procedure TestEmptyUnit;
     procedure TestEmptyUnit;
     procedure TestIf;
     procedure TestIf;
+    procedure TestFor;
   end;
   end;
 
 
 implementation
 implementation
@@ -91,13 +92,14 @@ begin
 end;
 end;
 
 
 procedure TCustomTestSrcMap.CheckSrcMap(const aTitle: string);
 procedure TCustomTestSrcMap.CheckSrcMap(const aTitle: string);
+{$IFDEF VerbosePas2JS}
 var
 var
   i: Integer;
   i: Integer;
+{$ENDIF}
 begin
 begin
   {$IFDEF VerbosePas2JS}
   {$IFDEF VerbosePas2JS}
   writeln('TCustomTestSrcMap.CheckSrcMap ',aTitle);
   writeln('TCustomTestSrcMap.CheckSrcMap ',aTitle);
-  {$ENDIF}
-  for i:=0 to SrcMap.Count-1 do
+  {for i:=0 to SrcMap.Count-1 do
     begin
     begin
     write('TCustomTestSrcMap.CheckSrcMap i=',i,' Gen=',
     write('TCustomTestSrcMap.CheckSrcMap i=',i,' Gen=',
       SrcMap[i].GeneratedLine,',',SrcMap[i].GeneratedColumn);
       SrcMap[i].GeneratedLine,',',SrcMap[i].GeneratedColumn);
@@ -105,10 +107,12 @@ begin
     if SrcMap[i].SrcFileIndex>0 then
     if SrcMap[i].SrcFileIndex>0 then
       write(SrcMap.SourceFiles[SrcMap[i].SrcFileIndex],',');
       write(SrcMap.SourceFiles[SrcMap[i].SrcFileIndex],',');
     writeln(SrcMap[i].SrcLine,',',SrcMap[i].SrcColumn);
     writeln(SrcMap[i].SrcLine,',',SrcMap[i].SrcColumn);
-    end;
+    end;}
   for i:=1 to JSSource.Count do
   for i:=1 to JSSource.Count do
     WriteSrcMapLine(i);
     WriteSrcMapLine(i);
+  writeln('......012345678901234567890123456789012345678901234567890123456789');
   WriteSources(Filename,1,1);
   WriteSources(Filename,1,1);
+  {$ENDIF}
 end;
 end;
 
 
 procedure TCustomTestSrcMap.WriteSrcMapLine(GeneratedLine: integer);
 procedure TCustomTestSrcMap.WriteSrcMapLine(GeneratedLine: integer);
@@ -234,6 +238,19 @@ begin
   CheckSrcMap('TestEmptyProgram');
   CheckSrcMap('TestEmptyProgram');
 end;
 end;
 
 
+procedure TTestSrcMap.TestFor;
+begin
+  StartProgram(false);
+  Add([
+  'var Runner, i: longint;',
+  'begin',
+  '  for Runner := 1000 + 2000 to 3000 do',
+  '    inc(i);',
+  '']);
+  ConvertProgram;
+  CheckSrcMap('TestEmptyProgram');
+end;
+
 Initialization
 Initialization
   RegisterTests([TTestSrcMap]);
   RegisterTests([TTestSrcMap]);