📄 uidentparser.pas
字号:
{ 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 + -