View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0016931 | FPC | Packages | public | 2010-07-15 09:26 | 2011-07-23 16:45 |
Reporter | Dmitry Boyarintsev | Assigned To | Michael Van Canneyt | ||
Priority | normal | Severity | minor | Reproducibility | have not tried |
Status | closed | Resolution | fixed | ||
Fixed in Version | 2.4.4 | ||||
Summary | 0016931: fcl-passrc: expression parser patch | ||||
Description | * split TPasExpPart into hierarchy of classes TPasExpr-> TBinary TUnary .. (as discussed) * fixed "ranges" parsing * fixed error for parsing expressions, finishing right after binary operator, i.e. "10+;" ** added SParserExpectedIdentifier error message * simplified TokenToExprOp usage | ||||
Tags | No tags attached. | ||||
Fixed in Revision | 15590 | ||||
FPCOldBugId | 0 | ||||
FPCTarget | |||||
Attached Files |
|
2010-07-15 09:26
|
passrc.patch (13,810 bytes)
Index: src/pastree.pp =================================================================== --- src/pastree.pp (revision 15574) +++ src/pastree.pp (working copy) @@ -67,8 +67,8 @@ SPasTreeDestructorImpl = 'destructor implementation'; type - TPasExprKind = (pekIdent, pekNumber, pekString, pekSet, - pekPrefix, pekPostfix, pekBinary, pekFuncParams, pekArrayParams); + TPasExprKind = (pekIdent, pekNumber, pekString, pekSet, pekRange, + pekUnary, pekBinary, pekFuncParams, pekArrayParams); TExprOpCode = (eopNone, eopAdd,eopSubtract,eopMultiply,eopDivide, eopDiv,eopMod, eopPower,// arithmetic @@ -79,25 +79,46 @@ eopIn,eopIs,eopAs, eopSymmetricaldifference, // Specials eopAddress); - { TPasExprPart } + { TPasExpr } - TPasExprPart = class + TPasExpr = class Kind : TPasExprKind; - Left : TPasExprPart; - Right : TPasExprPart; OpCode : TexprOpcode; - Value : AnsiString; - Params : array of TPasExprPart; + constructor Create(AKind: TPasExprKind; AOpCode: TexprOpcode); + end; + + TUnaryExpr = class(TPasExpr) + Operand : TPasExpr; + constructor Create(AOperand: TPasExpr; AOpCode: TExprOpCode); + destructor Destroy; override; + end; + + { TBinaryExpr } + + TBinaryExpr = class(TPasExpr) + left : TPasExpr; + right : TPasExpr; + constructor Create(xleft, xright: TPasExpr; AOpCode: TExprOpCode); + constructor CreateRange(xleft, xright: TPasExpr); + destructor Destroy; override; + end; + + TPrimitiveExpr = class(TPasExpr) + Value : AnsiString; + constructor Create(AKind: TPasExprKind; const AValue : Ansistring); + end; + + { TParamsExpr } + + TParamsExpr = class(TPasExpr) + Value : TPasExpr; + Params : array of TPasExpr; + {pekArray, pekFuncCall, pekSet} constructor Create(AKind: TPasExprKind); - constructor CreateWithText(AKind: TPasExprKind; const AValue : Ansistring); - constructor CreatePrefix(rightExp: TPasExprPart; const AOpCode: TExprOpCode); - constructor CreatePostfix(leftExp: TPasExprPart; const AOpCode: TExprOpCode); - constructor CreateBinary(xleft, xright: TPasExprPart; const AOpCode: TExprOpCode); destructor Destroy; override; - procedure AddParam(xp: TPasExprPart); + procedure AddParam(xp: TPasExpr); end; - // Visitor pattern. TPassTreeVisitor = class; @@ -467,7 +488,7 @@ Value: string; Modifiers : string; AbsoluteLocation : String; - Expr: TPasExprPart; + Expr: TPasExpr; end; { TPasConst } @@ -2315,52 +2336,61 @@ Result:=true; end; -{ TPasExprPart } +{ TPasExpr } -constructor TPasExprPart.Create(AKind:TPasExprKind); +constructor TPasExpr.Create(AKind: TPasExprKind; AOpCode: TexprOpcode); begin Kind:=AKind; + OpCode:=AOpCode; end; -constructor TPasExprPart.CreateWithText(AKind:TPasExprKind;const AValue: AnsiString); +{ TPrimitiveExpr } + +constructor TPrimitiveExpr.Create(AKind: TPasExprKind; const AValue : Ansistring); begin - Create(AKind); + inherited Create(AKind, eopNone); Value:=AValue; end; -constructor TPasExprPart.CreatePrefix(rightExp: TPasExprPart; const AOpCode: TExprOpCode); +{ TUnaryExpr } + +constructor TUnaryExpr.Create(AOperand: TPasExpr; AOpCode: TExprOpCode); begin - Create(pekPrefix); - right:=rightExp; - Opcode:=AOpCode; + inherited Create(pekUnary, AOpCode); + Operand:=AOperand; end; -constructor TPasExprPart.CreatePostfix(leftExp: TPasExprPart; const AOpCode: TExprOpCode); +destructor TUnaryExpr.Destroy; begin - Create(pekPostfix); - left:=leftExp; - Opcode:=AOpCode; + Operand.Free; end; -constructor TPasExprPart.CreateBinary(xleft, xright: TPasExprPart; const AOpCode: TExprOpcode); +{ TBinaryExpr } + +constructor TBinaryExpr.Create(xleft,xright:TPasExpr; AOpCode:TExprOpCode); begin - Create(pekBinary); + inherited Create(pekBinary, AOpCode); left:=xleft; right:=xright; - Opcode:=AOpCode; end; -destructor TPasExprPart.Destroy; -var - i : Integer; +constructor TBinaryExpr.CreateRange(xleft,xright:TPasExpr); begin + inherited Create(pekRange, eopNone); + left:=xleft; + right:=xright; +end; + +destructor TBinaryExpr.Destroy; +begin left.Free; right.Free; - for i:=0 to length(Params)-1 do Params[i].Free; inherited Destroy; end; -procedure TPasExprPart.AddParam(xp:TPasExprPart); +{ TParamsExpr } + +procedure TParamsExpr.AddParam(xp:TPasExpr); var i : Integer; begin @@ -2369,6 +2399,17 @@ Params[i]:=xp; end; +constructor TParamsExpr.Create(AKind: TPasExprKind); +begin + inherited Create(AKind, eopNone) +end; +destructor TParamsExpr.Destroy; +var + i : Integer; +begin + for i:=0 to length(Params)-1 do Params[i].Free; + inherited Destroy; +end; end. Index: src/pparser.pp =================================================================== --- src/pparser.pp (revision 15574) +++ src/pparser.pp (working copy) @@ -45,6 +45,7 @@ SParserInterfaceTokenError = 'Invalid token in interface section of unit'; SParserImplementationTokenError = 'Invalid token in implementation section of unit'; SParserInvalidTypeDef = 'Invalid type definition'; + SParserExpectedIdentifier = 'Identifier expected'; type TPasTreeContainer = class @@ -115,7 +116,7 @@ procedure ParseExc(const Msg: String); protected function OpLevel(t: TToken): Integer; - Function TokenToExprOp (AToken : TToken; Const AString : String) : TExprOpCode; + Function TokenToExprOp (AToken : TToken) : TExprOpCode; function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement): TPasElement;overload; function CreateElement(AClass: TPTreeElement; const AName: String; @@ -123,8 +124,8 @@ Function IsHint(Const S : String; var AHint : TPasMemberHint) : Boolean; Function CheckHint(Element : TPasElement; ExpectSemiColon : Boolean) : TPasMemberHints; - function ParseParams(paramskind: TPasExprKind): TPasExprPart; - function ParseExpIdent: TPasExprPart; + function ParseParams(paramskind: TPasExprKind): TParamsExpr; + function ParseExpIdent: TPasExpr; public Options : set of TPOptions; CurModule: TPasModule; @@ -142,7 +143,7 @@ function ParseComplexType(Parent : TPasElement = Nil): TPasType; procedure ParseArrayType(Element: TPasArrayType); procedure ParseFileType(Element: TPasFileType); - function DoParseExpression: TPasExprPart; + function DoParseExpression: TPasExpr; function ParseExpression: String; function ParseCommand: String; // single, not compound command like begin..end procedure AddProcOrFunction(Declarations: TPasDeclarations; AProc: TPasProcedure); @@ -646,21 +647,23 @@ ]; -function TPasParser.ParseParams(paramskind: TPasExprKind): TPasExprPart; +function TPasParser.ParseParams(paramskind: TPasExprKind): TParamsExpr; var - params : TPasExprPart; - p : TPasExprPart; + params : TParamsExpr; + p : TPasExpr; PClose : TToken; begin Result:=nil; - if CurToken<>tkBraceOpen then Exit; - if paramskind in [pekArrayParams, pekSet] then - PClose:=tkSquaredBraceClose - else + if paramskind in [pekArrayParams, pekSet] then begin + if CurToken<>tkSquaredBraceOpen then Exit; + PClose:=tkSquaredBraceClose; + end else begin + if CurToken<>tkBraceOpen then Exit; PClose:=tkBraceClose; + end; - params:=TPasExprPart.Create(paramskind); + params:=TParamsExpr.Create(paramskind); try NextToken; if not (CurToken in EndExprToken) then begin @@ -689,7 +692,7 @@ end; end; -Function TPasParser.TokenToExprOp (AToken : TToken; Const AString : String) : TExprOpCode; +Function TPasParser.TokenToExprOp (AToken : TToken) : TExprOpCode; begin Case AToken of @@ -718,68 +721,65 @@ tkNot : Result:=eopNot; tkIn : Result:=eopIn; else - Raise Exception.CreateFmt('Not an operand: (%d : %s)',[AToken,Astring]); + Raise Exception.CreateFmt('Not an operand: (%d : %s)',[AToken,TokenInfos[AToken]]); end; end; -function TPasParser.ParseExpIdent:TPasExprPart; +function TPasParser.ParseExpIdent:TPasExpr; var - x, t : TPasExprPart; - eofid : Boolean; + x : TPasExpr; + prm : TParamsExpr; + u : TUnaryExpr; + b : TBinaryExpr; begin Result:=nil; - eofid:=True; case CurToken of - tkString: begin - x:=TPasExprPart.CreateWithText(pekString, CurTokenString); - NextToken; - end; - tkNumber: - begin - x:=TPasExprPart.CreateWithText(pekNumber, CurTokenString); - NextToken; - end; - tkSquaredBraceOpen: - x:=ParseParams(pekSet); - tkIdentifier: begin - x:=TPasExprPart.CreateWithText(pekIdent, CurTokenText); - eofid:=False; - end; + tkString: x:=TPrimitiveExpr.Create(pekString, CurTokenString); + tkNumber: x:=TPrimitiveExpr.Create(pekNumber, CurTokenString); + tkIdentifier: x:=TPrimitiveExpr.Create(pekIdent, CurTokenText); + tkSquaredBraceOpen: x:=ParseParams(pekSet); + else + ParseExc(SParserExpectedIdentifier); end; - if eofid then begin - Result:=x; - Exit; - end; + if x.Kind<>pekSet then NextToken; try - NextToken; - while CurToken in [tkBraceOpen, tkSquaredBraceOpen, tkCaret] do - case CurToken of - tkBraceOpen: begin - t:=ParseParams(pekFuncParams); - if not Assigned(t) then Exit; - t.left:=x; - x:=t; + if x.Kind=pekIdent then begin + while CurToken in [tkBraceOpen, tkSquaredBraceOpen, tkCaret] do + case CurToken of + tkBraceOpen: begin + prm:=ParseParams(pekFuncParams); + if not Assigned(prm) then Exit; + prm.Value:=x; + x:=prm; + end; + tkSquaredBraceOpen: begin + prm:=ParseParams(pekArrayParams); + if not Assigned(prm) then Exit; + prm.Value:=x; + x:=prm; + end; + tkCaret: begin + u:=TUnaryExpr.Create(x, TokenToExprOp(CurToken)); + x:=u; + NextToken; + end; end; - tkSquaredBraceOpen: begin - t:=ParseParams(pekArrayParams); - if not Assigned(t) then Exit; - t.left:=x; - x:=t; - end; - tkCaret: begin - t:=TPasExprPart.CreatePostfix(x, TokenToExprOp(CurToken,TokenInfos[CurToken])); - NextToken; - x:=t; - end; + + if CurToken in [tkDot, tkas] then begin + NextToken; + b:=TBinaryExpr.Create(x, ParseExpIdent, TokenToExprOp(CurToken)); + if not Assigned(b.right) then Exit; // error + x:=b; end; + end; - if CurToken in [tkDot, tkas] then begin + if CurToken = tkDotDot then begin NextToken; - x:=TPasExprPart.CreateBinary(x, ParseExpIdent, TokenToExprOp(CurToken,TokenInfos[CurToken])); - if not Assigned(x.right) then - Exit; // error? + b:=TBinaryExpr.CreateRange(x, DoParseExpression); + if not Assigned(b.right) then Exit; // error + x:=b; end; Result:=x; @@ -804,22 +804,23 @@ end; end; -function TPasParser.DoParseExpression: TPasExprPart; +function TPasParser.DoParseExpression: TPasExpr; var expstack : TList; opstack : TList; pcount : Integer; - x : TPasExprPart; + x : TPasExpr; i : Integer; tempop : TToken; + AllowEnd : Boolean; const PrefixSym = [tkPlus, tkMinus, tknot, tkAt]; // + - not @ - function PopExp: TPasExprPart; inline; + function PopExp: TPasExpr; inline; begin if expstack.Count>0 then begin - Result:=TPasExprPart(expstack[expstack.Count-1]); + Result:=TPasExpr(expstack[expstack.Count-1]); expstack.Delete(expstack.Count-1); end else Result:=nil; @@ -845,13 +846,13 @@ procedure PopAndPushOperator; var t : TToken; - xright : TPasExprPart; - xleft : TPasExprPart; + xright : TPasExpr; + xleft : TPasExpr; begin t:=PopOper; xright:=PopExp; xleft:=PopExp; - expstack.Add(TPasExprPart.CreateBinary(xleft, xright, TokenToExprOp(t,TokenInfos[t]))); + expstack.Add(TBinaryExpr.Create(xleft, xright, TokenToExprOp(t))); end; begin @@ -860,6 +861,7 @@ opstack := TList.Create; try repeat + AllowEnd:=True; pcount:=0; while CurToken in PrefixSym do begin PushOper(CurToken); @@ -872,18 +874,20 @@ x:=DoParseExpression(); if CurToken<>tkBraceClose then Exit; NextToken; - end else + end else begin x:=ParseExpIdent; + end; if not Assigned(x) then Exit; expstack.Add(x); for i:=1 to pcount do begin tempop:=PopOper; - expstack.Add( TPasExprPart.CreatePrefix( PopExp, TokenToExprOp(tempop,TokenInfos[tempop]) )); + expstack.Add( TUnaryExpr.Create( PopExp, TokenToExprOp(tempop) )); end; if not (CurToken in EndExprToken) then begin // Adjusting order of the operations + AllowEnd:=False; tempop:=PeekOper; while (opstack.Count>0) and (OpLevel(tempop)>=OpLevel(CurToken)) do begin PopAndPushOperator; @@ -893,12 +897,12 @@ NextToken; end; - until CurToken in EndExprToken; + until AllowEnd and (CurToken in EndExprToken); while opstack.Count>0 do PopAndPushOperator; // only 1 expression should be on the stack, at the end of the correct expression - if expstack.Count=1 then Result:=TPasExprPart(expstack[0]); + if expstack.Count=1 then Result:=TPasExpr(expstack[0]); finally if not Assigned(Result) then begin |
|
Thanks for the effort ! |
Date Modified | Username | Field | Change |
---|---|---|---|
2010-07-15 09:26 | Dmitry Boyarintsev | New Issue | |
2010-07-15 09:26 | Dmitry Boyarintsev | File Added: passrc.patch | |
2010-07-16 20:58 | Michael Van Canneyt | Status | new => assigned |
2010-07-16 20:58 | Michael Van Canneyt | Assigned To | => Michael Van Canneyt |
2010-07-16 21:04 | Michael Van Canneyt | Fixed in Revision | => 15590 |
2010-07-16 21:04 | Michael Van Canneyt | Status | assigned => resolved |
2010-07-16 21:04 | Michael Van Canneyt | Fixed in Version | => 2.5.1 |
2010-07-16 21:04 | Michael Van Canneyt | Resolution | open => fixed |
2010-07-16 21:04 | Michael Van Canneyt | Target Version | => 3.0.0 |
2010-07-16 21:04 | Michael Van Canneyt | Note Added: 0039395 | |
2010-07-16 21:10 | Dmitry Boyarintsev | Status | resolved => closed |
2011-05-01 16:07 | Marco van de Voort | FPCOldBugId | => 0 |
2011-05-01 16:07 | Marco van de Voort | Fixed in Version | 2.5.1 => 2.4.4 |
2011-05-01 16:07 | Marco van de Voort | Target Version | 3.0.0 => |
2011-05-02 17:35 | Marco van de Voort | Status | closed => resolved |
2011-07-23 16:45 | Dmitry Boyarintsev | Status | resolved => closed |