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

📄 uconditionalparser.pas

📁 DelphiDoc is a program for automatic generation of documentation on a Delphi-Project. At the momen
💻 PAS
📖 第 1 页 / 共 5 页
字号:
     begin
      if FConditionalCompiling.Count = 0 then
       Exception(etPreCompiler, '"$ELSE" without "$IFxxx" found!');

      ValidCmds := FConditionalCompiling.Last;
      if not (cccelse in ValidCmds) then
       Exception(etPreCompiler, '"$ELSE" after another "$ELSE" found!');

       //$ELSE and $ELSEIF not allowed anymore
      ValidCmds := ValidCmds - [cccelse, cccelseif];
      FConditionalCompiling.Pop;
      FConditionalCompiling.Add(ValidCmds);
      Skip(Command);                       //now just skip "body" in ELSE-part
      FConditionalCompiling.Pop;
     end
    else
   //end of conditional compiling command found?
     if Cmd = 'endif' then
      begin
       if FConditionalCompiling.Count = 0 then
        Exception(etPreCompiler, '"$ENDIF" without "$IFxxx" found!');

       if not (cccendif in FConditionalCompiling.Last) then
        Exception(etPreCompiler,
                  '"$ENDIF" (instead of "$IFEND") after "$IF" found!');

       FConditionalCompiling.Pop;            //just remove the command
      end
     else
   //new conditional compiling command found?
      if (Cmd = 'ifdef') or (Cmd = 'ifndef') or (Cmd = 'ifopt') then
       begin                       //conditional compiling
        if FirstParam = '' then
         Exception(etPreCompiler, 'Parameter for "$IFxxx" missing!');

        if (Cmd[3] = 'o') then     //$IFOPT found?
         begin
          if (Length(FirstParam) <> 2) or
             not (FirstParam[1] in ['A'..'Z', 'a'..'z']) or
             not (FirstParam[2] in ['+', '-']) then
           Exception(etPreCompiler,
                     'Character and "+" or "-" after $IFOPT expected, failed!');

          //delete text if compiler switch differs from the +/-
          SkipBody := TheDefines.Options[UpCase(FirstParam[1])] <>
                      (FirstParam[2] = '+');
         end
        else          //delete text if symbol not defined xor $define
         SkipBody := (TheDefines.Defines.IndexOf(FirstParam) <> -1) <>
                     (Cmd[3] = 'd');

        //add conditional compiling command
        FConditionalCompiling.Add([cccelse, cccelseif, cccifend, cccendif]);
        if SkipBody then                  //"body" should be skipped?
         begin
          repeat
            CmdFound := Skip(Command);        //get next conditional command
          until (CmdFound <> cccelseif) or  //until part not to skip found
                GetConditionalCompilingDecision(Command);

          if CmdFound <> cccelseif then     //not just another part?
           begin
            FConditionalCompiling.Pop;        //remove conditional command
            if CmdFound = cccelse then        //if only $ELSE
             //add it again without $ELSE
             FConditionalCompiling.Add([cccifend, cccendif])
            else
             Assert((CmdFound = cccendif) or (CmdFound = cccifend));
           end;
         end;
       end
      else
   //end of conditional compiling command found?
       if Cmd = 'ifend' then
        begin
         if FConditionalCompiling.Count = 0 then
          Exception(etPreCompiler, '"$IFEND" without "$IF" found!');

         if not (cccifend in FConditionalCompiling.Last) then
          Exception(etPreCompiler,
                    '"$IFEND" (instead of "$ENDIF") after "$IFxxx" found!');

         FConditionalCompiling.Pop;              //just remove the command
        end
       else
   //new conditional compiling command found?
        if (Cmd = 'if') or (Cmd = 'elseif') then
         begin
          if FirstParam = '' then
           ExceptionFmt(etPreCompiler,
                       'Parameter for "$%s" missing!', [UpperCase(Cmd)]);

          if Cmd[1] <> 'i' then                //$ELSEIF ?
           begin
            if FConditionalCompiling.Count = 0 then
             Exception(etPreCompiler, '"$ELSEIF" without "$IF" found!');

            if not (cccelse in FConditionalCompiling.Last) then
             Exception(etPreCompiler,
                       '"$ELSEIF" without "$IF" or after "$ELSE" found!');
           end
          else                      //$IF => add conditional compiling command
           FConditionalCompiling.Add([cccelse, cccelseif, cccifend, cccendif]);

          //is expression not true?
          if not GetConditionalCompilingDecision(Command) then
           begin
            repeat
              CmdFound := Skip(Command);         //skip "body"
            until (CmdFound <> cccelseif) or   //until end or true part reached
                  GetConditionalCompilingDecision(Command);

            if CmdFound <> cccelseif then      //not just another part
             begin
              FConditionalCompiling.Pop;         //remove conditional command
              if CmdFound = cccelse then         //if it is $ELSE
               //add again without $ELSE
               FConditionalCompiling.Add([cccifend, cccendif])
              else
               Assert((CmdFound = cccifend) or (CmdFound = cccendif));
             end;
           end;
         end
        else
   //inclusion of another file found?
         if (Cmd = 'include') or (Cmd = 'i') then
          Result := HandleInclude(FirstParam)     //include it
         else
   //compiler message found?
          if Cmd = 'message' then                //just generate a message
           WarningMessage(etPreCompiler, 'Compiler-$Message: ' + Command);
