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

📄 uconditionalparser.pas

📁 DelphiDoc is a program for automatic generation of documentation on a Delphi-Project. At the momen
💻 PAS
📖 第 1 页 / 共 5 页
字号:
 if not Assigned(TheDefines) then
  TheDefines := FThisFile.Defines;

 Parser := TTokenParser.Create;             //parser for the expression
 try
   Parser.PascalDialect := PascalDialect;
   Position := AbsoluteLastTokenStartPos;   //parser the expression
   Parser.ParseString(Expression, Position.Row, Position.Column);

   NextToken := '';
   ParseExpression(NextToken, pAll, Value); //evaluate the expression
 finally
  Parser.Free;
 end;

 if NextToken <> '' then
  ExceptionFmt(etPreCompiler,
               'Unexpected token in condition after "$IF" or "$ELSEIF": "%s"!',
               [NextToken]);

 if Value.kind = vkNone then
  ExceptionFmt(etPreCompiler,
               'Invalid condition after "$IF" or "$ELSEIF": "%s"!',
               [Expression]);

 //return the boolean value of the expression (if possible)
 Result := ((Value.kind = vkBoolean) and (Value.bool)) or
           ((Value.kind = vkNumber) and (Value.num <> 0));
end;































{Checks if the Extended Syntax is enabled at the moment.
~result if the Extended Syntax is enabled currently }
function TConditionalParser.IsExtendedSyntaxEnabled: Boolean;
begin
 if Assigned(FIncludedFile) then                  //includes a file?
  //use setting of the included file
  Result := FIncludedFile.IsExtendedSyntaxEnabled
 else
  if Assigned(FDefinesIncluded) then                //is included?
   Result := FDefinesIncluded.Options['X']            //use state of the parser
  else
   Result := inherited IsExtendedSyntaxEnabled;       //return setting of file
end;




{Returns the next token (after the current position).
~param Token returns the found token or '' if no token could be found
~result if a token could be found }
function TConditionalParser.DoGetToken(var Token: String): Boolean;

 {Gets the next token in this file (not in an included one). }
 procedure GetNextToken;
 var       FromIncluded   :Boolean; //whether token was read from included file
 begin
  FromIncluded := False;
  Result := DoDoGetToken(Token);            //get the token

  while Result and (Token <> '') and        //it is a comment for the compiler?
        ((Token[1] = '{') or
         ((Length(Token) >= 2) and (Token[1] = '(') and (Token[2] = '*'))) do
   begin
    if Token[1] = '{' then                    //delete comment braces
     Token := Copy(Token, 3, Length(Token) - 3)
    else
     Token := Copy(Token, 4, Length(Token) - 5);

    FromIncluded := HandleCompilerOption(Token); //handle the compiler option
    if FromIncluded then                         //new included file?
     Result := DoGetToken(Token)                   //get token in included file
    else
     Result := DoDoGetToken(Token);                //get the next token
   end;

  if Result and not FromIncluded and not Assigned(FIncludedByFile) then
   begin
    FThisFile.Statistic.Increment(pfsTokens);
    FThisFile.Statistic.Increment(pfsTokensNotIncluded);
   end;
 end;

var      TokenPosition     :TTokenPosition; //effective position of the token
begin
 if Assigned(FIncludedFile) then         //currently reading an included file?
  begin
   try
     Result := FIncludedFile.GetToken(Token);    //get token in $INCLUDEd file
     if Result and not Assigned(FIncludedByFile) then
      FThisFile.Statistic.Increment(pfsTokens);
   except
     if ExceptObject is EParseException then     //in case of an exception
      with EParseException(ExceptObject) do        //change file data to this
       begin
        Message := Format('In $INCLUDEd file %s %d:%d:' + LineDelimiter,
                          [ExtractFileName(FIncludedFile.ThisFile.FilePath),
                           ErrorPosition.Row, ErrorPosition.Column]) + Message;
        TheFile := Self.FThisFile;
        ErrorPosition := AbsoluteLastTokenStartPos; //position of the $INCLUDE
       end;
     raise;
   end;

   if Result then                    //a token was read from the included file?
    begin
     //read its effective position and set it
     TokenPosition := FIncludedFile.GetLastTokenPositions;
     SetEffectivePositionOfLastToken(TokenPosition.FEffectiveFile,
                                     TokenPosition.FEffectivePosition);
    end
   else                                         //token not found/end of file
    begin
     //change the changed compiler options also in the including file
     if Assigned(FDefinesIncluded) then           //is in turn included?
      begin                                         //change local defines
       FDefinesIncluded.Options := FIncludedFile.FDefinesIncluded.Options;
       FDefinesIncluded.Defines.Assign(FIncludedFile.FDefinesIncluded.Defines);
      end
     else
      begin                                         //change defines of files
       FThisFile.Defines.Options := FIncludedFile.FDefinesIncluded.Options;
       FThisFile.Defines.Defines.Assign(FIncludedFile.FDefinesIncluded.
                                                                      Defines);
      end;

     try
       FIncludedFile.Free;                        //free included file
     finally
      FIncludedFile := nil;                       //no file included currently
     end;
     GetNextToken;                                //get the next token
    end;
  end //if assigned(FIncludedFile)
 else
  GetNextToken;                              //just get the next token
