codetools: fixed parsing non advanced records

git-svn-id: branches/fixes_2_0@61480 -
This commit is contained in:
mattias 2019-06-26 14:09:51 +00:00
parent 48c9baaca6
commit 18a0c25719
3 changed files with 98 additions and 38 deletions

View File

@ -208,7 +208,8 @@ type
// keyword lists
procedure BuildDefaultKeyWordFunctions; override;
function ParseType(StartPos: integer): boolean;
function ParseInnerClass(StartPos: integer): boolean;
function ParseInnerClass(StartPos: integer; ClassDesc: TCodeTreeNodeDesc): boolean;
function ParseInnerBasicRecord(StartPos: integer): boolean;
function UnexpectedKeyWord: boolean;
function EndOfSourceExpected: boolean;
// read functions
@ -481,9 +482,9 @@ begin
Result:=KeyWordFuncTypeDefault;
end;
function TPascalParserTool.ParseInnerClass(StartPos: integer
): boolean;
// KeyWordFunctions for parsing in a class/object/record/interface
function TPascalParserTool.ParseInnerClass(StartPos: integer;
ClassDesc: TCodeTreeNodeDesc): boolean;
// KeyWordFunctions for parsing in a class/object/advrecord/interface
var
p: PChar;
begin
@ -503,7 +504,7 @@ begin
';': exit(true);
'C':
case UpChars[p[1]] of
'A': if CompareSrcIdentifiers(p,'CASE') then exit(KeyWordFuncTypeRecordCase);
'A': if (ClassDesc=ctnRecordType) and CompareSrcIdentifiers(p,'CASE') then exit(KeyWordFuncTypeRecordCase);
'L': if CompareSrcIdentifiers(p,'CLASS') then exit(KeyWordFuncClassClass);
'O': if CompareSrcIdentifiers(p,'CONSTRUCTOR') then exit(KeyWordFuncClassMethod)
else if CompareSrcIdentifiers(p,'CONST') then exit(KeyWordFuncClassConstSection);
@ -530,7 +531,8 @@ begin
case UpChars[p[3]] of
'C': if CompareSrcIdentifiers(p,'PROCEDURE') then exit(KeyWordFuncClassMethod);
'P': if CompareSrcIdentifiers(p,'PROPERTY') then exit(KeyWordFuncClassProperty);
'T': if CompareSrcIdentifiers(p,'PROTECTED') then exit(KeyWordFuncClassSection);
'T': if (ClassDesc<>ctnRecordType) and CompareSrcIdentifiers(p,'PROTECTED') then
exit(KeyWordFuncClassSection);
end;
end;
'U':
@ -562,6 +564,35 @@ begin
Result:=KeyWordFuncClassIdentifier;
end;
function TPascalParserTool.ParseInnerBasicRecord(StartPos: integer): boolean;
// KeyWordFunctions for parsing in a *non* advanced record
var
p: PChar;
begin
if StartPos>SrcLen then exit(false);
p:=@Src[StartPos];
case UpChars[p^] of
'[':
begin
ReadAttribute;
exit(true);
end;
'(':
begin
ReadTilBracketClose(true);
exit(true);
end;
';': exit(true);
'C':
case UpChars[p[1]] of
'A': if CompareSrcIdentifiers(p,'CASE') then exit(KeyWordFuncTypeRecordCase);
end;
'E':
if CompareSrcIdentifiers(p,'END') then exit(false);
end;
Result:=KeyWordFuncClassIdentifier;
end;
function TPascalParserTool.UnexpectedKeyWord: boolean;
begin
Result:=false;
@ -4425,7 +4456,7 @@ begin
if CurPos.Flag<>cafSemicolon then begin
// parse till "end" of interface/dispinterface/objcprotocol
repeat
if not ParseInnerClass(CurPos.StartPos) then
if not ParseInnerClass(CurPos.StartPos,IntfDesc) then
begin
if CurPos.Flag<>cafEnd then
SaveRaiseStringExpectedButAtomFound(20170421195747,'end');
@ -4503,17 +4534,20 @@ var
IsForward: Boolean;
ClassDesc: TCodeTreeNodeDesc;
ClassNode: TCodeTreeNode;
IsHelper: Boolean;
IsHelper, IsBasicRecord: Boolean;
HelperForNode: TCodeTreeNode;
begin
//debugln(['TPascalParserTool.KeyWordFuncTypeClass START ',GetAtom,' ',CleanPosToStr(CurPos.StartPos),' ',CurNode.DescAsString]);
// class or 'class of' start found
IsBasicRecord:=false;
if UpAtomIs('CLASS') then
ClassDesc:=ctnClass
else if UpAtomIs('OBJECT') then
ClassDesc:=ctnObject
else if UpAtomIs('RECORD') then
ClassDesc:=ctnRecordType
else if UpAtomIs('RECORD') then begin
ClassDesc:=ctnRecordType;
IsBasicRecord:=not (cmsAdvancedRecords in Scanner.CompilerModeSwitches);
end
else if UpAtomIs('OBJCCLASS') then
ClassDesc:=ctnObjCClass
else if UpAtomIs('OBJCCATEGORY') then
@ -4560,22 +4594,18 @@ begin
SaveRaiseCharExpectedButAtomFound(20170421195756,';');
end else begin
if CurPos.Flag=cafWord then begin
if UpAtomIs('SEALED') then begin
while UpAtomIs('SEALED') do begin
CreateChildNode;
CurNode.Desc:=ctnClassSealed;
CurNode.EndPos:=CurPos.EndPos;
EndChildNode;
ReadNextAtom;
end;
end else if UpAtomIs('ABSTRACT') then begin
while UpAtomIs('ABSTRACT') do begin
CreateChildNode;
CurNode.Desc:=ctnClassAbstract;
CurNode.EndPos:=CurPos.EndPos;
EndChildNode;
ReadNextAtom;
end;
if (ClassDesc=ctnClass) and UpAtomIs('SEALED') then begin
CreateChildNode;
CurNode.Desc:=ctnClassSealed;
CurNode.EndPos:=CurPos.EndPos;
EndChildNode;
ReadNextAtom;
end else if (ClassDesc=ctnClass) and UpAtomIs('ABSTRACT') then begin
CreateChildNode;
CurNode.Desc:=ctnClassAbstract;
CurNode.EndPos:=CurPos.EndPos;
EndChildNode;
ReadNextAtom;
end;
if UpAtomIs('EXTERNAL') then begin
if (ClassDesc in [ctnObjCClass,ctnObjCCategory])
@ -4663,16 +4693,29 @@ begin
CurNode.Desc:=ctnClassPublic;
CurNode.StartPos:=LastAtoms.GetPriorAtom.EndPos;
// parse till "end" of class/object
repeat
//DebugLn(['TPascalParserTool.KeyWordFuncTypeClass Atom=',GetAtom,' ',CurPos.StartPos>=ClassNode.EndPos]);
if not ParseInnerClass(CurPos.StartPos) then
begin
if CurPos.Flag<>cafEnd then
SaveRaiseStringExpectedButAtomFound(20170421195803,'end');
break;
end;
ReadNextAtom;
until false;
if IsBasicRecord then begin
repeat
//DebugLn(['TPascalParserTool.KeyWordFuncTypeClass Atom=',GetAtom,' ',CurPos.StartPos>=ClassNode.EndPos]);
if not ParseInnerBasicRecord(CurPos.StartPos) then
begin
if CurPos.Flag<>cafEnd then
SaveRaiseStringExpectedButAtomFound(20190626160145,'end');
break;
end;
ReadNextAtom;
until false;
end else begin
repeat
//DebugLn(['TPascalParserTool.KeyWordFuncTypeClass Atom=',GetAtom,' ',CurPos.StartPos>=ClassNode.EndPos]);
if not ParseInnerClass(CurPos.StartPos,ClassDesc) then
begin
if CurPos.Flag<>cafEnd then
SaveRaiseStringExpectedButAtomFound(20170421195803,'end');
break;
end;
ReadNextAtom;
until false;
end;
// end last sub section
if CurNode.Desc in AllClassSubSections then begin
CurNode.EndPos:=CurPos.StartPos;

