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

📄 uconditionalparser.pas

📁 DelphiDoc is a program for automatic generation of documentation on a Delphi-Project. At the momen
💻 PAS
📖 第 1 页 / 共 5 页
字号:

    Finish := False;                     //assume not finished
    if Result = 'if' then                //"$IF" found?
     SkipIf                                //skip this commands
    else                                 //older conditional commands found?
     if (Result = 'ifdef') or (Result = 'ifndef') or (Result = 'ifopt') then
      SkipIfDef                            //skip this command
     else
      Finish := True;                      //else finish and return command

  until Finish;                        //as long as not finished

  if not Assigned(FIncludedByFile) then            //this is the main parser?
   FThisFile.Statistic.Increment(pfsCompilerDirectivesNotIncluded);
  GetMainParser.ThisFile.Statistic.Increment(pfsCompilerDirectives);
 end;


 {Skips everything after an $IFDEF, $IFNDEF or $IFOPT up to and including the
  $ENDIF. }
 procedure SkipIfDef;
 var       ElseFound    :Boolean;  //"$ELSE" already found
           Command      :String;   //a compiler command
           DummyParams  :String;   //parameters of the command
 begin
  ElseFound := False;              //no else found so far

  repeat
    Command := GetNextSkipCommand(DummyParams); //get next command

    if Command = 'else' then         //"$ELSE" found?
     begin
      if ElseFound then                //has already been found?
       Exception(etPreCompiler, '"$ELSE" found after another "$ELSE"!');
      ElseFound := True;               //has been found!
     end
    else                             //invalid command?
     if (Command = 'ifend') or (Command = 'elseif') then
      ExceptionFmt(etPreCompiler,
                   '"$%s" found after "$IFDEF", "$IFNDEF" or "$IFOPT"!',
                   [UpperCase(Command)]);

  until Command = 'endif';         //until the "$ENDIF" found
 end;



 {Skips everything after an $IF up to and including the $IFEND. }
 procedure SkipIf;
 var       ElseFound    :Boolean;  //"$ELSE" already found
           Command      :String;   //a compiler command
           DummyParams  :String;   //parameters of the command
 begin
  ElseFound := False;              //no else found so far

  repeat
    Command := GetNextSkipCommand(DummyParams); //get next command

    if Command = 'elseif' then                  //"$ELSEIF" found?
     begin
      if ElseFound then                           //still allowed?
       Exception(etPreCompiler, '"$ELSEIF" found after "$ELSE"!');
     end
    else
     if Command = 'else' then                   //"$ELSE" found?
      begin
       if ElseFound then                          //not yet found?
        Exception(etPreCompiler, '"$ELSE" found after another "$ELSE"!');
       ElseFound := True;                         //now found
      end
     else
      if Command = 'endif' then                 //"$ENDIF" not valid here???
       Exception(etPreCompiler,
                 '"$ENDIF" (instead of "$IFEND") found after "$IF"!');

  until Command = 'ifend';         //until the "$IFEND" found
 end;


 {Skips everything up to and including the next $ELSE, $ELSEIF, $ENDIF or
  $IFEND. Checks if it is valid with the stack.
 ~param Params the parameters of the conditional compiling command
 ~result the conditional compiling command found }
 function Skip(var Params: String): TConditionalCompilingCommand;
 var      Command        :String;            //the command
 begin
  repeat
    Command := GetNextSkipCommand(Params);     //get next command

    if Command = 'endif' then                  //get kind of command
     Result := cccendif
    else
     if Command = 'else' then
      Result := cccelse
     else
      if Command = 'ifend' then
       Result := cccifend
      else
       if Command = 'elseif' then
        Result := cccelseif
       else
        Result := cccif;                       //dummy: end not reached

  until Result <> cccif;                     //end reached?

  if not (Result in FConditionalCompiling.Last) then  //command here valid?
   ExceptionFmt(etPreCompiler,
                '"$%s" found, but not allowed here!', [UpperCase(Command)]);
 end;




