You've already forked lazarus-ccr
chelper: improved objc support:
Categories now can have protocol support. Added parameter method direction modified (in, byref, inout .. etc) Parsing of non-class entities (typedef, vars and funcs) within class declaration git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4004 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -86,6 +86,7 @@ type
|
|||||||
Protocols : TStringList;
|
Protocols : TStringList;
|
||||||
Vars : TList;
|
Vars : TList;
|
||||||
Methods : TList;
|
Methods : TList;
|
||||||
|
Entities : TList;
|
||||||
constructor Create(AOffset: Integer=-1); override;
|
constructor Create(AOffset: Integer=-1); override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
end;
|
end;
|
||||||
@ -98,6 +99,7 @@ type
|
|||||||
isForward : Boolean;
|
isForward : Boolean;
|
||||||
Protocols : TStringList;
|
Protocols : TStringList;
|
||||||
Methods : TList;
|
Methods : TList;
|
||||||
|
Entities : TList;
|
||||||
constructor Create(AOffset: Integer=-1); override;
|
constructor Create(AOffset: Integer=-1); override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
end;
|
end;
|
||||||
@ -119,7 +121,7 @@ function ParseClassList(AParser: TTextParser): TObjCClasses;
|
|||||||
function ParseInterface(AParser: TTextParser): TObjCInterface;
|
function ParseInterface(AParser: TTextParser): TObjCInterface;
|
||||||
function ParseMethod(AParser: TTextParser): TObjCMethod;
|
function ParseMethod(AParser: TTextParser): TObjCMethod;
|
||||||
function ParseProperty(AParser: TTextParser): TObjCProperty;
|
function ParseProperty(AParser: TTextParser): TObjCProperty;
|
||||||
function ParseMethods(AParser: TTextParser; MethodsList: TList; const EndToken: AnsiString = objcend): Boolean;
|
function ParseMethods(AParser: TTextParser; MethodsList, OthersList: TList; const EndToken: AnsiString = objcend): Boolean;
|
||||||
function ParseProtocol(AParser: TTextParser): TEntity;
|
function ParseProtocol(AParser: TTextParser): TEntity;
|
||||||
|
|
||||||
function ParseNextObjCEntity(AParser: TTextParser): TEntity;
|
function ParseNextObjCEntity(AParser: TTextParser): TEntity;
|
||||||
@ -258,34 +260,28 @@ begin
|
|||||||
AParser.NextToken;
|
AParser.NextToken;
|
||||||
if not ConsumeIdentifier(AParser, itf.SuperClass) then Exit;
|
if not ConsumeIdentifier(AParser, itf.SuperClass) then Exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// protocols
|
|
||||||
if AParser.Token='<' then begin
|
|
||||||
AParser.NextToken;
|
|
||||||
while AParser.Token<>'>' do begin
|
|
||||||
if not ConsumeIdentifier(AParser, nm) then Exit;
|
|
||||||
itf.Protocols.Add(nm);
|
|
||||||
if AParser.Token=',' then AParser.NextToken
|
|
||||||
else if AParser.Token<>'>' then begin
|
|
||||||
ErrorExpect(AParser, '>');
|
|
||||||
Exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
AParser.NextToken;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ todo: typedef could be found within class
|
|
||||||
while APArser.Token='typedef' do begin
|
|
||||||
ent := ParseTypeDef(APArser );
|
|
||||||
if not Assigned(ent) then Exit;
|
|
||||||
itf.Vars.Add(ent);
|
|
||||||
end;
|
|
||||||
}
|
|
||||||
|
|
||||||
ParseInstVars(AParser, itf.Vars);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if not ParseMethods(AParser, itf.Methods, objcend) then Exit;
|
// protocols, also can be specified for categories
|
||||||
|
if AParser.Token='<' then begin
|
||||||
|
AParser.NextToken;
|
||||||
|
while AParser.Token<>'>' do begin
|
||||||
|
if not ConsumeIdentifier(AParser, nm) then Exit;
|
||||||
|
itf.Protocols.Add(nm);
|
||||||
|
if AParser.Token=',' then AParser.NextToken
|
||||||
|
else if AParser.Token<>'>' then begin
|
||||||
|
ErrorExpect(AParser, '>');
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
AParser.NextToken;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
// categories cannot have instance variables
|
||||||
|
if not itf.isCategory then ParseInstVars(AParser, itf.Vars);
|
||||||
|
|
||||||
|
if not ParseMethods(AParser, itf.Methods, itf.Entities, objcend) then Exit;
|
||||||
if AParser.Token<>objcend then ErrorExpect(AParser, objcend);
|
if AParser.Token<>objcend then ErrorExpect(AParser, objcend);
|
||||||
|
|
||||||
Result:=itf;
|
Result:=itf;
|
||||||
@ -328,7 +324,7 @@ begin
|
|||||||
if AParser.Token='>' then AParser.NextToken;
|
if AParser.Token='>' then AParser.NextToken;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if ParseMethods(AParser, p.Methods, objcend) then
|
if ParseMethods(AParser, p.Methods, p.Entities, objcend) then
|
||||||
Result:=p;
|
Result:=p;
|
||||||
if AParser.Token<>objcend then ErrorExpect(AParser, objcend);
|
if AParser.Token<>objcend then ErrorExpect(AParser, objcend);
|
||||||
finally
|
finally
|
||||||
@ -377,7 +373,8 @@ end;
|
|||||||
constructor TObjCInterface.Create(AOffset:Integer);
|
constructor TObjCInterface.Create(AOffset:Integer);
|
||||||
begin
|
begin
|
||||||
Vars := TList.Create;
|
Vars := TList.Create;
|
||||||
Methods := TList.Create;
|
Methods := TList.Create;
|
||||||
|
Entities := TList.Create;
|
||||||
Protocols := TStringList.Create;
|
Protocols := TStringList.Create;
|
||||||
inherited Create(AOffset);
|
inherited Create(AOffset);
|
||||||
end;
|
end;
|
||||||
@ -390,10 +387,26 @@ begin
|
|||||||
Vars.Free;
|
Vars.Free;
|
||||||
for i:=0 to Methods.Count-1 do TObject(Methods[i]).Free;
|
for i:=0 to Methods.Count-1 do TObject(Methods[i]).Free;
|
||||||
Methods.Free;
|
Methods.Free;
|
||||||
|
for i:=0 to Entities.Count-1 do TObject(Entities[i]).Free;
|
||||||
|
Entities.Free;
|
||||||
Protocols.Free;
|
Protocols.Free;
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function isObjCParamMod(const t: string): Boolean;
|
||||||
|
begin
|
||||||
|
if t ='' then Result:=false
|
||||||
|
else begin
|
||||||
|
Result:=false;
|
||||||
|
case t[1] of
|
||||||
|
'c': if (t = 'const') then Result:=true;
|
||||||
|
'i': if (t = 'in') or (t = 'inout') then Result:=true;
|
||||||
|
'o': if (t = 'out') or (t='oneway') then Result:=true;
|
||||||
|
'b': if (t = 'bycopy') or (t='byref') then Result:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function ParseMethod(AParser: TTextParser): TObjCMethod;
|
function ParseMethod(AParser: TTextParser): TObjCMethod;
|
||||||
var
|
var
|
||||||
m : TObjCMethod;
|
m : TObjCMethod;
|
||||||
@ -425,9 +438,15 @@ begin
|
|||||||
|
|
||||||
while (AParser.Token<>';') and (AParser.Token<>',') do begin
|
while (AParser.Token<>';') and (AParser.Token<>',') do begin
|
||||||
if AParser.Token='(' then begin
|
if AParser.Token='(' then begin
|
||||||
prm:=ConsumeToken(AParser, '(') and
|
prm:=ConsumeToken(AParser, '(');
|
||||||
ParseName(APArser, atype, atname,[')']) and
|
if prm then begin
|
||||||
ConsumeToken(AParser, ')');
|
// todo: need to store them somewhere!
|
||||||
|
while isObjCParamMod(AParser.Token) do
|
||||||
|
AParser.NextToken;
|
||||||
|
|
||||||
|
prm:=ParseName(APArser, atype, atname,[')']) and
|
||||||
|
ConsumeToken(AParser, ')','parsing objc method paramter type');
|
||||||
|
end;
|
||||||
end else begin
|
end else begin
|
||||||
prm:=True;
|
prm:=True;
|
||||||
atype:=nil;
|
atype:=nil;
|
||||||
@ -440,7 +459,7 @@ begin
|
|||||||
// the next name starts
|
// the next name starts
|
||||||
if AParser.TokenType=tt_Ident then ConsumeIdentifier(AParser, nm) else nm:='';
|
if AParser.TokenType=tt_Ident then ConsumeIdentifier(AParser, nm) else nm:='';
|
||||||
if (AParser.Token<>';') and (AParser.Token<>',') then begin
|
if (AParser.Token<>';') and (AParser.Token<>',') then begin
|
||||||
if not ConsumeToken(AParser,':') then Exit;
|
if not ConsumeToken(AParser,':','parsing the objc method " '+Copy(Aparser.Buf, AParser.Index-30, 40)+'"') then Exit;
|
||||||
m.Name.Add(nm+':');
|
m.Name.Add(nm+':');
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -453,7 +472,7 @@ begin
|
|||||||
else ErrorExpect(AParser, '...');
|
else ErrorExpect(AParser, '...');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if not ConsumeToken(AParser, ';') then Exit;
|
if not ConsumeToken(AParser, ';','parsing the end of objc method') then Exit;
|
||||||
|
|
||||||
Result:=m;
|
Result:=m;
|
||||||
finally
|
finally
|
||||||
@ -461,32 +480,39 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ParseMethods(AParser: TTextParser; MethodsList: TList; const EndToken: AnsiString): Boolean;
|
function ParseMethods(AParser: TTextParser; MethodsList, OthersList: TList; const EndToken: AnsiString): Boolean;
|
||||||
var
|
var
|
||||||
m : TObjCMethod;
|
m : TObjCMethod;
|
||||||
p : TObjCProperty;
|
p : TObjCProperty;
|
||||||
opt : TObjCMethodOpt;
|
opt : TObjCMethodOpt;
|
||||||
s : AnsiString;
|
s : AnsiString;
|
||||||
|
ent : TEntity;
|
||||||
begin
|
begin
|
||||||
Result:=False;
|
Result:=False;
|
||||||
if not Assigned(MethodsList) or not Assigned(AParser) then Exit;
|
if not Assigned(MethodsList) or not Assigned(AParser) then Exit;
|
||||||
opt:=mo_Required;
|
opt:=mo_Required;
|
||||||
while (AParser.Token<>EndToken) and (AParser.Token<>'') and (AParser.Token[1] in ['+','-','@']) do begin
|
while (AParser.Token<>EndToken) and (AParser.Token<>'') do begin
|
||||||
if isObjCKeyword(AParser.Token) then begin
|
|
||||||
s:=GetObjCKeyword(AParser.Token);
|
if (AParser.Token[1] in ['+','-','@']) then begin
|
||||||
if s='property' then begin
|
if isObjCKeyword(AParser.Token) then begin
|
||||||
p:=ParseProperty(AParser);
|
s:=GetObjCKeyword(AParser.Token);
|
||||||
MethodsList.Add(p);
|
if s='property' then begin
|
||||||
|
p:=ParseProperty(AParser);
|
||||||
|
MethodsList.Add(p);
|
||||||
|
end else begin
|
||||||
|
if s='optional' then opt:=mo_Optional
|
||||||
|
else opt:=mo_Required;
|
||||||
|
AParser.NextToken;
|
||||||
|
end;
|
||||||
end else begin
|
end else begin
|
||||||
if s='optional' then opt:=mo_Optional
|
m:=ParseMethod(AParser);
|
||||||
else opt:=mo_Required;
|
if not Assigned(m) then Exit;
|
||||||
AParser.NextToken;
|
m.Option:=opt;
|
||||||
|
MethodsList.Add(m);
|
||||||
end;
|
end;
|
||||||
end else begin
|
end else begin
|
||||||
m:=ParseMethod(AParser);
|
ent:=ParseNextCEntity(AParser, false);
|
||||||
if not Assigned(m) then Exit;
|
AParser.NextToken;
|
||||||
m.Option:=opt;
|
|
||||||
MethodsList.Add(m);
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Result:=True;
|
Result:=True;
|
||||||
@ -542,6 +568,7 @@ begin
|
|||||||
inherited Create(AOffset);
|
inherited Create(AOffset);
|
||||||
Protocols := TStringList.Create;
|
Protocols := TStringList.Create;
|
||||||
Methods := TList.Create;
|
Methods := TList.Create;
|
||||||
|
Entities := TList.Create;
|
||||||
Names := TStringList.Create;
|
Names := TStringList.Create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -551,6 +578,8 @@ var
|
|||||||
begin
|
begin
|
||||||
for i:=0 to Methods.Count-1 do TObject(Methods[i]).Free;
|
for i:=0 to Methods.Count-1 do TObject(Methods[i]).Free;
|
||||||
Methods.Free;
|
Methods.Free;
|
||||||
|
for i:=0 to Entities.Count-1 do TObject(Entities[i]).Free;
|
||||||
|
Entities.Free;
|
||||||
Protocols.Free;
|
Protocols.Free;
|
||||||
Names.Free;
|
Names.Free;
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
|
Reference in New Issue
Block a user