View File

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="11"/>
<Version Value="12"/>
<General>
<Flags>
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
<CompatibilityMode Value="True"/>
</Flags>
<SessionStorage Value="InIDEConfig"/>
<MainUnit Value="0"/>
<Title Value="runtestscodetools"/>
<UseAppBundle Value="False"/>
<ResourceType Value="res"/>

View File

@ -44,6 +44,7 @@ type
published
procedure TestAtomRing;
procedure TestRecord_ClassOperators;
procedure TestRecord_Nonkeywords;
procedure TestDeprecated;
procedure TestMissingGenericKeywordObjFPCFail;
procedure TestParseGenericsDelphi;
@ -323,6 +324,7 @@ procedure TTestPascalParser.TestRecord_ClassOperators;
begin
StartProgram;
Add([
'{$modeswitch advancedrecords}',
'type',
' TFlag = (flag1);',
'{$Define FPC_HAS_MANAGEMENT_OPERATORS}',
@ -376,6 +378,21 @@ begin
ParseModule;
end;
procedure TTestPascalParser.TestRecord_Nonkeywords;
begin
StartProgram;
Add([
'type',
' t = record',
' public: word;',
' private: word;',
' protected: word;',
' published: word;',
' end;',
'begin']);
ParseModule;
end;
procedure TTestPascalParser.TestDeprecated;
begin
StartProgram;