⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cnscaners.pas

📁 CnCodeFormater Readme Author: passos Email: passos@cnpack.orgpassos@21cn.com Last Update:20
💻 PAS
📖 第 1 页 / 共 2 页
字号:
    end;
  end
  else
    Error(SInvalidBookmark);

  if Clear then
    ClearBookmark(Bookmark);
end;

procedure TAbstractScaner.SaveBookmark(var Bookmark: TScannerBookmark);
begin
  Bookmark := TScannerBookmark.Create;
  with Bookmark do
  begin
    OriginBookmark := FOrigin;
    SourcePtrBookmark := FSourcePtr;
    TokenBookmark := FToken;
    TokenPtrBookmark := FTokenPtr;
  end;
  FBookmarks.Add(Bookmark);
end;

procedure TAbstractScaner.ClearBookmark(var Bookmark: TScannerBookmark);
begin
  Bookmark := TScannerBookmark(FBookmarks.Extract(Bookmark));
  if Assigned(Bookmark) then
    FreeAndNil(Bookmark);
end;

function TAbstractScaner.ForwardToken(Count: Integer): TPascalToken;
var
  Bookmark: TScannerBookmark;
  I: Integer;
begin
  Result := Token;

  SaveBookmark(Bookmark);

  for I := 0 to Count - 1 do
  begin
    Result := NextToken;
    if Result = tokEOF then
      Exit;
  end;

  LoadBookmark(Bookmark);
end;

function TAbstractScaner.BlankString: string;
var
  L: Integer;
begin
  L := FBlankStringEnd - FBlankStringBegin;
  SetString(Result, FBlankStringBegin, L);
end;

{ TScaner }

constructor TScaner.Create(AStream: TStream; ACodeGen: TCnCodeGenerator);
begin
  AStream.Seek(0, soFromBeginning);
  FStream := AStream;
  FCodeGen := ACodeGen;

  inherited Create(AStream);
end;

constructor TScaner.Create(AStream: TStream);
begin
  Create(AStream, nil); //TCnCodeGenerator.Create);
end;

destructor TScaner.Destroy;
begin
  inherited Destroy;
end;

function TScaner.ForwardToken(Count: Integer): TPascalToken;
begin
  FCodeGen.LockOutput;
  try
    Result := inherited ForwardToken(Count);
  finally
    FCodeGen.UnLockOutput;
  end;
end;

