在CnPasCodeParser.pas这个文件中,第256行到270行,这里对tkClass进行判断的时候,漏了
一种情况,就是忘了判断这个时候可能出现的tkEnd,
因为在interface中类的声明情况可能如下
TSayHello = class
end;
而原来代码遗漏了这种情况下的判断。
我个人的修改如下
tkClass:
begin
if Lex.IsClass then
begin
Result.PosKind := pkClass;
DoNext(True);
if (Lex.TokenPos < CurrPos) and (Lex.TokenID = tkSemiColon) then
Result.PosKind := pkType
else if (Lex.TokenPos < CurrPos) and (Lex.TokenID = tkRoundOpen) then
begin
while (Lex.TokenPos < CurrPos) and not (Lex.TokenID in
[tkNull, tkRoundClose]) do
DoNext;
if (Lex.TokenPos < CurrPos) and (Lex.TokenID = tkRoundClose) then
begin
DoNext(True);
if (Lex.TokenPos < CurrPos) and (Lex.TokenID = tkSemiColon) then
Result.PosKind := pkType;
end;
end
//以下是加上去的情况处理 else if (Lex.TokenPos < CurrPos) and (Lex.TokenID = tkEnd) then
begin
DoNext(True);
if (Lex.TokenPos < CurrPos) and (Lex.TokenID = tkSemiColon) then
Result.PosKind := pkType;
end; //
if Result.PosKind = pkClass then
InClass := True;
end;
end;Author:
zjy Time: 2004-12-7 14:55 Subject: 多谢报告!
在您列出的代码中:
if (Lex.TokenPos < CurrPos) and (Lex.TokenID = tkSemiColon) then
Result.PosKind := pkType
这一句用来处理第一种情况。
else if (Lex.TokenPos < CurrPos) and (Lex.TokenID = tkRoundOpen) then
begin
while (Lex.TokenPos < CurrPos) and not (Lex.TokenID in
[tkNull, tkRoundClose]) do
DoNext;
if (Lex.TokenPos < CurrPos) and (Lex.TokenID = tkRoundClose) then
begin
DoNext(True);
if (Lex.TokenPos < CurrPos) and (Lex.TokenID = tkSemiColon) then
Result.PosKind := pkType;
end;
end
用来跳过类声明中括号部分的内容,如果找到 ) 后发现接着是一个 ; 号,说明是第二种情况,结束类处理。
否则:
if Result.PosKind = pkClass then
InClass := True;
标识当前在类定义中,恢复循环,直到遇见一个 end; 为止,用于处理后面的两种情况。
您增加的代码,如果去掉也是可以工作的,因为执行完 InClass := True 后,继续循环,如果紧接着是 end; 的话,会执行:
tkEnd:
begin
if InClass then
begin
Result.PosKind := pkType;
InClass := False;
end
我仔细分析了一下,原来的代码还是有问题,因为在判断 ( 和 ; 时已经 DoNext 过了,如果继续执行再 DoNext 一次,就可能会跳过 end; 标志了,我改成这样,测试已经正常了:
tkClass:
begin
if Lex.IsClass then
begin
Result.PosKind := pkClass;
DoNext(True);
if (Lex.TokenPos < CurrPos) and (Lex.TokenID = tkSemiColon) then
Result.PosKind := pkType
else if (Lex.TokenPos < CurrPos) and (Lex.TokenID = tkRoundOpen) then
begin
while (Lex.TokenPos < CurrPos) and not (Lex.TokenID in
[tkNull, tkRoundClose]) do
DoNext;
if (Lex.TokenPos < CurrPos) and (Lex.TokenID = tkRoundClose) then
begin
DoNext(True);
if (Lex.TokenPos < CurrPos) and (Lex.TokenID = tkSemiColon) then
Result.PosKind := pkType
else
begin
InClass := True;
Continue;
end;
end;
end
else
begin
InClass := True;
Continue;
end;
end;
end;Author:
littlerain Time: 2004-12-8 15:49