mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-17 04:29:25 +02:00
Debugger: fix parsing for array indexes (expanding array in watches / replace .. idx)
(cherry picked from commit 45a6759c3d
)
This commit is contained in:
parent
d04340fa7e
commit
3324959e82
@ -265,9 +265,35 @@ end;
|
||||
function GetExpressionForArrayElement(AnArrayExpression: AnsiString;
|
||||
AnIndex: String): AnsiString;
|
||||
var
|
||||
s, e, p, p2: PChar;
|
||||
MaybeBeforeRange, InString, FoundDotDot: Boolean;
|
||||
RStart, InRndBracket, InSqrBracket: Integer;
|
||||
s, e, p: PChar;
|
||||
MaybeBeforeArrayIdx, InString, FoundDotDot: Boolean;
|
||||
RStart, InRndBracket, InSqrBracket, InArrayIdxBracket: Integer;
|
||||
|
||||
RStartStack: array of record
|
||||
RStart: integer;
|
||||
InRnd, InSqr: integer;
|
||||
FoundDotDot: Boolean;
|
||||
end;
|
||||
|
||||
procedure PushData;
|
||||
begin
|
||||
if InArrayIdxBracket >= Length(RStartStack) then
|
||||
SetLength(RStartStack, InArrayIdxBracket + 8);
|
||||
RStartStack[InArrayIdxBracket].RStart := RStart;
|
||||
RStartStack[InArrayIdxBracket].InRnd := InRndBracket;
|
||||
RStartStack[InArrayIdxBracket].InSqr := InSqrBracket;
|
||||
RStartStack[InArrayIdxBracket].FoundDotDot := FoundDotDot;
|
||||
FoundDotDot := False;
|
||||
InRndBracket := 0;
|
||||
InSqrBracket := 0;
|
||||
end;
|
||||
procedure PopData;
|
||||
begin
|
||||
RStart := RStartStack[InArrayIdxBracket].RStart;
|
||||
InRndBracket := RStartStack[InArrayIdxBracket].InRnd;
|
||||
InSqrBracket := RStartStack[InArrayIdxBracket].InSqr;
|
||||
FoundDotDot := RStartStack[InArrayIdxBracket].FoundDotDot;
|
||||
end;
|
||||
begin
|
||||
Result := AnArrayExpression + '[' + AnIndex + ']';
|
||||
if AnArrayExpression = '' then
|
||||
@ -276,82 +302,112 @@ begin
|
||||
s := @AnArrayExpression[1];
|
||||
p := s;
|
||||
e := @AnArrayExpression[Length(AnArrayExpression)];
|
||||
MaybeBeforeRange := False;
|
||||
|
||||
MaybeBeforeArrayIdx := False;
|
||||
InRndBracket := 0;
|
||||
InSqrBracket := 0;
|
||||
FoundDotDot := False;
|
||||
InArrayIdxBracket := 0;
|
||||
InString := False;
|
||||
dec(p);
|
||||
while p < e do begin
|
||||
inc(p);
|
||||
if p^ = '''' then begin
|
||||
InString := not InString;
|
||||
MaybeBeforeRange := True; // sub-range of string
|
||||
MaybeBeforeArrayIdx := True; // sub-range of string
|
||||
Continue;
|
||||
end;
|
||||
if InString then
|
||||
Continue;
|
||||
|
||||
if p^ in ['@', '.', '+', '-', '*', '/', '(', ',', '=', '<', '>', '#', '$', '%', '&', '!'] then
|
||||
MaybeBeforeRange := False // after operator. A [1..5] would be a set of byte
|
||||
|
||||
else
|
||||
if (p - s >= 2) and
|
||||
(p[-2] in [#1..#32]) and (p[-1] in ['i', 'I']) and
|
||||
(p^ in ['n', 'N']) and (p[1] in [#1..#32])
|
||||
then
|
||||
MaybeBeforeRange := False // after IN operator. A [1..5] would be a set of byte
|
||||
if p^ in ['@', '.', '+', '-', '*', '/', '(', ',', '=', '<', '>', '#', '$', '%', '&', '!'] then begin
|
||||
MaybeBeforeArrayIdx := False; // after operator. A [1..5] would be a set of byte
|
||||
|
||||
else
|
||||
if p^ in ['a'..'z', 'A'..'Z', '_', ')', ']'] then
|
||||
MaybeBeforeRange := True // after identifier, or after ")" or "]"
|
||||
|
||||
else
|
||||
if (p^ = '[') and MaybeBeforeRange then begin
|
||||
// maybe found first range
|
||||
p2 := nil;
|
||||
RStart := p - s; // Length of substring before "["
|
||||
|
||||
|
||||
// check if this is a slice
|
||||
InRndBracket := 0;
|
||||
InSqrBracket := 0;
|
||||
FoundDotDot := False;
|
||||
while p < e do begin
|
||||
inc(p);
|
||||
if p^ = '''' then begin
|
||||
InString := not InString;
|
||||
Continue;
|
||||
end;
|
||||
if InString then
|
||||
Continue;
|
||||
if (p^ = '.') and (p[1] = '.') then begin FoundDotDot := True; inc(p); end
|
||||
else if (p^ = '(') then inc(InRndBracket)
|
||||
else if (p^ = ')') then begin
|
||||
dec(InRndBracket);
|
||||
if InRndBracket < 0 then
|
||||
break; // something wrong.
|
||||
if (InArrayIdxBracket > 0) and (InSqrBracket = 0) and (InRndBracket = 0) then begin
|
||||
if (p^ = '.') and (p[1] = '.') then begin
|
||||
if FoundDotDot then
|
||||
break; // something wrong
|
||||
FoundDotDot := True;
|
||||
inc(p);
|
||||
end
|
||||
else if (p^ = '[') then begin
|
||||
inc(InSqrBracket);
|
||||
if p2 = nil then p2 := p; // continue outer loop from here
|
||||
end
|
||||
else if (p^ = ']') then begin
|
||||
dec(InSqrBracket);
|
||||
if InSqrBracket < 0 then begin
|
||||
if (not FoundDotDot) or (InRndBracket <> 0) then
|
||||
break; // not a range, continue outer loop
|
||||
// Found
|
||||
else
|
||||
if (p^ = ',') then begin
|
||||
if FoundDotDot then begin
|
||||
Result := copy(AnArrayExpression, 1 , RStart+1) +
|
||||
AnIndex +
|
||||
copy(AnArrayExpression, p-s + 1, Length(AnArrayExpression));
|
||||
exit;
|
||||
end;
|
||||
RStart := p - s; // Length of substring before "["
|
||||
end;
|
||||
end;
|
||||
end
|
||||
|
||||
|
||||
MaybeBeforeRange := p2 = nil; // after "]"
|
||||
if p2 <> nil then
|
||||
p := p2; // continue after first "[" in above loop
|
||||
else
|
||||
if (p - s >= 2) and
|
||||
(p[-2] in [#1..#32]) and (p[-1] in ['i', 'I']) and
|
||||
(p^ in ['n', 'N']) and (p[1] in [#1..#32])
|
||||
then begin
|
||||
MaybeBeforeArrayIdx := False; // after IN operator. A [1..5] would be a set of byte
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
if p^ in ['a'..'z', 'A'..'Z', '_', ')', ']'] then begin
|
||||
MaybeBeforeArrayIdx := True; // after identifier, or after ")" or "]"
|
||||
if (p^ = ')') and (InArrayIdxBracket > 0) then begin
|
||||
dec(InRndBracket);
|
||||
MaybeBeforeArrayIdx := True;
|
||||
if InRndBracket < 0 then
|
||||
break; // something wrong.
|
||||
end
|
||||
else
|
||||
if (p^ = ']') then begin
|
||||
if InSqrBracket > 0 then begin
|
||||
dec(InSqrBracket);
|
||||
end
|
||||
else
|
||||
if InArrayIdxBracket > 0 then begin
|
||||
if InRndBracket > 0 then
|
||||
break; // something wrong
|
||||
if FoundDotDot then begin
|
||||
Result := copy(AnArrayExpression, 1 , RStart+1) +
|
||||
AnIndex +
|
||||
copy(AnArrayExpression, p-s + 1, Length(AnArrayExpression));
|
||||
exit;
|
||||
end;
|
||||
dec(InArrayIdxBracket);
|
||||
PopData;
|
||||
end
|
||||
else
|
||||
break; //something wrong
|
||||
end;
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
if (p^ = '(') and (InArrayIdxBracket > 0) then begin
|
||||
inc(InRndBracket);
|
||||
MaybeBeforeArrayIdx := False;
|
||||
end
|
||||
|
||||
else
|
||||
if (p^ = '[') then begin
|
||||
if (not MaybeBeforeArrayIdx) then begin
|
||||
inc(InSqrBracket);
|
||||
end
|
||||
else
|
||||
begin
|
||||
// maybe found first range
|
||||
PushData;
|
||||
|
||||
inc(InArrayIdxBracket);
|
||||
RStart := p - s; // Length of substring before "["
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -25,6 +25,11 @@ implementation
|
||||
{ TTestIdeDebuggerVarious }
|
||||
|
||||
procedure TTestIdeDebuggerVarious.TestExpressionForArrayElement;
|
||||
procedure Test(ABefore: string; AIdx: Integer; AnAfter: string);
|
||||
begin
|
||||
AssertEquals(ABefore+' @ ' + IntToStr(AIdx) + ' => '+AnAfter,
|
||||
AnAfter, GetExpressionForArrayElement(ABefore, AIdx));
|
||||
end;
|
||||
begin
|
||||
AssertEquals('a', 'a[11]', GetExpressionForArrayElement('a', 11));
|
||||
AssertEquals('(a)', '(a)[11]', GetExpressionForArrayElement('(a)', 11));
|
||||
@ -45,6 +50,30 @@ begin
|
||||
'PCellProps((TFpList((StringGrid1.FGrid.FCellArr.FCols.FList)^[2]).FList)^[0..3])^',
|
||||
GetExpressionForArrayElement('PCellProps((TFpList((StringGrid1.FGrid.FCellArr.FCols.FList)^[0..3]).FList)^[0..3])^', 2)
|
||||
);
|
||||
|
||||
// nested goes first
|
||||
Test('Foo(a[x[2..14]..99])', 11, 'Foo(a[x[11]..99])');
|
||||
Test('Foo(a[1+x[2..14]..99])', 11, 'Foo(a[1+x[11]..99])');
|
||||
Test('Foo(a[(1+x[2..14])..99])', 11, 'Foo(a[(1+x[11])..99])');
|
||||
Test('Foo(a[0..x[2..14]])', 11, 'Foo(a[0..x[11]])');
|
||||
Test('Foo(a[0..1+x[2..14]])', 11, 'Foo(a[0..1+x[11]])');
|
||||
Test('Foo(a[0..(1+x[2..14])])', 11, 'Foo(a[0..(1+x[11])])');
|
||||
|
||||
// not in set
|
||||
Test('Foo(a[x in [1..3]])', 11, 'Foo(a[x in [1..3]])[11]'); // no ..
|
||||
Test('Foo(a[x in [1..3]..True])', 11, 'Foo(a[11])');
|
||||
|
||||
Test('Foo(a[b[2..22]])', 11, 'Foo(a[b[11]])');
|
||||
Test('Foo(a[(1+b[2..22])])', 11, 'Foo(a[(1+b[11])])');
|
||||
|
||||
// ","
|
||||
Test('Foo(a[2..22,55..66])', 11, 'Foo(a[11,55..66])');
|
||||
Test('Foo(a[99,2..22])', 11, 'Foo(a[99,11])');
|
||||
|
||||
// set from array
|
||||
Test('e1 in [x[1..15]]', 11, 'e1 in [x[11]]');
|
||||
Test('e1 in [x[1..15]..x[33..35]]', 11, 'e1 in [x[11]..x[33..35]]');
|
||||
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
Loading…
Reference in New Issue
Block a user