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

📄 uidentparser.pas

📁 DelphiDoc is a program for automatic generation of documentation on a Delphi-Project. At the momen
💻 PAS
📖 第 1 页 / 共 5 页
字号:
{  JADD - Just Another DelphiDoc: Documentation from Delphi Source Code

Copyright (C) 2003-2008   Gerold Veith

This file is part of JADD - Just Another DelphiDoc.

DelphiDoc is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3 as
published by the Free Software Foundation.

DelphiDoc is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
}


unit UIdentParser;

{Contains the class ~[link TIdentifierParser] to parse the identifiers in the
 pascal data/file(s).
}


interface

uses SysUtils, Classes,
     UPascalConsts,
     UTokenParser, UBaseIdents, UExtIdents;


type


   { * * *  ***  * * *  ***   TIdentifierParser   ***  * * *  ***  * * *  }


  //when testing if the parser is at the end of a statement these special
  //tokens can be ignored;
  //"seSemicolon" is always tested and can't be ignored
  TIgnoreStatementEnd = (
//    iseBrace,   //don't treat a closing brace ) as the end of the statement

    iseEnd,   //don't treat the reserved word "end" as the end of the statement
    iseOf     //don't treat the reserved word "of" as the end of the statement

//    iseAbsolute //don't treat the directive absolute as the end of the stmt.
//  , iseEqual    //don't treat an equal sign = as the end of the statement
    );

  //a set of these tokens to be ignored can be given to the test functions
  TIgnoreStatementEnds = set of TIgnoreStatementEnd;




  //allowed directives to end expressions (all others are errors)
  TAllowedExpressionDirective = (
                                 //portability directives (deprecated, library,
                                 aedPortability,       //  platform)
                                 //"=" equal sign (initialization)
                                 aedEqual,
                                 //absolute (initialization (variables only))
                                 aedAbsolute,
                                 //"index"/"name"
                                 //(external function-declaration or exports)
                                 aedIndexName,
                                 //"resident" (exports)
                                 aedResident,
                                 //property attributes/directives
                                 aedProperty);

  //allowed directives to end expressions (all other are errors)
  TAllowedExpressionDirectives = set of TAllowedExpressionDirective;


  //used to parse ~[code array of const] to ~[code array of TVarRec] and the
  //index type of an array
  TParseTypeKind = (
                    ptkGeneral,           //its a general type
                    ptkParameter,         //the type is for a parameter
                    ptkArrayOfParameter,  //type is for an open array parameter
                    ptkArrayIndex         //type is the index of an array
                   );




  //classes of parsers of pascal data/files
  TIdentifierParserClass = class of TIdentifierParser;


  {Extends its base class to parse the identifiers in the pascal data.
   Functions will be parsed but the local identifiers not saved, the body of
   functions will only be skipped, this behaviour is overridden (and the
   parsing of the function bodies completed) in the class ~[linkClass
   TCodeParser]. This means only definitions will be parsed in this class, but
   no actual pascal code that can be executed. }
  TIdentifierParser = class(TTokenParser)
  private
    //the currently parsed record-like type
    FCurrentRecord: TRecordType;
    //current case of record like type
    FCurrentRecordCase: TRecordCase;


    //Returns if the token ends a statement.
    function IsEndOfStmtToken(const Token: String;
                           IgnoreStmtEnds: TIgnoreStatementEnds = []): Boolean;

  protected

    //the file to parse
    FThisFile: TPascalFile;


    //current scope while parsing
    FScope: TScope;

    //list of identifiers to which new should be added
    //the file-, record-type- oder local-list
    FActualIdents: TIdentifierList;

    //next global scope while parsing
    FGlobalScope: TScope;

    //list of identifiers to which the items of enumerations should be added;
    //file- oder local-list (maybe record-type-list in Dephi 8+ ?)
    FActualScopeIdents: TIdentifierList;





    //Initializes an Parser-Exception-Object before it gets raised.
    function InitExceptionObject(ExcpObj: Exception): Exception; override;


    //Returns the positions of the last returned token.
    function GetLastTokenPositions: TTokenPosition; override;

    //Assigns the position of the last token to the identifier.
    procedure SetPosition(Identifier: TIdentifier;
                          AlsoForwardPos: Boolean = True);
    //Assigns the position to the identifier.
    procedure SetOldPosition(Identifier: TIdentifier;
                             const Pos: TTokenPosition;
                             AlsoForwardPos: Boolean = True);



    //Skips the next token if it is a semicolon and returns if it was.
    function SkipSemicolon: Boolean;


    //Raises an exception, if it is not a valid name.
    procedure CheckIdentifierName(const Name: String; const Kind: String = '');







    //Reads portability directives.
    function ReadPortabilityIssues(var Token: String): TIdentPortabilities;

    //Reads portability directives of this file.
    function ReadOwnPortabilityIssues: String;








    {Handles a function after the head of the function, this means all
     declarations and the body. This method is implemented in ~[linkClass
     TCodeParser].
    ~param FuncIdent the identifier of the function that should be parsed
    ~result if "finalization" has been found }
    function ParseDeclarationsAndBody(FuncIdent: TFunction): Boolean; virtual;
                                                                      abstract;



    //Will be called for every pointer and class reference type in the just
    //ended block of type definitions and checks for forward references.
    procedure CallBackIdentTypeBlockEnd(Ident: TIdentType; Parent: TIdentifier;
                                        Data: TIdentifier);
    //Will be called when a block of type definitions has been ended and checks
    //for forward references.
    procedure TypeBlockHasEnded(StartIndex: Integer);


    {Will be called before and after any function and at the end of the
     section. Will be implemented in ~[linkClass TFileParser].
    ~param Startindex index of the first new identifier since the last time
                      this function has been called }
    procedure AfterDefinition(StartIndex: Integer); virtual; abstract;

    {Will be called after parsing the head of a function before parsing the
     local definitions and the body. Will be implemented in ~[linkClass
     TFileParser].
    ~param Func the function that is about to be parsed }
    procedure BeforeFunctionLocalsAndBody(Func: TFunction); virtual; abstract;



    //Parses the list of ancestors/parents of a class or interface.
    procedure ParseRecordLikeParents(TheRec: TRecordType; Ancestors: String);

    //Parses a constant expression.
    function ParseConstantExpression(var ExprTokens: String;
                     EndDirectives: TAllowedExpressionDirectives = []): String;




    //Parses a list of definitions of parameters in functions, function types
    //or the list of array indices of properties.
    procedure ParseParams(List: TIdentifierList; PropertyIndices: Boolean);



    //Parses and returns a type.
    function ParseType(var NextToken: String;
                       EndDirectives: TAllowedExpressionDirectives = [];
                       TypeKind: TParseTypeKind = ptkGeneral): TType;
    //Parses and returns a simple type (identifier or string) used by return
    //types of functions or the type of properties.
    function ParseFunctionReturnType: TType;
    //Parses the list of items of an enumeration.
    procedure ParseEnumItemList(EnumType: TEnumType);
    //Parses a function type.
    function ParseFunctionType(FuncKind: TFunctionKind): TFunctionType;
    //Parses a record-like type.
    function ParseRecordType(RecordKind: TRecordKind;
                             ForwardDecl: TRecordType): TRecordType;
    //Parses the variant part of a record.
    function ParseRecordCase(CurrentCase: TRecordCase): String;
    //Parses a field in a record-like type.
    function ParseField(const FieldName: String): String;
    //Parses a property.
    function ParseProperty(IsDispInterface: Boolean): TProperty;


    //Parses a function.
    function ParseFunction(FuncKind: TFunctionKind;
                           IsClassFunction, InInterface: Boolean): TFunction;
    //Parses the declaration of a type.
    function ParseTypeIdentifier(const IdentName: String): String;
    //Parses the declaration of a resourcestring.
    function ParseResourceString(const IdentName: String): String;
    //Parses the declaration of a constant.
    function ParseConstant(const IdentName: String): String;
    //Parses the declaration of variables.
    function ParseVariable(const IdentName: String;
                           IsThreadVar: Boolean): String;


  public
    //Saves the file to be parsed.
    constructor Create(TheFile: TPascalFile); virtual;


    property ThisFile: TPascalFile read FThisFile write FThisFile;
  end;



