mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-15 03:59:10 +02:00
codetools: implemented parsing struct
git-svn-id: trunk@14312 -
This commit is contained in:
parent
2f9c799570
commit
8d36f6dd13
@ -54,6 +54,8 @@ const
|
|||||||
ccnEnum = 5+ccnBase;// e.g. name = value;
|
ccnEnum = 5+ccnBase;// e.g. name = value;
|
||||||
ccnConstant = 6+ccnBase;// e.g. 1
|
ccnConstant = 6+ccnBase;// e.g. 1
|
||||||
ccnTypedef = 7+ccnBase;// e.g. typedef int TInt;
|
ccnTypedef = 7+ccnBase;// e.g. typedef int TInt;
|
||||||
|
ccnStruct = 8+ccnBase;// e.g. struct{};
|
||||||
|
ccnVariable = 9+ccnBase;// e.g. int i
|
||||||
|
|
||||||
type
|
type
|
||||||
TCCodeParserTool = class;
|
TCCodeParserTool = class;
|
||||||
@ -86,7 +88,9 @@ type
|
|||||||
procedure CloseNodes;
|
procedure CloseNodes;
|
||||||
|
|
||||||
procedure ReadEnum;
|
procedure ReadEnum;
|
||||||
|
procedure ReadStruct;
|
||||||
procedure ReadConstant;
|
procedure ReadConstant;
|
||||||
|
procedure ReadVariable;
|
||||||
|
|
||||||
procedure RaiseException(const AMessage: string);
|
procedure RaiseException(const AMessage: string);
|
||||||
procedure RaiseExpectedButAtomFound(const AToken: string);
|
procedure RaiseExpectedButAtomFound(const AToken: string);
|
||||||
@ -99,6 +103,9 @@ type
|
|||||||
SrcPos: Integer;
|
SrcPos: Integer;
|
||||||
AtomStart: integer;
|
AtomStart: integer;
|
||||||
ParseChangeStep: integer;
|
ParseChangeStep: integer;
|
||||||
|
|
||||||
|
LastSrcPos: integer;
|
||||||
|
LastAtomStart: integer;
|
||||||
|
|
||||||
constructor Create;
|
constructor Create;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -110,8 +117,10 @@ type
|
|||||||
|
|
||||||
procedure MoveCursorToPos(p: integer);
|
procedure MoveCursorToPos(p: integer);
|
||||||
procedure ReadNextAtom;
|
procedure ReadNextAtom;
|
||||||
|
procedure UndoReadNextAtom;
|
||||||
function ReadTilBracketClose(ExceptionOnNotFound: boolean): boolean;
|
function ReadTilBracketClose(ExceptionOnNotFound: boolean): boolean;
|
||||||
function AtomIs(const s: shortstring): boolean;
|
function AtomIs(const s: shortstring): boolean;
|
||||||
|
function AtomIsChar(const c: char): boolean;
|
||||||
function UpAtomIs(const s: shortstring): boolean;
|
function UpAtomIs(const s: shortstring): boolean;
|
||||||
function AtomIsIdentifier: boolean;
|
function AtomIsIdentifier: boolean;
|
||||||
function AtomIsStringConstant: boolean;
|
function AtomIsStringConstant: boolean;
|
||||||
@ -174,7 +183,7 @@ begin
|
|||||||
ReadEnum;
|
ReadEnum;
|
||||||
// read semicolon
|
// read semicolon
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
if not AtomIs(';') then
|
if not AtomIsChar(';') then
|
||||||
RaiseExpectedButAtomFound(';');
|
RaiseExpectedButAtomFound(';');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -186,7 +195,7 @@ begin
|
|||||||
if not AtomIsStringConstant then
|
if not AtomIsStringConstant then
|
||||||
RaiseExpectedButAtomFound('string constant');
|
RaiseExpectedButAtomFound('string constant');
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
if not AtomIs('{') then
|
if not AtomIsChar('{') then
|
||||||
RaiseExpectedButAtomFound('{');
|
RaiseExpectedButAtomFound('{');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -202,7 +211,7 @@ procedure TCCodeParserTool.ReadEnum;
|
|||||||
begin
|
begin
|
||||||
CreateChildNode(ccnEnums);
|
CreateChildNode(ccnEnums);
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
if not AtomIs('{') then
|
if not AtomIsChar('{') then
|
||||||
RaiseExpectedButAtomFound('{');
|
RaiseExpectedButAtomFound('{');
|
||||||
// read enums. Examples
|
// read enums. Examples
|
||||||
// name,
|
// name,
|
||||||
@ -213,19 +222,19 @@ begin
|
|||||||
// read enum
|
// read enum
|
||||||
CreateChildNode(ccnEnum);
|
CreateChildNode(ccnEnum);
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
if AtomIs('=') then begin
|
if AtomIsChar('=') then begin
|
||||||
// read value
|
// read value
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
ReadConstant;
|
ReadConstant;
|
||||||
end;
|
end;
|
||||||
EndChildNode;
|
EndChildNode;
|
||||||
end;
|
end;
|
||||||
if AtomIs(',') then begin
|
if AtomIsChar(',') then begin
|
||||||
// next enum
|
// next enum
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
if not AtomIsIdentifier then
|
if not AtomIsIdentifier then
|
||||||
RaiseExpectedButAtomFound('identifier');
|
RaiseExpectedButAtomFound('identifier');
|
||||||
end else if AtomIs('}') then begin
|
end else if AtomIsChar('}') then begin
|
||||||
break;
|
break;
|
||||||
end else
|
end else
|
||||||
RaiseExpectedButAtomFound('}');
|
RaiseExpectedButAtomFound('}');
|
||||||
@ -233,29 +242,72 @@ begin
|
|||||||
EndChildNode;
|
EndChildNode;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCCodeParserTool.ReadStruct;
|
||||||
|
(* For example:
|
||||||
|
typedef struct {
|
||||||
|
uint8_t b[6]; // implicit type
|
||||||
|
} __attribute__((packed)) bdaddr_t;
|
||||||
|
|
||||||
|
*)
|
||||||
|
begin
|
||||||
|
CreateChildNode(ccnStruct);
|
||||||
|
ReadNextAtom;
|
||||||
|
// read {
|
||||||
|
if not AtomIsChar('{') then
|
||||||
|
RaiseExpectedButAtomFound('{');
|
||||||
|
repeat
|
||||||
|
ReadNextAtom;
|
||||||
|
// read variables
|
||||||
|
if AtomIsIdentifier then begin
|
||||||
|
ReadVariable;
|
||||||
|
ReadNextAtom;
|
||||||
|
if AtomIsChar('}') then
|
||||||
|
break
|
||||||
|
else if AtomIsChar(';') then begin
|
||||||
|
// next identifier
|
||||||
|
end else
|
||||||
|
RaiseExpectedButAtomFound('}');
|
||||||
|
end else if AtomIsChar('}') then
|
||||||
|
break
|
||||||
|
else
|
||||||
|
RaiseExpectedButAtomFound('identifier');
|
||||||
|
until false;
|
||||||
|
// read attributes
|
||||||
|
ReadNextAtom;
|
||||||
|
if AtomIs('__attribute__') then begin
|
||||||
|
ReadNextAtom;
|
||||||
|
if not AtomIsChar('(') then
|
||||||
|
RaiseExpectedButAtomFound('(');
|
||||||
|
ReadTilBracketClose(true);
|
||||||
|
end else begin
|
||||||
|
UndoReadNextAtom;
|
||||||
|
end;
|
||||||
|
// close node
|
||||||
|
EndChildNode;
|
||||||
|
end;
|
||||||
|
|
||||||
function TCCodeParserTool.TypedefToken: boolean;
|
function TCCodeParserTool.TypedefToken: boolean;
|
||||||
begin
|
begin
|
||||||
Result:=true;
|
Result:=true;
|
||||||
CreateChildNode(ccnTypedef);
|
CreateChildNode(ccnTypedef);
|
||||||
// read type
|
// read type
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
DebugLn(['TCCodeParserTool.TypedefToken AAA1 ',GetAtom]);
|
|
||||||
if AtomIs('enum') then
|
if AtomIs('enum') then
|
||||||
ReadEnum
|
ReadEnum
|
||||||
|
else if AtomIs('struct') then
|
||||||
|
ReadStruct
|
||||||
else if AtomIsIdentifier then begin
|
else if AtomIsIdentifier then begin
|
||||||
ReadNextAtom;
|
|
||||||
end else
|
end else
|
||||||
RaiseExpectedButAtomFound('identifier');
|
RaiseExpectedButAtomFound('identifier');
|
||||||
// read typedef name
|
// read typedef name
|
||||||
DebugLn(['TCCodeParserTool.TypedefToken AAA2 ',GetAtom]);
|
ReadNextAtom;
|
||||||
if not AtomIsIdentifier then
|
if not AtomIsIdentifier then
|
||||||
RaiseExpectedButAtomFound('identifier');
|
RaiseExpectedButAtomFound('identifier');
|
||||||
// read semicolon
|
// read semicolon
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
DebugLn(['TCCodeParserTool.TypedefToken AAA3 ',GetAtom]);
|
if not AtomIsChar(';') then
|
||||||
if not AtomIs(';') then
|
|
||||||
RaiseExpectedButAtomFound(';');
|
RaiseExpectedButAtomFound(';');
|
||||||
CurNode.EndPos:=SrcPos;
|
|
||||||
EndChildNode;
|
EndChildNode;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -325,15 +377,16 @@ procedure TCCodeParserTool.ReadConstant;
|
|||||||
var
|
var
|
||||||
EndPos: LongInt;
|
EndPos: LongInt;
|
||||||
begin
|
begin
|
||||||
if AtomIs(',') or AtomIs(';') then
|
if AtomIsChar(',') or AtomIsChar(';') then
|
||||||
RaiseExpectedButAtomFound('identifier');
|
RaiseExpectedButAtomFound('identifier');
|
||||||
CreateChildNode(ccnConstant);
|
CreateChildNode(ccnConstant);
|
||||||
repeat
|
repeat
|
||||||
if AtomIs('(') or AtomIs('[') then
|
if AtomIsChar('(') or AtomIsChar('[') then
|
||||||
ReadTilBracketClose(true);
|
ReadTilBracketClose(true);
|
||||||
EndPos:=SrcPos;
|
EndPos:=SrcPos;
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
if AtomIs(',') or AtomIs(';') or AtomIs(')') or AtomIs(']') or AtomIs('}')
|
if AtomIsChar(',') or AtomIsChar(';')
|
||||||
|
or AtomIsChar(')') or AtomIsChar(']') or AtomIsChar('}')
|
||||||
then
|
then
|
||||||
break;
|
break;
|
||||||
until false;
|
until false;
|
||||||
@ -341,6 +394,26 @@ begin
|
|||||||
EndChildNode;
|
EndChildNode;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCCodeParserTool.ReadVariable;
|
||||||
|
(* Examples:
|
||||||
|
int i
|
||||||
|
uint8_t b[6]
|
||||||
|
*)
|
||||||
|
begin
|
||||||
|
CreateChildNode(ccnVariable);
|
||||||
|
// read name
|
||||||
|
ReadNextAtom;
|
||||||
|
if not AtomIsIdentifier then
|
||||||
|
RaiseExpectedButAtomFound('identifier');
|
||||||
|
ReadNextAtom;
|
||||||
|
if AtomIsChar('[') then begin
|
||||||
|
ReadTilBracketClose(true);
|
||||||
|
end else begin
|
||||||
|
UndoReadNextAtom;
|
||||||
|
end;
|
||||||
|
EndChildNode;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCCodeParserTool.RaiseException(const AMessage: string);
|
procedure TCCodeParserTool.RaiseException(const AMessage: string);
|
||||||
begin
|
begin
|
||||||
CloseNodes;
|
CloseNodes;
|
||||||
@ -402,17 +475,33 @@ procedure TCCodeParserTool.MoveCursorToPos(p: integer);
|
|||||||
begin
|
begin
|
||||||
SrcPos:=p;
|
SrcPos:=p;
|
||||||
AtomStart:=p;
|
AtomStart:=p;
|
||||||
|
LastAtomStart:=0;
|
||||||
|
LastSrcPos:=0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCCodeParserTool.ReadNextAtom;
|
procedure TCCodeParserTool.ReadNextAtom;
|
||||||
begin
|
begin
|
||||||
DebugLn(['TCCodeParserTool.ReadNextAtom START ',AtomStart,'-',SrcPos,' ',Src[SrcPos]]);
|
DebugLn(['TCCodeParserTool.ReadNextAtom START ',AtomStart,'-',SrcPos,' ',Src[SrcPos]]);
|
||||||
|
LastSrcPos:=SrcPos;
|
||||||
|
LastAtomStart:=AtomStart;
|
||||||
repeat
|
repeat
|
||||||
ReadRawNextCAtom(Src,SrcPos,AtomStart);
|
ReadRawNextCAtom(Src,SrcPos,AtomStart);
|
||||||
until (SrcPos>SrcLen) or (not (Src[AtomStart] in [#10,#13]));
|
until (SrcPos>SrcLen) or (not (Src[AtomStart] in [#10,#13]));
|
||||||
DebugLn(['TCCodeParserTool.ReadNextAtom END ',AtomStart,'-',SrcPos,' "',copy(Src,AtomStart,SrcPos-AtomStart),'"']);
|
DebugLn(['TCCodeParserTool.ReadNextAtom END ',AtomStart,'-',SrcPos,' "',copy(Src,AtomStart,SrcPos-AtomStart),'"']);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCCodeParserTool.UndoReadNextAtom;
|
||||||
|
begin
|
||||||
|
if LastSrcPos>0 then begin
|
||||||
|
SrcPos:=LastSrcPos;
|
||||||
|
AtomStart:=LastAtomStart;
|
||||||
|
LastSrcPos:=0;
|
||||||
|
LastAtomStart:=0;
|
||||||
|
end else begin
|
||||||
|
SrcPos:=AtomStart;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TCCodeParserTool.ReadTilBracketClose(
|
function TCCodeParserTool.ReadTilBracketClose(
|
||||||
ExceptionOnNotFound: boolean): boolean;
|
ExceptionOnNotFound: boolean): boolean;
|
||||||
// AtomStart must be on bracket open
|
// AtomStart must be on bracket open
|
||||||
@ -470,6 +559,14 @@ begin
|
|||||||
Result:=true;
|
Result:=true;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCCodeParserTool.AtomIsChar(const c: char): boolean;
|
||||||
|
begin
|
||||||
|
if SrcPos-AtomStart<>1 then exit(false);
|
||||||
|
if SrcPos>SrcLen then exit(false);
|
||||||
|
if Src[AtomStart]<>c then exit(false);
|
||||||
|
Result:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
function TCCodeParserTool.UpAtomIs(const s: shortstring): boolean;
|
function TCCodeParserTool.UpAtomIs(const s: shortstring): boolean;
|
||||||
var
|
var
|
||||||
len: Integer;
|
len: Integer;
|
||||||
|
Loading…
Reference in New Issue
Block a user