(*         {$MESSAGE 'Boo!'}                   -> HINT
           {$Message Hint  'Feed the cat.'}    -> HINT
           {$messaGe Warn  'Looks like rain.'} -> WARNING
           {$Message Error 'not implemented'}  -> ERROR
           {$Message Fatal 'dead'}             -> FATAL        *)



{
I = INCLUDE
L = LINK
M = MINSTACKSIZE/MAXSTACKSIZE
R = RESOURCE

$C PRELOAD = ?????????
}

{cpp:
HPPEMIT
NOINCLUDE
EXTERNALSYM

}


  end; //if Command <> ''
end;



{Handles the inclusion of a file.
~param FileName the name of the file to include
~result if a file was included }
function TConditionalParser.HandleInclude(FileName: String): Boolean;
var      Parser            :TConditionalParser; //original file
         FilePath          :String;             //absolut path of file
         i                 :Integer;            //counter through search paths
begin
 Assert(not Assigned(FIncludedFile));

 //'.pas' (or '.PAS' ???) may be automatically appended
 if ExtractFileExt(FileName) = '' then
  FileName := FileName + '.PAS';                  //'.pas' ???? correct ????

 {  $INCLUDE search paths:
             1.  current (file) path    (original file, not included?)
             2.  project path
             3.  project search paths
             4.  delphi search paths                                    }

 Parser := GetMainParser;                       //search original parser

 if IsAbsolutePath(FileName) then          //path to included file is absolute?
  FilePath := FileName                       //just use it
 else
  begin
   //search in path of original file
   FilePath := GetAbsolutePathRelative(
                          ExtractFilePath(Parser.ThisFile.FilePath), FileName);