implementation




   { * * *  ***  * * *  ***   TIdentifierParser   ***  * * *  ***  * * *  }



      //alphabetical list of reserved words possible outside of any function
const TopLevelWordsFile: array[0..14] of String =
       ('class',     'const',          'constructor', 'destructor',     'end',
        'exports',   'finalization',   'function',    'implementation',
                                                              'initialization',
        'procedure', 'resourcestring', 'threadvar',   'type',           'var');






{Saves the file to be parsed.
~param TheFile the file to parse and save the parsed data to }
constructor TIdentifierParser.Create(TheFile: TPascalFile);
begin
 inherited Create;                        //create the object

 assert(assigned(TheFile));
 FThisFile := TheFile;                    //save the file
 assert(not assigned(FThisFile.Parser));
 FThisFile.Parser := Self;                //and use this as its parser
end;











{Returns if the token ends a statement.
~param Token          the token to check, whether it ends the statement
~param IgnoreStmtEnds what ends of statements to ignore when determining it
~result if the statement is ended by the token }
function TIdentifierParser.IsEndOfStmtToken(const Token: String;
                           IgnoreStmtEnds: TIgnoreStatementEnds = []): Boolean;
var      Lower            :String;       //token in lower case
begin
 if Token = '' then                      //is an empty string?
  Result := True                           //end of file = end of statement
 else
  if length(Token) = 1 then              //is a single character?
   Result := Token[1] in [';', ')', '=']   //the character means the end?
//   Result := (Token[1] in [';', ')']) or
//             ((Token[1] = '=') {and not (iseEqual in IgnoreStmtEnds)})
  else
   begin                                   //the token is 'end' or 'of' and
    Lower := LowerCase(Token);             //that is not ignored?
    Result := (not (iseEnd in IgnoreStmtEnds) and (Lower = 'end')) or
              (not (iseOf in IgnoreStmtEnds) and (Lower = 'of'));
   end;
end;






{Initializes an Parser-Exception-Object before it gets raised. This function
 sets the file. It can be overridden in subclasses that have more
 information to set, where and why the error occured.
~param ExcpObj the exception object to be initialized
~result ExcpObj after the initialization }
function TIdentifierParser.InitExceptionObject(ExcpObj: Exception): Exception;
begin

⌨️ 快捷键说明

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