From e85c36df8765a1ef858881b29dcb17c7a842eb6d Mon Sep 17 00:00:00 2001 From: skalogryz Date: Tue, 3 Mar 2015 14:43:23 +0000 Subject: [PATCH] * cleanup unused variables * added processing for C++ sections (extern "C") * added additional error comment git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3987 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- components/chelper/cparsertypes.pas | 88 ++++++++++++++++++++-------- components/chelper/ctopasconvert.pas | 20 +++---- 2 files changed, 70 insertions(+), 38 deletions(-) diff --git a/components/chelper/cparsertypes.pas b/components/chelper/cparsertypes.pas index 371053da5..4e81d6b3b 100755 --- a/components/chelper/cparsertypes.pas +++ b/components/chelper/cparsertypes.pas @@ -139,7 +139,7 @@ type function NextToken: Boolean; function FindNextToken(var AToken: AnsiString; var ATokenType: TTokenType): Boolean; - procedure SetError(const ErrorCmt: AnsiString); + procedure SetError(const ErrorCmt: AnsiString; const Context: string = ''); end; { TEntity } @@ -251,6 +251,16 @@ type procedure PushToken(const AToken: AnsiString; ATokenType: TTokenType); end; + TCPPSection = class(TEntity); + + TCPPSectionOpen = class(TCPPSection) // an entity for: extern "C" { ... } + public + isCExtern : Boolean; + end; + + TCPPSectionClose = class(TCPPSection) // an entity for just closing character } + end; + const nk_Ident = 0; nk_Ref = 1; @@ -295,7 +305,7 @@ var ParsePreproc: function (AParser: TTextParser): TEntity = nil; function ParseNextEntity(AParser: TTextParser): TEntity; -function ParseNextCEntity(AParser: TTextParser): TEntity; // default ParseNextEntity +function ParseNextCEntity(AParser: TTextParser; ExpectCPPSection: Boolean = true): TEntity; // default ParseNextEntity function ParseCNamePart(Parser: TTextParser): TNamePart; // default ParseNamePart function ParseCExpression(AParser: TTextParser; var ExpS: AnsiString): Boolean; deprecated; @@ -321,8 +331,8 @@ function CreateCParser(const CHeaderText: AnsiString; type TCustomEntityProc = function (Parent: TEntity; Parser: TTextParser): TEntity; -procedure ErrorExpect(Parser: TTextParser; const Expect: AnsiString); -function ConsumeToken(Parser: TTextParser; const Token: AnsiString; const comment: string = ''): Boolean; +procedure ErrorExpect(Parser: TTextParser; const Expect: AnsiString; const Comment: string = '' ); +function ConsumeToken(Parser: TTextParser; const Token: AnsiString; const Comment: string = ''): Boolean; function ConsumeIdentifier(Parser: TTextParser; var Id: AnsiString): Boolean; function ParseCType(Parser: TTextParser): TEntity; @@ -939,8 +949,9 @@ begin end; end; -procedure TTextParser.SetError(const ErrorCmt: AnsiString); +procedure TTextParser.SetError(const ErrorCmt, Context: AnsiString); begin + if Context<>'' then Errors.Add('Error while '+ Context); Errors.Add(ErrorCmt); end; @@ -1496,7 +1507,7 @@ begin end; -procedure ParseSepcifiers(AParser: TTextParser; st: TStrings); +procedure ParseSpecifiers(AParser: TTextParser; st: TStrings); begin while isSomeSpecifier(AParser.Token) do begin st.Add(AParser.Token); @@ -1505,7 +1516,7 @@ begin end; -function ParseNextCEntity(AParser: TTextParser): TEntity; +function ParseNextCEntity(AParser: TTextParser; ExpectCPPSection: Boolean): TEntity; var s : AnsiString; tp : TEntity; @@ -1517,10 +1528,20 @@ begin if s='' then Exit; if s = 'typedef' then begin - Result:=ParseTypeDef(AParser); + Result:=ParseTypeDef(AParser) + end else if (s = '}') and ExpectCPPSection then begin + Result:=TCPPSectionClose.Create; + AParser.NextToken; + // need to exit here, so it won't fail on ";" + Exit; end else begin v:=TVarFuncEntity.Create(AParser.TokenPos); ParseNames(AParser, tp, v.Names, [';']); + if (v.Names.Count=0) and (tp is TCPPSectionOpen) then begin + Result:=tp; + // need to exit here, so it won't fail on ";" + Exit; + end; // declarations like: // fn (int i); @@ -1546,7 +1567,7 @@ begin if AParser.Token<>';' then begin Result.Free; Result:=nil; - ErrorExpect(AParser,';'); + ErrorExpect(AParser,';', 'parsing C entity declaration'); end; end; @@ -1555,17 +1576,17 @@ begin Result:=nil; end; -procedure ErrorExpect(Parser:TTextParser;const Expect:AnsiString); +procedure ErrorExpect(Parser:TTextParser; const Expect, Comment: string); begin //todo: duplication ? - Parser.SetError( ErrExpectStr( Expect, Parser.Token) ); + Parser.SetError( ErrExpectStr( Expect, Parser.Token ), Comment ); end; function ConsumeToken(Parser:TTextParser;const Token: AnsiString; const comment: string):Boolean; begin Result:=Parser.Token=Token; if Result then Parser.NextToken - else Parser.SetError( ErrExpectStr( Token, Parser.Token)+comment); + else Parser.SetError( ErrExpectStr( Token, Parser.Token), Comment); end; function ConsumeIdentifier(Parser: TTextParser; var Id: AnsiString): Boolean; @@ -1797,24 +1818,41 @@ var done : Boolean; specs : TStringList; s : AnsiString; + + extOfs : Integer; begin specs:=TStringList.Create; + try + //todo: this should be outside in C++ specific parsing + extOfs :=Parser.Index; // used for extern "C" only - ParseSepcifiers(Parser, specs); - NameType:=ParseCType(Parser); + ParseSpecifiers(Parser, specs); + NameType:=ParseCType(Parser); - s:=isCallConv(Parser.Token); - if s<>'' then begin - specs.Add(s); - Parser.NextToken; + // cpp extern "C" { + if (Parser.TokenType=tt_String) and (Parser.Token='"C"') and (specs.Count=1) and (specs[0]='extern')then begin + Parser.NextToken; + if not ConsumeToken(Parser, '{', 'extern "C"') then Exit; + NameType:=TCPPSectionOpen.Create(extOfs); + TCPPSectionOpen(NameType).isCExtern:=true; + NameType.EndOffset:=Parser.Index; + Result:=true; + Exit; + end; + + s:=isCallConv(Parser.Token); + if s<>'' then begin + specs.Add(s); + Parser.NextToken; + end; + + Result:=Assigned(NameType); + if Result then NameType.Specifiers.Assign(specs) + else Exit; + finally + Specs.Free; end; - Result:=Assigned(NameType); - if Result then NameType.Specifiers.Assign(specs); - specs.Free; - - if not Result then Exit; - try Result:=False; repeat @@ -1827,7 +1865,7 @@ begin done:=isEndOfName(Parser, EndChars); if not done then begin if Parser.Token <> ',' then begin - ErrorExpect(Parser, ';'); + ErrorExpect(Parser, ';', 'Parsing var/func declarations'); Exit; end; Parser.NextToken; diff --git a/components/chelper/ctopasconvert.pas b/components/chelper/ctopasconvert.pas index 00331983c..a18dbb487 100644 --- a/components/chelper/ctopasconvert.pas +++ b/components/chelper/ctopasconvert.pas @@ -596,9 +596,9 @@ function ParseCEntities(const inp: TParseInput; entList: TList; var outputInfo: TParseOutput): Boolean; var p : TTextParser; - cmt : TStopComment; + //cmt : TStopComment; ent : TEntity; - i : Integer; + //i : Integer; begin p:=inp.parser; //cmt:=inp.stopcmt; @@ -608,11 +608,13 @@ begin outputInfo.error.ErrorPos.Y:=0; outputInfo.error.isError:=false; + ent:=nil; repeat try - p.NextToken; - //ent := ParseNextEntityOrComment(p, cmt, outputInfo.error); + if not (ent is TCPPSection) then + p.NextToken; ent := ParseNextEntity(p); + except ent:=nil; end; @@ -653,7 +655,6 @@ var cmtlist : TList; cnv : TCodeConvertor; ofs : Integer; - pas : string; begin Result:=''; @@ -684,17 +685,10 @@ begin except on e: Exception do Result:=Result+LineEnding+ 'error while converting C code: ' + e.Message; end; - //Result := Result+GetEmptyLines(originText, ofs, ent.Offset); + Result := Result+GetEmptyLines(originText, ofs, ent.Offset); ofs:=ent.Offset; end; - //if Assigned(ent) and (p.Comments.IndexOf(ent)<0) then ent.Free; - //for i:=0 to p.Comments.Count-1 do TComment(p.Comments[i]).Free; - //p.Comments.Clear; - //cmt.Clear; - //until (ent=nil) or not AllText; - - {OffsetToLinePos(t, succidx, endPoint);} Result:=cnv.wr.Text; finally cnv.Free;