Files
MycLib/Src/AST/Myc.Ast.Identities.pas
T
Michael Schimmel 851f56c63f Ast list nodes
2025-11-29 18:59:16 +01:00

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.