function TScaner.NextToken: TPascalToken;

  procedure SkipTo(var P: PChar; TargetChar: Char);
  begin
    while (P^ <> TargetChar) do
    begin
      Inc(P);

      if (P^ = #0) then
      begin
        ReadBuffer;
        if FSourcePtr^ = #0 then
          Break;
      end;
    end;
  end;

var
  IsWideStr: Boolean;
  P: PChar;
begin
  SkipBlanks;
  P := FSourcePtr;
  FTokenPtr := P;
  case P^ of
    'A'..'Z', 'a'..'z', '_':
      begin
        Inc(P);
        while P^ in ['A'..'Z', 'a'..'z', '0'..'9', '_'] do Inc(P);
        Result := tokSymbol;
      end;
    '#', '''':
      begin
        IsWideStr := False;
        // parser string like this: 'abc'#10#13'def'#10#13
        while True do
          case P^ of
            '#':
              begin
                IsWideStr := True;
                Inc(P);
                while P^ in ['$', '0'..'9', 'a'..'f', 'A'..'F'] do Inc(P);
              end;
            '''':
              begin
                Inc(P);
                while True do
                  case P^ of
                    #0, #10, #13:
                      Error(SInvalidString);
                    '''':
                      begin
                        Inc(P);
                        Break;
                      end;
                  else
                    Inc(P);
                  end;
              end;
          else
            Break;
          end; // case P^ of

        FStringPtr := P;
        
        if IsWideStr then
          Result := tokWString
        else
          Result := tokString;
      end; // '#', '''': while True do

    '"':
      begin
        Inc(P);
        while not (P^ in ['"', #0, #10, #13]) do Inc(P);
        Result := tokString;
        if P^ = '"' then  // 和单引号字符串一样跳过最后一个双引号
          Inc(P);
        FStringPtr := P;
      end;

    '$':
      begin
        Inc(P);
        while P^ in ['0'..'9', 'A'..'F', 'a'..'f'] do
          Inc(P);
        Result := tokInteger;
      end;

    '*':
      begin
        Inc(P);
        Result := tokStar;
      end;

    '{':
      begin
        Inc(P);
        { TODO: Check Directive sign $}

        Result := tokComment;
        while ((P^ <> #0) and (P^ <> '}')) do
          Inc(P);

        if P^ = '}' then
        begin
          FBlankLinesAfterComment := 0;
          Inc(P);
          while P^ in [' ', #9] do
            Inc(P);
          if P^ = #13 then
          begin
            if not FASMMode then // ASM 模式下,换行作为语句结束符,不在注释内处理
            begin
              Inc(P);
              if P^ = #10 then
              begin
                Inc(FBlankLinesAfterComment);
                Inc(P);
              end;
            end;
          end;
        end
        else
          Error(SEndOfCommentExpected);
      end;

    '/':
      begin
        Inc(P);

        if P^ = '/' then
        begin
          Result := tokComment;
          while (P^ <> #0) and (P^ <> #13)
            do Inc(P); // 找行尾

          FBlankLinesAfterComment := 0;
          if P^ = #13 then
          begin
            if not FASMMode then // ASM 模式下,换行作为语句结束符,不在注释内处理
            begin
              Inc(P);
              if P^ = #10 then
              begin
                Inc(FBlankLinesAfterComment);
                Inc(P);
              end;
            end;
          end
          else
            Error(SEndOfCommentExpected);
        end
        else
          Result := tokDiv;
      end;

    '(':
      begin
        Inc(P);
        Result := tokLB;

        if P^ = '*' then
        begin
          Result := tokComment;

          Inc(P);
          FBlankLinesAfterComment := 0;
          while P^ <> #0 do
          begin
            if P^ = '*' then
            begin
              Inc(P);
              if P^ = ')' then
              begin
                Inc(P);
                while P^ in [' ', #9] do
                  Inc(P);

                if P^ = #13 then
                begin
                  if not FASMMode then // ASM 模式下,换行作为语句结束符,不在注释内处理
                  begin
                    Inc(P);
                    if P^ = #10 then
                    begin
                      Inc(FBlankLinesAfterComment);
                      Inc(P);
                    end;
                  end;
                end;

                Break;
              end;
            end
            else
              Inc(P);
          end;
        end;
      end;

    ')':
      begin
        Inc(P);
        Result := tokRB;
      end;

    '[':
      begin
        Inc(P);
        Result := tokSLB;
      end;

    ']':
      begin
        Inc(P);
        Result := tokSRB;
      end;

    '^':
      begin
        Inc(P);
        Result := tokHat;
      end;

    '=':
      begin
        Inc(P);
        Result := tokEQUAL;
      end;

    ':':
      begin
        Inc(P);
        if (P^ = '=') then
        begin
          Inc(P);
          Result := tokAssign;
        end else
          Result := tokColon;
      end;
      
    ';':
      begin
        Inc(P);
        Result := tokSemicolon;
      end;

    '.':
      begin
        Inc(P);

        if P^ = '.' then
        begin
          Result := tokRange;
          Inc(P);
        end else
          Result := tokDot;
      end;

    ',':
      begin
        Inc(P);
        Result := tokComma;
      end;

    '>':
      begin
        Inc(P);
        Result := tokGreat;
          
        if P^ = '<' then
        begin
          Result := tokNotEqual;
          Inc(P);
        end else
        if P^ = '=' then
        begin
          Result := tokGreatOrEqu;
          Inc(P);
        end;
      end;

    '<':
      begin
        Inc(P);
        Result := tokLess;
        
        if P^ = '=' then
        begin
          Result := tokLessOrEqu;
          Inc(P);
        end;

        if P^ = '>' then
        begin
          Result := tokNotEqual;
          Inc(P);
        end;
      end;

    '@':
      begin
        Inc(P);
        Result := tokAtSign;
      end;

    '+', '-':
      begin
        if P^ = '+' then
          Result := tokPlus
        else
          Result := tokMinus;

        Inc(P);
      end;

    '0'..'9':
      begin
        Inc(P);
        while P^ in ['0'..'9'] do Inc(P);
        Result := tokInteger;

        if (P^ = '.') and ((P+1)^ <> '.') then
        begin
          Inc(P);
          while P^ in ['0'..'9'] do Inc(P);
          Result := tokFloat;
        end;

        if P^ in ['e', 'E'] then
        begin
          Inc(P);
          if P^ in ['-', '+'] then
            Inc(P);
          while P^ in ['0'..'9'] do
            Inc(P);
          Result := tokFloat;
        end;

        if (P^ in ['c', 'C', 'd', 'D', 's', 'S']) then
        begin
          Result := tokFloat;
          FFloatType := P^;
          Inc(P);
        end
        else
          FFloatType := #0;
      end;
    #10:  // 如果有回车则处理,以 #10 为准
      begin
        Result := tokCRLF;
        Inc(P);
      end;
  else
    if P^ = #0 then
      Result := tokEOF
    else
      Result := tokUnknown;

    if Result <> tokEOF then
      Inc(P);
  end;

  FSourcePtr := P;
  FToken := Result;

  if Result = tokComment then // 当前是 Comment
  begin
    if Assigned(FCodeGen) then
    begin
      FCodeGen.Write(BlankString);
      FCodeGen.Write(TokenString);
    end;

    if not FFirstCommentInBlock then // 第一次碰到 Comment 时设置这个
    begin
      FFirstCommentInBlock := True;
      FBlankLinesBefore := FBlankLines;
    end;

    FPreviousIsComment := True;
    Result := NextToken;
    // 进入递归寻找下一个 Token,
    // 进入后 FFirstCommentInBlock 为 True,因此不会重新记录 FBlankLinesBefore
    FPreviousIsComment := False;
  end
  else
  begin
    // 只要当前不是 Comment 就设置非第一个 Comment 的标记
    FFirstCommentInBlock := False;

    if FPreviousIsComment then // 上一个是 Comment,记录这个到 上一个Comment的空行数
    begin
      // 最后一块注释的在递归最外层赋值,因此FBlankLinesAfter会被层层覆盖,
      // 代表最后一块注释后的空行数
      FBlankLinesAfter := FBlankLines + FBlankLinesAfterComment;
    end
    else // 上一个不是 Comment,当前也不是 Comment。全清0
    begin
      FBlankLinesAfter := 0;
      FBlankLinesBefore := 0;
      FBlankLines := 0;
    end;

    if FBackwardToken = tokComment then // 当前不是 Comment,但前一个是 Comment
      FCodeGen.Write(BlankString);

    if (Result = tokString) and (Length(TokenString) = 1) then
      Result := tokChar
    else if Result = tokSymbol then
      Result := StringToToken(TokenString);

    FToken := Result;
    FBackwardToken := FToken;
  end;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -