codetools: implemented start of extern c

git-svn-id: trunk@14283 -
This commit is contained in:
mattias 2008-02-27 15:22:12 +00:00
parent 1825f74f2a
commit 9519c2624f
7 changed files with 105 additions and 37 deletions

View File

@ -49,6 +49,7 @@ const
ccnRoot = 1+ccnBase;
ccnDirective = 2+ccnBase;// e.g. "#define a" ,can be multiple lines, without line end
ccnExtern = 3+ccnBase;// e.g. extern "C" {}
type
TCCodeParserTool = class;
@ -70,6 +71,7 @@ type
function OtherToken: boolean;
function DirectiveToken: boolean;
function ExternToken: boolean;
procedure InitKeyWordList;
procedure InitParser;
@ -78,6 +80,7 @@ type
procedure CloseNodes;
procedure RaiseException(const AMessage: string);
procedure RaiseExpectedButAtomFound(const AToken: string);
public
Code: TCodeBuffer;
Src: string;
@ -101,6 +104,7 @@ type
function AtomIs(const s: shortstring): boolean;
function UpAtomIs(const s: shortstring): boolean;
function AtomIsIdentifier: boolean;
function AtomIsStringConstant: boolean;
function GetAtom: string;
procedure Replace(FromPos, ToPos: integer; const NewSrc: string);
@ -152,12 +156,25 @@ begin
EndChildNode;
end;
function TCCodeParserTool.ExternToken: boolean;
begin
Result:=true;
CreateChildNode(ccnExtern);
ReadNextAtom;
if not AtomIsStringConstant then
RaiseExpectedButAtomFound('string constant');
ReadNextAtom;
if not AtomIs('{') then
RaiseExpectedButAtomFound('{');
end;
procedure TCCodeParserTool.InitKeyWordList;
begin
if FDefaultTokenList=nil then begin
FDefaultTokenList:=TKeyWordFunctionList.Create;
with FDefaultTokenList do begin
Add('#',{$ifdef FPC}@{$endif}DirectiveToken);
Add('extern',{$ifdef FPC}@{$endif}ExternToken);
DefaultKeyWordFunction:={$ifdef FPC}@{$endif}OtherToken;
end;
end;
@ -216,6 +233,11 @@ begin
raise ECCodeParserException.Create(Self,AMessage);
end;
procedure TCCodeParserTool.RaiseExpectedButAtomFound(const AToken: string);
begin
RaiseException(AToken+' expected, but '+GetAtom+' found');
end;
constructor TCCodeParserTool.Create;
begin
Tree:=TCodeTree.Create;
@ -318,6 +340,11 @@ begin
Result:=true;
end;
function TCCodeParserTool.AtomIsStringConstant: boolean;
begin
Result:=(AtomStart<SrcLen) and (Src[AtomStart]='"');
end;
function TCCodeParserTool.GetAtom: string;
begin
Result:=copy(Src,AtomStart,SrcPos-AtomStart);

View File

@ -1900,7 +1900,8 @@ var
NeededType:=ctnNone;
if BracketStartPos>0 then begin
if WordIsKeyWord.DoIt(@Src[ReferingPos]) then exit;
if WordIsKeyWord.DoItCaseInsensitive(@Src[ReferingPos]) then
exit;
// this is a type cast
NeededType:=ctnConstDefinition;
//GetReferingNode;

View File

@ -1930,7 +1930,8 @@ var
repeat
ReadNextAtom;
if (AtomStart<=SrcLen)
and IsKeyWordProcedureSpecifier.DoIt(@Src[AtomStart]) then begin
and IsKeyWordProcedureSpecifier.DoItCaseInsensitive(@Src[AtomStart])
then begin
if UpAtomIs('EXTERNAL') then
IsExternal:=true;
if UpAtomIs('FORWARD') then

View File