var       TheDefines   :TDefines; //the defines of the current file

 {Parses a compiler command/the first line of a compiler comment. Only the
  compiler switches are extracted and parsed.
 ~param Line the first line of a compiler comment after the $ }
 procedure ParseOption(var Line: String);
 var       Option     :String;      //the option (the first identifier)
           C          :Char;        //the compiler switch - character
           //index in the list of long names of the compiler switch
           Index      :Integer;
 begin
  repeat //until C = #0 or Line = ''

    Option := '';          //extract first option (identifier)
    while (Line <> '') and (Line[1] in IdentifierChars) do
     begin
      Option := Option + Line[1];
      Delete(Line, 1, 1);
     end;

    if Option <> '' then       //no identifier/text found?
     begin
      if Length(Option) = 1 then //only one single char?
       begin
        C := Option[1];             //use this as compiler switch
        if C in ['a'..'z'] then     //and use the upper case letter
         Dec(C, Ord('a') - Ord('A'));
       end
      else                   //search it as a long name for a compiler switch
       if IsWordIn(Option, LongCompilerOptions, Index) then
        C := ShortCompilerOptions[Index]    //and use the compiler switch
       else
        C := #0;                            //if not found abort
      case C of
        #0:  Line := Option + Line;           //abort and reset Line
        'A': if (Length(Option) > 1) and      //alignment of types
                (Option[1] in ['a', 'A']) and (Option[2] in ['0'..'9']) then
              TheDefines.Option['A'] := Option[2] <> '1'
             else
              if (Line <> '') then
               if Length(Option) = 1 then
                begin
                 if (Length(Line) = 1) and (Line[1] in ['+', '-']) then
                  TheDefines.Option['A'] := Line[1] = '+';
                end
               else
                if (UpperCase(Line) = ' ON') or (UpperCase(Line) = ' OFF') or
                   (Line = ' 1') or (Line = ' 2') or
                   (Line = ' 4') or (Line = ' 8') then
                 TheDefines.Option['A'] := (Line[3] = 'N') or
                                           (Line[2] in ['2', '4', '8']);
        'Y': if UpperCase(Option) = 'YD' then //gathering of references
              TheDefines.Option['Y'] := True    //"$YD" means also "$Y+"
             else
              if (Line <> '') then
               if Length(Option) = 1 then
                begin
                 if ((Length(Line) = 1) or (Line[2] = ',')) and
                    (Line[1] in ['+', '-']) then
                  begin
                   TheDefines.Option['Y'] := Line[1] = '+';
                   Delete(Line, 1, 1);
                  end;
                end
               else
                if (UpperCase(Line) = ' ON') or (UpperCase(Line) = ' OFF') then
                 TheDefines.Option['Y'] := Line[3] = 'N';
        'Z': if (Length(Option) > 1) and      //size of enumeration types
                (Option[1] in ['z', 'Z']) and (Option[2] in ['0'..'9']) then
              //minimal enumerations?
              TheDefines.Option['Z'] := Option[2] <> '1'
             else
              if (Line <> '') then
               if Length(Option) = 1 then
                begin
                 if ((Length(Line) = 1) or (Line[2] = ',')) and
                    (Line[1] in ['+', '-']) then
                  begin
                   TheDefines.Option['Z'] := Line[1] = '+';
                   Delete(Line, 1, 1);
                  end;
                 if (Length(Line) = 1) and (Line[1] in ['+', '-']) then
                  TheDefines.Option['Z'] := Line[1] = '+';
                end
               else
                if (UpperCase(Line) = ' ON') or (UpperCase(Line) = ' OFF') or
                   (Line = ' 1') or (Line = ' 2') or (Line = ' 4') then
                 TheDefines.Option['Z'] := (Line[3] = 'N') or
                                           (Line[2] in ['2', '4']);
      else
       if (C in ['A'..'Z']) and (Line <> '') and
          (((Length(Option) = 1) and                     //short option?
            ((Length(Line) = 1) or (Line[2] = ',')) and
            (Line[1] in ['+', '-'])) or
           ((Length(Option) > 1) and                     //long option?
            (UpperCase(Line) = ' ON') or (UpperCase(Line) = ' OFF'))
          ) then
        begin
         if ((Length(Line) = 1) or (Line[2] = ',')) and  //short option?
            (Line[1] in ['+', '-']) then
          begin                                 //set compiler switch by +/-
           TheDefines.Option[C] := Line[1] = '+';
           Delete(Line, 1, 1);
          end
         else                                   //set compiler switch by ON/OFF
          if (UpperCase(Line) = ' ON') or (UpperCase(Line) = ' OFF') then
           TheDefines.Option[C] := Line[3] = 'N';
        end
       else
        begin
         C := #0;                  //abort and
         Line := Option + Line;    //reset Line
        end;
      end;
      if (Line <> '') and (Line[1] <> ',') then //no further options?
       C := #0;                                   //abort
     end
    else
     C := #0;                             //no identifier => abort
  until (C = #0) or (Line = '');  //abort or no other option left
 end;





var       Cmd          :String;   //the first command (identifier)
          FirstParam   :String;   //the first parameter of the command
          i            :Integer;  //general indices
          //currently allowed conditional compiling commands
          ValidCmds    :TConditionalCompilingCommands;
          //if the "body" of a conditional compiling command should be skipped
          SkipBody     :Boolean;
          //the found conditional compiling command
          CmdFound     :TConditionalCompilingCommand;
begin
 if not Assigned(FIncludedByFile) then            //this is the main parser?
  FThisFile.Statistic.Increment(pfsCompilerDirectivesNotIncluded);
 GetMainParser.ThisFile.Statistic.Increment(pfsCompilerDirectives);


 Result := False;                //assume no file newly included
 if Command <> '' then           //command given?
  begin
   TheDefines := FDefinesIncluded; //get defines of the current file
   if not Assigned(TheDefines) then
    TheDefines := FThisFile.Defines;


   ParseOption(Command);           //try parsing the options

   i := Pos(' ', Command);         //extract command and first parameter
   if i = 0 then                     //no parameters?
    begin
     Cmd := Command;                   //use whole line as command
     Command := '';
    end
   else
    begin
     Cmd := Copy(Command, 1, i - 1);   //extract command
     Delete(Command, 1, i);

     Command := Trim(Command);
     FirstParam := Command;
     if Command <> '' then             //further parameters?
      if Command[1] = '''' then          //is a string (starting with "'")?
       begin
        Delete(FirstParam, 1, 1);          //get string without "'"
        i := Pos('''', FirstParam);
        if i = 0 then
         WarningMessage(etPreCompiler,
                        'Option to compiler-directive starting with "''" but no "''" following!')
        else
         Delete(FirstParam, i, High(Length(FirstParam)));
       end
      else
       begin
        i := Pos(' ', FirstParam);         //search the first space
        if i <> 0 then                     //delete it and anything following
         Delete(FirstParam, i, High(Length(FirstParam)));
       end;
    end;
   Cmd := LowerCase(Cmd);


   //handle the command:

   //simple compiler symbols to define or undefine?
   if (Cmd = 'define') or (Cmd = 'undef') then
    begin
     if Command = '' then
      Exception(etPreCompiler, 'Parameter for $define/$undef missing!');

     //search compiler symbol
     i := TheDefines.Defines.IndexOf(FirstParam);
     if Cmd[1] = 'd' then                         //should be defined?
      begin
       if i < 0 then                                //if not already defined
        TheDefines.Defines.Append(FirstParam);        //define it
      end
     else
      if i >= 0 then                                //if it is defined
       TheDefines.Defines.Delete(i);                  //undefine it
    end
   else
   //ELSE-part of conditional compiling command found?
    if Cmd = 'else' then

⌨️ 快捷键说明

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