end;


{Initializes an Parser-Exception-Object before it gets raised. Adds position in
 the including file to the exception object.
~param ExcpObj the exception object to be initialized
~result ExcpObj after the initialization }
function TConditionalParser.InitExceptionObject(ExcpObj: Exception): Exception;
var      Included   :TConditionalParser;  //counter through included files
//         LastPos    :TPosition;           //position in included file
begin
 Result := inherited InitExceptionObject(ExcpObj);

{
 Included := FIncludedFile;
 while Assigned(Included) do              //while another file included
  begin
   LastPos := Included.AbsoluteLastTokenStartPos; //get current position in it
   //and add it
   Result.Message := Format('In $INCLUDEd file %s %d:%d:' + LineDelimiter +
                            '...',
                            [ExtractFileName(Included.ThisFile.FilePath),
                             LastPos.Row, LastPos.Column]) +
                     Result.Message;
   Included := Included.CurrentlyIncludedFile;  //get file included by this one
  end;



 Included := FIncludedByFile;
 while Assigned(Included) do              //while included by another file
  begin
   LastPos := Included.AbsoluteLastTokenStartPos; //get current position in it
   //and add it
   Result.Message := Format('$INCLUDEd by file %s %d:%d:' + LineDelimiter +
                            '...',
                            [ExtractFileName(Included.ThisFile.FilePath),
                             LastPos.Row, LastPos.Column]) +
                     Result.Message;
   Included := Included.IncludedByFile;     //get the file including this one
  end;
}

 if Result is EParseException then        //extended information?
  begin
   Included := Self;
   //get included file currently reading tokens from
   while Assigned(Included.FIncludedFile) do
    Included := Included.FIncludedFile;

   //set file and position of the error
   EParseException(Result).EffectiveFile := Included.ThisFile;
   EParseException(Result).EffectiveErrorPosition :=
                                            Included.AbsoluteLastTokenStartPos;


   if Assigned(FIncludedByFile) then        //included by other files?
    begin
     Included := GetMainParser;               //get the original including file

     //set file and position of the original, first including file
     EParseException(Result).TheFile := Included.ThisFile;
     EParseException(Result).ErrorPosition :=
                                            Included.AbsoluteLastTokenStartPos;
    end;
  end;
end;
















{Handles a compiler option (if it understands it).
~param Command the compiler command in the comment
~result if a file was included }
function TConditionalParser.HandleCompilerOption(Command: String): Boolean;


 //Gets the next compiler command, skipping everything until it is found.
 function GetNextSkipCommand(var Params: String): String; forward;

 {Skips everything after an $IFDEF, $IFNDEF or $IFOPT up to and including the
  $ENDIF. }
 procedure SkipIfDef; forward;
 {Skips everything after an $IF up to and including the $IFEND. }
 procedure SkipIf; forward;

 {Skips everything up to and including the next $ELSE, $ELSEIF, $ENDIF or
  $IFEND. Checks if it is valid with the stack. }
 function Skip(var Params: String): TConditionalCompilingCommand; forward;

 //Parses a compiler command/the first line of a compiler comment.
 procedure ParseOption(var Line: String); forward;






 {Gets the next compiler command, skipping everything until it is found. Nested
  command blocks are recognized and skipped completely.
 ~param Params out: the parameters of the command
 ~result the next compiler command }
 function GetNextSkipCommand(var Params: String): String;
 var      IsDirective       :Boolean;  //if new token is a compiler directive
          i                 :Integer;  //end of the command in the comment
          Finish            :Boolean;  //if the command has been found
 begin
  Result := '';
  repeat                               //as long as not finished
    repeat                               //as long as no compiler command found
     if not DoDoGetToken(Result) then      //get a token
      Exception(etPreCompiler,
                'Unexpected end while searching for "$ENDIF"/"$IFEND"!');

     Assert(Result <> '');
     IsDirective := (Result[1] = '{') or   //is a compiler command?
                    ((Length(Result) >= 2) and
                     (Result[1] = '(') and (Result[2] = '*'));

     if not IsDirective then               //not a compiler command
      begin                                  //update the statistic
       if not assigned(FIncludedByFile) then      //this is the main parser?
        FThisFile.Statistic.Increment(pfsSkippedTokensNotIncluded);
       GetMainParser.ThisFile.Statistic.Increment(pfsSkippedTokens);
      end;

    until IsDirective;                   //until token is a compiler command

    //delete comment-signs and "$"
    if Result[1] = '{' then
     Result := Copy(Result, 3, Length(Result) - 3)
    else
     Result := Copy(Result, 4, Length(Result) - 5);

    i := Pos(' ', Result);               //extract command
    if i <> 0 then
     begin
      Params := Copy(Result, i + 1, High(Length(Result)));
      Result := Copy(Result, 1, i - 1)
     end
    else
     Params := '';
    Result := LowerCase(Result);

⌨️ 快捷键说明

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