From da88f7d21733a1cc1366a3292d133963996da691 Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 11 Mar 2017 13:28:22 +0000 Subject: [PATCH] * Fix bug #31283, parsing of Self as identifier git-svn-id: trunk@35562 - --- packages/fcl-passrc/src/pparser.pp | 70 ++++++++++++++++--------- packages/fcl-passrc/src/pscanner.pp | 12 ++++- packages/fcl-passrc/tests/tcscanner.pas | 9 +++- 3 files changed, 64 insertions(+), 27 deletions(-) diff --git a/packages/fcl-passrc/src/pparser.pp b/packages/fcl-passrc/src/pparser.pp index bec7f073bb..b66d10775d 100644 --- a/packages/fcl-passrc/src/pparser.pp +++ b/packages/fcl-passrc/src/pparser.pp @@ -932,7 +932,7 @@ function TPasParser.CheckHint(Element: TPasElement; ExpectSemiColon: Boolean Var Found : Boolean; h : TPasMemberHint; - + begin Result:=[]; Repeat @@ -1423,7 +1423,7 @@ begin NextToken; If CurToken=tkOf then Result.ElType := ParseType(Result,Scanner.CurSourcePos) - else + else ungettoken; end; @@ -1516,7 +1516,7 @@ begin tkLessEqualThan : Result:=eopLessthanEqual; tkGreaterEqualThan : Result:=eopGreaterThanEqual; tkPower : Result:=eopPower; - tkSymmetricalDifference : Result:=eopSymmetricalDifference; + tkSymmetricalDifference : Result:=eopSymmetricalDifference; tkIs : Result:=eopIs; tkAs : Result:=eopAs; tkSHR : Result:=eopSHR; @@ -1534,7 +1534,7 @@ begin ParseExc(nParserNotAnOperand,SParserNotAnOperand,[AToken,TokenInfos[AToken]]); end; end; - + function TPasParser.ParseExpIdent(AParent: TPasElement): TPasExpr; Function IsWriteOrstr(P : TPasExpr) : boolean; @@ -1550,6 +1550,30 @@ function TPasParser.ParseExpIdent(AParent: TPasElement): TPasExpr; Result:=(N='write') or (N='str') or (N='writeln'); end; end; + + Procedure HandleSelf(Var Last: TPasExpr); + + Var + b : TBinaryExpr; + optk : TToken; + + begin + NextToken; + if CurToken = tkDot then + begin // self.Write(EscapeText(AText)); + optk:=CurToken; + NextToken; + b:=CreateBinaryExpr(AParent,Last, ParseExpIdent(AParent), TokenToExprOp(optk)); + if not Assigned(b.right) then + begin + b.Release; + ParseExcExpectedIdentifier; + end; + Last:=b; + end; + UngetToken; + end; + var Last , Expr: TPasExpr; prm : TParamsExpr; @@ -1563,7 +1587,16 @@ begin tkString: Last:=CreatePrimitiveExpr(AParent,pekString,CurTokenString); tkChar: Last:=CreatePrimitiveExpr(AParent,pekString, CurTokenText); tkNumber: Last:=CreatePrimitiveExpr(AParent,pekNumber, CurTokenString); - tkIdentifier: Last:=CreatePrimitiveExpr(AParent,pekIdent, CurTokenText); + tkIdentifier: + begin + if CompareText(CurTokenText,'self')=0 then + begin + Last:=CreateSelfExpr(AParent); + HandleSelf(Last) + end + Else + Last:=CreatePrimitiveExpr(AParent,pekIdent, CurTokenText) + end; tkfalse, tktrue: Last:=CreateBoolConstExpr(Aparent,pekBoolConst, CurToken=tktrue); tknil: Last:=CreateNilExpr(AParent); tkSquaredBraceOpen: Last:=ParseParams(AParent,pekSet); @@ -1587,20 +1620,7 @@ begin tkself: begin Last:=CreateSelfExpr(AParent); - NextToken; - if CurToken = tkDot then - begin // self.Write(EscapeText(AText)); - optk:=CurToken; - NextToken; - b:=CreateBinaryExpr(AParent,Last, ParseExpIdent(AParent), TokenToExprOp(optk)); - if not Assigned(b.right) then - begin - b.Release; - ParseExcExpectedIdentifier; - end; - Last:=b; - end; - UngetToken; + HandleSelf(Last); end; tkAt: begin @@ -1724,7 +1744,7 @@ var i : Integer; tempop : TToken; NotBinary : Boolean; - + const PrefixSym = [tkPlus, tkMinus, tknot, tkAt]; // + - not @ BinaryOP = [tkMul, tkDivision, tkdiv, tkmod, tkDotDot, @@ -2372,6 +2392,7 @@ var if CurBlock=declType then Engine.FinishScope(stTypeSection,Declarations); CurBlock:=NewBlock; + Scanner.SetForceCaret(NewBlock=declType); end; var @@ -2492,7 +2513,6 @@ begin end; declType: begin - Scanner.SetForceCaret(True); TypeEl := ParseTypeDecl(Declarations); // Scanner.SetForceCaret(OldForceCaret); // It may have been switched off if Assigned(TypeEl) then // !!! @@ -2933,7 +2953,7 @@ var TypeName: String; NamePos: TPasSourcePos; OldForceCaret : Boolean; - + begin TypeName := CurTokenString; NamePos:=Scanner.CurSourcePos; @@ -3605,7 +3625,7 @@ begin begin ExpectToken(tkObject); Element.IsOfObject := True; - end + end else if (curToken = tkIs) then begin expectToken(tkIdentifier); @@ -3614,8 +3634,8 @@ begin Element.IsNested:=True; end else - UnGetToken; - end; + UnGetToken; + end; NextToken; if CurToken = tkEqual then begin diff --git a/packages/fcl-passrc/src/pscanner.pp b/packages/fcl-passrc/src/pscanner.pp index 0a422f9d72..a98f798cf3 100644 --- a/packages/fcl-passrc/src/pscanner.pp +++ b/packages/fcl-passrc/src/pscanner.pp @@ -383,7 +383,8 @@ type po_asmwhole, // store whole text between asm..end in TPasImplAsmStatement.Tokens po_nooverloadedprocs, // do not create TPasOverloadedProc for procs with same name po_keepclassforward, // disabled: delete class fowards when there is a class declaration - po_arrayrangeexpr // enable: create TPasArrayType.IndexRange, disable: create TPasArrayType.Ranges + po_arrayrangeexpr, // enable: create TPasArrayType.IndexRange, disable: create TPasArrayType.Ranges + po_selftoken // Self is a token. For backward compatibility. ); TPOptions = set of TPOption; @@ -1301,6 +1302,15 @@ begin tkComment: if not (FSkipComments or PPIsSkipping) then Break; + tkSelf: + begin + if Not (po_selftoken in Options) then + begin + FCurToken:=tkIdentifier; + Result:=FCurToken; + end; + Break; + end; else if not PPIsSkipping then break; diff --git a/packages/fcl-passrc/tests/tcscanner.pas b/packages/fcl-passrc/tests/tcscanner.pas index 0f1087f65e..0d41aa3d8b 100644 --- a/packages/fcl-passrc/tests/tcscanner.pas +++ b/packages/fcl-passrc/tests/tcscanner.pas @@ -82,6 +82,8 @@ type procedure TestNestedComment3; procedure TestNestedComment4; procedure TestIdentifier; + procedure TestSelf; + procedure TestSelfNoToken; procedure TestString; procedure TestNumber; procedure TestChar; @@ -170,7 +172,6 @@ type procedure TestRecord; procedure TestRepeat; procedure TestResourceString; - procedure TestSelf; procedure TestSet; procedure TestShl; procedure TestShr; @@ -1161,9 +1162,15 @@ end; procedure TTestScanner.TestSelf; begin + FScanner.Options:=FScanner.Options + [po_selftoken]; TestToken(tkself,'self'); end; +procedure TTestScanner.TestSelfNoToken; +begin + TestToken(tkIdentifier,'self'); +end; + procedure TTestScanner.TestSet;