codetools: ReadNextPascalAtom: delphi multi line string literal

This commit is contained in:
mattias 2023-11-10 15:00:57 +01:00
parent 6fac14495b
commit 0ac09485c6
3 changed files with 93 additions and 21 deletions

View File

@ -1971,7 +1971,7 @@ procedure ReadRawNextPascalAtom(var Position: PChar; out AtomStart: PChar;
const SrcEnd: PChar; NestedComments: boolean; SkipDirectives: boolean);
var
c1,c2:char;
CommentLvl: Integer;
CommentLvl, Lvl, i: Integer;
Src: PChar;
begin
Src:=Position;
@ -2137,10 +2137,46 @@ begin
'''':
begin
inc(Src);
while not (Src^ in ['''',#0,#10,#13]) do
inc(Src);
if Src^='''' then
inc(Src);
if (Src^='''') and (Src[1]='''') then begin
Lvl:=3;
inc(Src,2);
while Src^='''' do begin
inc(Lvl);
inc(Src);
end;
if Lvl and 1=1 then begin
if Src^ in [#10,#13] then begin
// delphi multi line string literal
while Src^<>#0 do begin
if (Src^='''') and (Src[1]='''') then begin
i:=2;
inc(Src,2);
while (Src^='''') and (i<Lvl) do begin
inc(i);
inc(Src);
end;
if i=Lvl then
break;
end else
inc(Src);
end;
end else begin
// e.g. '''a or '''''b
while not (Src^ in ['''',#0,#10,#13]) do
inc(Src);
if Src^='''' then
inc(Src);
end;
end else begin
// e.g. '' or '''' or ''''''
end;
end else begin
// normal string literal
while not (Src^ in ['''',#0,#10,#13]) do
inc(Src);
if Src^='''' then
inc(Src);
end;
end;
'`':
begin

View File

@ -4594,25 +4594,30 @@ procedure TLinkScanner.SkipTillEndifElse(SkippingUntil: TLSSkippingDirective);
inc(p);
inc(lvl);
end;
if (lvl and 1=1) and (p^ in [#10,#13]) then begin
// delphi 12 multiline string literal
while p^<>#0 do begin
if (p^='''') and (p[1]='''') then begin
i:=2;
inc(p,2);
while p^='''' do begin
inc(i);
if i=lvl then
exit;
end;
end else
if (lvl and 1=1) then begin
if (p^ in [#10,#13]) then begin
// delphi 12 multiline string literal
while p^<>#0 do begin
if (p^='''') and (p[1]='''') then begin
i:=2;
inc(p,2);
while p^='''' do begin
inc(i);
inc(p);
if i=lvl then
exit;
end;
end else
inc(p);
end;
end else begin
// e.g. '''a or '''''b
while not (p^ in ['''',#0,#10,#13]) do inc(p);
if p^='''' then
inc(p);
end;
end else begin
// normal string literal
while not (p^ in ['''',#0,#10,#13]) do inc(p);
if p^='''' then
inc(p);
// e.g. '''' or ''''''
end;
end;

View File

@ -49,6 +49,7 @@ type
procedure TestReIndent;
procedure TestSimpleFormat;
procedure TestStringToPascalConst;
procedure TestReadNextPascalAtom;
// FileProcs
procedure TestDateToCfgStr;
procedure TestFilenameIsMatching;
@ -321,6 +322,36 @@ begin
t('Foo'#10'Bar','''Foo''#10''Bar''');
end;
procedure TTestBasicCodeTools.TestReadNextPascalAtom;
procedure t(const Src, ExpectedAtom: string; ExpectedAtomStart: integer = 1);
var
p, AtomStart: Integer;
ActualAtom: String;
begin
p:=1;
ActualAtom:=ReadNextPascalAtom(Src,p,AtomStart);
if AtomStart<>ExpectedAtomStart then begin
Fail('Src=['+DbgStr(Src)+'] expected AtomStart='+dbgs(ExpectedAtomStart)+', but got '+dbgs(AtomStart));
end;
if ActualAtom<>ExpectedAtom then begin
Fail('Src=['+DbgStr(Src)+'] expected Atom='+DbgStr(ExpectedAtom)+', but got '+DbgStr(ActualAtom));
end;
end;
const
Apos = '''';
Apos2 = Apos+Apos;
Apos3 = Apos+Apos+Apos;
begin
t('','',1);
t(Apos2+' ',Apos2,1); // ''
t('''a''+','''a''',1); // 'a'+
t('''''''a''+','''''''a''',1); // '''a'+
t(Apos3+#10+'First'+Apos3+';',Apos3+#10+'First'+Apos3,1); // '''#10First''';
t(Apos3+Apos2+#10+'First'+Apos3+Apos2+';',Apos3+Apos2+#10+'First'+Apos3+Apos2,1); // '''#10First''';
end;
procedure TTestBasicCodeTools.TestDateToCfgStr;
procedure t(const Date: TDateTime; const aFormat, Expected: string);