@ -27,6 +27,8 @@ unit KeywordFuncLists;
{$ifdef FPC}{$mode objfpc}{$endif}{$H+}
{$R-} // turn range checking off for speed
interface
{ $DEFINE MEM_CHECK}
@ -49,6 +51,8 @@ type
end;
PKeyWordFunctionListItem = ^TKeyWordFunctionListItem;
{ TKeyWordFunctionList }
TKeyWordFunctionList = class
private
FItems: PKeyWordFunctionListItem;
@ -65,12 +69,14 @@ type
public
DefaultKeyWordFunction: TKeyWordFunction;
function DoIt(const AKeyWord: shortstring): boolean;
function DoIt(const ASource: string;
KeyWordStart, KeyWordLen: integer): boolean;
function DoIt(Identifier: PChar): boolean;
function DoItUppercase(const AnUpperSource: string;
KeyWordStart, KeyWordLen: integer): boolean;
function DoItCaseInsensitive(const AKeyWord: shortstring): boolean;
function DoItCaseInsensitive(const ASource: string;
KeyWordStart, KeyWordLen: integer): boolean;
function DoIt(const ASource: string;
KeyWordStart, KeyWordLen: integer): boolean;
function DoItUppercase(const AnUpperSource: string;
KeyWordStart, KeyWordLen: integer): boolean;
function DoItCaseInsensitive(Identifier: PChar): boolean;
function DoDataFunction(Start: PChar; Len: integer; Data: pointer): boolean;
procedure Clear;
procedure Add(const AKeyWord: shortstring;
@ -145,9 +151,8 @@ function IsUpperCaseStr(const s: string): boolean;
implementation
var
CharToHash: array[char] of integer;
CharToIHash: array[char] of integer;
UpWords: array[word] of word;
function UpperCaseStr(const s: string): string;
@ -181,11 +186,7 @@ end;
constructor TKeyWordFunctionList.Create;
begin
inherited Create;
FItems:=nil;
FCount:=0;
FCapacity:=0;
FSorted:=true;
FBucketStart:=nil;
FMaxHashIndex:=-1;
DefaultKeyWordFunction:={$ifdef FPC}@{$endif}AllwaysFalse;
end;
@ -220,7 +221,7 @@ begin
if KeyWordLen>20 then KeyWordLen:=20;
Result:=0;
for i:=1 to KeyWordLen do
inc(Result,CharToHash[AKeyWord[i]]);
inc(Result,CharToIHash[AKeyWord[i]]);
if Result>FMaxHashIndex then Result:=-1;
end;
@ -232,7 +233,7 @@ begin
AEnd:=AStart+ALen-1;
Result:=0;
for i:=AStart to AEnd do
inc(Result,CharToHash[ASource[i]]);
inc(Result,CharToIHash[ASource[i]]);
if Result>FMaxHashIndex then Result:=-1;
end;
@ -242,7 +243,7 @@ begin
Result:=0;
i:=20;
while (i>0) and IsIdentChar[Identifier[0]] do begin
inc(Result,CharToHash[Identifier[0]]);
inc(Result,CharToIHash[Identifier[0]]);
dec(i);
inc(Identifier);
end;
@ -255,7 +256,7 @@ begin
Result:=0;
if Len>20 then Len:=20;
while (Len>0) do begin
inc(Result,CharToHash[Start^]);
inc(Result,CharToIHash[Start^]);
dec(Len);
inc(Start);
end;
@ -289,7 +290,7 @@ begin
Result:=DefaultKeyWordFunction();
end;
function TKeyWordFunctionList.DoIt(const ASource: string;
function TKeyWordFunctionList.DoItCaseInsensitive(const ASource: string;
KeyWordStart, KeyWordLen: integer): boolean;
// ! does not test if length(ASource) >= KeyWordStart+KeyWordLen -1
var i, KeyPos, WordPos: integer;
@ -328,7 +329,47 @@ begin
Result:=DefaultKeyWordFunction();
end;
function TKeyWordFunctionList.DoIt(Identifier: PChar): boolean;
function TKeyWordFunctionList.DoIt(const ASource: string; KeyWordStart,
KeyWordLen: integer): boolean;
// ! does not test if length(ASource) >= KeyWordStart+KeyWordLen -1
var
i, KeyPos, WordPos: integer;
KeyWordFuncItem: PKeyWordFunctionListItem;
begin
if not FSorted then Sort;
i:=KeyWordToHashIndex(ASource,KeyWordStart,KeyWordLen);
if i>=0 then begin
i:=FBucketStart[i];
if i>=0 then begin
dec(KeyWordStart);
repeat
KeyWordFuncItem:=@FItems[i];
if length(KeyWordFuncItem^.KeyWord)=KeyWordLen then begin
KeyPos:=KeyWordLen;
WordPos:=KeyWordStart+KeyWordLen;
while (KeyPos>=1)
and (KeyWordFuncItem^.KeyWord[KeyPos]=ASource[WordPos]) do
begin
dec(KeyPos);
dec(WordPos);
end;
if KeyPos<1 then begin
if Assigned(KeyWordFuncItem^.DoIt) then
Result:=KeyWordFuncItem^.DoIt()
else
Result:=DefaultKeyWordFunction();
exit;
end;
end;
if (KeyWordFuncItem^.IsLast) then break;
inc(i);
until false;
end;
end;
Result:=DefaultKeyWordFunction();
end;
function TKeyWordFunctionList.DoItCaseInsensitive(Identifier: PChar): boolean;
// checks
var i, KeyPos, KeyWordLen: integer;
KeyWordFuncItem: PKeyWordFunctionListItem;
@ -638,11 +679,11 @@ var
c: char;
w: word;
begin
for c:=Low(UpChars) to High(UpChars) do begin
for c:=Low(char) to High(char) do begin
case c of
'a'..'z':CharToHash[c]:=ord(c)-ord('a')+1;
'A'..'Z':CharToHash[c]:=ord(c)-ord('A')+1;
else CharToHash[c]:=0;
'a'..'z':CharToIHash[c]:=ord(c)-ord('a')+1;
'A'..'Z':CharToIHash[c]:=ord(c)-ord('A')+1;
else CharToIHash[c]:=ord(c);
end;
UpChars[c]:=upcase(c);
IsLineEndChar[c]:=c in [#10,#13];

View File

@ -884,7 +884,7 @@ begin
DirLen:=SrcPos-DirStart;
if DirLen>255 then DirLen:=255;
FDirectiveName:=UpperCaseStr(copy(Src,DirStart,DirLen));
FDirectiveFuncList.DoIt(Src,DirStart,DirLen);
FDirectiveFuncList.DoItCaseInsensitive(Src,DirStart,DirLen);
SrcPos:=CommentEndPos;
end;
@ -958,7 +958,7 @@ begin
while (SrcPos<=SrcLen)
and (IsIdentChar[Src[SrcPos]]) do
inc(SrcPos);
KeywordFuncList.DoIt(Src,TokenStart,SrcPos-TokenStart);
KeywordFuncList.DoItCaseInsensitive(Src,TokenStart,SrcPos-TokenStart);
end;
'''','#':
begin
@ -2177,7 +2177,7 @@ begin
DirLen:=SrcPos-DirStart;
if DirLen>255 then DirLen:=255;
FDirectiveName:=UpperCaseStr(copy(Src,DirStart,DirLen));
Result:=FDirectiveFuncList.DoIt(Src,DirStart,DirLen);
Result:=FDirectiveFuncList.DoItCaseInsensitive(Src,DirStart,DirLen);
end else
Result:=true;
end;

View File

@ -286,18 +286,15 @@ begin
'"': // string constant
begin
while (Position<=Len) do begin
case (Source[Position]) of
'"':
begin
if (Source[Position]='"') then
begin
inc(Position);
while (Position<=Len)
and (Source[Position]<>'"') do
inc(Position);
while (Position<=Len)
and (Source[Position]<>'"') do
inc(Position);
inc(Position);
end;
else
inc(Position);
end else
break;
end;
end;
end;
'''': // char constant

View File

@ -1699,7 +1699,8 @@ begin
end;
// read specifiers
while not (CurPos.Flag in [cafSemicolon,cafNone]) do begin
if WordIsPropertySpecifier.DoIt(@Src[CurPos.StartPos]) then begin
if WordIsPropertySpecifier.DoItCaseInsensitive(@Src[CurPos.StartPos])
then begin
if AtomIs(s) then exit(true);
end else if CurPos.Flag=cafEdgedBracketOpen then begin
ReadTilBracketClose(true);