{
   if Assigned(Parser.ProjectFile) and not FileExists(FilePath) then
    FilePath := GetAbsolutePathRelative(ExtractFilePath(Parser.ProjectFile.
                                                                     FilePath),
                                        FileName);
}

   //if not found so far and search paths available
   if not FileExists(FilePath) and
      (Parser.ThisFile.Defines.SearchPath.Count > 0) then
    begin
     i := 0;                             //try with all search-paths ...
     repeat                                //get file in the path
       FilePath := ExtractShortPathName(ExpandFileName(
         GetAbsolutePathRelative(
                        ExtractFilePath(Parser.ThisFile.Defines.SearchPath[i]),
                        FileName)));
       Inc(i);
     //until every path tried or file found
     until (i = Parser.ThisFile.Defines.SearchPath.Count) or
           FileExists(FilePath);
    end;

   //if not found search in path of current file (Delphi 4 does not do this)
   if (Parser <> Self) and not FileExists(FilePath) then
    FilePath := GetAbsolutePathRelative(ExtractFilePath(FThisFile.FilePath),
                                        FileName);
  end;



 Result := FileExists(FilePath);     //file found?
 if not Result then
  WarningMessageFmt(etPreCompiler,
                    'File "%s" to $INCLUDE not found!', [FileName])
 else
  begin
   FilePath := ExtractShortPathName(FilePath);


   Parser := Self;                             //check if already including
   while Assigned(Parser) and (Parser.ThisFile.FilePath <> FilePath) do
    Parser := Parser.IncludedByFile;
   if Assigned(Parser) then                    //already including this file?
    WarningMessageFmt(etPreCompiler,
                      'Recursive inclusion of file "%s", ignored!', [FilePath])
   else
    begin
     Parser := GetMainParser;                    //search original parser again

     //check if file was already parsed as a file by its own
     if Assigned(Parser.ThisFile.FileList.GetFileAbsolute(FilePath)) then
      WarningMessage(etPreCompiler,
                     'Included file was already read as a normal file, this is probably an error!: ' +
                     FilePath);


     try
       //read INCLUDEd file and create parser for the included file
       FIncludedFile := TConditionalParser.Create(
                               Parser.ThisFile.FileList.IncludeFile(FilePath,
                                                                    FileName));
       FIncludedFile.ThisFile.Parser := nil;  //don't need reference on parser
       FIncludedFile.IncludedByFile := Self;
       FIncludedFile.PascalDialect := PascalDialect;

       if FIncludedFile.ThisFile.InternalFileName = '' then
        FIncludedFile.ThisFile.InternalFileName := '$I ' +
                                                   ExtractFileName(FileName);

       //create a copy of the defines - use same compiler defines
       FIncludedFile.FDefinesIncluded := TDefines.Create;
       if Assigned(FDefinesIncluded) then
        FIncludedFile.FDefinesIncluded.CopyOptions(FDefinesIncluded)
       else
        FIncludedFile.FDefinesIncluded.CopyOptions(FThisFile.Defines);
//       FIncludedFile.ThisFile.SetCompilerDefines(FThisFile.Defines, True);

       //pre-parse it
       FIncludedFile.SetContentToParse(FIncludedFile.ThisFile.Lines);


       //increment statistics values of main file by values of included file
       with GetMainParser.ThisFile.Statistic do
        begin
         IncrementBy(psfLines,
                     FIncludedFile.ThisFile.Statistic.Numbers[psfLines]);
         IncrementBy(psfCharacters,
                     FIncludedFile.ThisFile.Statistic.Numbers[psfCharacters]);
         IncrementBy(psfEmptyLines,
                     FIncludedFile.ThisFile.Statistic.Numbers[psfEmptyLines]);
         IncrementBy(psfLinesWithComments,
                     FIncludedFile.ThisFile.Statistic.Numbers[
                                                        psfLinesWithComments]);
         IncrementBy(psfLinesWithTokens,
                     FIncludedFile.ThisFile.Statistic.Numbers[
                                                          psfLinesWithTokens]);
        end;
     except
       if ExceptObject is EParseException then
        with EParseException(ExceptObject) do
         begin
          Message := Format('In $INCLUDEd file %s %d:%d (%s):' + LineDelimiter,
                            [FileName, ErrorPosition.Row, ErrorPosition.Column,
                             FilePath]) + Message;

          TheFile := Self.FThisFile;                //set data of this file
          //position of the $INCLUDE
          ErrorPosition := AbsoluteLastTokenStartPos;
         end;
       raise;
     end;

    end; //else assigned(Parser)     //recursive inclusion
  end; //else not Result

 Parser := GetMainParser;                          //get main parser (again)
 if Parser = Self then                             //this is the main parser?
  FThisFile.Statistic.Increment(pfsIncludedFiles);   //increment statistic
 Parser.ThisFile.Statistic.Increment(pfsAllIncludedFiles);  //ditto
end;

end.


⌨️ 快捷键说明

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