CnPack Forum


 
Subject: 一个小bug报告!
littlerain
新警察
Rank: 1



UID 210
Digest Posts 0
Credits 43
Posts 30
点点分 43
Reading Access 10
Registered 2003-11-3
Status Offline
Post at 2004-12-6 16:39  Profile | Blog | P.M. 
一个小bug报告!

在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;
Top
zjy
管理员
Rank: 9Rank: 9Rank: 9



UID 2
Digest Posts 6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
Post at 2004-12-7 14:55  Profile | Site | Blog | P.M. 
多谢报告!

这个Parser还很不完善,有时间我会好好改进一下:)




Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
Top
zjy
管理员
Rank: 9Rank: 9Rank: 9



UID 2
Digest Posts 6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
Post at 2004-12-8 14:53  Profile | Site | Blog | P.M. 
我查看了一下代码,原来的处理方式是考虑到 class 关键字有以下几种应用形式:
TMyClass = class; // 用来预先申明类
TMyClass = class(TObject, IUnknown); // 仅声明一个子类
TMyClass = class(TObject, IUnknown)  // 跟上一种相同
end;
TMyClass = class(TObject, IUnknown)  // 完整的声明
  FValue: Integer;
public
  ...
end;

在您列出的代码中:
      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

这个单元用在输入助手中,感觉功能还很欠缺,有时间我会写个更完善的语法分析单元。




Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
Top
zjy
管理员
Rank: 9Rank: 9Rank: 9



UID 2
Digest Posts 6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
Post at 2004-12-8 15:11  Profile | Site | Blog | P.M. 
我仔细分析了一下,原来的代码还是有问题,因为在判断 ( 和 ; 时已经 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;




Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
Top
littlerain
新警察
Rank: 1



UID 210
Digest Posts 0
Credits 43
Posts 30
点点分 43
Reading Access 10
Registered 2003-11-3
Status Offline
Post at 2004-12-8 15:49  Profile | Blog | P.M. 
谢谢您,yygw,
    希望您能早日完善这个parser,呵呵,还有希望cnwizard中的代码编辑器部分能够加强一下,
比如加入像coderush一样的代码模版功能
Top
 




All times are GMT++8, the time now is 2024-4-17 07:21

    本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz! 5.0.0  © 2001-2006 Comsenz Inc.
Processed in 0.010142 second(s), 7 queries , Gzip enabled

Clear Cookies - Contact Us - CnPack Website - Archiver - WAP