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); const SrcEnd: PChar; NestedComments: boolean; SkipDirectives: boolean);
var var
c1,c2:char; c1,c2:char;
CommentLvl: Integer; CommentLvl, Lvl, i: Integer;
Src: PChar; Src: PChar;
begin begin
Src:=Position; Src:=Position;
@ -2137,10 +2137,46 @@ begin
'''': '''':
begin begin
inc(Src); inc(Src);
while not (Src^ in ['''',#0,#10,#13]) do if (Src^='''') and (Src[1]='''') then begin
inc(Src); Lvl:=3;
if Src^='''' then inc(Src,2);
inc(Src); 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; end;
'`': '`':
begin begin

View File

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

View File

@ -49,6 +49,7 @@ type
procedure TestReIndent; procedure TestReIndent;
procedure TestSimpleFormat; procedure TestSimpleFormat;
procedure TestStringToPascalConst; procedure TestStringToPascalConst;
procedure TestReadNextPascalAtom;
// FileProcs // FileProcs
procedure TestDateToCfgStr; procedure TestDateToCfgStr;
procedure TestFilenameIsMatching; procedure TestFilenameIsMatching;
@ -321,6 +322,36 @@ begin
t('Foo'#10'Bar','''Foo''#10''Bar'''); t('Foo'#10'Bar','''Foo''#10''Bar''');
end; 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 TTestBasicCodeTools.TestDateToCfgStr;
procedure t(const Date: TDateTime; const aFormat, Expected: string); procedure t(const Date: TDateTime; const aFormat, Expected: string);