478 lines
13 KiB
ObjectPascal
478 lines
13 KiB
ObjectPascal
unit Myc.Ast.Identities;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.SysUtils,
|
|
Myc.Data.Value,
|
|
Myc.Data.Keyword;
|
|
|
|
type
|
|
// Forward declarations
|
|
INamedIdentity = interface;
|
|
IConstantIdentity = interface;
|
|
IKeywordIdentity = interface;
|
|
IDefinitionIdentity = interface;
|
|
IListIdentity = interface;
|
|
|
|
// Represents a position in the source code.
|
|
ISourceLocation = interface
|
|
function GetLine: Integer;
|
|
function GetCol: Integer;
|
|
function ToString: string;
|
|
property Line: Integer read GetLine;
|
|
property Col: Integer read GetCol;
|
|
end;
|
|
|
|
// Discriminator enum for identity types.
|
|
TAstIdentityKind = (
|
|
ikStructural, // Pure location, no extra data (e.g. If, Block)
|
|
ikNamed, // Identifier, MacroDef (Name + Location)
|
|
ikConstant, // Literals (Value + Location)
|
|
ikKeyword, // Keywords (Keyword + Location)
|
|
ikDefinition, // Complex definitions (DefString + Location)
|
|
ikList // Lists (Open/Close Tokens + Separator + Location)
|
|
);
|
|
|
|
// Base interface for the "Green Tree" nodes.
|
|
// Holds the raw syntax data and optional source location.
|
|
IAstIdentity = interface
|
|
{$region 'private'}
|
|
function GetKind: TAstIdentityKind;
|
|
function GetLocation: ISourceLocation;
|
|
{$endregion}
|
|
|
|
function ToString: string;
|
|
|
|
// Explicit casting methods (Fail-Fast)
|
|
function AsNamed: INamedIdentity;
|
|
function AsConstant: IConstantIdentity;
|
|
function AsKeyword: IKeywordIdentity;
|
|
function AsDefinition: IDefinitionIdentity;
|
|
function AsList: IListIdentity;
|
|
|
|
property Kind: TAstIdentityKind read GetKind;
|
|
|
|
// Optional: Returns nil if the node has no source mapping (e.g. generated code)
|
|
property Location: ISourceLocation read GetLocation;
|
|
end;
|
|
|
|
INamedIdentity = interface(IAstIdentity)
|
|
{$region 'private'}
|
|
function GetName: string;
|
|
{$endregion}
|
|
property Name: string read GetName;
|
|
end;
|
|
|
|
IConstantIdentity = interface(IAstIdentity)
|
|
{$region 'private'}
|
|
function GetValue: TDataValue;
|
|
{$endregion}
|
|
property Value: TDataValue read GetValue;
|
|
end;
|
|
|
|
IKeywordIdentity = interface(IAstIdentity)
|
|
{$region 'private'}
|
|
function GetValue: IKeyword;
|
|
{$endregion}
|
|
property Value: IKeyword read GetValue;
|
|
end;
|
|
|
|
IDefinitionIdentity = interface(IAstIdentity)
|
|
{$region 'private'}
|
|
function GetDefinition: string;
|
|
{$endregion}
|
|
property Definition: string read GetDefinition;
|
|
end;
|
|
|
|
// Spezifische Identität für Listen
|
|
IListIdentity = interface(IAstIdentity)
|
|
{$region 'private'}
|
|
function GetOpenToken: string;
|
|
function GetCloseToken: string;
|
|
function GetSeparator: string;
|
|
{$endregion}
|
|
property OpenToken: string read GetOpenToken;
|
|
property CloseToken: string read GetCloseToken;
|
|
property Separator: string read GetSeparator;
|
|
end;
|
|
|
|
// Factory and static access.
|
|
TIdentities = record
|
|
public
|
|
class function Location(ALine, ACol: Integer): ISourceLocation; static;
|
|
|
|
class function Structural(const ALoc: ISourceLocation = nil): IAstIdentity; static;
|
|
class function Identifier(const AName: string; const ALoc: ISourceLocation = nil): INamedIdentity; static;
|
|
class function Constant(const AValue: TDataValue; const ALoc: ISourceLocation = nil): IConstantIdentity; static;
|
|
class function Keyword(const AValue: IKeyword; const ALoc: ISourceLocation = nil): IKeywordIdentity; static;
|
|
class function Definition(const ADef: string; const ALoc: ISourceLocation = nil): IDefinitionIdentity; static;
|
|
|
|
class function List(const AOpen, AClose, ASeparator: string; const ALoc: ISourceLocation = nil): IListIdentity; static;
|
|
end;
|
|
|
|
implementation
|
|
|
|
type
|
|
TSourceLocation = class(TInterfacedObject, ISourceLocation)
|
|
private
|
|
FLine, FCol: Integer;
|
|
function GetLine: Integer;
|
|
function GetCol: Integer;
|
|
public
|
|
constructor Create(ALine, ACol: Integer);
|
|
function ToString: string; override;
|
|
end;
|
|
|
|
// Abstract base implementation providing the casting logic
|
|
TAbstractIdentity = class(TInterfacedObject, IAstIdentity)
|
|
private
|
|
FLocation: ISourceLocation;
|
|
function GetKind: TAstIdentityKind; virtual; abstract;
|
|
function GetLocation: ISourceLocation;
|
|
public
|
|
constructor Create(const ALoc: ISourceLocation);
|
|
function ToString: string; override;
|
|
|
|
function AsNamed: INamedIdentity; virtual;
|
|
function AsConstant: IConstantIdentity; virtual;
|
|
function AsKeyword: IKeywordIdentity; virtual;
|
|
function AsDefinition: IDefinitionIdentity; virtual;
|
|
function AsList: IListIdentity; virtual;
|
|
end;
|
|
|
|
TStructuralIdentity = class(TAbstractIdentity)
|
|
protected
|
|
function GetKind: TAstIdentityKind; override;
|
|
end;
|
|
|
|
TNamedIdentity = class(TAbstractIdentity, INamedIdentity)
|
|
private
|
|
FName: string;
|
|
function GetName: string;
|
|
protected
|
|
function GetKind: TAstIdentityKind; override;
|
|
public
|
|
constructor Create(const AName: string; const ALoc: ISourceLocation);
|
|
function ToString: string; override;
|
|
function AsNamed: INamedIdentity; override;
|
|
end;
|
|
|
|
TConstantIdentity = class(TAbstractIdentity, IConstantIdentity)
|
|
private
|
|
FValue: TDataValue;
|
|
function GetValue: TDataValue;
|
|
protected
|
|
function GetKind: TAstIdentityKind; override;
|
|
public
|
|
constructor Create(const AValue: TDataValue; const ALoc: ISourceLocation);
|
|
function ToString: string; override;
|
|
function AsConstant: IConstantIdentity; override;
|
|
end;
|
|
|
|
TKeywordIdentity = class(TAbstractIdentity, IKeywordIdentity)
|
|
private
|
|
FValue: IKeyword;
|
|
function GetValue: IKeyword;
|
|
protected
|
|
function GetKind: TAstIdentityKind; override;
|
|
public
|
|
constructor Create(const AValue: IKeyword; const ALoc: ISourceLocation);
|
|
function ToString: string; override;
|
|
function AsKeyword: IKeywordIdentity; override;
|
|
end;
|
|
|
|
TDefinitionIdentity = class(TAbstractIdentity, IDefinitionIdentity)
|
|
private
|
|
FDefinition: string;
|
|
function GetDefinition: string;
|
|
protected
|
|
function GetKind: TAstIdentityKind; override;
|
|
public
|
|
constructor Create(const ADef: string; const ALoc: ISourceLocation);
|
|
function ToString: string; override;
|
|
function AsDefinition: IDefinitionIdentity; override;
|
|
end;
|
|
|
|
TListIdentity = class(TAbstractIdentity, IListIdentity)
|
|
private
|
|
FOpen, FClose, FSeparator: string;
|
|
function GetOpenToken: string;
|
|
function GetCloseToken: string;
|
|
function GetSeparator: string;
|
|
protected
|
|
function GetKind: TAstIdentityKind; override;
|
|
public
|
|
constructor Create(const AOpen, AClose, ASeparator: string; const ALoc: ISourceLocation);
|
|
function ToString: string; override;
|
|
function AsList: IListIdentity; override;
|
|
end;
|
|
|
|
{ TSourceLocation }
|
|
|
|
constructor TSourceLocation.Create(ALine, ACol: Integer);
|
|
begin
|
|
inherited Create;
|
|
FLine := ALine;
|
|
FCol := ACol;
|
|
end;
|
|
|
|
function TSourceLocation.GetCol: Integer;
|
|
begin
|
|
Result := FCol;
|
|
end;
|
|
|
|
function TSourceLocation.GetLine: Integer;
|
|
begin
|
|
Result := FLine;
|
|
end;
|
|
|
|
function TSourceLocation.ToString: string;
|
|
begin
|
|
Result := Format('Line %d, Col %d', [FLine, FCol]);
|
|
end;
|
|
|
|
{ TAbstractIdentity }
|
|
|
|
constructor TAbstractIdentity.Create(const ALoc: ISourceLocation);
|
|
begin
|
|
inherited Create;
|
|
FLocation := ALoc;
|
|
end;
|
|
|
|
function TAbstractIdentity.GetLocation: ISourceLocation;
|
|
begin
|
|
Result := FLocation;
|
|
end;
|
|
|
|
function TAbstractIdentity.ToString: string;
|
|
begin
|
|
if Assigned(FLocation) then
|
|
Result := FLocation.ToString
|
|
else
|
|
Result := '<unknown location>';
|
|
end;
|
|
|
|
function TAbstractIdentity.AsNamed: INamedIdentity;
|
|
begin
|
|
raise EInvalidCast.Create('Identity is not a Named Identity');
|
|
end;
|
|
|
|
function TAbstractIdentity.AsConstant: IConstantIdentity;
|
|
begin
|
|
raise EInvalidCast.Create('Identity is not a Constant Identity');
|
|
end;
|
|
|
|
function TAbstractIdentity.AsKeyword: IKeywordIdentity;
|
|
begin
|
|
raise EInvalidCast.Create('Identity is not a Keyword Identity');
|
|
end;
|
|
|
|
function TAbstractIdentity.AsDefinition: IDefinitionIdentity;
|
|
begin
|
|
raise EInvalidCast.Create('Identity is not a Definition Identity');
|
|
end;
|
|
|
|
function TAbstractIdentity.AsList: IListIdentity;
|
|
begin
|
|
raise EInvalidCast.Create('Identity is not a List Identity');
|
|
end;
|
|
|
|
{ TStructuralIdentity }
|
|
|
|
function TStructuralIdentity.GetKind: TAstIdentityKind;
|
|
begin
|
|
Result := ikStructural;
|
|
end;
|
|
|
|
{ TNamedIdentity }
|
|
|
|
constructor TNamedIdentity.Create(const AName: string; const ALoc: ISourceLocation);
|
|
begin
|
|
inherited Create(ALoc);
|
|
FName := AName;
|
|
end;
|
|
|
|
function TNamedIdentity.GetKind: TAstIdentityKind;
|
|
begin
|
|
Result := ikNamed;
|
|
end;
|
|
|
|
function TNamedIdentity.GetName: string;
|
|
begin
|
|
Result := FName;
|
|
end;
|
|
|
|
function TNamedIdentity.AsNamed: INamedIdentity;
|
|
begin
|
|
Result := Self;
|
|
end;
|
|
|
|
function TNamedIdentity.ToString: string;
|
|
begin
|
|
Result := Format('Name: "%s" (%s)', [FName, inherited ToString]);
|
|
end;
|
|
|
|
{ TConstantIdentity }
|
|
|
|
constructor TConstantIdentity.Create(const AValue: TDataValue; const ALoc: ISourceLocation);
|
|
begin
|
|
inherited Create(ALoc);
|
|
FValue := AValue;
|
|
end;
|
|
|
|
function TConstantIdentity.GetKind: TAstIdentityKind;
|
|
begin
|
|
Result := ikConstant;
|
|
end;
|
|
|
|
function TConstantIdentity.GetValue: TDataValue;
|
|
begin
|
|
Result := FValue;
|
|
end;
|
|
|
|
function TConstantIdentity.AsConstant: IConstantIdentity;
|
|
begin
|
|
Result := Self;
|
|
end;
|
|
|
|
function TConstantIdentity.ToString: string;
|
|
begin
|
|
Result := Format('Const: %s (%s)', [FValue.ToString, inherited ToString]);
|
|
end;
|
|
|
|
{ TKeywordIdentity }
|
|
|
|
constructor TKeywordIdentity.Create(const AValue: IKeyword; const ALoc: ISourceLocation);
|
|
begin
|
|
inherited Create(ALoc);
|
|
FValue := AValue;
|
|
end;
|
|
|
|
function TKeywordIdentity.GetKind: TAstIdentityKind;
|
|
begin
|
|
Result := ikKeyword;
|
|
end;
|
|
|
|
function TKeywordIdentity.GetValue: IKeyword;
|
|
begin
|
|
Result := FValue;
|
|
end;
|
|
|
|
function TKeywordIdentity.AsKeyword: IKeywordIdentity;
|
|
begin
|
|
Result := Self;
|
|
end;
|
|
|
|
function TKeywordIdentity.ToString: string;
|
|
begin
|
|
Result := Format('Keyword: :%s (%s)', [FValue.Name, inherited ToString]);
|
|
end;
|
|
|
|
{ TDefinitionIdentity }
|
|
|
|
constructor TDefinitionIdentity.Create(const ADef: string; const ALoc: ISourceLocation);
|
|
begin
|
|
inherited Create(ALoc);
|
|
FDefinition := ADef;
|
|
end;
|
|
|
|
function TDefinitionIdentity.GetKind: TAstIdentityKind;
|
|
begin
|
|
Result := ikDefinition;
|
|
end;
|
|
|
|
function TDefinitionIdentity.GetDefinition: string;
|
|
begin
|
|
Result := FDefinition;
|
|
end;
|
|
|
|
function TDefinitionIdentity.AsDefinition: IDefinitionIdentity;
|
|
begin
|
|
Result := Self;
|
|
end;
|
|
|
|
function TDefinitionIdentity.ToString: string;
|
|
begin
|
|
Result := Format('Def: "%s" (%s)', [FDefinition, inherited ToString]);
|
|
end;
|
|
|
|
{ TListIdentity }
|
|
|
|
constructor TListIdentity.Create(const AOpen, AClose, ASeparator: string; const ALoc: ISourceLocation);
|
|
begin
|
|
inherited Create(ALoc);
|
|
FOpen := AOpen;
|
|
FClose := AClose;
|
|
FSeparator := ASeparator;
|
|
end;
|
|
|
|
function TListIdentity.GetKind: TAstIdentityKind;
|
|
begin
|
|
Result := ikList;
|
|
end;
|
|
|
|
function TListIdentity.GetOpenToken: string;
|
|
begin
|
|
Result := FOpen;
|
|
end;
|
|
|
|
function TListIdentity.GetCloseToken: string;
|
|
begin
|
|
Result := FClose;
|
|
end;
|
|
|
|
function TListIdentity.GetSeparator: string;
|
|
begin
|
|
Result := FSeparator;
|
|
end;
|
|
|
|
function TListIdentity.AsList: IListIdentity;
|
|
begin
|
|
Result := Self;
|
|
end;
|
|
|
|
function TListIdentity.ToString: string;
|
|
begin
|
|
Result := Format('List: "%s...%s" (Sep: "%s") (%s)', [FOpen, FClose, FSeparator, inherited ToString]);
|
|
end;
|
|
|
|
{ TIdentities }
|
|
|
|
class function TIdentities.Location(ALine, ACol: Integer): ISourceLocation;
|
|
begin
|
|
Result := TSourceLocation.Create(ALine, ACol);
|
|
end;
|
|
|
|
class function TIdentities.Structural(const ALoc: ISourceLocation): IAstIdentity;
|
|
begin
|
|
Result := TStructuralIdentity.Create(ALoc);
|
|
end;
|
|
|
|
class function TIdentities.Identifier(const AName: string; const ALoc: ISourceLocation): INamedIdentity;
|
|
begin
|
|
Result := TNamedIdentity.Create(AName, ALoc);
|
|
end;
|
|
|
|
class function TIdentities.Constant(const AValue: TDataValue; const ALoc: ISourceLocation): IConstantIdentity;
|
|
begin
|
|
Result := TConstantIdentity.Create(AValue, ALoc);
|
|
end;
|
|
|
|
class function TIdentities.Keyword(const AValue: IKeyword; const ALoc: ISourceLocation): IKeywordIdentity;
|
|
begin
|
|
Result := TKeywordIdentity.Create(AValue, ALoc);
|
|
end;
|
|
|
|
class function TIdentities.Definition(const ADef: string; const ALoc: ISourceLocation): IDefinitionIdentity;
|
|
begin
|
|
Result := TDefinitionIdentity.Create(ADef, ALoc);
|
|
end;
|
|
|
|
class function TIdentities.List(const AOpen, AClose, ASeparator: string; const ALoc: ISourceLocation): IListIdentity;
|
|
begin
|
|
Result := TListIdentity.Create(AOpen, AClose, ASeparator, ALoc);
|
|
end;
|
|
|
|
end.
|